// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2010 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include #if defined(FC_OS_WIN32) # include #endif #ifdef FC_OS_MACOSX # include #else # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SoAxisCrossKit.h" #include "SoDevicePixelRatioElement.h" using namespace Gui; SO_KIT_SOURCE(SoShapeScale) // Constructor. SoShapeScale::SoShapeScale() { SO_KIT_CONSTRUCTOR(SoShapeScale); SO_KIT_ADD_FIELD(active, (true)); SO_KIT_ADD_FIELD(scaleFactor, (1.0f)); SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, false, this, "", false); SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(shape, SoNode, SoCube, true, topSeparator, "", true); SO_KIT_ADD_CATALOG_ENTRY(scale, SoScale, false, topSeparator, shape, false); SO_KIT_INIT_INSTANCE(); } // Destructor. SoShapeScale::~SoShapeScale() = default; void SoShapeScale::initClass() { SO_KIT_INIT_CLASS(SoShapeScale, SoBaseKit, "BaseKit"); } void SoShapeScale::GLRender(SoGLRenderAction* action) { auto* scale = static_cast(this->getAnyPart(SbName("scale"), true)); if (!this->active.getValue()) { SbVec3f v(1.0f, 1.0f, 1.0f); if (scale->scaleFactor.getValue() != v) { scale->scaleFactor = v; } } else { SoState* state = action->getState(); const SbViewportRegion& vp = SoViewportRegionElement::get(state); const SbViewVolume& vv = SoViewVolumeElement::get(state); SbVec3f center(0.0f, 0.0f, 0.0f); float nsize = this->scaleFactor.getValue() / float(vp.getViewportSizePixels()[0]); SoModelMatrixElement::get(state).multVecMatrix(center, center); // world coords float sf = vv.getWorldToScreenScale(center, nsize); sf *= SoDevicePixelRatioElement::get(state); SbVec3f v(sf, sf, sf); if (scale->scaleFactor.getValue() != v) { scale->scaleFactor = v; } } inherited::GLRender(action); } // -------------------------------------------------------------- SO_KIT_SOURCE(SoAxisCrossKit) void SoAxisCrossKit::initClass() { SO_KIT_INIT_CLASS(SoAxisCrossKit, SoBaseKit, "BaseKit"); } SoAxisCrossKit::SoAxisCrossKit() { SO_KIT_CONSTRUCTOR(SoAxisCrossKit); // Add the parts to the catalog... SO_KIT_ADD_CATALOG_ENTRY(xAxis, SoShapeKit, true, this, "", true); SO_KIT_ADD_CATALOG_ENTRY(xHead, SoShapeKit, true, this, "", true); SO_KIT_ADD_CATALOG_ENTRY(yAxis, SoShapeKit, true, this, "", true); SO_KIT_ADD_CATALOG_ENTRY(yHead, SoShapeKit, true, this, "", true); SO_KIT_ADD_CATALOG_ENTRY(zAxis, SoShapeKit, true, this, "", true); SO_KIT_ADD_CATALOG_ENTRY(zHead, SoShapeKit, true, this, "", true); SO_KIT_INIT_INSTANCE(); createAxes(); } SoAxisCrossKit::~SoAxisCrossKit() = default; // This kit is made up entirely of SoShapeKits. // Since SoShapeKits do not affect state, neither does this. SbBool SoAxisCrossKit::affectsState() const { return false; } void SoAxisCrossKit::addWriteReference(SoOutput* /*out*/, SbBool /*isfromfield*/) { // this node should not be written out to a file } void SoAxisCrossKit::getBoundingBox(SoGetBoundingBoxAction* action) { inherited::getBoundingBox(action); action->resetCenter(); action->setCenter(SbVec3f(0, 0, 0), false); } // Set up parts for default configuration of the jumping jack void SoAxisCrossKit::createAxes() { // Create the heads. auto head = new SoCone; head->bottomRadius.setValue(5); head->height.setValue(10); setPart("xHead.shape", head); setPart("yHead.shape", head); setPart("zHead.shape", head); // Create the axes. auto coords = new SoCoordinate3; coords->point.set1Value(0, SbVec3f(0, 0, 0)); coords->point.set1Value(1, SbVec3f(90, 0, 0)); setPart("xAxis.coordinate3", coords); setPart("yAxis.coordinate3", coords); setPart("zAxis.coordinate3", coords); auto shape = new SoLineSet; setPart("xAxis.shape", shape); setPart("yAxis.shape", shape); setPart("zAxis.shape", shape); // Place the axes and heads set("yAxis.transform", "rotation 0 0 1 1.5707999"); set("zAxis.transform", "rotation 0 1 0 -1.5707999"); set("xHead.transform", "translation 95 0 0"); set("xHead.transform", "scaleFactor 0.5 1.5 0.5"); set("xHead.transform", "rotation 0 0 -1 1.5707999"); set("yHead.transform", "translation 0 95 0"); set("yHead.transform", "scaleFactor 0.5 1.5 0.5"); set("yHead.transform", "rotation 0 0 1 0"); set("zHead.transform", "translation 0 0 95"); set("zHead.transform", "scaleFactor 0.5 1.5 0.5"); set("zHead.transform", "rotation 1 0 0 1.5707999"); // Set colors & styles set("xAxis.appearance.lightModel", "model BASE_COLOR"); set("xHead.appearance.lightModel", "model BASE_COLOR"); set("yAxis.appearance.lightModel", "model BASE_COLOR"); set("yHead.appearance.lightModel", "model BASE_COLOR"); set("zAxis.appearance.lightModel", "model BASE_COLOR"); set("zHead.appearance.lightModel", "model BASE_COLOR"); set("xAxis.appearance.drawStyle", "lineWidth 1"); set("yAxis.appearance.drawStyle", "lineWidth 1"); set("zAxis.appearance.drawStyle", "lineWidth 1"); unsigned long colorLong; Base::Color color; std::stringstream parameterstring; colorLong = Gui::ViewParams::instance()->getAxisXColor(); color = Base::Color(static_cast(colorLong)); parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; set("xAxis.appearance.material", parameterstring.str().c_str()); set("xHead.appearance.material", parameterstring.str().c_str()); colorLong = Gui::ViewParams::instance()->getAxisYColor(); color = Base::Color(static_cast(colorLong)); parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; set("yAxis.appearance.material", parameterstring.str().c_str()); set("yHead.appearance.material", parameterstring.str().c_str()); colorLong = Gui::ViewParams::instance()->getAxisZColor(); color = Base::Color(static_cast(colorLong)); parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; set("zAxis.appearance.material", parameterstring.str().c_str()); set("zHead.appearance.material", parameterstring.str().c_str()); // Make unpickable set("xAxis.pickStyle", "style UNPICKABLE"); set("xHead.pickStyle", "style UNPICKABLE"); set("yAxis.pickStyle", "style UNPICKABLE"); set("yHead.pickStyle", "style UNPICKABLE"); set("zAxis.pickStyle", "style UNPICKABLE"); set("zHead.pickStyle", "style UNPICKABLE"); } // -------------------------------------------------------------- SO_NODE_SOURCE(SoRegPoint) void SoRegPoint::initClass() { SO_NODE_INIT_CLASS(SoRegPoint, SoShape, "Shape"); } SoRegPoint::SoRegPoint() { SO_NODE_CONSTRUCTOR(SoRegPoint); SO_NODE_ADD_FIELD(base, (SbVec3f(0, 0, 0))); SO_NODE_ADD_FIELD(normal, (SbVec3f(1, 1, 1))); SO_NODE_ADD_FIELD(length, (3.0)); SO_NODE_ADD_FIELD(color, (1.0f, 0.447059f, 0.337255f)); SO_NODE_ADD_FIELD(text, ("")); root = new SoSeparator(); root->ref(); // translation auto move = new SoTranslation(); move->translation.setValue(base.getValue() + normal.getValue() * length.getValue()); root->addChild(move); // sub-group auto col = new SoBaseColor(); col->rgb.setValue(this->color.getValue()); auto font = new SoFontStyle; font->size = 14; auto sub = new SoSeparator(); sub->addChild(col); sub->addChild(font); sub->addChild(new SoText2()); root->addChild(sub); } SoRegPoint::~SoRegPoint() { root->unref(); } /** * Renders the probe with text label and a bullet at the base point. */ void SoRegPoint::GLRender(SoGLRenderAction* action) { if (shouldGLRender(action)) { SoState* state = action->getState(); state->push(); SoMaterialBundle mb(action); SoTextureCoordinateBundle tb(action, true, false); SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); mb.sendFirst(); // make sure we have the correct material SbVec3f p1 = base.getValue(); SbVec3f p2 = p1 + normal.getValue() * length.getValue(); glLineWidth(1.0f); glColor3fv(color.getValue().getValue()); glBegin(GL_LINE_STRIP); glVertex3d(p1[0], p1[1], p1[2]); glVertex3d(p2[0], p2[1], p2[2]); glEnd(); glPointSize(5.0f); glBegin(GL_POINTS); glVertex3fv(p1.getValue()); glEnd(); glPointSize(2.0f); glBegin(GL_POINTS); glVertex3fv(p2.getValue()); glEnd(); root->GLRender(action); state->pop(); } } void SoRegPoint::generatePrimitives(SoAction* /*action*/) {} /** * Sets the bounding box of the probe to \a box and its center to \a center. */ void SoRegPoint::computeBBox(SoAction* action, SbBox3f& box, SbVec3f& center) { root->doAction(action); if (action->getTypeId().isDerivedFrom(SoGetBoundingBoxAction::getClassTypeId())) { static_cast(action)->resetCenter(); } SbVec3f p1 = base.getValue(); SbVec3f p2 = p1 + normal.getValue() * length.getValue(); box.extendBy(p1); box.extendBy(p2); center = box.getCenter(); } void SoRegPoint::notify(SoNotList* node) { SoField* f = node->getLastField(); if (f == &this->base || f == &this->normal || f == &this->length) { auto move = static_cast(root->getChild(0)); move->translation.setValue(base.getValue() + normal.getValue() * length.getValue()); } else if (f == &this->color) { auto sub = static_cast(root->getChild(1)); auto col = static_cast(sub->getChild(0)); col->rgb = this->color.getValue(); } else if (f == &this->text) { auto sub = static_cast(root->getChild(1)); auto label = static_cast(sub->getChild(2)); label->string = this->text.getValue(); } SoShape::notify(node); }