File indexing completed on 2024-04-14 03:49:28

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "tool.h"
0008 #include "particle.h"
0009 #include "rigidbody.h"
0010 #include <QtGlobal>
0011 
0012 namespace StepCore {
0013 
0014 STEPCORE_META_OBJECT(NoteImage, QT_TRANSLATE_NOOP("ObjectClass", "NoteImage"), QT_TRANSLATE_NOOP("ObjectDescription", "NoteImage: an image embedded in Note"), 0,
0015     STEPCORE_SUPER_CLASS(Item),
0016     STEPCORE_PROPERTY_RW(QByteArray, image, QT_TRANSLATE_NOOP("PropertyName", "image"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Image data"), image, setImage)
0017     )
0018 
0019 STEPCORE_META_OBJECT(NoteFormula, QT_TRANSLATE_NOOP("ObjectClass", "NoteFormula"), QT_TRANSLATE_NOOP("ObjectDescription", "NoteFormula: a formula embedded in Note"), 0,
0020     STEPCORE_SUPER_CLASS(NoteImage),
0021     STEPCORE_PROPERTY_RW(QString, code, QT_TRANSLATE_NOOP("PropertyName", "code"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Formula code"), code, setCode)
0022     )
0023 
0024 STEPCORE_META_OBJECT(Note, QT_TRANSLATE_NOOP("ObjectClass", "Note"), QT_TRANSLATE_NOOP("ObjectDescription", "Note: displays a textual note on the scene"), 0,
0025     STEPCORE_SUPER_CLASS(ItemGroup) STEPCORE_SUPER_CLASS(Tool),
0026     STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, QT_TRANSLATE_NOOP("PropertyName", "position"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Note position on the scene"), position, setPosition)
0027     STEPCORE_PROPERTY_RW(StepCore::Vector2d, size, QT_TRANSLATE_NOOP("PropertyName", "size"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Note size on the scene"), size, setSize)
0028     STEPCORE_PROPERTY_RW(QString, text, QT_TRANSLATE_NOOP("PropertyName", "text"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Text"), text, setText)
0029     )
0030 
0031 STEPCORE_META_OBJECT(Graph, QT_TRANSLATE_NOOP("ObjectClass", "Graph"), QT_TRANSLATE_NOOP("ObjectDescription", "Graph: plots a graph of any properties"), 0,
0032     STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Tool),
0033     STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, QT_TRANSLATE_NOOP("PropertyName", "position"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Graph position on the scene"), position, setPosition)
0034     STEPCORE_PROPERTY_RW(StepCore::Vector2d, size, QT_TRANSLATE_NOOP("PropertyName", "size"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Graph size on the scene"), size, setSize)
0035     STEPCORE_PROPERTY_RW(Object*, objectX, QT_TRANSLATE_NOOP("PropertyName", "objectX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "X axis: object"), objectX, setObjectX)
0036     STEPCORE_PROPERTY_RW(QString, propertyX, QT_TRANSLATE_NOOP("PropertyName", "propertyX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "X axis: object property"), propertyX, setPropertyX)
0037     STEPCORE_PROPERTY_RW(int, indexX, QT_TRANSLATE_NOOP("PropertyName", "indexX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "X axis: vector index"), indexX, setIndexX)
0038     STEPCORE_PROPERTY_RW(Object*, objectY, QT_TRANSLATE_NOOP("PropertyName", "objectY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Y axis: object"), objectY, setObjectY)
0039     STEPCORE_PROPERTY_RW(QString, propertyY, QT_TRANSLATE_NOOP("PropertyName", "propertyY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Y axis: property"), propertyY, setPropertyY)
0040     STEPCORE_PROPERTY_RW(int, indexY, QT_TRANSLATE_NOOP("PropertyName", "indexY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Y axis: vector index"), indexY, setIndexY)
0041     STEPCORE_PROPERTY_RW(bool, autoLimitsX, QT_TRANSLATE_NOOP("PropertyName", "autoLimitsX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Auto-limits along X axis"), autoLimitsX, setAutoLimitsX)
0042     STEPCORE_PROPERTY_RW(bool, autoLimitsY, QT_TRANSLATE_NOOP("PropertyName", "autoLimitsY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Auto-limits along Y axis"), autoLimitsY, setAutoLimitsY)
0043     STEPCORE_PROPERTY_RW(StepCore::Vector2d, limitsX, QT_TRANSLATE_NOOP("PropertyName", "limitsX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Limits along X axis"), limitsX, setLimitsX)
0044     STEPCORE_PROPERTY_RW(StepCore::Vector2d, limitsY, QT_TRANSLATE_NOOP("PropertyName", "limitsY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Limits along Y axis"), limitsY, setLimitsY)
0045     STEPCORE_PROPERTY_RW(bool, showPoints, QT_TRANSLATE_NOOP("PropertyName", "showPoints"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Show points on the graph"), showPoints, setShowPoints)
0046     STEPCORE_PROPERTY_RW(bool, showLines, QT_TRANSLATE_NOOP("PropertyName", "showLines"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Show lines on the graph"), showLines, setShowLines)
0047     STEPCORE_PROPERTY_R (StepCore::Vector2d, currentValue, QT_TRANSLATE_NOOP("PropertyName", "currentValue"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Current value"), currentValue)
0048     STEPCORE_PROPERTY_RW_D(StepCore::Vector2dList, points, QT_TRANSLATE_NOOP("PropertyName", "points"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "points"), points, setPoints)
0049     STEPCORE_PROPERTY_R (QString, unitsX, QT_TRANSLATE_NOOP("PropertyName", "unitsX"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyName", "Units along X axis"), unitsX)
0050     STEPCORE_PROPERTY_R (QString, unitsY, QT_TRANSLATE_NOOP("PropertyName", "unitsY"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyName", "Units along Y axis"), unitsY)
0051     )
0052 
0053 STEPCORE_META_OBJECT(Meter, QT_TRANSLATE_NOOP("ObjectClass", "Meter"), QT_TRANSLATE_NOOP("ObjectDescription", "Meter: displays any property on the scene"), 0,
0054     STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Tool),
0055     STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, QT_TRANSLATE_NOOP("PropertyName", "position"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Meter position on the scene"), position, setPosition)
0056     STEPCORE_PROPERTY_RW(StepCore::Vector2d, size, QT_TRANSLATE_NOOP("PropertyName", "size"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Meter size on the scene"), size, setSize)
0057     STEPCORE_PROPERTY_RW(Object*, object, QT_TRANSLATE_NOOP("PropertyName", "object"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Observed object"), object, setObject)
0058     STEPCORE_PROPERTY_RW(QString, property, QT_TRANSLATE_NOOP("PropertyName", "property"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Observed property"), property, setProperty)
0059     STEPCORE_PROPERTY_RW(int, index, QT_TRANSLATE_NOOP("PropertyName", "index"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Vector index"), index, setIndex)
0060     STEPCORE_PROPERTY_RW(int, digits, QT_TRANSLATE_NOOP("PropertyName", "digits"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Display digits"), digits, setDigits)
0061     STEPCORE_PROPERTY_R (double, value, QT_TRANSLATE_NOOP("PropertyName", "value"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Value"), value)
0062     STEPCORE_PROPERTY_R (QString, units, QT_TRANSLATE_NOOP("PropertyName", "units"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Units of measured property"), units)
0063     )
0064 
0065 STEPCORE_META_OBJECT(Controller, QT_TRANSLATE_NOOP("ObjectClass", "Controller"), QT_TRANSLATE_NOOP("ObjectDescription", "Controller: allows to easily control any property"), 0,
0066     STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Tool),
0067     STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, QT_TRANSLATE_NOOP("PropertyName", "position"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Controller position on the scene"), position, setPosition)
0068     STEPCORE_PROPERTY_RW(StepCore::Vector2d, size, QT_TRANSLATE_NOOP("PropertyName", "size"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Controller size on the scene"), size, setSize)
0069     STEPCORE_PROPERTY_RW(Object*, object, QT_TRANSLATE_NOOP("PropertyName", "object"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Controlled object"), object, setObject)
0070     STEPCORE_PROPERTY_RW(QString, property, QT_TRANSLATE_NOOP("PropertyName", "property"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Controlled property"), property, setProperty)
0071     STEPCORE_PROPERTY_RW(int, index, QT_TRANSLATE_NOOP("PropertyName", "index"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Vector index"), index, setIndex)
0072     STEPCORE_PROPERTY_RW(StepCore::Vector2d, limits, QT_TRANSLATE_NOOP("PropertyName", "limits"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Limits"), limits, setLimits)
0073     STEPCORE_PROPERTY_RW(QString, increaseShortcut, QT_TRANSLATE_NOOP("PropertyName", "increaseShortcut"), STEPCORE_UNITS_NULL,
0074                             QT_TRANSLATE_NOOP("PropertyDescription", "Shortcut to increase the value"), increaseShortcut, setIncreaseShortcut)
0075     STEPCORE_PROPERTY_RW(QString, decreaseShortcut, QT_TRANSLATE_NOOP("PropertyName", "decreaseShortcut"), STEPCORE_UNITS_NULL,
0076                             QT_TRANSLATE_NOOP("PropertyDescription", "Shortcut to decrease the value"), decreaseShortcut, setDecreaseShortcut)
0077     STEPCORE_PROPERTY_RW(double, increment, QT_TRANSLATE_NOOP("PropertyName", "increment"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Increment value"), increment, setIncrement)
0078     STEPCORE_PROPERTY_RWF(double, value, QT_TRANSLATE_NOOP("PropertyName", "value"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Value"),
0079                             MetaProperty::DYNAMIC | MetaProperty::SIDEEFFECTS, value, setValue)
0080     STEPCORE_PROPERTY_R (QString, units, QT_TRANSLATE_NOOP("PropertyName", "units"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Units of controlled property"), units)
0081     )
0082 
0083 STEPCORE_META_OBJECT(Tracer, QT_TRANSLATE_NOOP("ObjectClass", "Tracer"), QT_TRANSLATE_NOOP("ObjectDescription", "Tracer: traces trajectory of a point on a body"), 0,
0084     STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Tool),
0085     STEPCORE_PROPERTY_RW(Object*, body, QT_TRANSLATE_NOOP("PropertyName", "body"), STEPCORE_UNITS_NULL, QT_TRANSLATE_NOOP("PropertyDescription", "Traced body"), body, setBody)
0086     STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition, QT_TRANSLATE_NOOP("PropertyName", "localPosition"), QT_TRANSLATE_NOOP("Units", "m"),
0087                     QT_TRANSLATE_NOOP("PropertyDescription", "Local position"), localPosition, setLocalPosition)
0088     STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position, QT_TRANSLATE_NOOP("PropertyName", "position"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "Position"), position)
0089     STEPCORE_PROPERTY_RW_D(StepCore::Vector2dList, points, QT_TRANSLATE_NOOP("PropertyName", "points"), QT_TRANSLATE_NOOP("Units", "m"), QT_TRANSLATE_NOOP("PropertyDescription", "points"), points, setPoints)
0090     )
0091 
0092 namespace {
0093 
0094 static double variantToDouble(const QVariant& v, int index, bool *ok)
0095 {
0096     if(ok) *ok = true;
0097 
0098     if(v.userType() == qMetaTypeId<Vector2d>()) {
0099         if(index >= 0 && index < 2) return v.value<Vector2d>()[index];
0100     } else {
0101         if(index == -1) return v.toDouble(ok);
0102     }
0103 
0104     if(ok) *ok = false;
0105     return 0.0;
0106 }
0107 
0108 static QVariant doubleToVariant(const QVariant& v, int index, double newV, bool *ok)
0109 {
0110     if(ok) *ok = true;
0111 
0112     if(v.userType() == qMetaTypeId<Vector2d>()) {
0113         if(index >= 0 && index < 2) {
0114             Vector2d vector = v.value<Vector2d>();
0115             vector[index] = newV;
0116             return QVariant::fromValue(vector);
0117         }
0118     } else {
0119         if(index == -1) {
0120             bool ok1; v.toDouble(&ok1);
0121             if(ok1) return newV;
0122         }
0123     }
0124 
0125     if(ok) *ok = false;
0126     return 0.0;
0127 }
0128 
0129 }
0130 
0131 Note::Note(const Vector2d &position, const Vector2d &size, const QString &text)
0132     : _position(position), _size(size), _text(text)
0133 {
0134 }
0135 
0136 Graph::Graph(const Vector2d &position, const Vector2d &size)
0137     : _position(position), _size(size),
0138       _objectX(nullptr), _propertyX(), _indexX(-1),
0139       _objectY(nullptr), _propertyY(), _indexY(-1),
0140       _autoLimitsX(true), _autoLimitsY(true),
0141       _limitsX(0,1), _limitsY(0,1),
0142       _showLines(true), _showPoints(false)
0143 {
0144 }
0145 
0146 bool Graph::isValidX() const
0147 {
0148     bool ok;
0149     const MetaProperty* prX = propertyXPtr(); if(!prX) return false;
0150     variantToDouble(prX->readVariant(_objectX), _indexX, &ok);
0151     return ok;
0152 }
0153 
0154 bool Graph::isValidY() const
0155 {
0156     bool ok;
0157     const MetaProperty* prY = propertyYPtr(); if(!prY) return false;
0158     variantToDouble(prY->readVariant(_objectY), _indexY, &ok);
0159     return ok;
0160 }
0161 
0162 Vector2d Graph::currentValue(bool* ok) const
0163 {
0164     const MetaProperty* prX = propertyXPtr();
0165     const MetaProperty* prY = propertyYPtr();
0166 
0167     if(prX && prY) {
0168         bool ok1, ok2;
0169         Vector2d point(variantToDouble(prX->readVariant(_objectX), _indexX, &ok1),
0170                        variantToDouble(prY->readVariant(_objectY), _indexY, &ok2));
0171         if(ok1 && ok2) {
0172             if(ok) *ok = true;
0173             return point;
0174         }
0175     }
0176 
0177     if(ok) *ok = false;
0178     return Vector2d::Zero();
0179 }
0180 
0181 Vector2d Graph::recordPoint(bool* ok)
0182 {
0183     bool ok1;
0184     Vector2d point(currentValue(&ok1));
0185     if(ok1) {
0186         if(ok) *ok = true;
0187         _points.push_back(point);
0188         return point;
0189     }
0190 
0191     if(ok) *ok = false;
0192     return Vector2d::Zero();
0193 }
0194 
0195 /*
0196 void Graph::worldItemRemoved(Item* item)
0197 {
0198     if(item == 0) return;
0199     if(item == _objectX) setObjectX(0);
0200     if(item == _objectY) setObjectY(0);
0201 }
0202 
0203 void Graph::setWorld(World* world)
0204 {
0205     if(world == NULL) {
0206         setObjectX(0);
0207         setObjectY(0);
0208     } else if(this->world() != NULL) { 
0209         if(_objectX != NULL) _objectX = world->object(_objectX->name());
0210         if(_objectY != NULL) _objectY = world->object(_objectY->name());
0211     }
0212     Item::setWorld(world);
0213 }
0214 */
0215 
0216 QString Graph::unitsX() const
0217 {
0218     const MetaProperty* pr = propertyXPtr();
0219     if(!pr && !isValidX()) return QString();
0220 
0221     return pr->units();
0222 }
0223 
0224 QString Graph::unitsY() const
0225 {
0226     const MetaProperty* pr = propertyYPtr();
0227     if(!pr && !isValidY()) return QString();
0228 
0229     return pr->units();
0230 }
0231 
0232 Meter::Meter(const Vector2d &position, const Vector2d &size)
0233     : _position(position), _size(size),
0234       _object(nullptr), _property(), _index(-1),
0235       _digits(7)
0236 {
0237 }
0238 
0239 bool Meter::isValid() const
0240 {
0241     bool ok;
0242     const MetaProperty* pr = propertyPtr(); if(!pr) return false;
0243     variantToDouble(pr->readVariant(_object), _index, &ok);
0244     return ok;
0245 }
0246 
0247 double Meter::value(bool* ok) const
0248 {
0249     const MetaProperty* pr = propertyPtr();
0250 
0251     if(pr) {
0252         bool ok1;
0253         double v = variantToDouble(pr->readVariant(_object), _index, &ok1);
0254         if(ok1) {
0255             if(ok) *ok = true;
0256             return v;
0257         }
0258     }
0259 
0260     if(ok) *ok = false;
0261     return 0;
0262 }
0263 
0264 QString Meter::units() const
0265 {
0266     const MetaProperty* pr = propertyPtr();
0267     if(!pr && !isValid()) return QString();
0268 
0269     return pr->units();
0270 }
0271 
0272 /*
0273 void Meter::worldItemRemoved(Item* item)
0274 {
0275     if(item == 0) return;
0276     if(item == _object) setObject(0);
0277 }
0278 
0279 void Meter::setWorld(World* world)
0280 {
0281     if(world == NULL) {
0282         setObject(0);
0283     } else if(this->world() != NULL) { 
0284         if(_object != NULL) _object = world->object(_object->name());
0285     }
0286     Item::setWorld(world);
0287 }
0288 */
0289 
0290 Controller::Controller(const Vector2d &position, const Vector2d &size)
0291     : _position(position), _size(size),
0292       _object(nullptr), _property(), _index(-1),
0293       _limits(-1,1), _increment(0.1)
0294 {
0295 }
0296 
0297 bool Controller::isValid() const
0298 {
0299     bool ok;
0300     const MetaProperty* pr = propertyPtr(); if(!pr) return false;
0301     variantToDouble(pr->readVariant(_object), _index, &ok);
0302     return ok && pr->isWritable();
0303 }
0304 
0305 double Controller::value(bool* ok) const
0306 {
0307     const MetaProperty* pr = propertyPtr();
0308 
0309     if(pr && pr->isWritable()) {
0310         bool ok1;
0311         double v = variantToDouble(pr->readVariant(_object), _index, &ok1);
0312         if(ok1) {
0313             if(ok) *ok = true;
0314             return v;
0315         }
0316     }
0317 
0318     if(ok) *ok = false;
0319     return 0;
0320 }
0321 
0322 void Controller::setValue(double value, bool* ok = nullptr)
0323 {
0324     const MetaProperty* pr = propertyPtr();
0325 
0326     if(pr && pr->isWritable()) {
0327         bool ok1;
0328         QVariant v = doubleToVariant(pr->readVariant(_object), _index, value, &ok1);
0329         if(ok1) {
0330             if(ok) *ok = true;
0331             pr->writeVariant(_object, v);
0332         }
0333     }
0334 
0335     if(ok) *ok = false;
0336 }
0337 
0338 QString Controller::units() const
0339 {
0340     const MetaProperty* pr = propertyPtr();
0341     if(!pr && !isValid()) return QString();
0342 
0343     return pr->units();
0344 }
0345 
0346 /*
0347 void Controller::worldItemRemoved(Item* item)
0348 {
0349     if(item == 0) return;
0350     if(item == _object) setObject(0);
0351 }
0352 
0353 void Controller::setWorld(World* world)
0354 {
0355     if(world == NULL) {
0356         setObject(0);
0357     } else if(this->world() != NULL) { 
0358         if(_object != NULL) _object = world->object(_object->name());
0359     }
0360     Item::setWorld(world);
0361 }
0362 */
0363 
0364 Tracer::Tracer(Object* body, const Vector2d& localPosition)
0365     : _localPosition(localPosition)
0366 {
0367     setColor(0xff0000ff);
0368     setBody(body);
0369 }
0370 
0371 void Tracer::setBody(Object* body)
0372 {
0373     if(body) {
0374         if(body->metaObject()->inherits<Particle>()) {
0375             _body = body;
0376             _p = static_cast<Particle*>(body);
0377             _r = nullptr;
0378             return;
0379         } else if(body->metaObject()->inherits<RigidBody>()) {
0380             _body = body;
0381             _p = nullptr;
0382             _r = static_cast<RigidBody*>(body);
0383             return;
0384         }
0385     }
0386     _body = nullptr;
0387     _p = nullptr;
0388     _r = nullptr;
0389 }
0390 
0391 Vector2d Tracer::position() const
0392 {
0393     if(_p) return _p->position() + _localPosition;
0394     else if(_r) return _r->pointLocalToWorld(_localPosition);
0395     return _localPosition;
0396 }
0397 
0398 /*
0399 void Tracer::worldItemRemoved(Item* item)
0400 {
0401     if(item == _body) setBody(NULL);
0402 }
0403 
0404 void Tracer::setWorld(World* world)
0405 {
0406     if(world == NULL) {
0407         setBody(NULL);
0408     } else if(this->world() != NULL) { 
0409         if(_body != NULL) setBody(world->item(body()->name()));
0410     }
0411     Item::setWorld(world);
0412 }
0413 */
0414 
0415 } // namespace StepCore
0416