#include "iconcomponent.h" #include #include #include #include #include #include #include #include #include #include namespace VCtrl { //////////////////////////////////////////////////////////////////////////////// const dtEntity::StringId IconComponent::TYPE(dtEntity::SID("Icon")); const dtEntity::StringId IconComponent::PathId(dtEntity::SID("Path")); const dtEntity::StringId IconComponent::VOffsetId(dtEntity::SID("VOffset")); //////////////////////////////////////////////////////////////////////////////// IconComponent::IconComponent() : dtEntityOSG::TransformComponent(new osg::AutoTransform()) , mPath( dtEntity::DynamicStringProperty::SetValueCB(this, &IconComponent::SetPath), dtEntity:: DynamicStringProperty::GetValueCB(this, &IconComponent::GetPath) ) , mVOffset( dtEntity::DynamicFloatProperty::SetValueCB(this, &IconComponent::SetVOffset), dtEntity:: DynamicFloatProperty::GetValueCB(this, &IconComponent::GetVOffset) ) { Register(PathId, &mPath); Register(VOffsetId, &mVOffset); osg::AutoTransform *tr = static_cast(GetNode()); tr->setName("icon"); tr->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN); tr->setAutoScaleToScreen(true); tr->setNodeMask(dtEntity::NodeMasks::PICKABLE | dtEntity::NodeMasks::VISIBLE); tr->setNormal(osg::Vec3(0, 1, 0)); osg::StateSet *ss = tr->getOrCreateStateSet(); ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); ss->setRenderBinDetails(90, "DepthSortedBin"); ss->setMode(GL_BLEND, osg::StateAttribute::ON); ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::ref_ptr lw = new osg::LineWidth(); lw->setWidth(2); ss->setAttributeAndModes(lw, osg::StateAttribute::ON); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::Rebuild() { #define DOT_RADIUS 5 osg::AutoTransform *tr = static_cast(GetNode()); tr->dirtyBound(); tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 10)); tr->removeChildren(0, tr->getNumChildren()); if (!mVisible) return; osg::ref_ptr g = new osg::Geode(); tr->addChild(g); tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 1)); int x, y, w, h; if (mShowDot) { x = y = -DOT_RADIUS * 2; w = h = DOT_RADIUS * 4; osg::ref_ptr circle = new osg::Geometry(); osg::Vec4Array *colours = new osg::Vec4Array(1); (*colours)[0] = mColor; circle->setColorArray(colours); circle->setColorBinding(osg::Geometry::BIND_OVERALL); const unsigned int n_points = 16; osg::Vec3Array *coords = new osg::Vec3Array(n_points + 2); (*coords)[0] = osg::Vec3(0, 0, 0); const double dx = 2.0 * osg::PI / n_points; for (unsigned int j = 1; j < n_points + 2; ++j) (*coords)[j].set(osg::Vec3(cos(dx * j) * DOT_RADIUS, sin(dx * j) * DOT_RADIUS, 0)); circle->setVertexArray(coords); circle->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, n_points + 2)); g->addDrawable(circle); } else { osg::ref_ptr img = osgDB::readImageFile(mPathVal); if (img.valid()) { int b = 4; g->addDrawable(IconSystem::CreateSquare(img->s(), img->t(), mVOffsetVal, mOriginAtBottom, img)); if (mOriginAtBottom) { x = -img->s() / 2 - b; y = 0 - b; w = img->s() + b * 2; h = img->t() + b * 2; } else { x = -img->s() / 2 - b; y = -img->t() / 2 - b; w = img->s() + b * 2; h = img->t() + b * 2; } } else { LOG_ERROR("Could not read symbol from path '" << mPathVal<< "'"); return; } } if (mSelected) { osg::ref_ptr sel = new osg::Geometry(); g->addDrawable(sel); osg::Vec4Array *colours = new osg::Vec4Array(1); (*colours)[0] = osg::Vec4(1, 0, 0, 1); sel->setColorArray(colours); sel->setColorBinding(osg::Geometry::BIND_OVERALL); osg::Vec3Array *coords = new osg::Vec3Array(4); (*coords)[0] = osg::Vec3(x , y , 0); (*coords)[1] = osg::Vec3(x , y + h, 0); (*coords)[2] = osg::Vec3(x + w, y + h, 0); (*coords)[3] = osg::Vec3(x + w, y , 0); sel->setVertexArray(coords); sel->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4)); osg::ref_ptr p = new osg::PolygonMode; p->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); sel->getOrCreateStateSet()->setAttribute(p); } } //////////////////////////////////////////////////////////////////////////////// std::string IconComponent::GetPath() const { return mPathVal; } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetPath(const std::string &path) { mPathVal = path; Rebuild(); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::Reload() { if(mPathVal.size()) { Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// float IconComponent::GetVOffset() const { return mVOffsetVal; } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetVOffset(float v) { if (mVOffsetVal != v) { mVOffsetVal = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// dtEntity::Vec3d IconComponent::GetTranslation() const { osg::AutoTransform *tr = static_cast(GetNode()); return tr->getPosition(); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetTranslation(const dtEntity::Vec3d &v) { osg::AutoTransform *tr = static_cast(GetNode()); tr->setPosition(v); } //////////////////////////////////////////////////////////////////////////////// dtEntity::Vec3d IconComponent::GetScale() const { osg::AutoTransform *tr = static_cast(GetNode()); return tr->getScale(); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetScale(const dtEntity::Vec3d &v) { osg::AutoTransform *tr = static_cast(GetNode()); tr->setScale(v); } //////////////////////////////////////////////////////////////////////////////// dtEntity::Quat IconComponent::GetRotation() const { osg::AutoTransform *tr = static_cast(GetNode()); return tr->getRotation(); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetRotation(const dtEntity::Quat &v) { osg::AutoTransform *tr = static_cast(GetNode()); tr->setRotation(v); } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetColor(const osg::Vec4 &v) { if (mColor != v) { mColor = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetShowDot(bool v) { if (mShowDot != v) { mShowDot = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetOriginAtBottom(bool v) { if (mOriginAtBottom != v) { mOriginAtBottom = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// bool IconComponent::GetShowSelection() const { return mSelected; } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetShowSelection(bool v) { if (mSelected != v) { mSelected = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetVisible(bool v) { if (mVisible != v) { mVisible = v; Rebuild(); } } //////////////////////////////////////////////////////////////////////////////// void IconComponent::SetRoomNumber(int roomNumber) { mRoomNumber = roomNumber; } //////////////////////////////////////////////////////////////////////////// IconSystem::IconSystem(dtEntity::EntityManager &em) : dtEntity::DefaultEntitySystem(em, dtEntityOSG::TransformComponent::TYPE) { } //////////////////////////////////////////////////////////////////////////// osg::Drawable *IconSystem::CreateSquare(float width, float height, float voffset, bool originAtBottom, osg::Image *image) { // set up the Geometry. osg::Geometry *geom = new osg::Geometry; osg::Vec3Array *coords = new osg::Vec3Array(4); if (originAtBottom) { (*coords)[0] = osg::Vec3(-width / 2.0f, voffset, 0); (*coords)[1] = osg::Vec3(width / 2.0f, voffset, 0); (*coords)[2] = osg::Vec3(width / 2.0f, voffset + height, 0); (*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height, 0); } else { (*coords)[0] = osg::Vec3(-width / 2.0f, voffset - height / 2, 0); (*coords)[1] = osg::Vec3(width / 2.0f, voffset - height / 2, 0); (*coords)[2] = osg::Vec3(width / 2.0f, voffset + height / 2, 0); (*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height / 2, 0); } geom->setVertexArray(coords); osg::Vec3Array *norms = new osg::Vec3Array(1); (*norms)[0] = osg::Vec3(0, 1, 0); geom->setNormalArray(norms); geom->setNormalBinding(osg::Geometry::BIND_OVERALL); osg::Vec4Array *colours = new osg::Vec4Array(1); (*colours)[0] = osg::Vec4(1, 1, 1, 1); geom->setColorArray(colours); geom->setColorBinding(osg::Geometry::BIND_OVERALL); osg::Vec2Array *tcoords = new osg::Vec2Array(4); (*tcoords)[0].set(0.0f, 0.0f); (*tcoords)[1].set(1.0f, 0.0f); (*tcoords)[2].set(1.0f, 1.0f); (*tcoords)[3].set(0.0f, 1.0f); geom->setTexCoordArray(0, tcoords); geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); if (image) { osg::StateSet *stateset = geom->getOrCreateStateSet(); osg::Texture2D *texture = new osg::Texture2D; texture->setResizeNonPowerOfTwoHint(false); texture->setImage(image); stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); } return geom; } }