refactor(instance): added functions for accessing root datamodel and renamed to gDataModel
This commit is contained in:
parent
a47d2c2b57
commit
215f8ed500
10 changed files with 79 additions and 34 deletions
|
@ -45,12 +45,12 @@ int main() {
|
|||
glfwMakeContextCurrent(window);
|
||||
glewInit();
|
||||
|
||||
dataModel->Init();
|
||||
gDataModel->Init();
|
||||
simulationInit();
|
||||
renderInit(window, 1200, 900);
|
||||
|
||||
// Baseplate
|
||||
workspace()->AddChild(Part::New({
|
||||
gWorkspace()->AddChild(Part::New({
|
||||
.position = glm::vec3(0, -5, 0),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(512, 1.2, 512),
|
||||
|
@ -58,14 +58,14 @@ int main() {
|
|||
.anchored = true,
|
||||
}));
|
||||
|
||||
workspace()->AddChild(lastPart = Part::New({
|
||||
gWorkspace()->AddChild(lastPart = Part::New({
|
||||
.position = glm::vec3(0),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(4, 1.2, 2),
|
||||
.color = glm::vec3(0.639216f, 0.635294f, 0.647059f),
|
||||
}));
|
||||
|
||||
for (InstanceRef inst : workspace()->GetChildren()) {
|
||||
for (InstanceRef inst : gWorkspace()->GetChildren()) {
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
syncPartPhysics(part);
|
||||
|
@ -158,7 +158,7 @@ void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
|
|||
|
||||
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
if (key == GLFW_KEY_F && action == GLFW_PRESS) {
|
||||
workspace()->AddChild(lastPart = Part::New({
|
||||
gWorkspace()->AddChild(lastPart = Part::New({
|
||||
.position = camera.cameraPos + camera.cameraFront * glm::vec3(3),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(1, 1, 1),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
Camera camera(glm::vec3(0.0, 0.0, 3.0));
|
||||
//std::vector<Part> parts;
|
||||
std::shared_ptr<DataModel> dataModel = DataModel::New();
|
||||
std::shared_ptr<DataModel> gDataModel = DataModel::New();
|
||||
std::optional<HierarchyPreUpdateHandler> hierarchyPreUpdateHandler;
|
||||
std::optional<HierarchyPostUpdateHandler> hierarchyPostUpdateHandler;
|
||||
std::shared_ptr<Handles> editorToolHandles = Handles::New();
|
||||
|
|
|
@ -15,8 +15,8 @@ typedef std::function<void(std::vector<InstanceRefWeak> oldSelection, std::vecto
|
|||
// TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS
|
||||
|
||||
extern Camera camera;
|
||||
extern std::shared_ptr<DataModel> dataModel;
|
||||
inline std::shared_ptr<Workspace> workspace() { return std::dynamic_pointer_cast<Workspace>(dataModel->services["Workspace"]); }
|
||||
extern std::shared_ptr<DataModel> gDataModel;
|
||||
inline std::shared_ptr<Workspace> gWorkspace() { return std::dynamic_pointer_cast<Workspace>(gDataModel->services["Workspace"]); }
|
||||
extern std::optional<HierarchyPreUpdateHandler> hierarchyPreUpdateHandler;
|
||||
extern std::optional<HierarchyPostUpdateHandler> hierarchyPostUpdateHandler;
|
||||
extern std::shared_ptr<Handles> editorToolHandles;
|
||||
|
|
|
@ -72,6 +72,36 @@ bool Instance::SetParent(std::optional<std::shared_ptr<Instance>> newParent) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<DataModel>> Instance::dataModel() {
|
||||
// TODO: This algorithm will defer calculations to every time the root data model
|
||||
// is accessed from any instance. This is inefficient as this can happen many times
|
||||
// a tick. A better option is to cache these values and only update them if the ancestry
|
||||
// changes, as that happens way less often.
|
||||
|
||||
std::optional<std::shared_ptr<Instance>> currentParent = GetParent();
|
||||
while (currentParent) {
|
||||
if (currentParent.value()->GetClass() == &DataModel::TYPE)
|
||||
return std::dynamic_pointer_cast<DataModel>(currentParent.value());
|
||||
|
||||
currentParent = currentParent.value()->GetParent();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<Workspace>> Instance::workspace() {
|
||||
// See comment in above function
|
||||
std::optional<std::shared_ptr<Instance>> currentParent = GetParent();
|
||||
while (currentParent) {
|
||||
if (currentParent.value()->GetClass() == &DataModel::TYPE)
|
||||
return std::dynamic_pointer_cast<Workspace>(currentParent.value());
|
||||
|
||||
currentParent = currentParent.value()->GetParent();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<Instance>> Instance::GetParent() {
|
||||
if (!parent.has_value()) return std::nullopt;
|
||||
if (parent.value().expired()) return std::nullopt;
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
class Instance;
|
||||
typedef std::shared_ptr<Instance>(*InstanceConstructor)();
|
||||
|
||||
class DataModel;
|
||||
class Workspace;
|
||||
|
||||
// Struct describing information about an instance
|
||||
struct InstanceType {
|
||||
const InstanceType* super; // May be null
|
||||
|
@ -48,6 +51,13 @@ protected:
|
|||
|
||||
virtual void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent);
|
||||
|
||||
// The root data model this object is a descendant of
|
||||
std::optional<std::shared_ptr<DataModel>> dataModel();
|
||||
// The root workspace this object is a descendant of
|
||||
// NOTE: This value is not necessarily present if dataModel is present
|
||||
// Objects under services other than workspace will NOT have this field set
|
||||
std::optional<std::shared_ptr<Workspace>> workspace();
|
||||
|
||||
template <typename T> inline std::shared_ptr<T> shared() { return std::dynamic_pointer_cast<T>(this->shared_from_this()); }
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
|
|
@ -77,7 +77,7 @@ void physicsStep(float deltaTime) {
|
|||
|
||||
// Naive implementation. Parts are only considered so if they are just under Workspace
|
||||
// TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance
|
||||
for (InstanceRef obj : workspace()->GetChildren()) {
|
||||
for (InstanceRef obj : gWorkspace()->GetChildren()) {
|
||||
if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
|
||||
const rp::Transform& transform = part->rigidBody->getTransform();
|
||||
|
|
|
@ -125,7 +125,7 @@ void renderParts() {
|
|||
|
||||
// Sort by nearest
|
||||
std::map<float, std::shared_ptr<Part>> sorted;
|
||||
for (InstanceRef inst : workspace()->GetChildren()) {
|
||||
for (InstanceRef inst : gWorkspace()->GetChildren()) {
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
if (part->transparency > 0.00001) {
|
||||
|
@ -288,7 +288,7 @@ void renderAABB() {
|
|||
ghostShader->set("color", glm::vec3(1.f, 0.f, 0.f));
|
||||
|
||||
// Sort by nearest
|
||||
for (InstanceRef inst : workspace()->GetChildren()) {
|
||||
for (InstanceRef inst : gWorkspace()->GetChildren()) {
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
glm::mat4 model = Data::CFrame::IDENTITY + part->cframe.Position();
|
||||
|
|
|
@ -400,7 +400,7 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) {
|
|||
else if (evt->key() == Qt::Key_D) moveX = -1;
|
||||
|
||||
if (evt->key() == Qt::Key_F) {
|
||||
workspace()->AddChild(lastPart = Part::New({
|
||||
gWorkspace()->AddChild(lastPart = Part::New({
|
||||
.position = camera.cameraPos + camera.cameraFront * glm::vec3(3),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(1, 1, 1),
|
||||
|
|
|
@ -49,7 +49,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
dataModel->Init();
|
||||
gDataModel->Init();
|
||||
|
||||
ui->setupUi(this);
|
||||
timer.start(33, this);
|
||||
|
@ -136,11 +136,11 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
if (result == QMessageBox::Cancel) return;
|
||||
if (result == QMessageBox::Save) {
|
||||
std::optional<std::string> path;
|
||||
if (!dataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + dataModel->name));
|
||||
if (!gDataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name));
|
||||
if (!path || path == "") return;
|
||||
|
||||
dataModel->SaveToFile(path);
|
||||
gDataModel->SaveToFile(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -150,15 +150,15 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
// TL;DR: This stinks and I need to fix it.)
|
||||
ui->mainWidget->lastPart = Part::New();
|
||||
|
||||
dataModel = DataModel::New();
|
||||
dataModel->Init();
|
||||
ui->explorerView->updateRoot(dataModel);
|
||||
gDataModel = DataModel::New();
|
||||
gDataModel->Init();
|
||||
ui->explorerView->updateRoot(gDataModel);
|
||||
|
||||
// TODO: Remove this and use a proper fix. This *WILL* cause a leak and memory issues in the future
|
||||
simulationInit();
|
||||
|
||||
// Baseplate
|
||||
workspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
gWorkspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
.position = glm::vec3(0, -5, 0),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(512, 1.2, 512),
|
||||
|
@ -171,25 +171,30 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
connect(ui->actionSave, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path;
|
||||
if (!dataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + dataModel->name));
|
||||
if (!gDataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name));
|
||||
if (!path || path == "") return;
|
||||
|
||||
dataModel->SaveToFile(path);
|
||||
gDataModel->SaveToFile(path);
|
||||
});
|
||||
|
||||
connect(ui->actionSaveAs, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save as " + dataModel->name));
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save as " + gDataModel->name));
|
||||
if (!path || path == "") return;
|
||||
|
||||
dataModel->SaveToFile(path);
|
||||
gDataModel->SaveToFile(path);
|
||||
});
|
||||
|
||||
connect(ui->actionOpen, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptOpen);
|
||||
if (!path || path == "") return;
|
||||
|
||||
// // See TODO: Also remove this (the reaso
|
||||
// ui->mainWidget->lastPart = Part::New();
|
||||
|
||||
// simulationInit();
|
||||
std::shared_ptr<DataModel> newModel = DataModel::LoadFromFile(path.value());
|
||||
dataModel = newModel;
|
||||
gDataModel = newModel;
|
||||
ui->explorerView->updateRoot(newModel);
|
||||
});
|
||||
|
||||
|
@ -242,7 +247,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
for (pugi::xml_node instNode : rootDoc.children()) {
|
||||
InstanceRef inst = Instance::Deserialize(&instNode);
|
||||
workspace()->AddChild(inst);
|
||||
gWorkspace()->AddChild(inst);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -322,7 +327,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
simulationInit();
|
||||
|
||||
// Baseplate
|
||||
workspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
gWorkspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
.position = glm::vec3(0, -5, 0),
|
||||
.rotation = glm::vec3(0),
|
||||
.size = glm::vec3(512, 1.2, 512),
|
||||
|
@ -332,7 +337,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
ui->mainWidget->lastPart->name = "Baseplate";
|
||||
syncPartPhysics(ui->mainWidget->lastPart);
|
||||
|
||||
workspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
gWorkspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||
.position = glm::vec3(0),
|
||||
.rotation = glm::vec3(0.5, 2, 1),
|
||||
.size = glm::vec3(4, 1.2, 2),
|
||||
|
@ -354,11 +359,11 @@ void MainWindow::closeEvent(QCloseEvent* evt) {
|
|||
if (result == QMessageBox::Cancel) return evt->ignore();
|
||||
if (result == QMessageBox::Save) {
|
||||
std::optional<std::string> path;
|
||||
if (!dataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + dataModel->name));
|
||||
if (!gDataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name));
|
||||
if (!path || path == "") return evt->ignore();
|
||||
|
||||
dataModel->SaveToFile(path);
|
||||
gDataModel->SaveToFile(path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
ExplorerView::ExplorerView(QWidget* parent):
|
||||
QTreeView(parent),
|
||||
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(dataModel))) {
|
||||
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(gDataModel))) {
|
||||
|
||||
this->setModel(&model);
|
||||
// Disabling the root decoration will cause the expand/collapse chevrons to be hidden too, we don't want that
|
||||
|
@ -29,7 +29,7 @@ ExplorerView::ExplorerView(QWidget* parent):
|
|||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
// Expand workspace
|
||||
this->expand(model.ObjectToIndex(workspace()));
|
||||
this->expand(model.ObjectToIndex(gWorkspace()));
|
||||
|
||||
connect(this, &QTreeView::customContextMenuRequested, this, [&](const QPoint& point) {
|
||||
QModelIndex index = this->indexAt(point);
|
||||
|
|
Loading…
Add table
Reference in a new issue