Skip to content

Commit

Permalink
Merge pull request openscad#5577 from openscad/3mf-export-dialog
Browse files Browse the repository at this point in the history
Add export dialog for 3MF.
  • Loading branch information
t-paul authored Jan 13, 2025
2 parents 3d2d3f2 + d2c5eca commit 0e6f663
Show file tree
Hide file tree
Showing 56 changed files with 3,670 additions and 1,809 deletions.
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ set(CORE_SOURCES
src/core/CgalAdvNode.cc
src/core/Children.cc
src/core/ColorNode.cc
src/core/ColorUtil.cc
src/core/Context.cc
src/core/ContextFrame.cc
src/core/ContextMemoryManager.cc
Expand All @@ -813,6 +814,7 @@ set(CORE_SOURCES
src/core/RenderVariables.cc
src/core/RotateExtrudeNode.cc
src/core/ScopeContext.cc
src/core/Settings.cc
src/core/SourceFile.cc
src/core/SourceFileCache.cc
src/core/StatCache.cc
Expand Down Expand Up @@ -1079,6 +1081,7 @@ set(GUI_SOURCES
src/gui/Editor.cc
src/gui/ErrorLog.cc
src/gui/EventFilter.h
src/gui/Export3mfDialog.cc
src/gui/ExportPdfDialog.cc
src/gui/FontListDialog.cc
src/gui/FontListTableView.cc
Expand All @@ -1105,7 +1108,6 @@ set(GUI_SOURCES
src/gui/ScadApi.cc
src/gui/ScadLexer.cc
src/gui/ScintillaEditor.cc
src/gui/Settings.cc
src/gui/SettingsWriter.cc
src/gui/TabManager.cc
src/gui/TabWidget.cc
Expand Down Expand Up @@ -1147,6 +1149,7 @@ set(GUI_HEADERS
src/gui/Editor.h
src/gui/ErrorLog.h
src/gui/EventFilter.h
src/gui/Export3mfDialog.h
src/gui/ExportPdfDialog.h
src/gui/FontList.h
src/gui/FontListDialog.h
Expand All @@ -1172,7 +1175,6 @@ set(GUI_HEADERS
src/gui/ScadApi.h
src/gui/ScadLexer.h
src/gui/ScintillaEditor.h
src/gui/Settings.h
src/gui/SettingsWriter.h
src/gui/TabManager.h
src/gui/TabWidget.h
Expand Down Expand Up @@ -1200,6 +1202,7 @@ set(GUI_UIS
src/gui/Animate.ui
src/gui/Console.ui
src/gui/ErrorLog.ui
src/gui/Export3mfDialog.ui
src/gui/ExportPdfDialog.ui
src/gui/FontList.ui
src/gui/FontListDialog.ui
Expand Down
2 changes: 1 addition & 1 deletion resources/common.qrc.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<file>icons/prefs3DView.png</file>
<file>icons/prefsEditor.png</file>
<file>icons/prefsUpdate.png</file>

<file>icons/prefsDialogs.png</file>
<file>icons/close.png</file>
<file>icons/information-icons-error.png</file>
<file>icons/information-icons-info.png</file>
Expand Down
5 changes: 4 additions & 1 deletion resources/icons/license.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Taken from http://tango.freedesktop.org/Tango_Icon_Library, version 0.8.90 / public domain:
https://web.archive.org/web/20160120233412/http://tango.freedesktop.org/Tango_Icon_Library
http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz

- prefsFeatures.png (converted from preferences-system.svg)
- prefsFeatures.png (converted from categories/preferences-system.svg)
- prefsDialogs.png (converted from actions/window-new.svg)

https://openclipart.org/detail/35425/tango-desktop-peripherals / Tango Icon Library / public domain:

Expand Down
Binary file added resources/icons/prefsDialogs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 2 additions & 40 deletions src/core/ColorNode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "core/Builtins.h"
#include "core/Children.h"
#include "core/Parameters.h"
#include "core/ColorUtil.h"
#include "utils/printutils.h"
#include <algorithm>
#include <utility>
Expand Down Expand Up @@ -200,45 +201,6 @@ std::unordered_map<std::string, Color4f> webcolors{
{"transparent", {0, 0, 0, 0}}
};

// Parses hex colors according to: https://drafts.csswg.org/css-color/#typedef-hex-color.
// If the input is invalid, returns boost::none.
// Supports the following formats:
// * "#rrggbb"
// * "#rrggbbaa"
// * "#rgb"
// * "#rgba"
boost::optional<Color4f> parse_hex_color(const std::string& hex) {
// validate size. short syntax uses one hex digit per color channel instead of 2.
const bool short_syntax = hex.size() == 4 || hex.size() == 5;
const bool long_syntax = hex.size() == 7 || hex.size() == 9;
if (!short_syntax && !long_syntax) return boost::none;

// validate
if (hex[0] != '#') return boost::none;
if (!std::all_of(std::begin(hex) + 1, std::end(hex),
[](char c) {
return std::isxdigit(static_cast<unsigned char>(c));
})) {
return boost::none;
}

// number of characters per color channel
const int stride = short_syntax ? 1 : 2;
const float channel_max = short_syntax ? 15.0f : 255.0f;

Color4f rgba;
rgba[3] = 1.0; // default alpha to 100%

for (unsigned i = 0; i < (hex.size() - 1) / stride; ++i) {
const std::string chunk = hex.substr(1 + i * stride, stride);

// convert the hex character(s) from base 16 to base 10
rgba[i] = stoi(chunk, nullptr, 16) / channel_max;
}

return rgba;
}

static std::shared_ptr<AbstractNode> builtin_color(const ModuleInstantiation *inst, Arguments arguments, const Children& children)
{
auto node = std::make_shared<ColorNode>(inst);
Expand All @@ -259,7 +221,7 @@ static std::shared_ptr<AbstractNode> builtin_color(const ModuleInstantiation *in
node->color = webcolors.at(colorname);
} else {
// Try parsing it as a hex color such as "#rrggbb".
const auto hexColor = parse_hex_color(colorname);
const auto hexColor = OpenSCAD::parse_hex_color(colorname);
if (hexColor) {
node->color = *hexColor;
} else {
Expand Down
101 changes: 101 additions & 0 deletions src/core/ColorUtil.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "core/ColorUtil.h"

namespace OpenSCAD {

// See http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
void rgbtohsv(float r, float g, float b, float& h, float& s, float& v)
{
float K = 0.f;

if (g < b) {
std::swap(g, b);
K = -1.f;
}

if (r < g) {
std::swap(r, g);
K = -2.f / 6.f - K;
}

float chroma = r - std::min(g, b);
h = std::fabs(K + (g - b) / (6.f * chroma + 1e-20f));
s = chroma / (r + 1e-20f);
v = r;
}

Color4f getColorHSV(const Color4f& col)
{
float h, s, v;
OpenSCAD::rgbtohsv(col[0], col[1], col[2], h, s, v);
return {h, s, v, col[3]};
}

/**
* Calculate contrast color. Based on the article
* http://gamedev.stackexchange.com/questions/38536/given-a-rgb-color-x-how-to-find-the-most-contrasting-color-y
*
* @param col the input color
* @return a color with high contrast to the input color
*/
Color4f getContrastColor(const Color4f& col)
{
Color4f hsv = getColorHSV(col);
float Y = 0.2126f * col[0] + 0.7152f * col[1] + 0.0722f * col[2];
float S = hsv[1];

if (S < 0.5) {
// low saturation, choose between black / white based on luminance Y
float val = Y > 0.5 ? 0.0f : 1.0f;
return {val, val, val, 1.0f};
} else {
float H = 360 * hsv[0];
if ((H < 60) || (H > 300)) {
return {0.0f, 1.0f, 1.0f, 1.0f}; // red -> cyan
} else if (H < 180) {
return {1.0f, 0.0f, 1.0f, 1.0f}; // green -> magenta
} else {
return {1.0f, 1.0f, 0.0f, 1.0f}; // blue -> yellow
}
}
}

// Parses hex colors according to: https://drafts.csswg.org/css-color/#typedef-hex-color.
// If the input is invalid, returns boost::none.
// Supports the following formats:
// * "#rrggbb"
// * "#rrggbbaa"
// * "#rgb"
// * "#rgba"
std::optional<Color4f> parse_hex_color(const std::string& hex) {
// validate size. short syntax uses one hex digit per color channel instead of 2.
const bool short_syntax = hex.size() == 4 || hex.size() == 5;
const bool long_syntax = hex.size() == 7 || hex.size() == 9;
if (!short_syntax && !long_syntax) return {};

// validate
if (hex[0] != '#') return {};
if (!std::all_of(std::begin(hex) + 1, std::end(hex),
[](char c) {
return std::isxdigit(static_cast<unsigned char>(c));
})) {
return {};
}

// number of characters per color channel
const int stride = short_syntax ? 1 : 2;
const float channel_max = short_syntax ? 15.0f : 255.0f;

Color4f rgba;
rgba[3] = 1.0; // default alpha to 100%

for (unsigned i = 0; i < (hex.size() - 1) / stride; ++i) {
const std::string chunk = hex.substr(1 + i * stride, stride);

// convert the hex character(s) from base 16 to base 10
rgba[i] = stoi(chunk, nullptr, 16) / channel_max;
}

return rgba;
}

} // namespace
31 changes: 31 additions & 0 deletions src/core/ColorUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <string>
#include <optional>

#include "linalg.h"

template<> struct std::hash<Color4f> {
std::size_t operator()(Color4f const& c) const noexcept {
std::size_t hash = 0;
for (int idx = 0;idx < 4;idx++) {
std::size_t h = std::hash<float>{}(c[idx]);
hash = h ^ (hash << 1);
}
return hash;
}
};

namespace OpenSCAD {

inline Color4f CORNFIELD_FACE_COLOR{ 0xf9, 0xd7, 0x2c, 255 };

void rgbtohsv(float r, float g, float b, float& h, float& s, float& v);

std::optional<Color4f> parse_hex_color(const std::string& hex);

Color4f getContrastColor(const Color4f& col);

Color4f getColorHSV(const Color4f& col);

} // namespace
Loading

0 comments on commit 0e6f663

Please sign in to comment.