911124
911124
#include <tools assistant.h=""></tools>
911124
fa009d
#include <tools tool.h=""></tools>
fa009d
fa009d
#include <toonz tapplication.h=""></toonz>
fa009d
#include <toonz txsheet.h=""></toonz>
fa009d
#include <toonz txsheethandle.h=""></toonz>
fa009d
#include <toonz txshlevelhandle.h=""></toonz>
fa009d
#include <toonz tframehandle.h=""></toonz>
fa009d
#include <toonz tobjecthandle.h=""></toonz>
fa009d
#include <toonz dpiscale.h=""></toonz>
fa009d
9cf8be
#include <tgl.h></tgl.h>
3bac66
#include <tproperty.h></tproperty.h>
9cf8be
911124
#include <limits></limits>
c5e805
#include <cassert></cassert>
911124
fa009d
fa009d
e48ced
#ifdef MACOSX
370a7e
const double TAssistantBase::lineWidthScale = 1.5;
e48ced
#else
370a7e
const double TAssistantBase::lineWidthScale = 1.0;
e48ced
#endif
911124
d9b9f4
d9b9f4
unsigned int TAssistantBase::drawFlags = 0;
d9b9f4
d9b9f4
911124
//************************************************************************
911124
//    TGuideline implementation
911124
//************************************************************************
911124
4df9cd
void
8074a5
TGuideline::drawSegment(
8074a5
  const TPointD &p0,
8074a5
  const TPointD &p1,
8074a5
  double pixelSize,
8074a5
  bool active,
8074a5
  bool enabled ) const
8074a5
{
dba7b5
  double colorBlack[4] = { 0.0, 0.0, 0.0, 0.25 };
dba7b5
  double colorWhite[4] = { 1.0, 1.0, 1.0, 0.25 };
8074a5
8074a5
  if (!this->enabled || !enabled)
dba7b5
    colorBlack[3] = (colorWhite[3] = 0.125);
dba7b5
  else if (active)
dba7b5
    colorBlack[3] = (colorWhite[3] = 0.5);
4df9cd
4df9cd
  glPushAttrib(GL_ALL_ATTRIB_BITS);
4df9cd
  tglEnableBlending();
370a7e
  tglEnableLineSmooth(true, 1.0 * TAssistant::lineWidthScale);
4df9cd
  TPointD d = p1 - p0;
4df9cd
  double k = norm2(d);
4df9cd
  if (k > TConsts::epsilon*TConsts::epsilon) {
370a7e
    k = 0.5*pixelSize*TAssistant::lineWidthScale/sqrt(k);
4df9cd
    d = TPointD(-k*d.y, k*d.x);
4df9cd
    glColor4dv(colorWhite);
4df9cd
    tglDrawSegment(p0 - d, p1 - d);
4df9cd
    glColor4dv(colorBlack);
4df9cd
    tglDrawSegment(p0 + d, p1 + d);
4df9cd
  }
4df9cd
  glPopAttrib();
4df9cd
}
4df9cd
4df9cd
//---------------------------------------------------------------------------------------------------
4df9cd
911124
double
9cf8be
TGuideline::calcTrackWeight(const TTrack &track, const TAffine &toScreen, bool &outLongEnough) const {
9cf8be
  outLongEnough = false;
8074a5
  if (!enabled || track.size() < 2)
911124
    return std::numeric_limits<double>::infinity();</double>
911124
911124
  const double snapLenght = 20.0;
911124
  const double snapScale = 1.0;
362052
  const double maxLength = 2.0*snapLenght*snapScale;
911124
911124
  double sumWeight = 0.0;
911124
  double sumLength = 0.0;
911124
  double sumDeviation = 0.0;
911124
9cf8be
  TPointD prev = toScreen*track[0].position;
0abdef
  for(int i = 1; i < track.size(); ++i) {
911124
    const TTrackPoint &tp = track[i];
0abdef
    TTrackPoint mid = TTrack::interpolationLinear(track[i-1], track[i], 0.5);
9cf8be
    TPointD p = toScreen*tp.position;
911124
    double length = tdistance(p, prev);
911124
    sumLength += length;
911124
911124
    double midStepLength = sumLength - 0.5*length;
9f0c16
    if (midStepLength > TConsts::epsilon) {
911124
      double weight = length*logNormalDistribuitionUnscaled(midStepLength, snapLenght, snapScale);
911124
      sumWeight += weight;
911124
f278a5
      double deviation = tdistance(
f278a5
        toScreen*mid.position,
f278a5
        toScreen*nearestPoint(mid.position) );
911124
      sumDeviation += weight*deviation;
911124
    }
911124
    prev = p;
9cf8be
9cf8be
    if (sumLength >= maxLength)
f278a5
      { outLongEnough = i < track.fixedSize(); break; }
911124
  }
9f0c16
  return sumWeight > TConsts::epsilon
9cf8be
       ? sumDeviation/sumWeight
9cf8be
       : std::numeric_limits<double>::infinity();</double>
911124
}
911124
911124
//---------------------------------------------------------------------------------------------------
911124
911124
TGuidelineP
9cf8be
TGuideline::findBest(const TGuidelineList &guidelines, const TTrack &track, const TAffine &toScreen, bool &outLongEnough) {
9cf8be
  outLongEnough = true;
911124
  double bestWeight = 0.0;
911124
  TGuidelineP best;
911124
  for(TGuidelineList::const_iterator i = guidelines.begin(); i != guidelines.end(); ++i) {
9cf8be
    double weight = (*i)->calcTrackWeight(track, toScreen, outLongEnough);
911124
    if (!best || weight < bestWeight)
911124
      { bestWeight = weight; best = *i; }
911124
  }
911124
  return best;
911124
}
911124
911124
911124
//************************************************************************
249386
//    TAssistantPoint implementation
249386
//************************************************************************
249386
7900ea
TAssistantPoint::TAssistantPoint(const TStringId &name, const TPointD &defPosition):
c5e805
  name(name),
7900ea
  defPosition(defPosition),
c5e805
  type(Circle),
e48ced
  position(defPosition),
249386
  radius(10.0),
c5e805
  visible(true),
249386
  selected() { }
249386
249386
249386
//************************************************************************
4da757
//    TAssistantType implementation
4da757
//************************************************************************
4da757
4da757
TMetaObjectHandler*
4da757
TAssistantType::createHandler(TMetaObject &obj) const
4da757
  { return createAssistant(obj); }
4da757
4da757
4da757
//************************************************************************
096df2
//    TAssistantBase implementation
911124
//************************************************************************
911124
096df2
TAssistantBase::TAssistantBase(TMetaObject &object):
9cf8be
  TMetaObjectHandler(object),
3bac66
  m_idEnabled("enabled"),
9cf8be
  m_idPoints("points"),
9cf8be
  m_idX("x"),
3bac66
  m_idY("y"),
c5e805
  m_basePoint()
3bac66
{
4da757
  addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()) );
3bac66
}
3bac66
3bac66
//---------------------------------------------------------------------------------------------------
3bac66
c5e805
TAssistantPoint&
096df2
TAssistantBase::addPoint(
c5e805
  const TStringId &name,
c5e805
  TAssistantPoint::Type type,
7900ea
  const TPointD &defPosition,
c5e805
  bool visible,
c5e805
  double radius )
c5e805
{
c5e805
  assert(!m_points.count(name));
c5e805
  TAssistantPoint &p = m_points.insert(
7900ea
    TAssistantPointMap::value_type(name, TAssistantPoint(name, defPosition)) ).first->second;
7900ea
  m_pointsOrder.push_back(&p);
c5e805
  p.type     = type;
c5e805
  p.radius   = radius;
c5e805
  p.visible  = visible;
c5e805
  if (!m_basePoint) m_basePoint = &p;
c5e805
  return p;
c5e805
}
c5e805
c5e805
//---------------------------------------------------------------------------------------------------
c5e805
c5e805
TAssistantPoint&
096df2
TAssistantBase::addPoint(
c5e805
  const TStringId &name,
c5e805
  TAssistantPoint::Type type,
7900ea
  const TPointD &defPosition,
c5e805
  bool visible )
7900ea
    { return addPoint(name, type, defPosition, visible, 10.0); }
c5e805
c5e805
//---------------------------------------------------------------------------------------------------
c5e805
c5e805
const TAssistantPoint&
096df2
TAssistantBase::getBasePoint() const
c5e805
  { assert(m_basePoint); return *m_basePoint; }
c5e805
c5e805
//---------------------------------------------------------------------------------------------------
c5e805
3bac66
void
096df2
TAssistantBase::addProperty(TProperty *p)
4da757
  { m_properties.add(p); }
4da757
4da757
//---------------------------------------------------------------------------------------------------
4da757
4da757
void
096df2
TAssistantBase::setTranslation(const TStringId &name, const QString &localName) const
4da757
  { m_properties.getProperty(name)->setQStringName( localName ); }
4da757
4da757
//---------------------------------------------------------------------------------------------------
4da757
4da757
void
096df2
TAssistantBase::updateTranslation() const
096df2
  { setTranslation(m_idEnabled, tr("Enabled")); }
3bac66
3bac66
//---------------------------------------------------------------------------------------------------
3bac66
3bac66
void
096df2
TAssistantBase::onSetDefaults() {
3bac66
  setEnabled(true);
7900ea
  for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i)
7900ea
    i->second.position = i->second.defPosition;
7900ea
  fixPoints();
7900ea
  fixData();
3bac66
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
c5e805
void
096df2
TAssistantBase::fixPoints()
c5e805
  { onFixPoints(); }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
b15438
bool
096df2
TAssistantBase::move(const TPointD &position) {
7900ea
  TPointD d = position - getBasePoint().position;
b15438
  if (d != TPointD()) {
b15438
    for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i)
b15438
      i->second.position += d;
b15438
    fixPoints();
b15438
    return true;
b15438
  }
b15438
  return false;
7900ea
}
7900ea
7900ea
//---------------------------------------------------------------------------------------------------
7900ea
b15438
bool
096df2
TAssistantBase::movePoint(const TStringId &name, const TPointD &position) {
c5e805
  TAssistantPointMap::iterator i = m_points.find(name);
b15438
  if (i != m_points.end() && i->second.position != position) {
c5e805
    onMovePoint(i->second, position);
b15438
    return true;
b15438
  }
b15438
  return false;
c5e805
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::setPointSelection(const TStringId &name, bool selected)  const {
c5e805
  if (const TAssistantPoint *p = findPoint(name))
c5e805
    p->selected = selected;
c5e805
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::setAllPointsSelection(bool selected) const {
c5e805
  for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i)
c5e805
    i->second.selected = selected;
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::onDataChanged(const TVariant &value) {
9cf8be
  const TVariant& pointsData = data()[m_idPoints];
9cf8be
  TVariantPathEntry entry;
9cf8be
9cf8be
  if (&value == &data() || &value == &pointsData)
9cf8be
    onAllDataChanged();
9cf8be
  else
c5e805
  if (pointsData.getChildPathEntry(value, entry) && entry.isField()) {
9cf8be
    const TVariant& pointData = pointsData[entry];
9cf8be
    TPointD position = TPointD(
9cf8be
      pointData[m_idX].getDouble(),
9cf8be
      pointData[m_idY].getDouble() );
c5e805
    movePoint(entry.field(), position);
3bac66
  } else
3bac66
  if (data().getChildPathEntry(value, entry) && entry.isField()) {
7900ea
    onDataFieldChanged(entry.field(), data()[entry.field()]);
9cf8be
  }
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::onDataFieldChanged(const TStringId &name, const TVariant &value)
096df2
  { updateProperty(name, value); }
7900ea
7900ea
//---------------------------------------------------------------------------------------------------
7900ea
7900ea
void
096df2
TAssistantBase::onAllDataChanged() {
9cf8be
  const TVariant& pointsData = data()[m_idPoints];
c5e805
  for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i) {
c5e805
    const TVariant& pointData = pointsData[i->first];
c5e805
    i->second.position = TPointD(
9cf8be
      pointData[m_idX].getDouble(),
9cf8be
      pointData[m_idY].getDouble() );
9cf8be
  }
249386
  fixPoints();
3bac66
  updateProperties();
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::onFixPoints()
9cf8be
  { }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::onMovePoint(TAssistantPoint &point, const TPointD &position)
c5e805
  { point.position = position; }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::onFixData() {
9cf8be
  TVariant& pointsData = data()[m_idPoints];
c5e805
  for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i) {
c5e805
    TVariant& pointData = pointsData[i->first];
c5e805
    pointData[m_idX].setDouble( i->second.position.x );
c5e805
    pointData[m_idY].setDouble( i->second.position.y );
9cf8be
  }
3bac66
}
3bac66
3bac66
//---------------------------------------------------------------------------------------------------
3bac66
3bac66
void
096df2
TAssistantBase::updateProperties() {
3bac66
  const TVariantMap &map = data().getMap();
3bac66
  for(TVariantMap::const_iterator i = map.begin(); i != map.end(); ++i)
3bac66
    if (i->first != m_idPoints)
3bac66
      updateProperty(i->first, i->second);
3bac66
}
3bac66
3bac66
//---------------------------------------------------------------------------------------------------
3bac66
3bac66
void
096df2
TAssistantBase::updateProperty(const TStringId &name, const TVariant &value) {
3bac66
  TProperty *property = m_properties.getProperty(name);
3bac66
  if (!property)
3bac66
    return;
3bac66
3bac66
  if (TBoolProperty *boolProperty = dynamic_cast<tboolproperty*>(property)) {</tboolproperty*>
3bac66
    boolProperty->setValue( value.getBool() );
3bac66
  } else
3bac66
  if (TDoubleProperty *doubleProperty = dynamic_cast<tdoubleproperty*>(property)) {</tdoubleproperty*>
3bac66
    doubleProperty->setValue( value.getDouble() );
3bac66
  } else
b52c5a
  if (TIntProperty *intProperty = dynamic_cast<tintproperty*>(property)) {</tintproperty*>
b52c5a
    intProperty->setValue( (int)value.getDouble() );
b52c5a
  } else
3bac66
  if (TStringProperty *stringProperty = dynamic_cast<tstringproperty*>(property)) {</tstringproperty*>
3bac66
    stringProperty->setValue( to_wstring(value.getString()) );
3bac66
  } else
3bac66
  if (TEnumProperty *enumProperty = dynamic_cast<tenumproperty*>(property)) {</tenumproperty*>
3bac66
    enumProperty->setValue( to_wstring(value.getString()) );
3bac66
  }
3bac66
}
3bac66
3bac66
//---------------------------------------------------------------------------------------------------
3bac66
3bac66
void
096df2
TAssistantBase::onPropertyChanged(const TStringId &name) {
3bac66
  TProperty *property = m_properties.getProperty(name);
3bac66
  if (!property)
3bac66
    return;
3bac66
3bac66
  if (name == m_idPoints)
3bac66
    return;
3bac66
3bac66
  if (TBoolProperty *boolProperty = dynamic_cast<tboolproperty*>(property)) {</tboolproperty*>
3bac66
    data()[name].setBool( boolProperty->getValue() );
3bac66
  } else
3bac66
  if (TDoubleProperty *doubleProperty = dynamic_cast<tdoubleproperty*>(property)) {</tdoubleproperty*>
3bac66
    data()[name].setDouble( doubleProperty->getValue() );
3bac66
  } else
b52c5a
  if (TIntProperty *intProperty = dynamic_cast<tintproperty*>(property)) {</tintproperty*>
b52c5a
    data()[name].setDouble( (double)intProperty->getValue() );
b52c5a
  } else
3bac66
  if (TStringProperty *stringProperty = dynamic_cast<tstringproperty*>(property)) {</tstringproperty*>
3bac66
    data()[name].setString( to_string(stringProperty->getValue()) );
3bac66
  } else
3bac66
  if (TEnumProperty *enumProperty = dynamic_cast<tenumproperty*>(property)) {</tenumproperty*>
3bac66
    data()[name].setString( to_string(enumProperty->getValue()) );
3bac66
  }
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
c7854d
double
096df2
TAssistantBase::getDrawingAlpha(bool enabled) const
c7854d
  { return enabled && this->getEnabled() ? 0.5 : 0.25; }
c7854d
c7854d
//---------------------------------------------------------------------------------------------------
c7854d
c7854d
double
096df2
TAssistantBase::getDrawingGridAlpha() const
c7854d
  { return 0.2; }
c7854d
c7854d
//---------------------------------------------------------------------------------------------------
c7854d
9cf8be
void
096df2
TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const {
c7854d
  double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
c7854d
  double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
d9b9f4
  
d9b9f4
  if (drawFlags & DRAW_ERROR) colorBlack[0] = 1;
4df9cd
4df9cd
  glPushAttrib(GL_ALL_ATTRIB_BITS);
4df9cd
  tglEnableBlending();
370a7e
  tglEnableLineSmooth(true, 1.0 * lineWidthScale);
4df9cd
  TPointD d = p1 - p0;
4df9cd
  double k = norm2(d);
4df9cd
  if (k > TConsts::epsilon*TConsts::epsilon) {
370a7e
    k = 0.5*pixelSize*lineWidthScale/sqrt(k);
4df9cd
    d = TPointD(-k*d.y, k*d.x);
4df9cd
    glColor4dv(colorWhite);
4df9cd
    tglDrawSegment(p0 - d, p1 - d);
4df9cd
    glColor4dv(colorBlack);
4df9cd
    tglDrawSegment(p0 + d, p1 + d);
4df9cd
  }
4df9cd
  glPopAttrib();
4df9cd
}
4df9cd
4df9cd
//---------------------------------------------------------------------------------------------------
4df9cd
4df9cd
void
096df2
TAssistantBase::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) const {
f278a5
  TPointD d = normal*5*pixelSize;
f278a5
  drawSegment(p - d,p + d, pixelSize, alpha);
f278a5
}
f278a5
f278a5
//---------------------------------------------------------------------------------------------------
f278a5
f278a5
void
096df2
TAssistantBase::drawDot(const TPointD &p, double alpha) const {
c7854d
  double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
c7854d
  double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
7900ea
7900ea
  glPushAttrib(GL_ALL_ATTRIB_BITS);
7900ea
  tglEnableBlending();
7900ea
7900ea
  glColor4dv(colorWhite);
7c7225
  tglEnablePointSmooth(6.0);
7900ea
  glBegin(GL_POINTS);
7900ea
  glVertex2d(p.x, p.y);
7900ea
  glEnd();
7900ea
7900ea
  glColor4dv(colorBlack);
7c7225
  tglEnablePointSmooth(3.0);
7900ea
  glBegin(GL_POINTS);
7900ea
  glVertex2d(p.x, p.y);
7900ea
  glEnd();
7900ea
7900ea
  glPopAttrib();
7900ea
}
7900ea
7900ea
//---------------------------------------------------------------------------------------------------
7900ea
7900ea
void
096df2
TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const {
c5e805
  if (!point.visible) return;
c5e805
249386
  double radius = point.radius;
9cf8be
  double crossSize = 1.2*radius;
9cf8be
c7854d
  double alpha = 0.5;
c7854d
  double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
c7854d
  double colorGray[4]  = { 0.5, 0.5, 0.5, alpha };
c7854d
  double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
e48ced
  double width = 1.5;
9cf8be
9cf8be
  if (point.selected) {
9cf8be
    colorBlack[2] = 1.0;
9cf8be
    colorGray[2] = 1.0;
249386
    width = 2.0;
9cf8be
  }
9cf8be
9cf8be
  glPushAttrib(GL_ALL_ATTRIB_BITS);
9cf8be
249386
  // fill
9cf8be
  tglEnableBlending();
9cf8be
  if (point.type == TAssistantPoint::CircleFill) {
9cf8be
    glColor4dv(colorGray);
9cf8be
    tglDrawDisk(point.position, radius*pixelSize);
9cf8be
  }
9cf8be
249386
  TPointD crossDx(pixelSize*crossSize, 0.0);
249386
  TPointD crossDy(0.0, pixelSize*crossSize);
c7854d
  TPointD gridDx(pixelSize*radius, 0.0);
c7854d
  TPointD gridDy(0.0, pixelSize*radius);
9cf8be
249386
  // back line
370a7e
  tglEnableLineSmooth(true, 2.0*width*lineWidthScale);
249386
  glColor4dv(colorWhite);
249386
  if (point.type == TAssistantPoint::CircleCross) {
249386
    tglDrawSegment(point.position - crossDx, point.position + crossDx);
249386
    tglDrawSegment(point.position - crossDy, point.position + crossDy);
e48ced
  }
249386
  tglDrawCircle(point.position, radius*pixelSize);
9cf8be
249386
  // front line
370a7e
  glLineWidth(width * lineWidthScale);
9cf8be
  glColor4dv(colorBlack);
249386
  if (point.type == TAssistantPoint::CircleCross) {
249386
    tglDrawSegment(point.position - crossDx, point.position + crossDx);
249386
    tglDrawSegment(point.position - crossDy, point.position + crossDy);
249386
  }
249386
  tglDrawCircle(point.position, radius*pixelSize);
9cf8be
c7854d
  // dots
c7854d
  switch(point.type) {
c7854d
  case TAssistantPoint::CircleDoubleDots:
c7854d
    drawDot(point.position - gridDx*0.5, alpha);
c7854d
    drawDot(point.position + gridDx*0.5, alpha);
c7854d
    drawDot(point.position - gridDy*0.5, alpha);
c7854d
    drawDot(point.position + gridDy*0.5, alpha);
c7854d
    //no break
c7854d
  case TAssistantPoint::CircleDots:
c7854d
    drawDot(point.position - gridDx, alpha);
c7854d
    drawDot(point.position + gridDx, alpha);
c7854d
    drawDot(point.position - gridDy, alpha);
c7854d
    drawDot(point.position + gridDy, alpha);
c7854d
    //no break
c7854d
  case TAssistantPoint::Circle:
c7854d
    drawDot(point.position, alpha);
c7854d
    break;
c7854d
  default:
c7854d
    break;
c7854d
  }
c7854d
9cf8be
  glPopAttrib();
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
1c1f1a
TAssistantBase::drawIndex(const TPointD &p, int index, bool selected, double pixelSize) const {
1c1f1a
  static const int segments[7][4] = {
1c1f1a
    { 0, 2, 1, 2 },   // A
1c1f1a
    { 1, 1, 1, 2 },   // B    + A +
1c1f1a
    { 1, 0, 1, 1 },   // C    F   B
1c1f1a
    { 0, 0, 1, 0 },   // D    + G +
1c1f1a
    { 0, 0, 0, 1 },   // E    E   C
1c1f1a
    { 0, 1, 0, 2 },   // F    + D +
1c1f1a
    { 0, 1, 1, 1 } }; // G
1c1f1a
    
1c1f1a
  static const int glyphs[][7] = {
1c1f1a
  // A B C D E F G
1c1f1a
    {1,1,1,1,1,1,0},   // 0
1c1f1a
    {0,1,1,0,0,0,0},   // 1
1c1f1a
    {1,1,0,1,1,0,1},   // 2
1c1f1a
    {1,1,1,1,0,0,1},   // 3
1c1f1a
    {0,1,1,0,0,1,1},   // 4
1c1f1a
    {1,0,1,1,0,1,1},   // 5
1c1f1a
    {1,0,1,1,1,1,1},   // 6
1c1f1a
    {1,1,1,0,0,1,0},   // 7
1c1f1a
    {1,1,1,1,1,1,1},   // 8
1c1f1a
    {1,1,1,1,0,1,1} }; // 9
1c1f1a
  
1c1f1a
  if (index < 0) index = 0;
1c1f1a
  
1c1f1a
  int len = 0;
1c1f1a
  int digits[16] = {};
1c1f1a
  for(int i = index; i; i /= 10)
1c1f1a
    digits[len++] = i%10;
1c1f1a
  if (!len) len = 1;
1c1f1a
  
1c1f1a
  double w = 5, h = 5, d = 0.5, dx = w+2;
1c1f1a
  double alpha = 0.5;
1c1f1a
  double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
1c1f1a
  double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
1c1f1a
  if (selected) colorBlack[2] = 1.0;
1c1f1a
1c1f1a
  glPushAttrib(GL_ALL_ATTRIB_BITS);
1c1f1a
  tglEnableBlending();
370a7e
  tglEnableLineSmooth(true, 1.0 * lineWidthScale);
370a7e
  double k = 0.5*pixelSize*lineWidthScale;
1c1f1a
  
1c1f1a
  double y = p.y;
1c1f1a
  for(int i = 0; i < len; ++i) {
1c1f1a
    double x = p.x + dx*(len-i-1);
1c1f1a
    const int *g = glyphs[digits[i]];
1c1f1a
    for(int i = 0; i < 7; ++i) {
1c1f1a
      if (!g[i]) continue;
1c1f1a
      const int *s = segments[i];
1c1f1a
      if (s[0] == s[2]) {
1c1f1a
        // vertical
1c1f1a
        glColor4dv(colorWhite);
1c1f1a
        tglDrawSegment(
1c1f1a
          TPointD(x + s[0]*w + k, y + s[1]*h + d),
1c1f1a
          TPointD(x + s[2]*w + k, y + s[3]*h - d) );
1c1f1a
        glColor4dv(colorBlack);
1c1f1a
        tglDrawSegment(
1c1f1a
          TPointD(x + s[0]*w - k, y + s[1]*h + d),
1c1f1a
          TPointD(x + s[2]*w - k, y + s[3]*h - d) );
1c1f1a
      } else {
1c1f1a
        // horisontal
1c1f1a
        glColor4dv(colorWhite);
1c1f1a
        tglDrawSegment(
1c1f1a
          TPointD(x + s[0]*w + d, y + s[1]*h + k),
1c1f1a
          TPointD(x + s[2]*w - d, y + s[3]*h + k) );
1c1f1a
        glColor4dv(colorBlack);
1c1f1a
        tglDrawSegment(
1c1f1a
          TPointD(x + s[0]*w + d, y + s[1]*h - k),
1c1f1a
          TPointD(x + s[2]*w - d, y + s[3]*h - k) );
1c1f1a
      }
1c1f1a
    }
1c1f1a
  }
1c1f1a
  glPopAttrib();
1c1f1a
}
1c1f1a
1c1f1a
//---------------------------------------------------------------------------------------------------
1c1f1a
1c1f1a
void
d9b9f4
TAssistantBase::draw(TToolViewer*, bool) const
9cf8be
  { }
9cf8be
9cf8be
//---------------------------------------------------------------------------------------------------
9cf8be
9cf8be
void
096df2
TAssistantBase::drawEdit(TToolViewer *viewer) const {
9cf8be
  // paint all points
4df9cd
  draw(viewer);
9cf8be
  double pixelSize = sqrt(tglGetPixelSize2());
c5e805
  for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i)
c5e805
    drawPoint(i->second, pixelSize);
9cf8be
}
9cf8be
1c1f1a
//---------------------------------------------------------------------------------------------------
1c1f1a
1c1f1a
void
1c1f1a
TAssistantBase::drawEdit(TToolViewer *viewer, int index) const {
1c1f1a
  drawEdit(viewer);
1c1f1a
  drawIndex(
1c1f1a
    getBasePoint().position + TPointD(8, 8),
1c1f1a
    index, getBasePoint().selected, sqrt(tglGetPixelSize2()) );
1c1f1a
}
1c1f1a
096df2
096df2
//************************************************************************
096df2
//    TAssistant implementation
096df2
//************************************************************************
096df2
096df2
TAssistant::TAssistant(TMetaObject &object):
096df2
  TAssistantBase(object),
096df2
  m_idMagnetism("magnetism")
096df2
  { addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()) ); }
096df2
096df2
//---------------------------------------------------------------------------------------------------
096df2
096df2
void
096df2
TAssistant::updateTranslation() const {
096df2
  TAssistantBase::updateTranslation();
096df2
  setTranslation(m_idMagnetism, tr("Magnetism"));
096df2
}
096df2
096df2
//---------------------------------------------------------------------------------------------------
096df2
096df2
void
096df2
TAssistant::onSetDefaults() {
096df2
  setMagnetism(1.0);
096df2
  TAssistantBase::onSetDefaults();
096df2
}
096df2
096df2
//---------------------------------------------------------------------------------------------------
096df2
096df2
void
096df2
TAssistant::onFixData() {
096df2
  TAssistantBase::onFixData();
096df2
  setMagnetism( std::max(0.0, std::min(1.0, getMagnetism())) );
096df2
}
096df2
096df2
//---------------------------------------------------------------------------------------------------
096df2
096df2
void
096df2
TAssistant::getGuidelines(const TPointD&, const TAffine&, TGuidelineList&) const
096df2
  { }
096df2
9cf8be
//---------------------------------------------------------------------------------------------------
9a49d4
9a49d4
bool
9a49d4
TAssistant::calcPerspectiveStep(
9a49d4
  double minStep,
9a49d4
  double minX,
9a49d4
  double maxX,
9a49d4
  double x0,
9a49d4
  double x1,
9a49d4
  double x2,
9a49d4
  double &outK,
9a49d4
  double &outMin,
9a49d4
  double &outMax )
9a49d4
{
9a49d4
  outK = outMin = outMax = 0.0;
9a49d4
9a49d4
  double dx1 = x1 - x0;
9a49d4
  double dx2 = x2 - x0;
9a49d4
  if (fabs(dx1) <= TConsts::epsilon) return false;
9a49d4
  if (fabs(dx2) <= TConsts::epsilon) return false;
9a49d4
  if ((dx1 < 0.0) != (dx2 < 0.0)) dx2 = -dx2;
9a49d4
  if (fabs(dx2 - dx1) <= minStep) return false;
9a49d4
  if (fabs(dx2) < fabs(dx1)) std::swap(dx1, dx2);
9a49d4
9a49d4
  if (x0 <= minX + TConsts::epsilon && dx1 < 0.0) return false;
9a49d4
  if (x0 >= maxX - TConsts::epsilon && dx1 > 0.0) return false;
9a49d4
9a49d4
  outK = dx2/dx1;
9a49d4
  double minI = log(minStep/fabs(dx1*(1.0 - 1.0/outK)))/log(outK);
9a49d4
  outMin = dx1*pow(outK, floor(minI - TConsts::epsilon));
9a49d4
  if (fabs(outMin) < TConsts::epsilon) return false;
9a49d4
  outMax = (dx1 > 0.0 ? maxX : minX) - x0;
9a49d4
  return true;
9a49d4
}
fa009d
fa009d
fa009d
bool
fa009d
TAssistant::scanAssistants(
fa009d
  TTool *tool,
fa009d
  const TPointD *positions,
fa009d
  int positionsCount,
fa009d
  TGuidelineList *outGuidelines,
fa009d
  bool draw,
fa009d
  bool enabledOnly,
fa009d
  bool markEnabled,
fa009d
  bool drawGuidelines,
fa009d
  TImage *skipImage )
fa009d
{
fa009d
  TGuidelineList guidelines;
fa009d
  if (drawGuidelines && !outGuidelines)
fa009d
    outGuidelines = &guidelines;
fa009d
fa009d
  bool found = false;
fa009d
  bool findGuidelines = (positions && positionsCount > 0 && outGuidelines);
fa009d
  if (!findGuidelines) drawGuidelines = false;
fa009d
  bool doSomething = findGuidelines || draw;
fa009d
  
fa009d
  if (tool)
fa009d
  if (TToolViewer *viewer = tool->getViewer())
fa009d
  if (TApplication *application = tool->getApplication())
fa009d
  if (TXshLevelHandle *levelHandle = application->getCurrentLevel())
fa009d
  if (TXshLevel *level = levelHandle->getLevel())
fa009d
  if (TXshSimpleLevel *simpleLevel = level->getSimpleLevel())
fa009d
  if (TFrameHandle *frameHandle = application->getCurrentFrame())
fa009d
  if (TXsheetHandle *XsheetHandle = application->getCurrentXsheet())
fa009d
  if (TXsheet *Xsheet = XsheetHandle->getXsheet())
fa009d
  {
fa009d
    TPointD dpiScale = getCurrentDpiScale(simpleLevel, tool->getCurrentFid());
fa009d
    int frame = frameHandle->getFrame();
fa009d
    int count = Xsheet->getColumnCount();
fa009d
    TAffine worldToTrack;
fa009d
    if ( tool->getToolType() & TTool::LevelTool
fa009d
      && !application->getCurrentObject()->isSpline() )
fa009d
    {
fa009d
      worldToTrack.a11 /= dpiScale.x;
fa009d
      worldToTrack.a22 /= dpiScale.y;
fa009d
    }
fa009d
fa009d
    for(int i = 0; i < count; ++i)
fa009d
      if (TXshColumn *column = Xsheet->getColumn(i))
fa009d
      if (column->isCamstandVisible())
fa009d
      if (column->isPreviewVisible())
fa009d
      if (TImageP image = Xsheet->getCell(frame, i).getImage(false))
fa009d
      if (image != skipImage)
fa009d
      if (image->getType() == TImage::META)
fa009d
      if (TMetaImage *metaImage = dynamic_cast<tmetaimage*>(image.getPointer()))</tmetaimage*>
fa009d
      {
fa009d
        TAffine imageToTrack = worldToTrack * tool->getColumnMatrix(i);
fa009d
        if (draw) { glPushMatrix(); tglMultMatrix(imageToTrack); }
fa009d
fa009d
        TMetaImage::Reader reader(*metaImage);
fa009d
        for(TMetaObjectListCW::iterator i = reader->begin(); i != reader->end(); ++i)
fa009d
          if (*i)
fa009d
          if (const TAssistant *assistant = (*i)->getHandler<tassistant>())</tassistant>
fa009d
          if (!enabledOnly || assistant->getEnabled())
fa009d
          {
fa009d
            found = true;
b52c5a
            if (!doSomething) return true;
fa009d
            if (findGuidelines)
fa009d
              for(int i = 0; i < positionsCount; ++i)
fa009d
                assistant->getGuidelines(positions[i], imageToTrack, *outGuidelines);
fa009d
            if (draw) assistant->draw(viewer, assistant->getEnabled() && markEnabled);
fa009d
          }
fa009d
fa009d
        if (draw) glPopMatrix();
fa009d
      }
fa009d
  }
fa009d
  
fa009d
  if (drawGuidelines)
fa009d
    for(TGuidelineList::const_iterator i = outGuidelines->begin(); i != outGuidelines->end(); ++i)
fa009d
      (*i)->draw();
fa009d
  
fa009d
  return found;
fa009d
}