// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2005 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 #include #include #include #include #ifdef FC_OS_WIN32 # include #endif #ifdef FC_OS_MACOSX # include #else # include #endif #include "SoFCBackgroundGradient.h" static const std::array big_circle = [] { constexpr float pi = std::numbers::pi_v; constexpr float sqrt2 = std::numbers::sqrt2_v; std::array result; int c = 0; for (GLfloat i = 0; i < 2 * pi; i += 2 * pi / 32, c++) { result[c][0] = sqrt2 * cosf(i); result[c][1] = sqrt2 * sinf(i); } return result; }(); static const std::array small_oval = [] { constexpr float pi = std::numbers::pi_v; constexpr float sqrt2 = std::numbers::sqrt2_v; static const float sqrt1_2 = std::sqrt(1 / 2.F); std::array result; int c = 0; for (GLfloat i = 0; i < 2 * pi; i += 2 * pi / 32, c++) { result[c][0] = 0.3 * sqrt2 * cosf(i); result[c][1] = sqrt1_2 * sinf(i); } return result; }(); using namespace Gui; SO_NODE_SOURCE(SoFCBackgroundGradient) void SoFCBackgroundGradient::finish() { atexit_cleanup(); } /*! Constructor. */ SoFCBackgroundGradient::SoFCBackgroundGradient() { SO_NODE_CONSTRUCTOR(SoFCBackgroundGradient); fCol.setValue(0.5f, 0.5f, 0.8f); tCol.setValue(0.7f, 0.7f, 0.9f); mCol.setValue(1.0f, 1.0f, 1.0f); gradient = Gradient::LINEAR; } /*! Destructor. */ SoFCBackgroundGradient::~SoFCBackgroundGradient() = default; // doc from parent void SoFCBackgroundGradient::initClass() { SO_NODE_INIT_CLASS(SoFCBackgroundGradient, SoNode, "Node"); } void SoFCBackgroundGradient::GLRender(SoGLRenderAction* /*action*/) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); if (gradient == Gradient::LINEAR) { glBegin(GL_TRIANGLE_STRIP); if (mCol[0] < 0) { glColor3f(fCol[0], fCol[1], fCol[2]); glVertex2f(-1, 1); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2f(-1, -1); glColor3f(fCol[0], fCol[1], fCol[2]); glVertex2f(1, 1); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2f(1, -1); } else { glColor3f(fCol[0], fCol[1], fCol[2]); glVertex2f(-1, 1); glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2f(-1, 0); glColor3f(fCol[0], fCol[1], fCol[2]); glVertex2f(1, 1); glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2f(1, 0); glEnd(); glBegin(GL_TRIANGLE_STRIP); glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2f(-1, 0); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2f(-1, -1); glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2f(1, 0); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2f(1, -1); } } else { // radial gradient glBegin(GL_TRIANGLE_FAN); glColor3f(fCol[0], fCol[1], fCol[2]); glVertex2f(0.0f, 0.0f); if (mCol[0] < 0) { // simple radial gradient glColor3f(tCol[0], tCol[1], tCol[2]); for (const GLfloat* vertex : big_circle) { glVertex2fv(vertex); } glVertex2fv(big_circle.front()); } else { glColor3f(mCol[0], mCol[1], mCol[2]); for (const GLfloat* vertex : small_oval) { glVertex2fv(vertex); } glVertex2fv(small_oval.front()); glEnd(); glBegin(GL_TRIANGLE_STRIP); for (std::size_t i = 0; i < small_oval.size(); i++) { glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2fv(small_oval[i]); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2fv(big_circle[i]); } glColor3f(mCol[0], mCol[1], mCol[2]); glVertex2fv(small_oval.front()); glColor3f(tCol[0], tCol[1], tCol[2]); glVertex2fv(big_circle.front()); } } // end of radial gradient glEnd(); glPopAttrib(); glPopMatrix(); // restore modelview glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } void SoFCBackgroundGradient::setGradient(SoFCBackgroundGradient::Gradient grad) { gradient = grad; } SoFCBackgroundGradient::Gradient SoFCBackgroundGradient::getGradient() const { return gradient; } void SoFCBackgroundGradient::setColorGradient(const SbColor& fromColor, const SbColor& toColor) { fCol = fromColor; tCol = toColor; mCol[0] = -1.0f; } void SoFCBackgroundGradient::setColorGradient( const SbColor& fromColor, const SbColor& toColor, const SbColor& midColor ) { fCol = fromColor; tCol = toColor; mCol = midColor; }