CCompiled and runed with working visuals
This commit is contained in:
parent
2455f90550
commit
3b389bdc17
8 changed files with 308 additions and 153 deletions
|
|
@ -112,6 +112,145 @@ void Graphics::Canvas::text(
|
||||||
popClamp();
|
popClamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::Canvas::drawColorwheel(const RectF& rec, const RGB& col) {
|
||||||
|
|
||||||
|
float const x = rec.x;
|
||||||
|
float const y = rec.y;
|
||||||
|
float const w = rec.z;
|
||||||
|
float const h = rec.w;
|
||||||
|
|
||||||
|
HSV hsv = tp::HSV(col);
|
||||||
|
float const hue = hsv.h / (NVG_PI * 2);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
float r0, r1, ax, ay, bx, by, cx, cy, aeps, r;
|
||||||
|
NVGpaint paint;
|
||||||
|
|
||||||
|
nvgSave(mContext->vg);
|
||||||
|
|
||||||
|
cx = x + w * 0.5f;
|
||||||
|
cy = y + h * 0.5f;
|
||||||
|
r1 = (w < h ? w : h) * 0.5f - 5.0f;
|
||||||
|
r0 = r1 - 13.0f;
|
||||||
|
aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
float a0 = (float) i / 6.0f * NVG_PI * 2.0f - aeps;
|
||||||
|
float a1 = (float) (i + 1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgArc(mContext->vg, cx, cy, r0, a0, a1, NVG_CW);
|
||||||
|
nvgArc(mContext->vg, cx, cy, r1, a1, a0, NVG_CCW);
|
||||||
|
nvgClosePath(mContext->vg);
|
||||||
|
ax = cx + cosf(a0) * (r0 + r1) * 0.5f;
|
||||||
|
ay = cy + sinf(a0) * (r0 + r1) * 0.5f;
|
||||||
|
bx = cx + cosf(a1) * (r0 + r1) * 0.5f;
|
||||||
|
by = cy + sinf(a1) * (r0 + r1) * 0.5f;
|
||||||
|
paint = nvgLinearGradient(
|
||||||
|
mContext->vg,
|
||||||
|
ax,
|
||||||
|
ay,
|
||||||
|
bx,
|
||||||
|
by,
|
||||||
|
nvgHSLA(a0 / (NVG_PI * 2), 1.0f, 0.55f, 255),
|
||||||
|
nvgHSLA(a1 / (NVG_PI * 2), 1.0f, 0.55f, 255)
|
||||||
|
);
|
||||||
|
nvgFillPaint(mContext->vg, paint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgCircle(mContext->vg, cx, cy, r0 - 0.5f);
|
||||||
|
nvgCircle(mContext->vg, cx, cy, r1 + 0.5f);
|
||||||
|
nvgStrokeColor(mContext->vg, nvgRGBA(0, 0, 0, 64));
|
||||||
|
nvgStrokeWidth(mContext->vg, 1.0f);
|
||||||
|
nvgStroke(mContext->vg);
|
||||||
|
|
||||||
|
// Selector
|
||||||
|
nvgSave(mContext->vg);
|
||||||
|
nvgTranslate(mContext->vg, cx, cy);
|
||||||
|
nvgRotate(mContext->vg, hue * NVG_PI * 2);
|
||||||
|
|
||||||
|
// Marker on
|
||||||
|
nvgStrokeWidth(mContext->vg, 2.0f);
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgRect(mContext->vg, r0 - 1, -3, r1 - r0 + 2, 6);
|
||||||
|
nvgStrokeColor(mContext->vg, nvgRGBA(255, 255, 255, 192));
|
||||||
|
nvgStroke(mContext->vg);
|
||||||
|
|
||||||
|
paint = nvgBoxGradient(mContext->vg, r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, nvgRGBA(0, 0, 0, 128), nvgRGBA(0, 0, 0, 0));
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgRect(mContext->vg, r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20);
|
||||||
|
nvgRect(mContext->vg, r0 - 2, -4, r1 - r0 + 4, 8);
|
||||||
|
nvgPathWinding(mContext->vg, NVG_HOLE);
|
||||||
|
nvgFillPaint(mContext->vg, paint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
|
||||||
|
// Center triangle
|
||||||
|
r = r0 - 6;
|
||||||
|
ax = cosf(120.0f / 180.0f * NVG_PI) * r;
|
||||||
|
ay = sinf(120.0f / 180.0f * NVG_PI) * r;
|
||||||
|
bx = cosf(-120.0f / 180.0f * NVG_PI) * r;
|
||||||
|
by = sinf(-120.0f / 180.0f * NVG_PI) * r;
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgMoveTo(mContext->vg, r, 0);
|
||||||
|
nvgLineTo(mContext->vg, ax, ay);
|
||||||
|
nvgLineTo(mContext->vg, bx, by);
|
||||||
|
nvgClosePath(mContext->vg);
|
||||||
|
paint = nvgLinearGradient(mContext->vg, r, 0, ax, ay, nvgHSLA(hue, 1.0f, 0.5f, 255), nvgRGBA(255, 255, 255, 255));
|
||||||
|
nvgFillPaint(mContext->vg, paint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
paint = nvgLinearGradient(mContext->vg, (r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255));
|
||||||
|
nvgFillPaint(mContext->vg, paint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
nvgStrokeColor(mContext->vg, nvgRGBA(0, 0, 0, 64));
|
||||||
|
nvgStroke(mContext->vg);
|
||||||
|
|
||||||
|
// Select circle on triangle
|
||||||
|
float yt = hsv.v * hsv.s;
|
||||||
|
float xt = hsv.v - 0.5 * yt;
|
||||||
|
ay = sinf(120.0f / 180.0f * NVG_PI) * r * (-1.0f + xt * 2.0f);
|
||||||
|
ax = cosf(120.0f / 180.0f * NVG_PI) * r * (1.0f - yt * 3.f);
|
||||||
|
nvgStrokeWidth(mContext->vg, 2.0f);
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgCircle(mContext->vg, ax, ay, 5);
|
||||||
|
nvgStrokeColor(mContext->vg, nvgRGBA(255, 255, 255, 192));
|
||||||
|
nvgStroke(mContext->vg);
|
||||||
|
|
||||||
|
paint = nvgRadialGradient(mContext->vg, ax, ay, 7, 9, nvgRGBA(0, 0, 0, 64), nvgRGBA(0, 0, 0, 0));
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgRect(mContext->vg, ax - 20, ay - 20, 40, 40);
|
||||||
|
nvgCircle(mContext->vg, ax, ay, 7);
|
||||||
|
nvgPathWinding(mContext->vg, NVG_HOLE);
|
||||||
|
nvgFillPaint(mContext->vg, paint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
|
||||||
|
nvgRestore(mContext->vg);
|
||||||
|
|
||||||
|
nvgRestore(mContext->vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
|
||||||
|
auto imgPaint = nvgImagePattern(mContext->vg, rec.x, rec.y, rec.z, rec.w, angle, image->id, alpha);
|
||||||
|
nvgBeginPath(mContext->vg);
|
||||||
|
nvgRoundedRect(mContext->vg, rec.x, rec.y, rec.z, rec.w, rounding);
|
||||||
|
nvgFillPaint(mContext->vg, imgPaint);
|
||||||
|
nvgFill(mContext->vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Graphics::Canvas::ImageHandle Graphics::Canvas::createImageFromTextId(ualni id, Vec2F size) {
|
||||||
|
#ifdef ENV_OS_ANDROID
|
||||||
|
return { (ualni) nvglCreateImageFromHandleGLES3(mContext->vg, id, size.x, size.y, 0) };
|
||||||
|
#else
|
||||||
|
return { (ualni) nvglCreateImageFromHandleGL3(mContext->vg, id, size.x, size.y, 0) };
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::Canvas::deleteImageHandle(ImageHandle image) {
|
||||||
|
if (image.id) {
|
||||||
|
nvgDeleteImage(mContext->vg, image.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::Canvas::proc() { nvgBeginFrame(mContext->vg, mWidth, mHeight, 1.0); }
|
void Graphics::Canvas::proc() { nvgBeginFrame(mContext->vg, mWidth, mHeight, 1.0); }
|
||||||
|
|
||||||
void Graphics::Canvas::draw() { nvgEndFrame(mContext->vg); }
|
void Graphics::Canvas::draw() { nvgEndFrame(mContext->vg); }
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,21 @@ namespace tp {
|
||||||
RB = 0x0202,
|
RB = 0x0202,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImageHandle {
|
||||||
|
ualni id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
RectF getAvaliableArea();
|
RectF getAvaliableArea();
|
||||||
void pushClamp(const RectF& rec);
|
void pushClamp(const RectF& rec);
|
||||||
void popClamp();
|
void popClamp();
|
||||||
void rect(const RectF& rec, const RGBA& col, halnf round = 0);
|
void rect(const RectF& rec, const RGBA& col, halnf round = 0);
|
||||||
void text(const char*, const RectF&, halnf size, Align, halnf marging, const RGBA&);
|
void text(const char*, const RectF&, halnf size, Align, halnf marging, const RGBA&);
|
||||||
|
|
||||||
|
void drawColorwheel(const RectF& rec, const RGB& col);
|
||||||
|
|
||||||
|
ImageHandle createImageFromTextId(ualni id, Vec2F size);
|
||||||
|
void deleteImageHandle(ImageHandle image);
|
||||||
|
void drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding);
|
||||||
// TODO : API
|
// TODO : API
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,18 @@
|
||||||
|
|
||||||
#include "Graphics.hpp"
|
#include "Graphics.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "Widgets.hpp"
|
#include "Sketch3DWidget.hpp"
|
||||||
|
|
||||||
void runApp() {
|
void runApp() {
|
||||||
|
|
||||||
tp::GlobalGUIConfig config;
|
tp::GlobalGUIConfig config;
|
||||||
tp::gGlobalGUIConfig = &config;
|
tp::gGlobalGUIConfig = &config;
|
||||||
|
|
||||||
tp::LabelWidget<tp::Window::Events, tp::Graphics::Canvas> gui;
|
|
||||||
|
|
||||||
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
auto window = tp::Window::createWindow(800, 600, "Window 1");
|
||||||
|
|
||||||
|
{
|
||||||
|
tp::Sketch3DWidget<tp::Window::Events, tp::Graphics::Canvas> gui(window->getCanvas(), {800, 1000});
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
while (!window->shouldClose()) {
|
while (!window->shouldClose()) {
|
||||||
window->processEvents();
|
window->processEvents();
|
||||||
|
|
@ -28,6 +29,7 @@ void runApp() {
|
||||||
window->draw();
|
window->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tp::Window::destroyWindow(window);
|
tp::Window::destroyWindow(window);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include "FrameBuffer.hpp"
|
#include "FrameBuffer.hpp"
|
||||||
#include "GraphicsApi.hpp"
|
#include "GraphicsApi.hpp"
|
||||||
|
|
||||||
void glerr(GLenum type);
|
void glerr(GLenum type) { printf("GL ERROR\n"); }
|
||||||
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
|
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#include "Sketch3D.hpp"
|
#include "Sketch3D.hpp"
|
||||||
|
|
||||||
using namespace strokes;
|
using namespace tp;
|
||||||
|
|
||||||
Stroke::GLHandles::GLHandles() {
|
Stroke::GLHandles::GLHandles() {
|
||||||
glGenVertexArrays(1, &VertexArrayID);
|
glGenVertexArrays(1, &VertexArrayID);
|
||||||
|
|
@ -300,6 +300,11 @@ Project::Project() {
|
||||||
|
|
||||||
mActiveBrush = "pencil";
|
mActiveBrush = "pencil";
|
||||||
|
|
||||||
|
Stroke* debug = new Stroke();
|
||||||
|
debug->mPoints = { { { 0, 0, 0 }, 1 }, { { 1, 1, 1 } , 1} };
|
||||||
|
debug->updateGpuBuffers();
|
||||||
|
|
||||||
|
mLayers.last()->strokes.pushBack(debug);
|
||||||
|
|
||||||
auto vec = mCamera.project({0, 0, 0});
|
auto vec = mCamera.project({0, 0, 0});
|
||||||
vec = mCamera.project({-1, 0, 0});
|
vec = mCamera.project({-1, 0, 0});
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
#include "List.hpp"
|
#include "List.hpp"
|
||||||
|
|
@ -10,7 +11,7 @@
|
||||||
#include "FrameBuffer.hpp"
|
#include "FrameBuffer.hpp"
|
||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
|
|
||||||
namespace strokes {
|
namespace tp {
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class Project;
|
class Project;
|
||||||
|
|
@ -21,12 +22,12 @@ namespace strokes {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Point {
|
struct Point {
|
||||||
tp::Vec3F pos;
|
Vec3F pos = { 0, 0, 0 };
|
||||||
tp::halnf thickness = NULL;
|
halnf thickness = NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
tp::Buffer<Point> mPoints;
|
Buffer<Point> mPoints;
|
||||||
tp::RGBA mCol;
|
RGBA mCol;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct GLHandles {
|
struct GLHandles {
|
||||||
|
|
@ -34,7 +35,7 @@ namespace strokes {
|
||||||
GLuint vertexbuffer = 0;
|
GLuint vertexbuffer = 0;
|
||||||
GLuint vbo_len = 0;
|
GLuint vbo_len = 0;
|
||||||
GLHandles();
|
GLHandles();
|
||||||
void sendDataToGPU(tp::Buffer<Point>* mPoints);
|
void sendDataToGPU(Buffer<Point>* mPoints);
|
||||||
~GLHandles();
|
~GLHandles();
|
||||||
} mGl;
|
} mGl;
|
||||||
|
|
||||||
|
|
@ -42,57 +43,57 @@ namespace strokes {
|
||||||
|
|
||||||
Stroke();
|
Stroke();
|
||||||
|
|
||||||
void denoisePos(tp::halni passes);
|
void denoisePos(halni passes);
|
||||||
void denoiseThickness(tp::halni passes);
|
void denoiseThickness(halni passes);
|
||||||
void compress(tp::halnf factor);
|
void compress(halnf factor);
|
||||||
void subdiv(tp::halnf precition, tp::Camera* cam, tp::halni passes = 1);
|
void subdiv(halnf precition, Camera* cam, halni passes = 1);
|
||||||
|
|
||||||
void updateGpuBuffers();
|
void updateGpuBuffers();
|
||||||
|
|
||||||
tp::Buffer<Point>& buff();
|
Buffer<Point>& buff();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Brush {
|
class Brush {
|
||||||
public:
|
public:
|
||||||
tp::String mType = "equal";
|
String mType = "equal";
|
||||||
Brush() {}
|
Brush() {}
|
||||||
virtual void sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) {}
|
virtual void sample(Project* proj, Vec2F crs, halnf pressure) {}
|
||||||
virtual void draw(Renderer* render, tp::Camera* camera) {}
|
virtual void draw(Renderer* render, Camera* camera) {}
|
||||||
virtual ~Brush() {}
|
virtual ~Brush() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PencilBrush : public Brush {
|
class PencilBrush : public Brush {
|
||||||
|
|
||||||
tp::halnf mPrecision = 0.001f;
|
halnf mPrecision = 0.001f;
|
||||||
|
|
||||||
tp::halni mDenoisePassesPos = 1;
|
halni mDenoisePassesPos = 1;
|
||||||
tp::halni mDenoisePassesThick = 3;
|
halni mDenoisePassesThick = 3;
|
||||||
tp::halnf mCompressionFactor = 0.0001f;
|
halnf mCompressionFactor = 0.0001f;
|
||||||
tp::halni mSubdivPasses = 3;
|
halni mSubdivPasses = 3;
|
||||||
bool mEnableCompression = true;
|
bool mEnableCompression = true;
|
||||||
|
|
||||||
tp::halni mMaxPoints = 100;
|
halni mMaxPoints = 100;
|
||||||
|
|
||||||
Stroke* mStroke = NULL;
|
Stroke* mStroke = NULL;
|
||||||
Stroke mShowStroke;
|
Stroke mShowStroke;
|
||||||
|
|
||||||
void unsureReady(Stroke* stroke, tp::Camera* cam, bool debug = false);
|
void unsureReady(Stroke* stroke, Camera* cam, bool debug = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
tp::RGBA mCol = tp::RGBA(1.0f);
|
RGBA mCol = RGBA(1.0f);
|
||||||
tp::halnf mSize = 0.01f;
|
halnf mSize = 0.01f;
|
||||||
|
|
||||||
PencilBrush();
|
PencilBrush();
|
||||||
virtual void sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) override;
|
virtual void sample(Project* proj, Vec2F crs, halnf pressure) override;
|
||||||
virtual void draw(Renderer* render, tp::Camera* camera) override;
|
virtual void draw(Renderer* render, Camera* camera) override;
|
||||||
virtual ~PencilBrush();
|
virtual ~PencilBrush();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EraserBrush : public Brush {
|
struct EraserBrush : public Brush {
|
||||||
EraserBrush() { mType = "eraser"; }
|
EraserBrush() { mType = "eraser"; }
|
||||||
virtual void sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) override {}
|
virtual void sample(Project* proj, Vec2F crs, halnf pressure) override {}
|
||||||
virtual void draw(Renderer* render, tp::Camera* camera) override {}
|
virtual void draw(Renderer* render, Camera* camera) override {}
|
||||||
virtual ~EraserBrush() {}
|
virtual ~EraserBrush() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -101,29 +102,29 @@ namespace strokes {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Layer {
|
struct Layer {
|
||||||
tp::String name = "new layer";
|
String name = "new layer";
|
||||||
tp::List<Stroke*> strokes;
|
List<Stroke*> strokes;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
~Layer();
|
~Layer();
|
||||||
};
|
};
|
||||||
|
|
||||||
tp::Buffer<Layer*> mLayers;
|
Buffer<Layer*> mLayers;
|
||||||
tp::halni mActiveLayer = -1;
|
halni mActiveLayer = -1;
|
||||||
|
|
||||||
tp::Camera mCamera;
|
Camera mCamera;
|
||||||
tp::RGBA mBackgroundColor = { 0.22f, 0.22f, 0.25f, 1.f };
|
RGBA mBackgroundColor = { 0.22f, 0.22f, 0.25f, 1.f };
|
||||||
|
|
||||||
tp::Map<tp::String, Brush*> mBrushes;
|
Map<String, Brush*> mBrushes;
|
||||||
tp::String mActiveBrush;
|
String mActiveBrush;
|
||||||
|
|
||||||
Project();
|
Project();
|
||||||
~Project();
|
~Project();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
tp::RenderBuffer mBufferDowncast;
|
RenderBuffer mBufferDowncast;
|
||||||
tp::RenderBuffer mBuffer;
|
RenderBuffer mBuffer;
|
||||||
tp::RenderShader mShader;
|
RenderShader mShader;
|
||||||
|
|
||||||
// shader uniforms
|
// shader uniforms
|
||||||
GLuint mMatrixUniform = 0;
|
GLuint mMatrixUniform = 0;
|
||||||
|
|
@ -133,64 +134,64 @@ namespace strokes {
|
||||||
GLuint mBGColUniform = 0;
|
GLuint mBGColUniform = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Renderer(tp::Vec2F size);
|
Renderer(Vec2F size);
|
||||||
|
|
||||||
void renderBegin();
|
void renderBegin();
|
||||||
void setViewport(tp::RectF viewport);
|
void setViewport(RectF viewport);
|
||||||
void drawStroke(Stroke* str, tp::Camera* camera);
|
void drawStroke(Stroke* str, Camera* camera);
|
||||||
void renderEnd();
|
void renderEnd();
|
||||||
|
|
||||||
void setClearCol(tp::RGBA col);
|
void setClearCol(RGBA col);
|
||||||
tp::uhalni getTextudeId();
|
uhalni getTextudeId();
|
||||||
tp::RenderBuffer* getBuff();
|
RenderBuffer* getBuff();
|
||||||
|
|
||||||
~Renderer();
|
~Renderer();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void Project::save(tp::File& file) {
|
void Project::save(File& file) {
|
||||||
file.write<tp::Camera>(&mCamera);
|
file.write<Camera>(&mCamera);
|
||||||
file.write<tp::rgba>(&mBackgroundColor);
|
file.write<rgba>(&mBackgroundColor);
|
||||||
file.write<tp::halni>(&mActiveLayer);
|
file.write<halni>(&mActiveLayer);
|
||||||
|
|
||||||
tp::alni lay_len = mLayers.length();
|
alni lay_len = mLayers.length();
|
||||||
file.write<tp::alni>(&lay_len);
|
file.write<alni>(&lay_len);
|
||||||
for (auto layer : mLayers) {
|
for (auto layer : mLayers) {
|
||||||
layer.data()->name.save(&file);
|
layer.data()->name.save(&file);
|
||||||
|
|
||||||
file.write<bool>(&layer.data()->enabled);
|
file.write<bool>(&layer.data()->enabled);
|
||||||
|
|
||||||
tp::alni len = layer.data()->strokes.length();
|
alni len = layer.data()->strokes.length();
|
||||||
file.write<tp::alni>(&len);
|
file.write<alni>(&len);
|
||||||
for (auto stiter : layer.data()->strokes) {
|
for (auto stiter : layer.data()->strokes) {
|
||||||
stiter->save(file);
|
stiter->save(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::load(tp::File& file) {
|
void Project::load(File& file) {
|
||||||
file.read<tp::Camera>(&mCamera);
|
file.read<Camera>(&mCamera);
|
||||||
file.read<tp::rgba>(&mBackgroundColor);
|
file.read<rgba>(&mBackgroundColor);
|
||||||
file.read<tp::halni>(&mActiveLayer);
|
file.read<halni>(&mActiveLayer);
|
||||||
|
|
||||||
tp::alni layers_len;
|
alni layers_len;
|
||||||
file.read<tp::alni>(&layers_len);
|
file.read<alni>(&layers_len);
|
||||||
mLayers.reserve(layers_len);
|
mLayers.reserve(layers_len);
|
||||||
|
|
||||||
for (tp::alni idx = 0; idx < layers_len; idx++) {
|
for (alni idx = 0; idx < layers_len; idx++) {
|
||||||
|
|
||||||
tp::string key; key.load(&file);
|
string key; key.load(&file);
|
||||||
auto layer = new Layer();
|
auto layer = new Layer();
|
||||||
layer->name = key;
|
layer->name = key;
|
||||||
mLayers[idx] = layer;
|
mLayers[idx] = layer;
|
||||||
|
|
||||||
file.read<bool>(&layer->enabled);
|
file.read<bool>(&layer->enabled);
|
||||||
|
|
||||||
tp::alni len;
|
alni len;
|
||||||
file.read<tp::alni>(&len);
|
file.read<alni>(&len);
|
||||||
|
|
||||||
for (tp::alni str_idx = 0; str_idx < len; str_idx++) {
|
for (alni str_idx = 0; str_idx < len; str_idx++) {
|
||||||
auto str = new Stroke();
|
auto str = new Stroke();
|
||||||
layer->strokes.pushBack(str);
|
layer->strokes.pushBack(str);
|
||||||
layer->strokes.last()->data->load(file);
|
layer->strokes.last()->data->load(file);
|
||||||
|
|
@ -200,22 +201,22 @@ void Project::load(tp::File& file) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void Stroke::save(tp::File& file) {
|
void Stroke::save(File& file) {
|
||||||
file.write<tp::rgba>(&mCol);
|
file.write<rgba>(&mCol);
|
||||||
|
|
||||||
tp::alni length = mPoints.length();
|
alni length = mPoints.length();
|
||||||
file.write<tp::alni>(&length);
|
file.write<alni>(&length);
|
||||||
for (auto piter : mPoints) {
|
for (auto piter : mPoints) {
|
||||||
file.write<Point>(&piter.data());
|
file.write<Point>(&piter.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stroke::load(tp::File& file) {
|
void Stroke::load(File& file) {
|
||||||
tp::rgba color;
|
rgba color;
|
||||||
file.read<tp::rgba>(&color);
|
file.read<rgba>(&color);
|
||||||
|
|
||||||
tp::alni p_len;
|
alni p_len;
|
||||||
file.read<tp::alni>(&p_len);
|
file.read<alni>(&p_len);
|
||||||
|
|
||||||
mPoints.reserve(p_len);
|
mPoints.reserve(p_len);
|
||||||
for (auto piter : mPoints) {
|
for (auto piter : mPoints) {
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// #include "Fram.h"
|
#include "Sketch3D.hpp"
|
||||||
|
#include "Widgets.hpp"
|
||||||
|
|
||||||
class Widget {
|
namespace tp {
|
||||||
void destructor(StrokesWidget* self) {
|
|
||||||
self->mRenderer.~Renderer();
|
template <typename Events, typename Canvas>
|
||||||
self->mImage.free(self->mDrawer);
|
class Sketch3DWidget : public Widget<Events, Canvas> {
|
||||||
self->mImage.~ImageHandle();
|
public:
|
||||||
|
|
||||||
|
Canvas* mCanvas = nullptr;
|
||||||
|
|
||||||
|
Sketch3DWidget(Canvas& canvas, Vec2F renderResolution) :
|
||||||
|
mRenderer(renderResolution) {
|
||||||
|
mImage = canvas.createImageFromTextId(mRenderer.getBuff()->texId(), mRenderer.getBuff()->getSize());
|
||||||
|
mCanvas = &canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
void procInputs(StrokesWidget* self, nd::GUIInputs* inputs) {
|
~Sketch3DWidget() {
|
||||||
auto proj = self->getTargetProject();
|
mCanvas->deleteImageHandle(mImage);
|
||||||
if (!proj) {
|
}
|
||||||
|
|
||||||
|
void proc(const Events& events, const RectF& areaParent, const RectF& area) override {
|
||||||
|
|
||||||
|
this->mArea = area;
|
||||||
|
this->mVisible = area.isOverlap(areaParent);
|
||||||
|
if (!this->mVisible) return;
|
||||||
|
|
||||||
|
mProject.mCamera.setRatio(this->mArea.w / this->mArea.z);
|
||||||
|
|
||||||
|
// mProject.mBackgroundColor = col_obj_bg->mCol;
|
||||||
|
|
||||||
|
if (!this->mArea.isInside(events.getPos())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rec = self->getRect();
|
halnf pressure = 0.f;
|
||||||
proj->mCamera.set_ratio(rec.w / rec.z);
|
|
||||||
|
|
||||||
auto col_obj_bg = self->getMember<obj::ColorObject>("bg_color");
|
auto idx = mProject.mBrushes.presents(mProject.mActiveBrush);
|
||||||
if (col_obj_bg) {
|
|
||||||
proj->mBackgroundColor = col_obj_bg->mCol;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rec.inside(inputs->mCrsPrev)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pressure = inputs->mPressure;
|
|
||||||
if (!inputs->Anticipating()) {
|
|
||||||
pressure = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto idx = proj->mBrushes.presents(proj->mActiveBrush);
|
|
||||||
if (idx) {
|
if (idx) {
|
||||||
auto brush = proj->mBrushes.getSlotVal(idx);
|
auto brush = mProject.mBrushes.getSlotVal(idx);
|
||||||
auto crs = (inputs->mCrs - rec.pos);
|
auto crs = (events.getPos() - this->mArea.pos);
|
||||||
crs.x /= rec.z;
|
crs.x /= this->mArea.z;
|
||||||
crs.y /= rec.w;
|
crs.y /= this->mArea.w;
|
||||||
crs = (crs - 0.5) * 2;
|
crs = (crs - 0.5) * 2;
|
||||||
|
|
||||||
if (brush->mType == "pencil") {
|
if (brush->mType == "pencil") {
|
||||||
auto col_obj = self->getMember<obj::ColorObject>("draw_color");
|
((tp::PencilBrush*) brush)->mCol = RGBA(1.f);
|
||||||
if (col_obj) {
|
}
|
||||||
((strokes::PencilBrush*) brush)->mCol = col_obj->mCol;
|
|
||||||
|
brush->sample(&mProject, crs, pressure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
brush->sample(proj, crs, pressure);
|
void draw(Canvas& canvas) override {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void presentOutput(StrokesWidget* self, nd::GUIdrawer* drawer) {
|
mRenderer.setViewport({ 0, 0, this->mArea.z, this->mArea.w });
|
||||||
auto proj = self->getTargetProject();
|
mRenderer.setClearCol(mProject.mBackgroundColor);
|
||||||
if (!proj) {
|
mRenderer.renderBegin();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self->mImage.mId) {
|
for (auto lay : mProject.mLayers) {
|
||||||
self->mDrawer = drawer;
|
|
||||||
self->mImage.createFromBuff(self->mRenderer.getBuff(), drawer);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto rec = self->getRect();
|
|
||||||
self->mRenderer.setViewport({ 0, 0, rec.z, rec.w });
|
|
||||||
self->mRenderer.setClearCol(proj->mBackgroundColor);
|
|
||||||
self->mRenderer.renderBegin();
|
|
||||||
|
|
||||||
for (auto lay : proj->mLayers) {
|
|
||||||
if (lay.data()->enabled) {
|
if (lay.data()->enabled) {
|
||||||
for (auto str : lay.data()->strokes) {
|
for (auto str : lay.data()->strokes) {
|
||||||
self->mRenderer.drawStroke(str.data(), &proj->mCamera);
|
mRenderer.drawStroke(str.data(), &mProject.mCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto idx = proj->mBrushes.presents(proj->mActiveBrush);
|
auto idx = mProject.mBrushes.presents(mProject.mActiveBrush);
|
||||||
if (idx) {
|
if (idx) {
|
||||||
auto brush = proj->mBrushes.getSlotVal(idx);
|
auto brush = mProject.mBrushes.getSlotVal(idx);
|
||||||
brush->draw(&self->mRenderer, &proj->mCamera);
|
brush->draw(&mRenderer, &mProject.mCamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->mRenderer.renderEnd();
|
mRenderer.renderEnd();
|
||||||
|
|
||||||
drawer->drawImage(rec, &self->mImage, 0, 1, 12);
|
canvas.drawImage(this->mArea, &mImage, 0, 1, 12);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
private:
|
||||||
|
Project mProject;
|
||||||
|
Renderer mRenderer;
|
||||||
|
Canvas::ImageHandle mImage;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -49,7 +49,7 @@ namespace tp {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void draw(Canvas& canvas) const {
|
virtual void draw(Canvas& canvas) {
|
||||||
if (!mVisible) {
|
if (!mVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue