DYTSrouce/src/ui/ModelBrowser/ModelTreeWidget.cpp
2025-11-04 00:23:24 +08:00

427 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ui/ModelBrowser/ModelTreeWidget.h"
#include <QResizeEvent>
#include <QUuid>
#include <QVariant>
#include <QMenu>
#include <osgEarthUtil/EarthManipulator>
#include "common/RecourceHelper.h"
#include "common/SpdLogger.h"
#include "entities/EntitiesManager.h"
#include "entities/ComponentFactory.h"
#include "viewer/OsgViewer.h"
#include "viewer/OsgView.h"
#include "viewer/OsgCameraManipulator.h"
#include "viewer/CameraControlManipulator.h"
#include "ui/ModelBrowser/EntityConstent.h"
#include "workspace/WorkSpaceManager.h"
ModelTreeWidget::ModelTreeWidget(QWidget* parent)
: QTreeWidget(parent){
setColumnCount(1);
connect(this, &QTreeWidget::itemClicked, this, &ModelTreeWidget::OnWorkItemCliecked);
connect(this, &QTreeWidget::itemDoubleClicked, this, &ModelTreeWidget::OnItemDoubleClicked);
}
ModelTreeWidget::~ModelTreeWidget() {
}
void ModelTreeWidget::OnWorkspaceChange(WorkSpace* workSpace) {
LOG_INFO("WorkSpace change");
clear();
currentWorkSpace_ = workSpace;
if (nullptr == currentWorkSpace_) {
LOG_WARN("workspace is nullptr");
return;
}
connect(workSpace, &WorkSpace::EntityAdded, this, &ModelTreeWidget::OnEntityAdded);
connect(workSpace, &WorkSpace::EntityRemoved, this, &ModelTreeWidget::OnEntityRemoved);
connect(workSpace, &WorkSpace::FilesChanged, this, &ModelTreeWidget::OnWorkspaceFilesChanged);
const QString& name = currentWorkSpace_->GetName();
root_ = new QTreeWidgetItem(this);
root_->setText(0, name);
QVariant root;
root.setValue(currentWorkSpace_);
root_->setData(0, E_Workspace, root);
root_->setData(0, E_UUid, currentWorkSpace_->GetUUid());
addTopLevelItem(root_);
const std::vector<Entity*>& entities = currentWorkSpace_->GetEntities();
for (const auto& entity : entities) {
AddEntity(root_, entity);
}
// Create and populate curve entries branch
curvesRoot_ = new QTreeWidgetItem(root_);
curvesRoot_->setText(0, tr("Curves"));
curvesRoot_->setData(0, E_UUid, QString("CurvesRoot"));
PopulateCurveEntries();
}
void ModelTreeWidget::OnEntityAdded(Entity* entity) {
if (nullptr == entity) {
LOG_WARN("entity is nullptr");
return;
}
const QString& entityName = entity->GetName();
QTreeWidgetItem* item = new QTreeWidgetItem;
connect(entity, &Entity::NameChanged, [item](const QString& name) {
LOG_WARN("entity name changed: {}", name.toStdString());
item->setText(0, name);
}
);
item->setText(0, entityName);
QVariant root;
root.setValue(entity);
item->setData(0, E_Entity, root);
item->setData(0, E_UUid, entity->GetUUid());
root_->addChild(item);
}
void ModelTreeWidget::OnEntityRemoved(Entity* entity) {
if (nullptr == entity) {
LOG_WARN("entity is nullptr");
return;
}
const QString& uuid = entity->GetUUid();
FindAndRemoveItem(uuid);
}
void ModelTreeWidget::contextMenuEvent(QContextMenuEvent* event) {
QTreeWidgetItem* item = itemAt(event->pos());
if (nullptr != item) {
QVariant value = item->data(0, E_Entity);
if (!value.isValid()) {
LOG_WARN("unknown data E_Entity");
return;
}
Entity* entity = value.value<Entity*>();
PopupEntityMenu(event, entity);
} else {
return;
QMenu menu(this);
QAction* addEntiy = new QAction(tr("Add boke Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("boke/boke.ive", "boke");
}
);
menu.addAction(addEntiy);
addEntiy = new QAction(tr("Add lsjhqt Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("lsjhqt/lsjhqt.flt", "lsjhqt");
}
);
menu.addAction(addEntiy);
addEntiy = new QAction(tr("Add nimizi Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("nimizi/nimizi.ive", "nimizi");
}
);
menu.addAction(addEntiy);
addEntiy = new QAction(tr("Add tkdlj Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("tkdlj/tkdlj.ive", "tkdlj");
}
);
menu.addAction(addEntiy);
addEntiy = new QAction(tr("Add jiaofan Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("jf/decorative-shape-008.obj", "jiaofan");
}
);
menu.addAction(addEntiy);
addEntiy = new QAction(tr("Add satellite Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() {
OnAddSatelliteEntity();
}
);
menu.addAction(addEntiy);
// <20><>ʾ<EFBFBD>˵<EFBFBD>
menu.exec(event->globalPos());
}
}
void ModelTreeWidget::OnWorkItemChanged(WorkSpaceItem* item) {
LOG_INFO("WorkItemChanged");
if (nullptr == item) {
LOG_WARN("item is nullptr");
return;
}
}
void ModelTreeWidget::OnWorkItemCliecked(QTreeWidgetItem* item, int column) {
// Prefer entity, then file entry, then workspace
QVariant value = item->data(column, E_Entity);
if (value.isValid()) { emit EntityChange(value); return; }
value = item->data(column, E_FileEntry);
if (value.isValid()) { emit FileEntryChange(value); return; }
value = item->data(column, E_Workspace);
if (value.isValid()) { emit WorkSpaceChange(value); return; }
LOG_WARN("unknown data rol");
}
void ModelTreeWidget::OnItemDoubleClicked(QTreeWidgetItem* item, int column) {
QVariant value = item->data(column, E_Entity);
bool isEntity = true;
if (!value.isValid()) {
LOG_WARN("unknown data E_Entity");
return;
}
Entity* entity = value.value<Entity*>();
if (nullptr == entity) {
LOG_WARN("entity is nullptr");
return;
}
OnTrackEntity(entity);
}
void ModelTreeWidget::OnAddMeshEntity(const QString& mesh, const QString& name) {
if (nullptr == currentWorkSpace_) {
LOG_WARN("currentWorkSpace_ is nullptr");
return;
}
Entity* entity = EntitiesManager::Get().CreateMesh(mesh);
int count = currentWorkSpace_->GetEntities().size();
entity->SetName(QString("%1_%2").arg(name).arg(count));
currentWorkSpace_->AddEntity(entity);
OnAddComponent("LabelComponent", entity);
}
SceneComponent* ModelTreeWidget::OnAddComponent(const QString& typeName, Entity* entity) {
LOG_INFO("enter, typename:{}", typeName.toStdString().c_str());
if (nullptr == entity) {
LOG_WARN("entity is nullptr");
return nullptr;
}
SceneComponent* rootComponent = entity->GetRootComponent();
SceneComponent* conponent = ComponentFactory::Create(typeName, rootComponent);
conponent->AttachTo(rootComponent);
//conponent->AttachEntity(entity);
QVariant value;
value.setValue(entity);
emit EntityChange(value);
return conponent;
}
void ModelTreeWidget::OnDeleteEntity(Entity* entity) {
LOG_INFO("enter");
if (nullptr == entity) {
LOG_WARN("entity is nullptr");
return;
}
entity->Destory();
}
void ModelTreeWidget::PopupEntityMenu(QContextMenuEvent* event, Entity* entity) {
QMenu menu(this);
if (nullptr != entity) {
auto workspace = entity->GetWorkspace();
if (nullptr == workspace) {
LOG_WARN("workspace is nullptr");
return;
}
if (workspace->GetTrackEntity() == entity) {
QAction* releaseTrack = new QAction(tr("Release Track"), this);
connect(releaseTrack, &QAction::triggered, [this]() {
OnTrackEntity(nullptr);
}
);
menu.addAction(releaseTrack);
}
else {
QAction* addEntiy = new QAction(tr("Track"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnTrackEntity(entity);
}
);
}
}
bool hasLableComponent = entity->HasComponent("LabelComponent");
if (!hasLableComponent) {
QAction* addEntiy = new QAction(tr("Add Label Component"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("LabelComponent", entity);
}
);
}
bool hasMeshComponent = entity->HasComponent("MeshComponent");
if (!hasMeshComponent) {
QAction* addEntiy = new QAction(tr("Add Mesh Component"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("MeshComponent", entity);
}
);
}
bool hasPathComponent = entity->HasComponent("PathComponent");
if (!hasPathComponent) {
QAction* addEntiy = new QAction(tr("Add Path Component"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("PathComponent", entity);
}
);
}
QAction* addEntiy = new QAction(tr("Delete"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnDeleteEntity(entity);
}
);
menu.exec(event->globalPos());
}
void ModelTreeWidget::FindAndRemoveItem(const QString& itemToRemove) {
for (int i = 0; i < topLevelItemCount(); ++i) {
QTreeWidgetItem* topItem = topLevelItem(i);
if (RemoveItemFromParent(topItem, itemToRemove)) {
break;
}
}
}
bool ModelTreeWidget::RemoveItemFromParent(QTreeWidgetItem* parentItem, const QString& itemToRemove) {
for (int i = 0; i < parentItem->childCount(); ++i) {
QTreeWidgetItem* childItem = parentItem->child(i);
const QString uuid = childItem->data(0, E_UUid).toString();
if (uuid == itemToRemove) {
while (childItem->childCount() > 0) {
QTreeWidgetItem* grandChildItem = childItem->child(0);
childItem->removeChild(grandChildItem);
}
parentItem->removeChild(childItem);
return true;
}
if (RemoveItemFromParent(childItem, itemToRemove)) {
return true;
}
}
return false;
}
void ModelTreeWidget::OnAddSatelliteEntity() {
if (nullptr == currentWorkSpace_) {
LOG_WARN("currentWorkSpace_ is nullptr");
return;
}
//const QString mesh("sat/sat.ive");
const QString mesh("satellite/satellite.ive");
Entity* entity = EntitiesManager::Get().CreateMesh(mesh);
int count = currentWorkSpace_->GetEntities().size();
entity->SetName(QString("%1_%2").arg("satellite").arg(count));
OnAddComponent("ConeWaveComponent", entity);
currentWorkSpace_->AddEntity(entity);
}
void ModelTreeWidget::OnTrackEntity(Entity* entity) {
auto workspace = WorkSpaceManager::Get().GetCurrent();
if (!workspace){
LOG_WARN("scene is nullptr");
return;
}
if (nullptr == entity) {
LOG_INFO("clear track entity");
workspace->UntrackEntity();
return;
}
LOG_INFO("track entity: {}", entity->GetName().toStdString());
workspace->TrackEntity(entity);
}
void ModelTreeWidget::AddEntity(class QTreeWidgetItem* parent, Entity* entity) {
const QString& entityName = entity->GetName();
QTreeWidgetItem* item = new QTreeWidgetItem;
connect(entity, &Entity::NameChanged, [item](const QString& name) {
LOG_WARN("entity name changed: {}", name.toStdString());
item->setText(0, name);
}
);
item->setText(0, entityName);
QVariant root;
root.setValue(entity);
item->setData(0, E_Entity, root);
item->setData(0, E_UUid, entity->GetUUid());
parent->addChild(item);
const std::vector<Entity*>& childer = entity->GetChilder();
for (const auto& child : childer) {
AddEntity(item, child);
}
}
void ModelTreeWidget::PopulateCurveEntries() {
if (!currentWorkSpace_ || !curvesRoot_) return;
// Clear existing curve children
while (curvesRoot_->childCount() > 0) {
QTreeWidgetItem* child = curvesRoot_->child(0);
curvesRoot_->removeChild(child);
delete child;
}
const auto entries = currentWorkSpace_->GetFileEntries(FileEntryType::Curve);
for (const auto& entry : entries) {
if (!entry) continue;
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setText(0, entry->GetName());
QVariant v;
v.setValue(entry.get());
item->setData(0, E_FileEntry, v);
item->setData(0, E_UUid, QString("Curve:%1").arg(entry->GetFileName()));
curvesRoot_->addChild(item);
}
}
void ModelTreeWidget::OnWorkspaceFilesChanged(FileEntryType type, std::shared_ptr<FileEntry> /*fileEntry*/) {
if (type == FileEntryType::Curve) {
PopulateCurveEntries();
}
}