diff --git a/deps/assimp/CMakeLists.txt b/deps/assimp/CMakeLists.txt index 04e66330..e55d4242 100644 --- a/deps/assimp/CMakeLists.txt +++ b/deps/assimp/CMakeLists.txt @@ -13,6 +13,7 @@ set(ASSIMP_BUILD_BLEND_IMPORTER ON CACHE BOOL "" FORCE) set(ASSIMP_BUILD_FBX_IMPORTER ON CACHE BOOL "" FORCE) set(ASSIMP_BUILD_GLTF_IMPORTER ON CACHE BOOL "" FORCE) set(ASSIMP_BUILD_OBJ_IMPORTER ON CACHE BOOL "" FORCE) +set(ASSIMP_BUILD_STL_IMPORTER ON CACHE BOOL "" FORCE) set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(ASSIMP_INSTALL OFF CACHE BOOL "" FORCE) set(ASSIMP_INJECT_DEBUG_POSTFIX OFF CACHE BOOL "" FORCE) diff --git a/examples/scenes/text/assets/text.otn b/examples/scenes/text/assets/text.otn index 482ccc66..afa29326 100644 --- a/examples/scenes/text/assets/text.otn +++ b/examples/scenes/text/assets/text.otn @@ -14,6 +14,26 @@ "from": 2873823255, "id": 2160878527, "to": 3195650876 + }, + { + "from": 4048718069, + "id": 2920632154, + "to": 729637025 + }, + { + "from": 3521990454, + "id": 2178711956, + "to": 2381672726 + }, + { + "from": 2547115557, + "id": 1069569191, + "to": 3761969199 + }, + { + "from": 143155056, + "id": 3271718652, + "to": 605994486 } ], "metadata": {}, @@ -34,6 +54,54 @@ "x": 67.0, "y": 77.0 }, + { + "id": 1509100340, + "inputs": [], + "outputs": [ + { + "id": 4048718069, + "name": "Value", + "type": "float" + } + ], + "title": "Size", + "type": "Float Input", + "value": 12.0, + "x": 69.0, + "y": 246.0 + }, + { + "id": 240854171, + "inputs": [], + "outputs": [ + { + "id": 3521990454, + "name": "Value", + "type": "string" + } + ], + "title": "Text", + "type": "String Input", + "value": "Test", + "x": 69.0, + "y": 160.0 + }, + { + "id": 2590841629, + "inputs": [], + "outputs": [ + { + "id": 143155056, + "name": "Value", + "type": "bool" + } + ], + "title": "Center", + "type": "Boolean Input", + "value": true, + "x": 71.0, + "y": 328.0 + }, { "id": 325703201, "inputs": [ @@ -45,14 +113,17 @@ { "id": 2381672726, "name": "Text", - "type": "string", - "value": "Test" + "type": "string" }, { "id": 729637025, "name": "Size", - "type": "float", - "value": 12.0 + "type": "float" + }, + { + "id": 605994486, + "name": "Center", + "type": "bool" } ], "outputs": [ @@ -67,6 +138,22 @@ "x": 408.0, "y": 52.0 }, + { + "id": 1210579916, + "inputs": [], + "outputs": [ + { + "id": 2547115557, + "name": "Value", + "type": "float" + } + ], + "title": "Depth", + "type": "Float Input", + "value": 3.0, + "x": 72.0, + "y": 410.0 + }, { "id": 3232750156, "inputs": [ @@ -78,14 +165,7 @@ { "id": 3761969199, "name": "Depth", - "type": "float", - "value": 3.0 - }, - { - "id": 4124497261, - "name": "Segments", - "type": "int", - "value": 400 + "type": "float" } ], "outputs": [ @@ -97,8 +177,8 @@ ], "title": "Extrude Shape", "type": "Extrude Shape", - "x": 667.0, - "y": 27.0 + "x": 665.0, + "y": 174.0 }, { "id": 2601550030, @@ -118,8 +198,8 @@ "outputs": [], "title": "Save Geometry To Virtual", "type": "Save Geometry To Virtual", - "x": 929.0, - "y": 28.0 + "x": 925.0, + "y": 174.0 } ] } \ No newline at end of file diff --git a/examples/scenes/text/text.ots b/examples/scenes/text/text.ots index a0637a1c..f8dde0bb 100644 --- a/examples/scenes/text/text.ots +++ b/examples/scenes/text/text.ots @@ -101,7 +101,7 @@ 1.0 ], "translation": [ - -9.0, + 0.0, -6.630000114440918, -3.2200000286102295 ] @@ -135,6 +135,18 @@ "component": "Nodes", "path": "assets/text.otn", "settings": { + "1210579916": { + "value": 3.0 + }, + "1509100340": { + "value": 12.0 + }, + "240854171": { + "value": "Test" + }, + "2590841629": { + "value": true + }, "2625173197": { "path": "assets/roboto.ttf" } diff --git a/gfx/shapes/OtCubicBezierSegment.h b/gfx/shapes/OtCubicBezierSegment.h index 525c361b..20b7d8e0 100644 --- a/gfx/shapes/OtCubicBezierSegment.h +++ b/gfx/shapes/OtCubicBezierSegment.h @@ -12,14 +12,14 @@ // Include files // -#include "OtShapeSegment.h" +#include "OtCurveSegment.h" // // OtCubicBezierSegment // -class OtCubicBezierSegment : public OtShapeSegment { +class OtCubicBezierSegment : public OtCurveSegment { public: // constructor inline OtCubicBezierSegment(const glm::vec2& v1, const glm::vec2& v2, const glm::vec2& v3, const glm::vec2& v4) { @@ -27,6 +27,7 @@ class OtCubicBezierSegment : public OtShapeSegment { p2 = v2; p3 = v3; p4 = v4; + calculateLength(); } // get a point in the segment at curve parameter t [0, 1] diff --git a/gfx/shapes/OtCurveSegment.h b/gfx/shapes/OtCurveSegment.h new file mode 100644 index 00000000..ed0c6914 --- /dev/null +++ b/gfx/shapes/OtCurveSegment.h @@ -0,0 +1,55 @@ +// ObjectTalk Scripting Language +// Copyright (c) 1993-2024 Johan A. Goossens. All rights reserved. +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + + +#pragma once + + +// +// Include files +// + +#include "glm/glm.hpp" + +#include "OtShapeSegment.h" + + +// +// OtCurveSegment +// + +class OtCurveSegment : public OtShapeSegment { + // get length of segment + float getLength() override {return length; }; + + // get points on segment + void getPoints(std::vector& result) override { + // determine point count based on size + int points = int(length / 0.1f); + + for (auto i = 1; i <= points; i++) { + result.push_back(getPoint((float) i / (float) points)); + } + } + +protected: + // get a point in the segment at curve parameter t [0, 1] + virtual glm::vec2 getPoint(float t) = 0; + + // calculate length of segment + inline void calculateLength(size_t division=100) { + glm::vec2 last = getPoint(0.0f); + + for (auto i = 1; i <= division; i++) { + glm::vec2 current = getPoint((float) i / (float) division); + length += glm::distance(current, last); + last = current; + } + } + + // total segment length + float length = 0.0f; +}; diff --git a/gfx/shapes/OtLineSegment.h b/gfx/shapes/OtLineSegment.h index 2b0d8f8b..109563d3 100644 --- a/gfx/shapes/OtLineSegment.h +++ b/gfx/shapes/OtLineSegment.h @@ -27,30 +27,16 @@ class OtLineSegment : public OtShapeSegment { p2 = v2; } - // get a point in the segment at curve parameter t [0, 1] - inline glm::vec2 getPoint(float t) override { - return glm::mix(p1, p2, t); - } - - // get a point in the segment at arc length u [0, 1] - inline glm::vec2 getPointAtArcLength(float u) override { - return getPoint(u); - } - - // get a unit vector tangent at t [0, 1] - inline glm::vec2 getTangent(float t) override { - return glm::normalize(p2 - p1); - } - - virtual inline glm::vec2 getTangentAt(float u) override { - return getTangent(u); - } - // get the length of the segment inline float getLength() override { return glm::distance(p1, p2); } + // get points on segment + virtual void getPoints(std::vector& result) override { + result.push_back(p2); + } + // convert segment to string representation inline std::string toString() override { return fmt::format("l {} {}\n", p2.x, p2.y); diff --git a/gfx/shapes/OtQuadraticBezierSegment.h b/gfx/shapes/OtQuadraticBezierSegment.h index c7948276..f1f225f5 100644 --- a/gfx/shapes/OtQuadraticBezierSegment.h +++ b/gfx/shapes/OtQuadraticBezierSegment.h @@ -12,20 +12,21 @@ // Include files // -#include "OtShapeSegment.h" +#include "OtCurveSegment.h" // // OtQuadraticBezierSegment // -class OtQuadraticBezierSegment : public OtShapeSegment { +class OtQuadraticBezierSegment : public OtCurveSegment { public: // constructor inline OtQuadraticBezierSegment(const glm::vec2& v1, const glm::vec2& v2, const glm::vec2& v3) { p1 = v1; p2 = v2; p3 = v3; + calculateLength(); } // get a point in the segment at curve parameter t [0, 1] diff --git a/gfx/shapes/OtShape.cpp b/gfx/shapes/OtShape.cpp index d96a1a64..fb7c2afd 100644 --- a/gfx/shapes/OtShape.cpp +++ b/gfx/shapes/OtShape.cpp @@ -10,6 +10,7 @@ // #include +#include #include "OtFunction.h" @@ -22,6 +23,52 @@ // void OtShape::load(const std::string &path) { + clear(); + + // read shape from file + try { + std::ifstream stream(path.c_str()); + + if (stream.fail()) { + OtError("Can't open file [{}] for reading", path); + } + + std::string line; + + while (std::getline(stream, line)) { + std::istringstream iss(line); + char command; + + if (line[0] == 'm') { + float x, y; + iss >> command >> x >> y; + moveTo(x, y); + + } else if (line[0] == 'l') { + float x, y; + iss >> command >> x >> y; + lineTo(x, y); + + } else if (line[0] == 'q') { + float cx, cy, x, y; + iss >> command >> cx >> cy >> x >> y; + quadraticCurveTo(cx, cy, x, y); + + } else if (line[0] == 'c') { + float cx1, cy1, cx2, cy2, x, y; + iss >> command >> cx1 >> cy1 >> cx2 >> cy2 >> x >> y; + bezierCurveTo(cx1, cy1, cx2, cy2, x, y); + + } else if (line[0] == 'z') { + close(); + } + } + + stream.close(); + + } catch (std::exception& e) { + OtError("Can't read from file [{}], error: {}", path, e.what()); + } } @@ -148,15 +195,18 @@ OtShape* OtShape::circle(float x, float y, float radius) { // OtShape::text // -OtShape* OtShape::text(OtFont& font, const std::string& text, float size) { +OtShape* OtShape::text(OtFont& font, const std::string& text, float size, bool center) { close(); + auto width = font.getWidth(text, size); + auto dx = center ? -width / 2.0f : 0.0f; + font.parseGlyph( text, size, - [&](float x, float y) { moveTo(x, y); }, - [&](float x, float y) { lineTo(x, y); }, - [&](float cx, float cy, float x, float y) { quadraticCurveTo(cx, cy, x, y); }, - [&](float cx1, float cy1, float cx2, float cy2, float x, float y) { bezierCurveTo(cx1, cy1, cx2, cy2, x, y); }); + [&](float x, float y) { moveTo(dx + x, y); }, + [&](float x, float y) { lineTo(dx + x, y); }, + [&](float cx, float cy, float x, float y) { quadraticCurveTo(dx + cx, cy, dx + x, y); }, + [&](float cx1, float cy1, float cx2, float cy2, float x, float y) { bezierCurveTo(dx + cx1, cy1, dx + cx2, cy2, dx + x, y); }); close(); return this; diff --git a/gfx/shapes/OtShape.h b/gfx/shapes/OtShape.h index 1ebc0814..211d66a8 100644 --- a/gfx/shapes/OtShape.h +++ b/gfx/shapes/OtShape.h @@ -53,7 +53,7 @@ class OtShape { // add simple geometries OtShape* circle(float x, float y, float radius); - OtShape* text(OtFont& font, const std::string& text, float size); + OtShape* text(OtFont& font, const std::string& text, float size, bool center); // get number of polygons in shape inline size_t getPolygonCount() { @@ -61,8 +61,8 @@ class OtShape { } // get Nth polygon - inline void getPolygon(std::vector& points, size_t n, size_t division) { - return (*paths)[n].getSpacedPoints(points, division); + inline void getPolygon(std::vector& points, size_t n) { + return (*paths)[n].getPoints(points); } // return area of polygon @@ -89,7 +89,7 @@ class OtShape { // see if shapes are identical inline bool operator==(OtShape& rhs) { - return paths == rhs.paths && version == rhs.version; + return version == rhs.version; } inline bool operator!=(OtShape& rhs) { diff --git a/gfx/shapes/OtShapePath.h b/gfx/shapes/OtShapePath.h index 5a184676..012bf3a0 100644 --- a/gfx/shapes/OtShapePath.h +++ b/gfx/shapes/OtShapePath.h @@ -18,90 +18,89 @@ #include "fmt/core.h" #include "glm/glm.hpp" -#include "OtShapeSegment.h" +#include "OtAssert.h" + #include "OtCubicBezierSegment.h" #include "OtLineSegment.h" #include "OtQuadraticBezierSegment.h" +#include "OtShapeSegment.h" // // OtShapePath // -class OtShapePath : public OtShapeSegment { +class OtShapePath { public: - // constructor - inline OtShapePath() { - lengths.push_back(0.0f); - } - // clear the path inline void clear() { segments.clear(); - lengths.clear(); - lengths.push_back(0.0f); + startPoint = glm::vec2(0.0); + currentPoint = glm::vec2(0.0); + state = undefined; } // create a path out of segments inline void moveTo(const glm::vec2& point) { + OtAssert(state == undefined); + state = started; startPoint = point; currentPoint = point; } inline void lineTo(const glm::vec2& point){ + OtAssert(state == started || state == building); + state = building; add(std::make_shared(currentPoint, point)); currentPoint = point; } inline void quadraticCurveTo(const glm::vec2& control, const glm::vec2& point) { + OtAssert(state == started || state == building); + state = building; add(std::make_shared(currentPoint, control, point)); currentPoint = point; } inline void bezierCurveTo(const glm::vec2& control1, const glm::vec2& control2, const glm::vec2& point) { + OtAssert(state == started || state == building); + state = building; add(std::make_shared(currentPoint, control1, control2, point)); currentPoint = point; } inline void close() { + OtAssert(state == building); + if (startPoint != currentPoint) { moveTo(startPoint); } - } - - // get a point on the path at t [0, 1] - inline glm::vec2 getPoint(float t) override { - return getPointAtArcLength(t); - } - - // get a point on the path at arc length u [0, 1] - inline glm::vec2 getPointAtArcLength(float u) override { - float fraction; - auto segment = findSegment(u, &fraction); - return segment->getPointAtArcLength(fraction); - } - - // get a unit vector tangent - inline glm::vec2 getTangent(float t) override { - return getTangentAt(t); - } - inline glm::vec2 getTangentAt(float u) override { - float fraction; - auto segment = findSegment(u, &fraction); - return segment->getTangentAt(fraction); + state = closed; } // get the length of the segment - inline float getLength() override { + inline float getLength() { return currentLength; } + // see if we have completed segments inline bool hasSegments() { return segments.size(); } - std::string toString() override { + // get points on entire shape + void getPoints(std::vector& result) { + OtAssert(state == closed); + result.clear(); + result.push_back(startPoint); + + for (auto& segment : segments) { + segment->getPoints(result); + } + } + + std::string toString() { std::string result = fmt::format("m {} {}\n", startPoint.x, startPoint.y); for (auto& segment : segments) { @@ -117,42 +116,16 @@ class OtShapePath : public OtShapeSegment { inline void add(std::shared_ptr segment) { currentLength += segment->getLength(); segments.push_back(segment); - lengths.push_back(currentLength); } - // find the segment at u [0, 1] - inline std::shared_ptr findSegment(float u, float* fraction) { - float target = currentLength * u; - size_t low = 0; - size_t high = lengths.size() - 1; - size_t i; - - while (low <= high) { - i = (low + high) / 2; - - if (target > lengths[i]) { - low = i + 1; - - } else if (target < lengths[i]) { - high = i - 1; - - } else { - if (i == lengths.size() - 1) { - *fraction = 1.0; - return segments[i - 1]; - - } else { - *fraction = 0.0; - return segments[i]; - } - } - } - - *fraction = (target - lengths[high]) / (lengths[high + 1] - lengths[high]); - return segments[high]; - } + // properties + enum { + undefined, + started, + building, + closed + } state = undefined; - // segments that make up this path std::vector> segments; glm::vec2 startPoint = glm::vec2(0.0); glm::vec2 currentPoint = glm::vec2(0.0); diff --git a/gfx/shapes/OtShapeSegment.h b/gfx/shapes/OtShapeSegment.h index be6e72f4..ca1b0a00 100644 --- a/gfx/shapes/OtShapeSegment.h +++ b/gfx/shapes/OtShapeSegment.h @@ -12,11 +12,8 @@ // Include files // -#include -#include #include -#include "fmt/core.h" #include "glm/glm.hpp" @@ -26,105 +23,12 @@ class OtShapeSegment { public: - // get a point in the segment at curve parameter t [0, 1] - virtual inline glm::vec2 getPoint(float t) { - return glm::vec2(0.0f); - } + // get length of segment + virtual float getLength() = 0; - // get a point in the segment at arc length u [0, 1] - virtual inline glm::vec2 getPointAtArcLength(float u) { - return getPoint(u2t(u)); - } - - // get sequence of points in segment - inline void getPoints(std::vector& result, size_t division = 5) { - result.clear(); - - for (auto i = 0; i <= division; i++) { - result.push_back(getPoint((float) i / (float) division)); - } - } - - // get sequence of equally spaced points in segment - inline void getSpacedPoints(std::vector& result, size_t division = 5) { - result.clear(); - - for (auto i = 0; i <= division; i++) { - result.push_back(getPointAtArcLength((float) i / (float) division)); - } - } - - // get a unit vector tangent at t [0, 1] - virtual inline glm::vec2 getTangent(float t) { - float delta = 0.0001f; - - return glm::normalize( - getPoint(std::clamp(t - delta, 0.0f, 1.0f)) - - getPoint(std::clamp(t - delta, 0.0f, 1.0f))); - } - - virtual inline glm::vec2 getTangentAt(float u) { - return getTangent(u2t(u)); - } - - // get the length of the segment - virtual inline float getLength() { - if (!lengths.size()) { - getLengths(); - } - - return lengths.back(); - } + // get points on segment + virtual void getPoints(std::vector& result) = 0; // convert segment to string representation - virtual inline std::string toString() { - return ""; - } - -protected: - // calculate list of cumulative segment lengths - std::vector lengths; - - inline void getLengths(size_t division=200) { - glm::vec2 current = getPoint(0.0f); - glm::vec2 last = current; - float sum = 0.0f; - lengths.push_back(0.0f); - - for (auto i = 1; i <= division; i++) { - current = getPoint((float) i / (float) division); - sum += glm::distance(current, last); - lengths.push_back(sum); - last = current; - } - } - - // convert arc length u to equation parameter t - inline float u2t(float u) { - if (!lengths.size()) { - getLengths(); - } - - float target = lengths.back() * u; - size_t low = 0; - size_t high = lengths.size() - 1; - size_t i; - - while (low <= high) { - i = (low + high) / 2; - - if (target > lengths[i]) { - low = i + 1; - - } else if (target < lengths[i]) { - high = i - 1; - - } else { - return (float) i / (float) (lengths.size() - 1); - } - } - - float fraction = (target - lengths[high]) / (lengths[high + 1] - lengths[high]); - return ((float) high + fraction) / (float) (lengths.size() - 1); - } + virtual std::string toString() = 0; }; diff --git a/ide/scene/OtSceneEditor.cpp b/ide/scene/OtSceneEditor.cpp index f6f8b841..78768707 100644 --- a/ide/scene/OtSceneEditor.cpp +++ b/ide/scene/OtSceneEditor.cpp @@ -762,9 +762,6 @@ void OtSceneEditor::renderEntity(OtEntity entity) { if (OtUiInputText("##rename", &component.tag)) { auto newValue = component.serialize(nullptr).dump(); nextTask = std::make_shared>(&scene, entity, oldValue, newValue); - } - - if (ImGui::IsItemDeactivated()) { renamingEntity = OtEntityNull; } diff --git a/nodes/core/OtNodes.cpp b/nodes/core/OtNodes.cpp index 04e335ae..fe9d0a86 100644 --- a/nodes/core/OtNodes.cpp +++ b/nodes/core/OtNodes.cpp @@ -11,9 +11,9 @@ #include #include -#include #include #include +#include #include "nlohmann/json.hpp" diff --git a/nodes/input/OtBoolInputNode.cpp b/nodes/input/OtBoolInputNode.cpp new file mode 100644 index 00000000..cba9f297 --- /dev/null +++ b/nodes/input/OtBoolInputNode.cpp @@ -0,0 +1,67 @@ +// ObjectTalk Scripting Language +// Copyright (c) 1993-2024 Johan A. Goossens. All rights reserved. +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + + +// +// Include files +// + +#include "imgui.h" +#include "nlohmann/json.hpp" + +#include "OtUi.h" + +#include "OtNodesFactory.h" + + +// +// OtBoolInputNode +// + +class OtBoolInputNode : public OtNodeClass { +public: + // configure node + inline void configure() override { + addOutputPin("Value", value)->addCustomRenderer([this](float width) { + auto old = serialize().dump(); + + if (customInputRendering(width)) { + oldState = old; + newState = serialize().dump(); + + if (newState != oldState) { + needsEvaluating = true; + needsSaving = true; + } + } + }, fieldWidth); + } + + // special rendering for input nodes + inline bool customInputRendering(float width) override { + ImGui::SetNextItemWidth(width); + return OtUiToggleButton("##value", &value); + } + + // (de)serialize node + void customSerialize(nlohmann::json* data, std::string* basedir) override { + (*data)["value"] = value; + } + + void customDeserialize(nlohmann::json* data, std::string* basedir) override { + value = data->value("value", false); + } + + static constexpr const char* nodeName = "Boolean Input"; + static constexpr int nodeCategory = OtNodeClass::input; + static constexpr int nodeKind = OtNodeClass::fixed; + static constexpr float fieldWidth = 100.0f; + +protected: + bool value = false; +}; + +static OtNodesFactoryRegister type; diff --git a/nodes/shape/OtExtrudeShapeNode.cpp b/nodes/shape/OtExtrudeShapeNode.cpp index 627414af..98f2a8ab 100644 --- a/nodes/shape/OtExtrudeShapeNode.cpp +++ b/nodes/shape/OtExtrudeShapeNode.cpp @@ -34,7 +34,6 @@ class OtExtrudeShapeNode : public OtNodeClass { inline void configure() override { addInputPin("Shape", shape); addInputPin("Depth", depth); - addInputPin("Segments", segments); addOutputPin("Geometry", geometry); } @@ -56,7 +55,7 @@ class OtExtrudeShapeNode : public OtNodeClass { for (auto i = 0; i < polygonCount; i++) { // get the points on the polygon - shape.getPolygon(polygon, i, segments); + shape.getPolygon(polygon, i); // determine winding order of first polygon if (i == 0) { @@ -86,11 +85,9 @@ class OtExtrudeShapeNode : public OtNodeClass { OtLogFatal("Can't tesselate geometry"); } - int vertexCount = tessGetVertexCount(tess); - int indexCount = tessGetElementCount(tess); - int offset = (uint32_t) mesh->getVertexCount(); - // create the front and back-facing vertices (interwoven) + int offset = (uint32_t) mesh->getVertexCount(); + int vertexCount = tessGetVertexCount(tess); const TESSreal* verts = tessGetVertices(tess); for (auto i = 0; i < vertexCount; i++) { @@ -102,6 +99,7 @@ class OtExtrudeShapeNode : public OtNodeClass { } // create the front and back-facing indices + int indexCount = tessGetElementCount(tess); const TESSindex* indices = tessGetElements(tess); for (auto i = 0; i < indexCount; i++) { @@ -119,6 +117,7 @@ class OtExtrudeShapeNode : public OtNodeClass { geometry.setMesh(mesh); } else { + // no valid shape so we clear out output geometry.clear(); } } @@ -130,7 +129,6 @@ class OtExtrudeShapeNode : public OtNodeClass { protected: OtShape shape; float depth = 1.0f; - int segments = 100; OtGeometry geometry; }; diff --git a/nodes/shape/OtTextToShapeNode.cpp b/nodes/shape/OtTextToShapeNode.cpp index 5e426ee5..25909183 100644 --- a/nodes/shape/OtTextToShapeNode.cpp +++ b/nodes/shape/OtTextToShapeNode.cpp @@ -28,6 +28,7 @@ class OtTextToShapeNode : public OtNodeClass { addInputPin("Font", font); addInputPin("Text", text); addInputPin("Size", size); + addInputPin("Center", center); addOutputPin("Shape", shape); } @@ -36,7 +37,7 @@ class OtTextToShapeNode : public OtNodeClass { shape.clear(); if (font.isValid() && text.size() && size != 0.0f) { - shape.text(font, text, size); + shape.text(font, text, size, center); } } @@ -48,6 +49,7 @@ class OtTextToShapeNode : public OtNodeClass { OtFont font; std::string text; float size = 12.0f; + bool center = true; OtShape shape; };