BVH draw cache working
This commit is contained in:
parent
1e51bf660f
commit
caea747f1e
12 changed files with 223 additions and 39 deletions
|
|
@ -127,6 +127,12 @@ void DrawComponent::final_update(DrawingProgram& drawP) {
|
|||
updateDraw = true;
|
||||
}
|
||||
|
||||
void DrawComponent::final_update_dont_invalidate_cache(DrawingProgram& drawP) {
|
||||
initialize_draw_data(drawP);
|
||||
finalize_update(drawP, false);
|
||||
updateDraw = true;
|
||||
}
|
||||
|
||||
void DrawComponent::client_send_place(DrawingProgram& drawP, uint64_t placement) {
|
||||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_PLACE_COMPONENT, placement, get_type(), this->coords, *this);
|
||||
}
|
||||
|
|
@ -151,8 +157,9 @@ void DrawComponent::client_send_transform_final(DrawingProgram& drawP, ServerCli
|
|||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_COMPONENT, false, id, this->coords);
|
||||
}
|
||||
|
||||
void DrawComponent::finalize_update(DrawingProgram& drawP) {
|
||||
drawP.compCache.preupdate_component(this);
|
||||
void DrawComponent::finalize_update(DrawingProgram& drawP, bool invalidateCache) {
|
||||
if(invalidateCache)
|
||||
drawP.compCache.preupdate_component(this);
|
||||
create_collider(drawP.colliderAllocated);
|
||||
updateDraw = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,9 +100,10 @@ class DrawComponent {
|
|||
virtual void draw(SkCanvas* canvas, const DrawData& drawData) = 0;
|
||||
void temp_update(DrawingProgram& drawP);
|
||||
void final_update(DrawingProgram& drawP);
|
||||
void final_update_dont_invalidate_cache(DrawingProgram& drawP);
|
||||
void transform_temp_update(DrawingProgram& drawP);
|
||||
virtual void initialize_draw_data(DrawingProgram& drawP) = 0;
|
||||
virtual void finalize_update(DrawingProgram& drawP);
|
||||
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, bool colliderAllocated) = 0;
|
||||
bool collides_with_world_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, bool colliderAllocated);
|
||||
|
|
|
|||
|
|
@ -1 +1,13 @@
|
|||
#include "DrawData.hpp"
|
||||
#include "DrawComponents/DrawComponent.hpp"
|
||||
|
||||
void DrawData::refresh_draw_optimizing_values() {
|
||||
clampDrawBetween = true;
|
||||
clampDrawMinimum = cam.c.inverseScale >> DRAWCOMP_MIN_SHIFT_BEFORE_DISAPPEAR;
|
||||
mipMapLevelOne = cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_ONE;
|
||||
mipMapLevelTwo = cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_TWO;
|
||||
mipMapLevelThree = cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_THREE;
|
||||
mipMapLevelFour = cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_FOUR;
|
||||
mipMapLevelFive = cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_FOUR;
|
||||
clampDrawMaximum = cam.c.inverseScale << DRAWCOMP_MAX_SHIFT_BEFORE_DISAPPEAR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,5 @@ struct DrawData {
|
|||
WorldScalar mipMapLevelThree;
|
||||
WorldScalar mipMapLevelFour;
|
||||
WorldScalar mipMapLevelFive;
|
||||
void refresh_draw_optimizing_values();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,11 +28,17 @@
|
|||
#include <poolstl.hpp>
|
||||
#endif
|
||||
|
||||
template <typename T> void parallel_loop_vector_any_type() {
|
||||
template <typename ContainerType> void parallel_loop_container(ContainerType& c, std::function<void(typename ContainerType::value_type&)> func) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
std::for_each(c.begin(), c.end(), func);
|
||||
#else
|
||||
std::for_each(std::execution::par_unseq, c.begin(), c.end(), func);
|
||||
#endif
|
||||
}
|
||||
|
||||
DrawingProgram::DrawingProgram(World& initWorld):
|
||||
world(initWorld),
|
||||
compCache(*this),
|
||||
components([&](){ return world.get_new_id(); }),
|
||||
brushTool(*this),
|
||||
eraserTool(*this),
|
||||
|
|
@ -134,11 +140,7 @@ void DrawingProgram::allocate_collider_memory() {
|
|||
}
|
||||
|
||||
void DrawingProgram::parallel_loop_all_components(std::function<void(const std::shared_ptr<CollabList<std::shared_ptr<DrawComponent>, ServerClientID>::ObjectInfo>&)> func) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
std::for_each(components.client_list().begin(), components.client_list().end(), func);
|
||||
#else
|
||||
std::for_each(std::execution::par_unseq, components.client_list().begin(), components.client_list().end(), func);
|
||||
#endif
|
||||
parallel_loop_container(components.client_list(), func);
|
||||
}
|
||||
|
||||
void DrawingProgram::check_all_collisions_base(const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam) {
|
||||
|
|
@ -249,7 +251,6 @@ void DrawingProgram::tool_options_gui() {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
t.gui.checkbox_field("Disable Draw Cache", "Disable Cache", &disableCache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +359,7 @@ void DrawingProgram::update() {
|
|||
c->obj->update(*this);
|
||||
}
|
||||
|
||||
compCache.update(components.client_list());
|
||||
compCache.update();
|
||||
}
|
||||
|
||||
void DrawingProgram::drag_drop_update() {
|
||||
|
|
@ -446,7 +447,7 @@ void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a)
|
|||
auto newComp = DrawComponent::allocate_comp_type(t);
|
||||
a(newComp->coords, *newComp);
|
||||
components.init_emplace_back(id, newComp);
|
||||
newComp->final_update(*this);
|
||||
newComp->final_update_dont_invalidate_cache(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -550,24 +551,23 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
c->obj->draw(canvas, drawData);
|
||||
}
|
||||
else {
|
||||
if(disableCache) {
|
||||
if(world.main.drawProgCache.disableDrawCache) {
|
||||
parallel_loop_all_components([&](auto& c) {
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
});
|
||||
for(auto& c : components.client_list())
|
||||
c->obj->draw(canvas, drawData);
|
||||
}
|
||||
else {
|
||||
for(auto& c : components.client_list())
|
||||
c->obj->drawSetupData.shouldDraw = false;
|
||||
compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](DrawingProgramCache::BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
for(auto& c : comps)
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
return true;
|
||||
});
|
||||
SkCanvas* drawProgCacheCanvas = world.main.drawProgCache.surface->getCanvas();
|
||||
drawProgCacheCanvas->clear(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
compCache.refresh_all_draw_cache(drawProgCacheCanvas, drawData);
|
||||
draw_components_to_canvas(drawProgCacheCanvas, drawData, false);
|
||||
canvas->drawImage(world.main.drawProgCache.surface->makeTemporaryImage(), 0, 0);
|
||||
}
|
||||
for(auto& c : components.client_list()) {
|
||||
c->obj->draw(canvas, drawData);
|
||||
|
||||
for(auto& c : components.client_list())
|
||||
c->obj->updateDraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
switch(controls.selectedTool) {
|
||||
|
|
@ -603,6 +603,44 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
}
|
||||
}
|
||||
|
||||
void DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache) {
|
||||
for(auto& c : components.client_list())
|
||||
c->obj->drawSetupData.shouldDraw = false;
|
||||
|
||||
std::vector<DrawingProgramCache::BVHNode*> cachedNodesToDraw;
|
||||
|
||||
compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](DrawingProgramCache::BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
if(!dontUseCache && node && node->drawCache && node->coords.inverseScale <= drawData.cam.c.inverseScale) {
|
||||
cachedNodesToDraw.emplace_back(node);
|
||||
return false;
|
||||
}
|
||||
for(auto& c : comps)
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
return true;
|
||||
});
|
||||
|
||||
for(uint64_t i = 0; i < components.client_list().size(); i++) {
|
||||
auto& c = components.client_list()[i];
|
||||
c->obj->draw(canvas, drawData);
|
||||
for(DrawingProgramCache::BVHNode* bvhNode : cachedNodesToDraw) {
|
||||
auto& drawCache = bvhNode->drawCache.value();
|
||||
if(drawCache.lastDrawnComponentPlacement == i) {
|
||||
canvas->save();
|
||||
bvhNode->coords.transform_sk_canvas(canvas, drawData);
|
||||
drawCache.lastRenderTime = std::chrono::steady_clock::now();
|
||||
|
||||
SkPaint p;
|
||||
p.setBlendMode(SkBlendMode::kSrc);
|
||||
|
||||
// Note, no mipmaps here. You might need to generate mipmaps in the future (withDefaultMipmaps)
|
||||
canvas->drawImage(drawCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kLinear, SkMipmapMode::kLinear}, &p);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector4f* DrawingProgram::get_foreground_color_ptr() {
|
||||
return &controls.foregroundColor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class DrawingProgram {
|
|||
|
||||
CollabListType components;
|
||||
|
||||
|
||||
Vector4f* get_foreground_color_ptr();
|
||||
private:
|
||||
std::atomic<bool> addFileInNextFrame = false;
|
||||
|
|
@ -79,7 +80,7 @@ class DrawingProgram {
|
|||
void add_undo_place_component(uint64_t placement, const std::shared_ptr<DrawComponent>& comp);
|
||||
void add_undo_place_components(uint64_t placement, const std::vector<std::shared_ptr<DrawComponent>>& comps);
|
||||
|
||||
bool disableCache = true;
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache);
|
||||
|
||||
BrushTool brushTool;
|
||||
EraserTool eraserTool;
|
||||
|
|
@ -135,4 +136,5 @@ class DrawingProgram {
|
|||
friend class ScreenshotTool;
|
||||
friend class EditTool;
|
||||
friend class ImageTool;
|
||||
friend class DrawingProgramCache;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
#include "DrawingProgramCache.hpp"
|
||||
#include "DrawingProgram.hpp"
|
||||
#include "../World.hpp"
|
||||
#include "../MainProgram.hpp"
|
||||
#include <chrono>
|
||||
|
||||
#ifdef USE_SKIA_BACKEND_GRAPHITE
|
||||
#include <include/gpu/graphite/Surface.h>
|
||||
#elif USE_SKIA_BACKEND_GANESH
|
||||
#include <include/gpu/ganesh/GrDirectContext.h>
|
||||
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
|
||||
#endif
|
||||
|
||||
#define MAXIMUM_DRAW_CACHE_SURFACES 32
|
||||
|
||||
DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP):
|
||||
drawP(initDrawP)
|
||||
{}
|
||||
|
||||
void DrawingProgramCache::build(std::vector<CollabListType::ObjectInfoPtr> components) {
|
||||
bvhRoot = BVHNode();
|
||||
unsortedComponents.clear();
|
||||
nodesWithCachedSurfaces.clear();
|
||||
std::erase_if(components, [&](auto& c) {
|
||||
if(!c->obj->worldAABB || c->obj->updateDraw) {
|
||||
unsortedComponents.emplace_back(c);
|
||||
|
|
@ -13,9 +31,9 @@ void DrawingProgramCache::build(std::vector<CollabListType::ObjectInfoPtr> compo
|
|||
build_bvh_node(bvhRoot, components);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::update(const std::vector<CollabListType::ObjectInfoPtr>& components) {
|
||||
if(unsortedComponents.size() >= 1)
|
||||
build(components);
|
||||
void DrawingProgramCache::update() {
|
||||
if(unsortedComponents.size() >= 750)
|
||||
build(drawP.components.client_list());
|
||||
}
|
||||
|
||||
void DrawingProgramCache::add_component(const CollabListType::ObjectInfoPtr& c) {
|
||||
|
|
@ -94,7 +112,9 @@ void DrawingProgramCache::build_bvh_node(BVHNode& node, std::vector<CollabListTy
|
|||
for(auto& c : components)
|
||||
node.bounds.include_aabb_in_bounds(c->obj->worldAABB.value());
|
||||
|
||||
if(components.size() < 50) {
|
||||
build_bvh_node_coords_and_resolution(node);
|
||||
|
||||
if(components.size() < 100) {
|
||||
node.components = components;
|
||||
return;
|
||||
}
|
||||
|
|
@ -123,6 +143,31 @@ void DrawingProgramCache::build_bvh_node(BVHNode& node, std::vector<CollabListTy
|
|||
}
|
||||
}
|
||||
|
||||
void DrawingProgramCache::build_bvh_node_coords_and_resolution(BVHNode& node) {
|
||||
// These are part of the draw cache data, but we're putting it out here, because:
|
||||
// - We dont have to recalculate it every time we refresh the cache
|
||||
// - Some of the data here is needed to determine whether to generate the cache in the first place
|
||||
|
||||
const int MAX_DIMENSION_RESOLUTION = 2000;
|
||||
|
||||
WorldVec cacheBoundDim = node.bounds.dim();
|
||||
if(cacheBoundDim.x() > cacheBoundDim.y()) {
|
||||
node.resolution.x() = MAX_DIMENSION_RESOLUTION;
|
||||
node.resolution.y() = MAX_DIMENSION_RESOLUTION * static_cast<double>(cacheBoundDim.y() / cacheBoundDim.x());
|
||||
}
|
||||
else {
|
||||
node.resolution.y() = MAX_DIMENSION_RESOLUTION;
|
||||
node.resolution.x() = MAX_DIMENSION_RESOLUTION * static_cast<double>(cacheBoundDim.x() / cacheBoundDim.y());
|
||||
}
|
||||
node.coords.rotation = 0.0;
|
||||
node.coords.pos = node.bounds.min;
|
||||
// Not necessary, but we choose the number that had less operations done on it for more accuracy
|
||||
if(node.resolution.x() > node.resolution.y())
|
||||
node.coords.inverseScale = cacheBoundDim.x().divide_double(node.resolution.x());
|
||||
else
|
||||
node.coords.inverseScale = cacheBoundDim.y().divide_double(node.resolution.y());
|
||||
}
|
||||
|
||||
void DrawingProgramCache::invalidate_cache_before_pos(uint64_t placementToInvalidateAt) {
|
||||
// We could use worldAABB of component to invalidate specific areas. However, that comes with some issues:
|
||||
// - The AABB couldve been changed from the last frame, so the current worldAABB doesnt actually represent what we should update
|
||||
|
|
@ -137,3 +182,62 @@ void DrawingProgramCache::invalidate_cache_before_pos(uint64_t placementToInvali
|
|||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void DrawingProgramCache::refresh_all_draw_cache(SkCanvas* canvas, const DrawData& drawData) {
|
||||
std::deque<BVHNode*> nodeFlatList; // We want to render children before parents, so that parents can make use of the cached children
|
||||
traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](DrawingProgramCache::BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
if(node && node->coords.inverseScale <= drawData.cam.c.inverseScale) {
|
||||
if(!node->drawCache)
|
||||
nodeFlatList.emplace_front(node);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if(!nodeFlatList.empty())
|
||||
refresh_draw_cache(*nodeFlatList.front(), drawData);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::refresh_draw_cache(BVHNode& bvhNode, const DrawData& drawData) {
|
||||
if(bvhNode.children.empty() && bvhNode.components.empty())
|
||||
return;
|
||||
|
||||
bvhNode.drawCache = std::nullopt;
|
||||
BVHNode::DrawCacheData drawCache;
|
||||
|
||||
SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(bvhNode.resolution.x(), bvhNode.resolution.y());
|
||||
#ifdef USE_SKIA_BACKEND_GRAPHITE
|
||||
drawCache.surface = SkSurfaces::RenderTarget(drawP.world.main.window.recorder(), imgInfo, skgpu::Mipmapped::kNo, drawP.world.main.window.defaultMSAASurfaceProps);
|
||||
#elif USE_SKIA_BACKEND_GANESH
|
||||
drawCache.surface = SkSurfaces::RenderTarget(drawP.world.main.window.ctx.get(), skgpu::Budgeted::kNo, imgInfo, drawP.world.main.window.defaultMSAASampleCount, &drawP.world.main.window.defaultMSAASurfaceProps);
|
||||
#endif
|
||||
|
||||
if(!drawCache.surface)
|
||||
throw std::runtime_error("[DrawingProgramCache::refresh_draw_cache] Could not make cache surface");
|
||||
|
||||
SkCanvas* cacheCanvas = drawCache.surface->getCanvas();
|
||||
|
||||
cacheCanvas->clear(SkColor4f{0, 0, 0, 0});
|
||||
|
||||
DrawData cacheDrawData = drawData;
|
||||
cacheDrawData.cam.c = bvhNode.coords;
|
||||
cacheDrawData.cam.changed = nullptr;
|
||||
cacheDrawData.cam.set_viewing_area(bvhNode.resolution.cast<float>());
|
||||
cacheDrawData.refresh_draw_optimizing_values();
|
||||
drawP.draw_components_to_canvas(cacheCanvas, cacheDrawData, false);
|
||||
|
||||
drawCache.lastDrawnComponentPlacement = drawP.components.client_list().size() - 1;
|
||||
drawCache.lastRenderTime = std::chrono::steady_clock::now();
|
||||
|
||||
bvhNode.drawCache = drawCache; // Set the drawCache after rendering is done, so that the draw function doesnt assume we have this node cached
|
||||
|
||||
while(nodesWithCachedSurfaces.size() >= MAXIMUM_DRAW_CACHE_SURFACES) {
|
||||
BVHNode* leastUsedNode = *nodesWithCachedSurfaces.begin();
|
||||
for(BVHNode* n : nodesWithCachedSurfaces) {
|
||||
if(n->drawCache.value().lastRenderTime < leastUsedNode->drawCache.value().lastRenderTime)
|
||||
leastUsedNode = n;
|
||||
}
|
||||
nodesWithCachedSurfaces.erase(leastUsedNode);
|
||||
}
|
||||
|
||||
nodesWithCachedSurfaces.emplace(&bvhNode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,26 +3,37 @@
|
|||
#include "../CollabList.hpp"
|
||||
#include "../DrawComponents/DrawComponent.hpp"
|
||||
#include <include/core/SkSurface.h>
|
||||
#include <unordered_set>
|
||||
|
||||
class DrawingProgram;
|
||||
|
||||
class DrawingProgramCache {
|
||||
public:
|
||||
typedef CollabList<std::shared_ptr<DrawComponent>, ServerClientID> CollabListType;
|
||||
void update(const std::vector<CollabListType::ObjectInfoPtr>& components);
|
||||
DrawingProgramCache(DrawingProgram& initDrawP);
|
||||
|
||||
void update();
|
||||
void erase_component(const CollabListType::ObjectInfoPtr& c);
|
||||
void add_component(const CollabListType::ObjectInfoPtr& c);
|
||||
void refresh_all_draw_cache(SkCanvas* canvas, const DrawData& drawData);
|
||||
|
||||
struct BVHNode {
|
||||
SCollision::AABB<WorldScalar> bounds;
|
||||
std::vector<CollabListType::ObjectInfoPtr> components;
|
||||
std::vector<BVHNode> children;
|
||||
|
||||
CoordSpaceHelper coords;
|
||||
Vector2i resolution;
|
||||
struct DrawCacheData {
|
||||
uint64_t lastDrawnComponentPlacement;
|
||||
sk_sp<SkSurface> surface;
|
||||
std::chrono::steady_clock::time_point lastRenderTime;
|
||||
};
|
||||
|
||||
std::optional<DrawCacheData> drawCache;
|
||||
};
|
||||
|
||||
std::vector<BVHNode*> nodesWithCachedSurfaces;
|
||||
std::unordered_set<BVHNode*> nodesWithCachedSurfaces;
|
||||
|
||||
void traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
|
||||
|
|
@ -31,6 +42,8 @@ class DrawingProgramCache {
|
|||
|
||||
void invalidate_cache_before_pos(uint64_t placementToInvalidateAt);
|
||||
private:
|
||||
void build_bvh_node_coords_and_resolution(BVHNode& node);
|
||||
void refresh_draw_cache(BVHNode& bvhNode, const DrawData& drawData);
|
||||
|
||||
void build(std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
|
||||
|
|
@ -40,4 +53,5 @@ class DrawingProgramCache {
|
|||
void build_bvh_node(BVHNode& node, std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
BVHNode bvhRoot;
|
||||
std::vector<CollabListType::ObjectInfoPtr> unsortedComponents;
|
||||
DrawingProgram& drawP;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ void ScreenshotTool::take_screenshot_area_hw(const sk_sp<SkSurface>& surface, Sk
|
|||
WorldScalar newInverseScale = (vectorZoom.x() + vectorZoom.y()) * WorldScalar(0.5);
|
||||
|
||||
drawP.world.drawData.cam.set_based_on_properties(drawP.world, topLeft, newInverseScale, controls.coords.rotation);
|
||||
drawP.world.drawData.cam.set_viewing_area(sectionImageSize.cast<float>());
|
||||
drawP.world.drawData.refresh_draw_optimizing_values();
|
||||
|
||||
GridManager::GridType oldGridType = drawP.world.main.grid.gridType;
|
||||
drawP.world.main.takingScreenshot = true;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class MainProgram {
|
|||
sk_sp<SkSurface> surface;
|
||||
std::shared_ptr<DrawComponent> firstCompUpdate = nullptr;
|
||||
SkCanvas* canvas;
|
||||
bool disableDrawCache = false;
|
||||
} drawProgCache;
|
||||
|
||||
struct Window {
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ nlohmann::json Toolbar::get_config_json() {
|
|||
toRet["themeInUse"] = themeData.themeCurrentlyLoaded;
|
||||
toRet["velocityAffectsBrushWidth"] = velocityAffectsBrushWidth;
|
||||
toRet["jumpTransitionEasing"] = jumpTransitionEasing;
|
||||
toRet["disableDrawCache"] = main.drawProgCache.disableDrawCache;
|
||||
|
||||
json tablet;
|
||||
tablet["pressureAffectsBrushWidth"] = tabletOptions.pressureAffectsBrushWidth;
|
||||
|
|
@ -271,6 +272,7 @@ void Toolbar::set_config_json(const nlohmann::json& j) {
|
|||
j.at("themeInUse").get_to(themeData.themeCurrentlyLoaded);
|
||||
j.at("velocityAffectsBrushWidth").get_to(velocityAffectsBrushWidth);
|
||||
j.at("jumpTransitionEasing").get_to(jumpTransitionEasing);
|
||||
j.at("disableDrawCache").get_to(main.drawProgCache.disableDrawCache);
|
||||
|
||||
j.at("tablet").at("pressureAffectsBrushWidth").get_to(tabletOptions.pressureAffectsBrushWidth);
|
||||
j.at("tablet").at("smoothingSamplingTime").get_to(tabletOptions.smoothingSamplingTime);
|
||||
|
|
@ -1156,6 +1158,7 @@ void Toolbar::options_menu() {
|
|||
}) {
|
||||
switch(generalSettingsOptions) {
|
||||
case GSETTINGS_GENERAL: {
|
||||
gui.push_id("general settings");
|
||||
gui.input_text_field("display name input", "Display Name", &main.displayName);
|
||||
main.update_display_names();
|
||||
gui.text_label("Note: Changes in display name dont affect canvases that are connected online");
|
||||
|
|
@ -1166,9 +1169,11 @@ void Toolbar::options_menu() {
|
|||
gui.slider_scalar_field("scroll zoom slider", "Scroll zoom speed", &scrollZoomSpeed, 0.0, 1.0, 3);
|
||||
gui.input_scalar_field("jump transition time", "Jump transition time", &jumpTransitionTime, 0.01f, 1000.0f, 2);
|
||||
gui.checkbox_field("changebrushwidthwithspeed", "Change brush size with mouse speed", &velocityAffectsBrushWidth);
|
||||
gui.pop_id();
|
||||
break;
|
||||
}
|
||||
case GSETTINGS_APPEARANCE: {
|
||||
gui.push_id("appearance settings");
|
||||
if(gui.radio_button_field("grid type no grid", "No Grid", (main.grid.gridType == GridManager::GRIDTYPE_NONE))) main.grid.gridType = GridManager::GRIDTYPE_NONE;
|
||||
if(gui.radio_button_field("grid type circle grid", "Circle Dot Grid", (main.grid.gridType == GridManager::GRIDTYPE_CIRCLEDOT))) main.grid.gridType = GridManager::GRIDTYPE_CIRCLEDOT;
|
||||
if(gui.radio_button_field("grid type square grid", "Square Dot Grid", (main.grid.gridType == GridManager::GRIDTYPE_SQUAREDOT))) main.grid.gridType = GridManager::GRIDTYPE_SQUAREDOT;
|
||||
|
|
@ -1176,6 +1181,7 @@ void Toolbar::options_menu() {
|
|||
gui.input_scalar_field("GUI Scale", "GUI Scale", &guiScale, 0.5f, 3.0f, 1);
|
||||
gui.input_scalar_field<uint16_t>("GUI Font Size", "GUI Font Size", &io->fontSize, 10, 30);
|
||||
gui.text_label("Note: Changing font size may break UI in some cases.");
|
||||
gui.pop_id();
|
||||
break;
|
||||
}
|
||||
case GSETTINGS_TABLET: {
|
||||
|
|
@ -1303,6 +1309,7 @@ void Toolbar::options_menu() {
|
|||
break;
|
||||
}
|
||||
case GSETTINGS_DEBUG: {
|
||||
gui.push_id("debug settings menu");
|
||||
gui.checkbox_field("show performance metrics", "Show Metrics", &showPerformance);
|
||||
gui.input_scalar_fields("jump transition easing", "Jump Easing", &jumpTransitionEasing, 4, -10.0f, 10.0f, 2);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
|
|
@ -1310,6 +1317,8 @@ void Toolbar::options_menu() {
|
|||
gui.text_label("Note: Requires restart to take effect. May cause bugs on Intel Graphics");
|
||||
gui.input_scalar_field("fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f);
|
||||
#endif
|
||||
gui.checkbox_field("Disable Draw Cache", "Disable BVH Draw Cache", &main.drawProgCache.disableDrawCache);
|
||||
gui.pop_id();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ void World::save_to_file(const std::filesystem::path& fileName) {
|
|||
void World::load_from_file(const std::filesystem::path& fileName, std::string_view buffer) {
|
||||
filePath = force_extension_on_path(fileName, FILE_EXTENSION);
|
||||
|
||||
|
||||
if(buffer.empty()) {
|
||||
std::ifstream f(filePath, std::ios::in | std::ios::binary);
|
||||
std::string fileHeader;
|
||||
|
|
@ -319,15 +320,7 @@ WorldScalar World::calculate_zoom_from_uniform_zoom(WorldScalar uniformZoom, Wor
|
|||
}
|
||||
|
||||
void World::draw(SkCanvas* canvas) {
|
||||
drawData.clampDrawBetween = true;
|
||||
|
||||
drawData.clampDrawMinimum = drawData.cam.c.inverseScale >> DRAWCOMP_MIN_SHIFT_BEFORE_DISAPPEAR;
|
||||
drawData.mipMapLevelOne = drawData.cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_ONE;
|
||||
drawData.mipMapLevelTwo = drawData.cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_TWO;
|
||||
drawData.mipMapLevelThree = drawData.cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_THREE;
|
||||
drawData.mipMapLevelFour = drawData.cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_FOUR;
|
||||
drawData.mipMapLevelFive = drawData.cam.c.inverseScale >> DRAWCOMP_MIPMAP_LEVEL_FOUR;
|
||||
drawData.clampDrawMaximum = drawData.cam.c.inverseScale << DRAWCOMP_MAX_SHIFT_BEFORE_DISAPPEAR;
|
||||
drawData.refresh_draw_optimizing_values();
|
||||
|
||||
drawProg.draw(canvas, drawData);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue