/
Team8
/
kittycad
Обзор
Документация
Войти
/
Team8
/
kittycad
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/data/document.cpp
259 строк
7 KB
levovix
fix;
10 янв 2026, 21:53
10 янв 2026, 21:53
eb2e123
Код
Авторство
О чём код?
#include "document.h" #include "data/sketch/sketch.h" #include "data/assembly/assembly.h" #include "gui/document_view.h" using namespace VSN; using namespace data; ref<Sketch> data::Document::getOrCreateActiveSketch() { if (activeSketch.expired()) { auto sketch = create<data::Sketch>( std::dynamic_pointer_cast<data::Document>(shared_from_this()) ); if (documentView != nullptr) { // todo: получать origin, xAxis и yAxis по направлению камеры (либо спрашивать у пользователя) } activeSketch = sketch; addChild(sketch); } return activeSketch.lock(); } void data::Document::setActiveSketch(ptr<Sketch> v) { activeSketch = v; if (documentView != nullptr) { documentView->documentUpdated(); } } ref<Assembly> data::Document::getOrCreateActiveAssembly() { if (activeAssembly.expired()) { auto assembly = create<data::Assembly>( std::dynamic_pointer_cast<data::Document>(shared_from_this()) ); activeAssembly = assembly; addChild(assembly); } return activeAssembly.lock(); } void data::Document::setActiveAssembly(ptr<Assembly> v) { activeAssembly = v; if (documentView != nullptr) { documentView->documentUpdated(); } } void data::Document::addTemporary(ref<C3dObject> child) { temporaryObjects.push_back(child); updateRequested = true; } void data::Document::removeTemporary(ref<C3dObject> child) { for (auto it = temporaryObjects.begin(); it < temporaryObjects.end();) { if ((*it).expired()) { it = temporaryObjects.erase(it); } else if ((*it).lock().get() == child.get()) { it = temporaryObjects.erase(it); } else { ++it; } } updateRequested = true; } void data::Document::addChild(ref<C3dObject> child) { removeTemporary(child); objects.push_back(child); updateRequested = true; } void data::Document::removeChild(ref<C3dObject> child) { for (auto it = objects.begin(); it < objects.end();) { if ((*it).get() == child.get()) { it = objects.erase(it); } else { ++it; } } updateRequested = true; } int setLevelRecursively( std::map<C3dObject*, int>& levels, ref<C3dObject> const& node, int startLevel, bool readonly, std::set<ISerializable*> const* filter ) { int& level = levels[node.get()]; int maxLevel = startLevel; if (startLevel > level) { maxLevel = level = startLevel; for (auto const& dependant : node->usedBy) { if (!dependant.expired()) { if (filter != nullptr && !filter->contains(dependant.lock().get())) { continue; } maxLevel = std::max(setLevelRecursively(levels, dependant.lock(), level + 1, readonly, filter), maxLevel); if (!readonly) { dependant.lock()->markDependencyChanged(node); } } } if (!node->m_parent.expired() && !(filter != nullptr && !filter->contains(node->m_parent.lock().get()))) { maxLevel = std::max(setLevelRecursively(levels, node->m_parent.lock(), level + 1, readonly, filter), maxLevel); if (!readonly) { node->m_parent.lock()->markDependencyChanged(node); } } } return maxLevel; } std::string formatObjects(std::map<C3dObject*, int> const& objects, char const* indent = "") { std::stringstream ss; for (auto [ent, level] : objects) { ss << indent << "[" << level << "] " << ent->typeName() << "(" << "id: " << ent->id() << ", name: " << ent->name() << ")\n"; } return ss.str(); } std::string formatObjects(std::vector<std::vector<C3dObject*>> const& objects, char const* indent = "") { std::stringstream ss; DumpContext c{.indent = 0, .stream = ss}; int levelN = 1; for (auto level : objects) { for (auto ent : level) { ss << indent << levelN << " "; ent->dumpType(c); ss << c.styleString << " \"" << ent->name() << "\"\n" << c.styleNormal; } ++levelN; } return ss.str(); } void data::Document::update() { updateRequested = false; std::vector<std::vector<C3dObject*>> updateGraph; if (!update(this, false, 10, false, &updateGraph)) { throw std::runtime_error( "Cycle dependency detected. Unable to update every object in document. Still needs to be updated:\n" + formatObjects(updateGraph, " ") ); } } bool data::Document::update( ISerializable* start, bool exceptSelf, int maxCycles, bool onlyTracedObjects, std::vector<std::vector<C3dObject*>>* outUpdateGraph ) { std::set<ISerializable*> allObjects; TraceContext tctx{allObjects}; int updateCount = 0; while (true) { ++updateCount; auto updateGraph = buildUpdateGraph(allObjects, start, exceptSelf, onlyTracedObjects, false); if (updateGraph.empty()) { break; } if (outUpdateGraph != nullptr) { *outUpdateGraph = updateGraph; } if (updateCount > maxCycles) { return false; } for (auto const& level : updateGraph) { for (auto const& ent : level) { if (ent->m_dependencyChanged) { ent->updateFromDependencies(); } else if (ent->m_propertyChanged) { ent->updateFromParams(); } } } } for (auto obj : allObjects) { if (exceptSelf && obj == start) { continue; } if (auto ent = std::dynamic_pointer_cast<C3dObject>(obj->shared_from_this())) { if (ent->m_visualChanged) { ent->buildVisual(); } } } return true; } std::vector<std::vector<data::C3dObject*>> data::Document::buildUpdateGraph( std::set<ISerializable*>& allObjects, ISerializable* start, bool exceptSelf, bool onlyTracedObjects, bool readonly ) { TraceContext tctx{allObjects}; allObjects.clear(); ::trace(tctx, start); if (exceptSelf) { allObjects.erase(start); } std::map<C3dObject*, int> updateGraph; // object -> level for (auto obj : allObjects) { obj->traceTemporary(tctx); } int maxLevel = 0; for (auto obj : allObjects) { if (auto ent = std::dynamic_pointer_cast<C3dObject>(obj->shared_from_this())) { if (ent->m_propertyChanged || ent->m_dependencyChanged) { maxLevel = std::max(setLevelRecursively(updateGraph, ent, 1, readonly, onlyTracedObjects ? &allObjects : nullptr), maxLevel); } } } if (maxLevel == 0) { return {}; } std::vector<std::vector<C3dObject*>> sortedUpdateGraph; sortedUpdateGraph.resize(maxLevel); for (auto const& [ent, level] : updateGraph) { sortedUpdateGraph[level - 1].push_back(ent); } return sortedUpdateGraph; } void data::Document::printUpdateGraph(ISerializable* start) { std::set<ISerializable*> allObjects; std::cout << formatObjects(buildUpdateGraph(allObjects, start, false, true, true)) << "\n"; }