feat(part): added locked property to prevent objects from being selected
This commit is contained in:
parent
07272dbe95
commit
ee05b8d9d5
6 changed files with 106 additions and 91 deletions
|
@ -42,6 +42,7 @@ int main() {
|
||||||
.size = glm::vec3(512, 1.2, 512),
|
.size = glm::vec3(512, 1.2, 512),
|
||||||
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
||||||
.anchored = true,
|
.anchored = true,
|
||||||
|
.locked = true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gWorkspace()->AddChild(lastPart = Part::New({
|
gWorkspace()->AddChild(lastPart = Part::New({
|
||||||
|
|
|
@ -62,7 +62,7 @@ Part::Part(): Part(PartConstructParams { .color = Data::Color3(0.639216f, 0.6352
|
||||||
}
|
}
|
||||||
|
|
||||||
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(params.position, params.rotation)),
|
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(params.position, params.rotation)),
|
||||||
size(params.size), color(params.color), anchored(params.anchored) {
|
size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
|
||||||
this->memberMap = std::make_unique<MemberMap>(MemberMap {
|
this->memberMap = std::make_unique<MemberMap>(MemberMap {
|
||||||
.super = std::move(this->memberMap),
|
.super = std::move(this->memberMap),
|
||||||
.members = {
|
.members = {
|
||||||
|
@ -71,6 +71,10 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par
|
||||||
.type = &Data::Bool::TYPE,
|
.type = &Data::Bool::TYPE,
|
||||||
.codec = fieldCodecOf<Data::Bool, bool>(),
|
.codec = fieldCodecOf<Data::Bool, bool>(),
|
||||||
.updateCallback = memberFunctionOf(&Part::onUpdated, this)
|
.updateCallback = memberFunctionOf(&Part::onUpdated, this)
|
||||||
|
}}, { "Locked", {
|
||||||
|
.backingField = &locked,
|
||||||
|
.type = &Data::Bool::TYPE,
|
||||||
|
.codec = fieldCodecOf<Data::Bool, bool>(),
|
||||||
}}, { "Position", {
|
}}, { "Position", {
|
||||||
.backingField = &cframe,
|
.backingField = &cframe,
|
||||||
.type = &Vector3::TYPE,
|
.type = &Vector3::TYPE,
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct PartConstructParams {
|
||||||
Data::Color3 color;
|
Data::Color3 color;
|
||||||
|
|
||||||
bool anchored = false;
|
bool anchored = false;
|
||||||
|
bool locked = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Part : public Instance {
|
class Part : public Instance {
|
||||||
|
@ -36,6 +37,7 @@ public:
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
|
|
||||||
bool anchored = false;
|
bool anchored = false;
|
||||||
|
bool locked = false;
|
||||||
rp::RigidBody* rigidBody = nullptr;
|
rp::RigidBody* rigidBody = nullptr;
|
||||||
|
|
||||||
SurfaceType topSurface = SurfaceType::SurfaceStuds;
|
SurfaceType topSurface = SurfaceType::SurfaceStuds;
|
||||||
|
|
|
@ -282,7 +282,7 @@ void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
||||||
if (rayHit && partFromBody(rayHit->body)->name != "Baseplate") {
|
if (rayHit && !partFromBody(rayHit->body)->locked) {
|
||||||
setCursor(Qt::OpenHandCursor);
|
setCursor(Qt::OpenHandCursor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
||||||
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
||||||
if (!rayHit || !partFromBody(rayHit->body)) return;
|
if (!rayHit || !partFromBody(rayHit->body)) return;
|
||||||
std::shared_ptr<Part> part = partFromBody(rayHit->body);
|
std::shared_ptr<Part> part = partFromBody(rayHit->body);
|
||||||
if (part->name == "Baseplate") return;
|
if (part->locked) return;
|
||||||
|
|
||||||
// Handle surface tool
|
// Handle surface tool
|
||||||
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
|
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
|
||||||
|
|
|
@ -72,6 +72,99 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
delete menu;
|
delete menu;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connectActionHandlers();
|
||||||
|
|
||||||
|
// Update handles
|
||||||
|
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
||||||
|
editorToolHandles->adornee = std::nullopt;
|
||||||
|
if (newSelection.size() == 0) return;
|
||||||
|
InstanceRef inst = newSelection[0].lock();
|
||||||
|
if (inst->GetClass() != &Part::TYPE) return;
|
||||||
|
|
||||||
|
editorToolHandles->adornee = std::dynamic_pointer_cast<Part>(inst);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update properties
|
||||||
|
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
||||||
|
if (newSelection.size() == 0) return;
|
||||||
|
if (newSelection.size() > 1)
|
||||||
|
ui->propertiesView->setSelected(std::nullopt);
|
||||||
|
ui->propertiesView->setSelected(newSelection[0].lock());
|
||||||
|
});
|
||||||
|
|
||||||
|
// ui->explorerView->Init(ui);
|
||||||
|
|
||||||
|
// Baseplate
|
||||||
|
gWorkspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
||||||
|
.position = glm::vec3(0, -5, 0),
|
||||||
|
.rotation = glm::vec3(0),
|
||||||
|
.size = glm::vec3(512, 1.2, 512),
|
||||||
|
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
||||||
|
.anchored = true,
|
||||||
|
.locked = true,
|
||||||
|
}));
|
||||||
|
ui->mainWidget->lastPart->name = "Baseplate";
|
||||||
|
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
||||||
|
|
||||||
|
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),
|
||||||
|
.color = glm::vec3(0.639216f, 0.635294f, 0.647059f),
|
||||||
|
}));
|
||||||
|
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent* evt) {
|
||||||
|
#ifdef NDEBUG
|
||||||
|
// Ask if the user wants to save their changes
|
||||||
|
// https://stackoverflow.com/a/33890731
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("Save changes before creating new document?");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Save);
|
||||||
|
int result = msgBox.exec();
|
||||||
|
|
||||||
|
if (result == QMessageBox::Cancel) return evt->ignore();
|
||||||
|
if (result == QMessageBox::Save) {
|
||||||
|
std::optional<std::string> path;
|
||||||
|
if (!gDataModel->HasFile())
|
||||||
|
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name));
|
||||||
|
if (!path || path == "") return evt->ignore();
|
||||||
|
|
||||||
|
gDataModel->SaveToFile(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::handleLog(Logger::LogLevel logLevel, std::string message) {
|
||||||
|
if (logLevel == Logger::LogLevel::DEBUG) return;
|
||||||
|
|
||||||
|
if (logLevel == Logger::LogLevel::INFO)
|
||||||
|
ui->outputTextView->appendHtml(QString("<p>%1</p>").arg(QString::fromStdString(message)));
|
||||||
|
if (logLevel == Logger::LogLevel::WARNING)
|
||||||
|
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 127, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
||||||
|
if (logLevel == Logger::LogLevel::ERROR || logLevel == Logger::LogLevel::FATAL_ERROR)
|
||||||
|
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 0, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
|
||||||
|
void MainWindow::timerEvent(QTimerEvent* evt) {
|
||||||
|
if (evt->timerId() != timer.timerId()) {
|
||||||
|
QWidget::timerEvent(evt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastTime).count();
|
||||||
|
lastTime = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
if (simulationPlaying)
|
||||||
|
gWorkspace()->PhysicsStep(deltaTime);
|
||||||
|
ui->mainWidget->update();
|
||||||
|
ui->mainWidget->updateCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::connectActionHandlers() {
|
||||||
// Explorer View
|
// Explorer View
|
||||||
|
|
||||||
ui->explorerView->buildContextMenu();
|
ui->explorerView->buildContextMenu();
|
||||||
|
@ -166,6 +259,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
.size = glm::vec3(512, 1.2, 512),
|
.size = glm::vec3(512, 1.2, 512),
|
||||||
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
||||||
.anchored = true,
|
.anchored = true,
|
||||||
|
.locked = true,
|
||||||
}));
|
}));
|
||||||
ui->mainWidget->lastPart->name = "Baseplate";
|
ui->mainWidget->lastPart->name = "Baseplate";
|
||||||
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
||||||
|
@ -309,94 +403,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
selectedParent->AddChild(inst.expect());
|
selectedParent->AddChild(inst.expect());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update handles
|
|
||||||
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
|
||||||
editorToolHandles->adornee = std::nullopt;
|
|
||||||
if (newSelection.size() == 0) return;
|
|
||||||
InstanceRef inst = newSelection[0].lock();
|
|
||||||
if (inst->GetClass() != &Part::TYPE) return;
|
|
||||||
|
|
||||||
editorToolHandles->adornee = std::dynamic_pointer_cast<Part>(inst);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update properties
|
|
||||||
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
|
||||||
if (newSelection.size() == 0) return;
|
|
||||||
if (newSelection.size() > 1)
|
|
||||||
ui->propertiesView->setSelected(std::nullopt);
|
|
||||||
ui->propertiesView->setSelected(newSelection[0].lock());
|
|
||||||
});
|
|
||||||
|
|
||||||
// ui->explorerView->Init(ui);
|
|
||||||
|
|
||||||
// Baseplate
|
|
||||||
gWorkspace()->AddChild(ui->mainWidget->lastPart = Part::New({
|
|
||||||
.position = glm::vec3(0, -5, 0),
|
|
||||||
.rotation = glm::vec3(0),
|
|
||||||
.size = glm::vec3(512, 1.2, 512),
|
|
||||||
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
|
||||||
.anchored = true,
|
|
||||||
}));
|
|
||||||
ui->mainWidget->lastPart->name = "Baseplate";
|
|
||||||
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
|
||||||
|
|
||||||
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),
|
|
||||||
.color = glm::vec3(0.639216f, 0.635294f, 0.647059f),
|
|
||||||
}));
|
|
||||||
gWorkspace()->SyncPartPhysics(ui->mainWidget->lastPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent* evt) {
|
|
||||||
#ifdef NDEBUG
|
|
||||||
// Ask if the user wants to save their changes
|
|
||||||
// https://stackoverflow.com/a/33890731
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setText("Save changes before creating new document?");
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::Save);
|
|
||||||
int result = msgBox.exec();
|
|
||||||
|
|
||||||
if (result == QMessageBox::Cancel) return evt->ignore();
|
|
||||||
if (result == QMessageBox::Save) {
|
|
||||||
std::optional<std::string> path;
|
|
||||||
if (!gDataModel->HasFile())
|
|
||||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + gDataModel->name));
|
|
||||||
if (!path || path == "") return evt->ignore();
|
|
||||||
|
|
||||||
gDataModel->SaveToFile(path);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::handleLog(Logger::LogLevel logLevel, std::string message) {
|
|
||||||
if (logLevel == Logger::LogLevel::DEBUG) return;
|
|
||||||
|
|
||||||
if (logLevel == Logger::LogLevel::INFO)
|
|
||||||
ui->outputTextView->appendHtml(QString("<p>%1</p>").arg(QString::fromStdString(message)));
|
|
||||||
if (logLevel == Logger::LogLevel::WARNING)
|
|
||||||
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 127, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
|
||||||
if (logLevel == Logger::LogLevel::ERROR || logLevel == Logger::LogLevel::FATAL_ERROR)
|
|
||||||
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 0, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
|
|
||||||
void MainWindow::timerEvent(QTimerEvent* evt) {
|
|
||||||
if (evt->timerId() != timer.timerId()) {
|
|
||||||
QWidget::timerEvent(evt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastTime).count();
|
|
||||||
lastTime = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
if (simulationPlaying)
|
|
||||||
gWorkspace()->PhysicsStep(deltaTime);
|
|
||||||
ui->mainWidget->update();
|
|
||||||
ui->mainWidget->updateCycle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateToolbars() {
|
void MainWindow::updateToolbars() {
|
||||||
|
|
|
@ -54,6 +54,8 @@ private:
|
||||||
void timerEvent(QTimerEvent*) override;
|
void timerEvent(QTimerEvent*) override;
|
||||||
void closeEvent(QCloseEvent* evt) override;
|
void closeEvent(QCloseEvent* evt) override;
|
||||||
void handleLog(Logger::LogLevel, std::string);
|
void handleLog(Logger::LogLevel, std::string);
|
||||||
|
|
||||||
|
void connectActionHandlers();
|
||||||
|
|
||||||
std::optional<std::string> openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title = "");
|
std::optional<std::string> openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title = "");
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue