Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
Merge pull request #77 from monadgroup/feature/42-global-module-library
Browse files Browse the repository at this point in the history
Add global module library, fixes #42
  • Loading branch information
cpdt committed Sep 26, 2018
2 parents 15f87cc + f3e694a commit dd4156f
Show file tree
Hide file tree
Showing 22 changed files with 403 additions and 118 deletions.
9 changes: 7 additions & 2 deletions editor/backend/AudioBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../model/serialize/ProjectSerializer.h"
#include "../resources/resource.h"
#include "../util.h"
#include "../widgets/InteractiveImport.h"
#include "../widgets/windows/MainWindow.h"

using namespace AxiomBackend;
Expand Down Expand Up @@ -62,8 +63,12 @@ QByteArray AudioBackend::serialize() {
void AudioBackend::deserialize(QByteArray *data) {
QDataStream stream(data, QIODevice::ReadOnly);
uint32_t readVersion = 0;
auto newProject =
AxiomModel::ProjectSerializer::deserialize(stream, &readVersion, [](QDataStream &stream, uint32_t version) {
auto newProject = AxiomModel::ProjectSerializer::deserialize(
stream, &readVersion,
[this](AxiomModel::Library *importLibrary) {
AxiomGui::doInteractiveLibraryImport(_editor->window()->library(), importLibrary);
},
[](QDataStream &stream, uint32_t version) {
QString linkedFile;
if (version >= 5) {
stream >> linkedFile;
Expand Down
19 changes: 11 additions & 8 deletions editor/model/Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ Library::~Library() = default;

Library::Library(QString activeTag, QString activeSearch,
std::vector<std::unique_ptr<AxiomModel::LibraryEntry>> entries)
: _entries(std::move(entries)), _activeTag(std::move(activeTag)), _activeSearch(std::move(activeSearch)) {
// add tags of all entries
for (const auto &entry : _entries) {
for (const auto &tag : entry->tags()) {
addTag(tag);
}
: _activeTag(std::move(activeTag)), _activeSearch(std::move(activeSearch)) {
// add all entries through the normal path, so we assign event handlers to them correctly
_entries.reserve(entries.size());
for (auto &entry : entries) {
addEntry(std::move(entry));
}
}

Expand Down Expand Up @@ -135,7 +134,10 @@ void Library::addEntry(std::unique_ptr<AxiomModel::LibraryEntry> entry) {
}
entryPtr->tagAdded.connect(this, &Library::addTag);
entryPtr->tagRemoved.connect(this, &Library::removeTag);
entryPtr->changed.connect(&changed);
entryPtr->cleanup.connect(this, [this, entryPtr]() { removeEntry(entryPtr); });

changed.trigger();
}

LibraryEntry *Library::findById(const QUuid &id) {
Expand Down Expand Up @@ -174,8 +176,9 @@ void Library::removeEntry(AxiomModel::LibraryEntry *entry) {
for (auto i = _entries.begin(); i != _entries.end(); i++) {
if (i->get() == entry) {
_entries.erase(i);
return;
break;
}
}
unreachable;

changed.trigger();
}
1 change: 1 addition & 0 deletions editor/model/Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace AxiomModel {
AxiomCommon::Event<const QString &> activeSearchChanged;
AxiomCommon::Event<const QString &> tagAdded;
AxiomCommon::Event<const QString &> tagRemoved;
AxiomCommon::Event<> changed;

Library();

Expand Down
5 changes: 3 additions & 2 deletions editor/model/LibraryEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ std::unique_ptr<LibraryEntry> LibraryEntry::create(QString name, const QUuid &ba
std::move(tags), std::move(root));
}

std::unique_ptr<LibraryEntry> LibraryEntry::create(QString name, std::set<QString> tags, Project *project) {
auto newRoot = std::make_unique<ModelRoot>(project);
std::unique_ptr<LibraryEntry> LibraryEntry::create(QString name, std::set<QString> tags) {
auto newRoot = std::make_unique<ModelRoot>();
newRoot->pool().registerObj(std::make_unique<RootSurface>(QUuid::createUuid(), QPointF(0, 0), 0, 0, newRoot.get()));
return create(std::move(name), QUuid::createUuid(), QUuid::createUuid(), QDateTime::currentDateTimeUtc(),
std::move(tags), std::move(newRoot));
Expand Down Expand Up @@ -61,6 +61,7 @@ void LibraryEntry::removeTag(const QString &tag) {
void LibraryEntry::modified() {
_modificationUuid = QUuid::createUuid();
_modificationDateTime = QDateTime::currentDateTimeUtc();
changed.trigger();
}

void LibraryEntry::remove() {
Expand Down
3 changes: 2 additions & 1 deletion editor/model/LibraryEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace AxiomModel {
AxiomCommon::Event<const QString &> nameChanged;
AxiomCommon::Event<const QString &> tagAdded;
AxiomCommon::Event<const QString &> tagRemoved;
AxiomCommon::Event<> changed;
AxiomCommon::Event<> removed;
AxiomCommon::Event<> cleanup;

Expand All @@ -27,7 +28,7 @@ namespace AxiomModel {
const QDateTime &modificationDateTime, std::set<QString> tags,
std::unique_ptr<ModelRoot> root);

static std::unique_ptr<LibraryEntry> create(QString name, std::set<QString> tags, Project *project);
static std::unique_ptr<LibraryEntry> create(QString name, std::set<QString> tags);

const QString &name() const { return _name; }

Expand Down
11 changes: 5 additions & 6 deletions editor/model/ModelRoot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

using namespace AxiomModel;

ModelRoot::ModelRoot(Project *project)
: _project(project), _history([this](std::vector<QUuid> items) { applyCompile(items); }),
ModelRoot::ModelRoot()
: _history([this](std::vector<QUuid> items) { applyCompile(items); }),
_nodeSurfaces(dynamicCastWatch<NodeSurface *>(_pool.sequence())),
_nodes(dynamicCastWatch<Node *>(_pool.sequence())),
_controlSurfaces(dynamicCastWatch<ControlSurface *>(_pool.sequence())),
Expand Down Expand Up @@ -80,9 +80,7 @@ void ModelRoot::applyCompile(const std::vector<QUuid> &items) {
applyItemsTo(items, &transaction);
applyTransaction(std::move(transaction));

if (!_project->linkedFile().isEmpty() || !_project->backend()->doesSaveInternally()) {
_project->setIsDirty(true);
}
modified.trigger();
}

void ModelRoot::applyTransaction(MaximCompiler::Transaction transaction) {
Expand All @@ -101,7 +99,8 @@ void ModelRoot::applyTransaction(MaximCompiler::Transaction transaction) {
obj->restoreState();
}
}
_project->backend()->internalUpdateConfiguration();

configurationChanged.trigger();
}

void ModelRoot::destroy() {
Expand Down
8 changes: 4 additions & 4 deletions editor/model/ModelRoot.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ namespace AxiomModel {

class RootSurface;

class ModelRoot {
class ModelRoot : public AxiomCommon::Hookable {
public:
using NodeSurfaceCollection = WatchSequence<NodeSurface *>;
using NodeCollection = WatchSequence<Node *>;
using ControlSurfaceCollection = WatchSequence<ControlSurface *>;
using ControlCollection = WatchSequence<Control *>;
using ConnectionCollection = WatchSequence<Connection *>;

explicit ModelRoot(Project *project);
AxiomCommon::Event<> modified;
AxiomCommon::Event<> configurationChanged;

Project *project() const { return _project; }
ModelRoot();

RootSurface *rootSurface() const;

Expand Down Expand Up @@ -89,7 +90,6 @@ namespace AxiomModel {
void destroy();

private:
Project *_project;
Pool _pool;
HistoryList _history;
NodeSurfaceCollection _nodeSurfaces;
Expand Down
30 changes: 22 additions & 8 deletions editor/model/Project.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "Project.h"

#include "../backend/AudioBackend.h"
#include "../backend/AudioConfiguration.h"
#include "Library.h"
#include "ModelRoot.h"
#include "PoolOperators.h"
#include "actions/CreatePortalNodeAction.h"
Expand All @@ -11,7 +11,9 @@
using namespace AxiomModel;

Project::Project(const AxiomBackend::DefaultConfiguration &defaultConfiguration)
: _mainRoot(std::make_unique<ModelRoot>(this)), _library(std::make_unique<Library>()) {
: _mainRoot(std::make_unique<ModelRoot>()) {
addRootListeners();

// setup default project
// 1. create default surface
auto rootId = QUuid::createUuid();
Expand Down Expand Up @@ -77,12 +79,9 @@ Project::Project(const AxiomBackend::DefaultConfiguration &defaultConfiguration)
}
}

Project::Project(QString linkedFile) : _linkedFile(std::move(linkedFile)) {}

void Project::init(std::unique_ptr<AxiomModel::ModelRoot> mainRoot, std::unique_ptr<AxiomModel::Library> library) {
_mainRoot = std::move(mainRoot);
_library = std::move(library);
_rootSurface = _mainRoot->rootSurface();
Project::Project(QString linkedFile, std::unique_ptr<AxiomModel::ModelRoot> mainRoot)
: _mainRoot(std::move(mainRoot)), _linkedFile(std::move(linkedFile)), _rootSurface(_mainRoot->rootSurface()) {
addRootListeners();
}

Project::~Project() {
Expand All @@ -102,3 +101,18 @@ void Project::setIsDirty(bool isDirty) {
isDirtyChanged.trigger(isDirty);
}
}

void Project::addRootListeners() {
_mainRoot->modified.connect(this, &Project::rootModified);
_mainRoot->configurationChanged.connect(this, &Project::rootConfigurationChanged);
}

void Project::rootModified() {
if (!linkedFile().isEmpty() || !backend()->doesSaveInternally()) {
setIsDirty(true);
}
}

void Project::rootConfigurationChanged() {
backend()->internalUpdateConfiguration();
}
14 changes: 7 additions & 7 deletions editor/model/Project.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ namespace AxiomBackend {
namespace AxiomModel {

class RootSurface;
class Library;
class ModelRoot;

class Project : public AxiomCommon::Hookable {
Expand All @@ -24,16 +23,12 @@ namespace AxiomModel {

explicit Project(const AxiomBackend::DefaultConfiguration &defaultConfiguration);

explicit Project(QString linkedFile);

void init(std::unique_ptr<ModelRoot> mainRoot, std::unique_ptr<Library> library);
Project(QString linkedFile, std::unique_ptr<ModelRoot> mainRoot);

~Project() override;

ModelRoot &mainRoot() const { return *_mainRoot; }

Library &library() const { return *_library; }

RootSurface *rootSurface() const { return _rootSurface; }

const QString &linkedFile() const { return _linkedFile; }
Expand All @@ -50,11 +45,16 @@ namespace AxiomModel {

private:
std::unique_ptr<ModelRoot> _mainRoot;
std::unique_ptr<Library> _library;
QString _linkedFile;
bool _isDirty = false;

AxiomBackend::AudioBackend *_backend = nullptr;
RootSurface *_rootSurface;

void addRootListeners();

void rootModified();

void rootConfigurationChanged();
};
}
2 changes: 1 addition & 1 deletion editor/model/actions/CreatePortalNodeAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ std::unique_ptr<CreatePortalNodeAction> CreatePortalNodeAction::create(const QUu
AxiomModel::ConnectionWire::WireType wireType,
AxiomModel::PortalControl::PortalType portalType,
AxiomModel::ModelRoot *root) {
auto portalId = root->project()->rootSurface()->takePortalId();
auto portalId = root->rootSurface()->takePortalId();
return create(QUuid::createUuid(), parentUuid, pos, std::move(name), QUuid::createUuid(), wireType, portalType,
portalId, QUuid::createUuid(), root);
}
Expand Down
9 changes: 4 additions & 5 deletions editor/model/serialize/LibrarySerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void LibrarySerializer::serialize(AxiomModel::Library *library, QDataStream &str
}
}

std::unique_ptr<Library> LibrarySerializer::deserialize(QDataStream &stream, uint32_t version, Project *project) {
std::unique_ptr<Library> LibrarySerializer::deserialize(QDataStream &stream, uint32_t version) {
QString activeTag;
stream >> activeTag;
QString activeSearch;
Expand All @@ -28,7 +28,7 @@ std::unique_ptr<Library> LibrarySerializer::deserialize(QDataStream &stream, uin
stream >> entryCount;
entries.reserve(entryCount);
for (uint32_t i = 0; i < entryCount; i++) {
entries.push_back(deserializeEntry(stream, version, project));
entries.push_back(deserializeEntry(stream, version));
}

return std::make_unique<Library>(std::move(activeTag), std::move(activeSearch), std::move(entries));
Expand All @@ -46,8 +46,7 @@ void LibrarySerializer::serializeEntry(AxiomModel::LibraryEntry *entry, QDataStr
ModelObjectSerializer::serializeRoot(entry->root(), false, stream);
}

std::unique_ptr<LibraryEntry> LibrarySerializer::deserializeEntry(QDataStream &stream, uint32_t version,
AxiomModel::Project *project) {
std::unique_ptr<LibraryEntry> LibrarySerializer::deserializeEntry(QDataStream &stream, uint32_t version) {
QString name;
stream >> name;
QUuid baseUuid;
Expand All @@ -69,7 +68,7 @@ std::unique_ptr<LibraryEntry> LibrarySerializer::deserializeEntry(QDataStream &s
// 0.4.0 (schema version 5) removed history from being serialized in the library
auto deserializeHistory = version < 5;

auto root = ModelObjectSerializer::deserializeRoot(stream, deserializeHistory, version, project);
auto root = ModelObjectSerializer::deserializeRoot(stream, deserializeHistory, version);
return LibraryEntry::create(std::move(name), baseUuid, modificationUuid, modificationDateTime, std::move(tags),
std::move(root));
}
4 changes: 2 additions & 2 deletions editor/model/serialize/LibrarySerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ namespace AxiomModel {
namespace LibrarySerializer {
void serialize(Library *library, QDataStream &stream);

std::unique_ptr<Library> deserialize(QDataStream &stream, uint32_t version, Project *project);
std::unique_ptr<Library> deserialize(QDataStream &stream, uint32_t version);

void serializeEntry(LibraryEntry *entry, QDataStream &stream);

std::unique_ptr<LibraryEntry> deserializeEntry(QDataStream &stream, uint32_t version, Project *project);
std::unique_ptr<LibraryEntry> deserializeEntry(QDataStream &stream, uint32_t version);
}
}
4 changes: 2 additions & 2 deletions editor/model/serialize/ModelObjectSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ std::vector<ModelObject *> ModelObjectSerializer::deserializeChunk(QDataStream &
}

std::unique_ptr<ModelRoot> ModelObjectSerializer::deserializeRoot(QDataStream &stream, bool includeHistory,
uint32_t version, Project *project) {
auto modelRoot = std::make_unique<ModelRoot>(project);
uint32_t version) {
auto modelRoot = std::make_unique<ModelRoot>();
IdentityReferenceMapper ref;
deserializeChunk(stream, version, modelRoot.get(), QUuid(), &ref);
if (includeHistory) {
Expand Down
4 changes: 1 addition & 3 deletions editor/model/serialize/ModelObjectSerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ namespace AxiomModel {

class ModelRoot;
class ReferenceMapper;
class Project;

namespace ModelObjectSerializer {
std::vector<ModelObject *> deserializeChunk(QDataStream &stream, uint32_t version, ModelRoot *root,
const QUuid &parent, ReferenceMapper *ref);

void serializeRoot(ModelRoot *root, bool includeHistory, QDataStream &stream);

std::unique_ptr<ModelRoot> deserializeRoot(QDataStream &stream, bool includeHistory, uint32_t version,
Project *project);
std::unique_ptr<ModelRoot> deserializeRoot(QDataStream &stream, bool includeHistory, uint32_t version);

void serialize(ModelObject *obj, QDataStream &stream, const QUuid &parent);

Expand Down
16 changes: 11 additions & 5 deletions editor/model/serialize/ProjectSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ void ProjectSerializer::serialize(AxiomModel::Project *project, QDataStream &str
writeHeader(stream, projectSchemaMagic);
writeLinkedFile(stream);
ModelObjectSerializer::serializeRoot(&project->mainRoot(), true, stream);
LibrarySerializer::serialize(&project->library(), stream);
}

std::unique_ptr<Project> ProjectSerializer::deserialize(QDataStream &stream, uint32_t *versionOut,
std::function<void(Library *)> importLibrary,
std::function<QString(QDataStream &, uint32_t)> getLinkedFile) {
uint32_t version;
if (!readHeader(stream, projectSchemaMagic, &version)) {
Expand All @@ -42,9 +42,15 @@ std::unique_ptr<Project> ProjectSerializer::deserialize(QDataStream &stream, uin
if (versionOut) *versionOut = version;

auto linkedFile = getLinkedFile(stream, version);
auto project = std::make_unique<Project>(linkedFile);
auto modelRoot = ModelObjectSerializer::deserializeRoot(stream, true, version, project.get());
auto library = LibrarySerializer::deserialize(stream, version, project.get());
project->init(std::move(modelRoot), std::move(library));
auto modelRoot = ModelObjectSerializer::deserializeRoot(stream, true, version);
auto project = std::make_unique<Project>(linkedFile, std::move(modelRoot));

// Before schema version 5, the module library was included in the project file. To ensure modules aren't lost,
// merge the library in.
if (version < 5) {
auto library = LibrarySerializer::deserialize(stream, version);
importLibrary(library.get());
}

return project;
}
Loading

0 comments on commit dd4156f

Please sign in to comment.