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),
|
||||
.color = glm::vec3(0.388235, 0.372549, 0.384314),
|
||||
.anchored = true,
|
||||
.locked = true,
|
||||
}));
|
||||
|
||||
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)),
|
||||
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 {
|
||||
.super = std::move(this->memberMap),
|
||||
.members = {
|
||||
|
@ -71,6 +71,10 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par
|
|||
.type = &Data::Bool::TYPE,
|
||||
.codec = fieldCodecOf<Data::Bool, bool>(),
|
||||
.updateCallback = memberFunctionOf(&Part::onUpdated, this)
|
||||
}}, { "Locked", {
|
||||
.backingField = &locked,
|
||||
.type = &Data::Bool::TYPE,
|
||||
.codec = fieldCodecOf<Data::Bool, bool>(),
|
||||
}}, { "Position", {
|
||||
.backingField = &cframe,
|
||||
.type = &Vector3::TYPE,
|
||||
|
|
|
@ -20,6 +20,7 @@ struct PartConstructParams {
|
|||
Data::Color3 color;
|
||||
|
||||
bool anchored = false;
|
||||
bool locked = false;
|
||||
};
|
||||
|
||||
class Part : public Instance {
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
bool selected = false;
|
||||
|
||||
bool anchored = false;
|
||||
bool locked = false;
|
||||
rp::RigidBody* rigidBody = nullptr;
|
||||
|
||||
SurfaceType topSurface = SurfaceType::SurfaceStuds;
|
||||
|
|
|
@ -282,7 +282,7 @@ void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
|
|||
};
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
|||
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
||||
if (!rayHit || !partFromBody(rayHit->body)) return;
|
||||
std::shared_ptr<Part> part = partFromBody(rayHit->body);
|
||||
if (part->name == "Baseplate") return;
|
||||
if (part->locked) return;
|
||||
|
||||
// Handle surface tool
|
||||
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
|
||||
|
|
|
@ -72,6 +72,99 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
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
|
||||
|
||||
ui->explorerView->buildContextMenu();
|
||||
|
@ -166,6 +259,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
.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);
|
||||
|
@ -309,94 +403,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
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() {
|
||||
|
|
|
@ -54,6 +54,8 @@ private:
|
|||
void timerEvent(QTimerEvent*) override;
|
||||
void closeEvent(QCloseEvent* evt) override;
|
||||
void handleLog(Logger::LogLevel, std::string);
|
||||
|
||||
void connectActionHandlers();
|
||||
|
||||
std::optional<std::string> openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title = "");
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue