Improved transform and clipboard paste performance, and share memory between copied brush strokes in some instances
This commit is contained in:
parent
c499f597d9
commit
1d0a7fc495
15 changed files with 115 additions and 61 deletions
|
|
@ -15,11 +15,11 @@
|
|||
#define DEFAULT_SMOOTHNESS 5
|
||||
|
||||
void DrawBrushStroke::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(d.points, d.color, d.hasRoundCaps);
|
||||
a(d->points, d->color, d->hasRoundCaps);
|
||||
}
|
||||
|
||||
void DrawBrushStroke::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(d.points, d.color, d.hasRoundCaps);
|
||||
a(d->points, d->color, d->hasRoundCaps);
|
||||
}
|
||||
|
||||
DrawComponentType DrawBrushStroke::get_type() const {
|
||||
|
|
@ -35,6 +35,18 @@ std::shared_ptr<DrawComponent> DrawBrushStroke::copy() const {
|
|||
return a;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrawComponent> DrawBrushStroke::deep_copy() const {
|
||||
auto a = std::make_shared<DrawBrushStroke>();
|
||||
a->d = d;
|
||||
a->coords = coords;
|
||||
// Just copy pointers over, brush strokes cant be edited so they can share the same memory
|
||||
a->vertices = vertices;
|
||||
a->verticesMipMap = verticesMipMap;
|
||||
a->bounds = bounds;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void DrawBrushStroke::update_from_delayed_ptr() {
|
||||
std::shared_ptr<DrawBrushStroke> newPtr = std::static_pointer_cast<DrawBrushStroke>(delayedUpdatePtr);
|
||||
d = newPtr->d;
|
||||
|
|
@ -63,11 +75,11 @@ void DrawBrushStroke::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
// return;
|
||||
|
||||
SkPaint paint;
|
||||
if(d.color.w() == 1.0) // Fully opaque, dont bother with blending
|
||||
if(d->color.w() == 1.0) // Fully opaque, dont bother with blending
|
||||
canvas->save();
|
||||
else
|
||||
canvas->saveLayerAlphaf(nullptr, d.color.w());
|
||||
paint.setColor4f(SkColor4f{d.color.x(), d.color.y(), d.color.z(), 1.0f});
|
||||
canvas->saveLayerAlphaf(nullptr, d->color.w());
|
||||
paint.setColor4f(SkColor4f{d->color.x(), d->color.y(), d->color.z(), 1.0f});
|
||||
canvas_do_calculated_transform(canvas);
|
||||
if(drawSetupData.mipmapLevel == 0)
|
||||
canvas->drawVertices(vertices, SkBlendMode::kClear, paint);
|
||||
|
|
@ -87,9 +99,9 @@ void DrawBrushStroke::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
}
|
||||
|
||||
void DrawBrushStroke::initialize_draw_data(DrawingProgram& drawP) {
|
||||
if(!d.points.empty()) {
|
||||
if(!d->points.empty()) {
|
||||
std::vector<SkPoint> vertexData;
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d.points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d->points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
auto triangleFunc = [&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
vertexData.emplace_back(a.x(), a.y());
|
||||
vertexData.emplace_back(b.x(), b.y());
|
||||
|
|
@ -126,7 +138,7 @@ std::vector<size_t> DrawBrushStroke::get_wedge_indices(const std::vector<DrawBru
|
|||
}
|
||||
|
||||
std::vector<DrawBrushStrokePoint> DrawBrushStroke::smooth_points(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) {
|
||||
std::vector<DrawBrushStrokePoint>& points = d.points;
|
||||
std::vector<DrawBrushStrokePoint>& points = d->points;
|
||||
|
||||
size_t pointsSize = endIndex - beginIndex + 1;
|
||||
if(pointsSize < 2)
|
||||
|
|
@ -170,7 +182,7 @@ std::vector<DrawBrushStrokePoint> DrawBrushStroke::smooth_points(size_t beginInd
|
|||
}
|
||||
|
||||
std::vector<DrawBrushStrokePoint> DrawBrushStroke::smooth_points_avg(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) {
|
||||
std::vector<DrawBrushStrokePoint>& points = d.points;
|
||||
std::vector<DrawBrushStrokePoint>& points = d->points;
|
||||
|
||||
size_t pointsSize = endIndex - beginIndex + 1;
|
||||
if(pointsSize < 2)
|
||||
|
|
@ -201,9 +213,9 @@ std::vector<DrawBrushStrokePoint> DrawBrushStroke::smooth_points_avg(size_t begi
|
|||
void DrawBrushStroke::create_triangles(const std::function<bool(Vector2f, Vector2f, Vector2f)>& passTriangleFunc, const std::vector<DrawBrushStrokePoint>& points, unsigned skipVertexCount) {
|
||||
const int ARC_SMOOTHNESS = 10;
|
||||
const int CIRCLE_SMOOTHNESS = 20;
|
||||
std::vector<DrawBrushStrokePoint>& pointsN = d.points;
|
||||
std::vector<DrawBrushStrokePoint>& pointsN = d->points;
|
||||
|
||||
if(pointsN.size() == 1 && d.hasRoundCaps) {
|
||||
if(pointsN.size() == 1 && d->hasRoundCaps) {
|
||||
std::vector<Vector2f> circlePoints = gen_circle_points(pointsN.front().pos, pointsN.front().width / 2.0f, CIRCLE_SMOOTHNESS);
|
||||
for(size_t i = 0; i < circlePoints.size(); i++)
|
||||
if(passTriangleFunc(pointsN.front().pos, circlePoints[i], circlePoints[(i + 1) % circlePoints.size()])) return;
|
||||
|
|
@ -228,7 +240,7 @@ void DrawBrushStroke::create_triangles(const std::function<bool(Vector2f, Vector
|
|||
vertArray[1] = points[pointsBegin].pos - perpPrev * points[pointsBegin].width * 0.5f;
|
||||
newIndex = 2;
|
||||
|
||||
if(d.hasRoundCaps && pointsBegin == 0) {
|
||||
if(d->hasRoundCaps && pointsBegin == 0) {
|
||||
Vector2f arcDirStart = (convert_vec2<Vector2f>(vertArray[0]) - points[0].pos).normalized();
|
||||
Vector2f arcDirEnd = (convert_vec2<Vector2f>(vertArray[1]) - points[0].pos).normalized();
|
||||
Vector2f arcDirCenter = (points[0].pos - points[1].pos).normalized();
|
||||
|
|
@ -320,7 +332,7 @@ void DrawBrushStroke::create_triangles(const std::function<bool(Vector2f, Vector
|
|||
for(size_t i = 0; i < arcPoints.size() - 1; i++)
|
||||
if(passTriangleFunc(wedgeCenter, arcPoints[i], arcPoints[i + 1])) return;
|
||||
}
|
||||
else if(d.hasRoundCaps) { // It's the last point, cap it off
|
||||
else if(d->hasRoundCaps) { // It's the last point, cap it off
|
||||
Vector2f arcDirStart = (convert_vec2<Vector2f>(vertArray[(newIndex + 1) % 3]) - points.back().pos).normalized();
|
||||
Vector2f arcDirEnd = (convert_vec2<Vector2f>(vertArray[(newIndex + 2) % 3]) - points.back().pos).normalized();
|
||||
Vector2f arcDirCenter = -rectDir;
|
||||
|
|
@ -335,10 +347,10 @@ void DrawBrushStroke::create_triangles(const std::function<bool(Vector2f, Vector
|
|||
|
||||
void DrawBrushStroke::create_collider() {
|
||||
using namespace SCollision;
|
||||
if(d.points.empty())
|
||||
if(d->points.empty())
|
||||
return;
|
||||
ColliderCollection<float> strokeObjects;
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d.points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d->points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
strokeObjects.triangle.emplace_back(a, b, c);
|
||||
return false;
|
||||
|
|
@ -352,8 +364,6 @@ void DrawBrushStroke::create_collider() {
|
|||
add_precheck_aabb_level(0, collisionTree.children);
|
||||
|
||||
bounds = collisionTree.objects.bounds;
|
||||
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
void DrawBrushStroke::add_precheck_aabb_level(size_t level, const std::vector<SCollision::BVHContainer<float>>& levelArray) {
|
||||
|
|
@ -366,7 +376,7 @@ void DrawBrushStroke::add_precheck_aabb_level(size_t level, const std::vector<SC
|
|||
}
|
||||
|
||||
void DrawBrushStroke::vertices_to_draw_data(sk_sp<SkVertices>& vertexDataPtr, const std::vector<SkPoint>& vertexData) {
|
||||
if((d.points.size() == 1 && d.hasRoundCaps) || d.points.size() >= 2)
|
||||
if((d->points.size() == 1 && d->hasRoundCaps) || d->points.size() >= 2)
|
||||
vertexDataPtr = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, vertexData.size(), vertexData.data(), nullptr, nullptr);
|
||||
else
|
||||
vertexDataPtr = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 0, nullptr, nullptr, nullptr);
|
||||
|
|
@ -390,7 +400,7 @@ bool DrawBrushStroke::collides_within_coords(const SCollision::ColliderCollectio
|
|||
return false;
|
||||
|
||||
bool toRet = false;
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d.points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
std::vector<DrawBrushStrokePoint> points = smooth_points(0, d->points.size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
toRet = SCollision::collide(checkAgainst, SCollision::Triangle<float>{a, b, c});
|
||||
return toRet;
|
||||
|
|
|
|||
|
|
@ -30,10 +30,13 @@ class DrawBrushStroke : public DrawComponent {
|
|||
std::vector<DrawBrushStrokePoint> points;
|
||||
Vector4f color;
|
||||
bool hasRoundCaps;
|
||||
} d;
|
||||
};
|
||||
std::shared_ptr<Data> d = std::make_shared<Data>(); // It's a pointer here since brush strokes cant be edited
|
||||
|
||||
#ifndef IS_SERVER
|
||||
virtual std::shared_ptr<DrawComponent> copy() const override;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const override;
|
||||
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) override;
|
||||
virtual void update(DrawingProgram& drawP) override;
|
||||
|
|
|
|||
|
|
@ -122,19 +122,24 @@ void DrawComponent::check_timers(DrawingProgram& drawP) {
|
|||
}
|
||||
|
||||
void DrawComponent::temp_update(DrawingProgram& drawP) {
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
if(collabListInfo.lock())
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
worldAABB = std::nullopt;
|
||||
initialize_draw_data(drawP);
|
||||
}
|
||||
|
||||
void DrawComponent::transform_temp_update(DrawingProgram& drawP) {
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
worldAABB = std::nullopt;
|
||||
}
|
||||
|
||||
void DrawComponent::final_update(DrawingProgram& drawP, bool invalidateCache) {
|
||||
if(invalidateCache && collabListInfo.lock())
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
initialize_draw_data(drawP);
|
||||
finalize_update(drawP, invalidateCache);
|
||||
create_collider();
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
void DrawComponent::transform_update(DrawingProgram& drawP, bool invalidateCache) {
|
||||
if(invalidateCache && collabListInfo.lock())
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
void DrawComponent::client_send_place_many(DrawingProgram& drawP, std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
|
|
@ -169,12 +174,6 @@ void DrawComponent::client_send_erase_set(DrawingProgram& drawP, const std::unor
|
|||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_ERASE_MANY_COMPONENTS, ids);
|
||||
}
|
||||
|
||||
void DrawComponent::finalize_update(DrawingProgram& drawP, bool invalidateCache) {
|
||||
if(invalidateCache && collabListInfo.lock())
|
||||
drawP.compCache.preupdate_component(collabListInfo.lock());
|
||||
create_collider();
|
||||
}
|
||||
|
||||
bool DrawComponent::collides_with_world_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld) {
|
||||
return collides_with(camCoords, checkAgainstWorld, camCoords.world_collider_to_coords<SCollision::ColliderCollection<float>>(checkAgainstWorld));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,13 +103,14 @@ class DrawComponent {
|
|||
virtual SCollision::AABB<float> get_obj_coord_bounds() const = 0;
|
||||
|
||||
virtual std::shared_ptr<DrawComponent> copy() const = 0;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const = 0;
|
||||
|
||||
virtual void create_collider() = 0;
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) = 0;
|
||||
void temp_update(DrawingProgram& drawP);
|
||||
void final_update(DrawingProgram& drawP, bool invalidateCache = true); // invalidateCache = false version should be thread safe
|
||||
void transform_temp_update(DrawingProgram& drawP);
|
||||
void transform_update(DrawingProgram& drawP, bool invalidateCache = true);
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) = 0;
|
||||
virtual void finalize_update(DrawingProgram& drawP, bool invalidateCache = true);
|
||||
virtual void update(DrawingProgram& drawP) = 0;
|
||||
virtual bool collides_within_coords(const SCollision::ColliderCollection<float>& checkAgainst) = 0;
|
||||
bool collides_with_world_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ std::shared_ptr<DrawComponent> DrawEllipse::copy() const {
|
|||
return a;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrawComponent> DrawEllipse::deep_copy() const {
|
||||
auto a = std::make_shared<DrawEllipse>();
|
||||
a->d = d;
|
||||
a->coords = coords;
|
||||
a->ellipsePath = ellipsePath;
|
||||
a->collisionTree = collisionTree;
|
||||
return a;
|
||||
}
|
||||
|
||||
void DrawEllipse::update_from_delayed_ptr() {
|
||||
std::shared_ptr<DrawEllipse> newPtr = std::static_pointer_cast<DrawEllipse>(delayedUpdatePtr);
|
||||
d = newPtr->d;
|
||||
|
|
@ -125,7 +134,6 @@ void DrawEllipse::create_collider() {
|
|||
|
||||
collisionTree.clear();
|
||||
collisionTree.calculate_bvh_recursive(strokeObjects);
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
SCollision::AABB<float> DrawEllipse::get_obj_coord_bounds() const {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ class DrawEllipse : public DrawComponent {
|
|||
|
||||
#ifndef IS_SERVER
|
||||
virtual std::shared_ptr<DrawComponent> copy() const override;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const override;
|
||||
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) override;
|
||||
virtual void update(DrawingProgram& drawP) override;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@ std::shared_ptr<DrawComponent> DrawImage::copy() const {
|
|||
return a;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrawComponent> DrawImage::deep_copy() const {
|
||||
auto a = std::make_shared<DrawImage>();
|
||||
a->d = d;
|
||||
a->coords = coords;
|
||||
a->imRect = imRect;
|
||||
a->collisionTree = collisionTree;
|
||||
return a;
|
||||
}
|
||||
|
||||
void DrawImage::update_from_delayed_ptr() {
|
||||
std::shared_ptr<DrawImage> newPtr = std::static_pointer_cast<DrawImage>(delayedUpdatePtr);
|
||||
d = newPtr->d;
|
||||
|
|
@ -86,7 +95,6 @@ void DrawImage::create_collider() {
|
|||
strokeObjects.triangle.emplace_back(newT[2], newT[3], newT[0]);
|
||||
collisionTree.clear();
|
||||
collisionTree.calculate_bvh_recursive(strokeObjects);
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
SCollision::AABB<float> DrawImage::get_obj_coord_bounds() const {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ class DrawImage : public DrawComponent {
|
|||
|
||||
#ifndef IS_SERVER
|
||||
virtual std::shared_ptr<DrawComponent> copy() const override;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const override;
|
||||
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) override;
|
||||
virtual void update(DrawingProgram& drawP) override;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@ std::shared_ptr<DrawComponent> DrawRectangle::copy() const {
|
|||
return a;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrawComponent> DrawRectangle::deep_copy() const {
|
||||
auto a = std::make_shared<DrawRectangle>();
|
||||
a->d = d;
|
||||
a->coords = coords;
|
||||
a->rectPath = rectPath;
|
||||
a->collisionTree = collisionTree;
|
||||
return a;
|
||||
}
|
||||
|
||||
void DrawRectangle::update_from_delayed_ptr() {
|
||||
std::shared_ptr<DrawRectangle> newPtr = std::static_pointer_cast<DrawRectangle>(delayedUpdatePtr);
|
||||
d = newPtr->d;
|
||||
|
|
@ -108,7 +117,6 @@ void DrawRectangle::create_collider() {
|
|||
|
||||
collisionTree.clear();
|
||||
collisionTree.calculate_bvh_recursive(strokeObjects);
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
SCollision::AABB<float> DrawRectangle::get_obj_coord_bounds() const {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ class DrawRectangle : public DrawComponent {
|
|||
|
||||
#ifndef IS_SERVER
|
||||
virtual std::shared_ptr<DrawComponent> copy() const override;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const override;
|
||||
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) override;
|
||||
virtual void update(DrawingProgram& drawP) override;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ std::shared_ptr<DrawComponent> DrawTextBox::copy() const {
|
|||
return a;
|
||||
}
|
||||
|
||||
std::shared_ptr<DrawComponent> DrawTextBox::deep_copy() const {
|
||||
auto a = std::make_shared<DrawTextBox>();
|
||||
a->d = d;
|
||||
a->coords = coords;
|
||||
a->textboxUpdate = false;
|
||||
a->collisionTree = collisionTree;
|
||||
a->textBox = textBox;
|
||||
return a;
|
||||
}
|
||||
|
||||
void DrawTextBox::update_from_delayed_ptr() {
|
||||
std::shared_ptr<DrawTextBox> newPtr = std::static_pointer_cast<DrawTextBox>(delayedUpdatePtr);
|
||||
d = newPtr->d;
|
||||
|
|
@ -118,7 +128,6 @@ void DrawTextBox::create_collider() {
|
|||
strokeObjects.triangle.emplace_back(newT[2], newT[3], newT[0]);
|
||||
collisionTree.clear();
|
||||
collisionTree.calculate_bvh_recursive(strokeObjects);
|
||||
calculate_world_bounds();
|
||||
}
|
||||
|
||||
SCollision::AABB<float> DrawTextBox::get_obj_coord_bounds() const {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class DrawTextBox : public DrawComponent {
|
|||
|
||||
#ifndef IS_SERVER
|
||||
virtual std::shared_ptr<DrawComponent> copy() const override;
|
||||
virtual std::shared_ptr<DrawComponent> deep_copy() const override;
|
||||
|
||||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) override;
|
||||
virtual bool collides_within_coords(const SCollision::ColliderCollection<float>& checkAgainst) override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue