Files
create/src/Gui/Inventor/SoAxisCrossKit.cpp
Kacper Donat a72a63232a Base: Move App::Color to Base
Every basic data type is stored in Base module, color is standing out as
one that does not. Moving it to Base opens possibilities to integrate it
better with the rest of FreeCAD.
2025-02-17 21:10:26 +01:00

383 lines
12 KiB
C++

/***************************************************************************
* Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 "PreCompiled.h"
#ifndef _PreComp_
# ifdef FC_OS_MACOSX
# include <OpenGL/gl.h>
# else
# include <GL/gl.h>
# endif
#include <sstream>
# include <Inventor/actions/SoGetBoundingBoxAction.h>
# include <Inventor/actions/SoGLRenderAction.h>
# include <Inventor/bundles/SoMaterialBundle.h>
# include <Inventor/bundles/SoTextureCoordinateBundle.h>
# include <Inventor/elements/SoLazyElement.h>
# include <Inventor/elements/SoModelMatrixElement.h>
# include <Inventor/elements/SoViewportRegionElement.h>
# include <Inventor/elements/SoViewVolumeElement.h>
# include <Inventor/nodekits/SoShapeKit.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoCone.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoCube.h>
# include <Inventor/nodes/SoFontStyle.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoScale.h>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoText2.h>
# include <Inventor/nodes/SoTranslation.h>
#endif
#include <Base/Color.h>
#include <Gui/ViewParams.h>
#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<SoScale*>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<SoGetBoundingBoxAction*>(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<SoTranslation*>(root->getChild(0));
move->translation.setValue(base.getValue() + normal.getValue() * length.getValue());
}
else if (f == &this->color) {
auto sub = static_cast<SoSeparator*>(root->getChild(1));
auto col = static_cast<SoBaseColor*>(sub->getChild(0));
col->rgb = this->color.getValue();
}
else if (f == &this->text) {
auto sub = static_cast<SoSeparator*>(root->getChild(1));
auto label = static_cast<SoText2*>(sub->getChild(2));
label->string = this->text.getValue();
}
SoShape::notify(node);
}