Sürükle bırak operasyonu için ImGUI nin bize sağlamış olduğu drag drop isimli bir araç var. Kendi kodumda bir ağaç yapısındaki ögelerin birbirine sürüklenip bırakılarak parent-child ilişkisini kurmasını istiyordum.
Kısacası şöyle.
void SceneManager::drawHierarchyTreeRecursive(Entity* entity) {
// ...
// --- BURASI: DRAG SOURCE (Sürüklemeyi Başlat) ---
if (ImGui::BeginDragDropSource()) {
// Sürüklenen nesnenin pointer'ını paketle (Payload)
ImGui::SetDragDropPayload("ENTITY_HIERARCHY_NODE", &entity, sizeof(Entity*));
// Sürüklerken farenin yanında ne görünsün?
ImGui::Text("Moving: %s", entity->name.c_str());
ImGui::EndDragDropSource();
}
// Drag drop aynı alana yapıldığı için başlama ve bitirme kodlarını da aynı yere yazıyoruz.
// --- BURASI: DRAG TARGET (Üzerine Bırakmayı Kabul Et) ---
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_HIERARCHY_NODE")) {
// Paketi aç (Sürüklenen Entity'yi al)
Entity* draggedEntity = *(Entity**)payload->Data;
// Kendi kendine veya zaten parent'ı olan birine bırakılmadığından emin ol
if (draggedEntity != entity) {
draggedEntity->transform->setParent(entity->transform.get());
}
}
ImGui::EndDragDropTarget();
}
// ...
}C++
Başka bir öğenin üzerine bırakmak yerine boş alana bırakmak istersek şöyle bir kod ekleyebiliriz
ImGui::Dummy(ImGui::GetContentRegionAvail()); // Boş bir alan yarat
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_HIERARCHY_NODE")) {
Entity* draggedEntity = *(Entity**)payload->Data;
draggedEntity->transform->setParent(nullptr); // Bağımsız yap
}
ImGui::EndDragDropTarget();
}C++Kodun tamamı şöyle.
std::vector<std::unique_ptr<Entity>> _entities{};
/// Call recursively to populate each level of children
void SceneManager::drawHierarchyTreeRecursive(Entity* entity) {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth;
if (isSelected(entity)) flags |= ImGuiTreeNodeFlags_Selected;
if (entity->transform->getChildren().empty()) flags |= ImGuiTreeNodeFlags_Leaf;
bool opened = false;
if (isLastSelected(entity)) {
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(230, 125, 15, 255)); // orange foreground
opened = ImGui::TreeNodeEx(entity->name.c_str(), flags);
ImGui::PopStyleColor(1);
}
else {
opened = ImGui::TreeNodeEx(entity->name.c_str(), flags);
}
// Seçme işlemi
if (ImGui::IsItemClicked()){
if (!ImGui::GetIO().KeyCtrl)
deselectAll();
select(entity);
}
// --- BURASI: DRAG SOURCE (Sürüklemeyi Başlat) ---
if (ImGui::BeginDragDropSource()) {
// Sürüklenen nesnenin pointer'ını paketle (Payload)
ImGui::SetDragDropPayload("ENTITY_HIERARCHY_NODE", &entity, sizeof(Entity*));
// Sürüklerken farenin yanında ne görünsün?
ImGui::Text("Moving: %s", entity->name.c_str());
ImGui::EndDragDropSource();
}
// --- BURASI: DRAG TARGET (Üzerine Bırakmayı Kabul Et) ---
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_HIERARCHY_NODE")) {
// Paketi aç (Sürüklenen Entity'yi al)
Entity* draggedEntity = *(Entity**)payload->Data;
// Kendi kendine veya zaten parent'ı olan birine bırakılmadığından emin ol
if (draggedEntity != entity) {
draggedEntity->transform->setParent(entity->transform.get());
}
}
ImGui::EndDragDropTarget();
}
// Recursive çağrı
if (opened) {
for (Transform* transform : entity->transform->getChildren())
drawHierarchyTreeRecursive(transform->owner);
ImGui::TreePop();
}
}
void SceneManager::onInspect()
{
// HIERARCHY PANEL
ImGuiTreeNodeFlags rootFlag =
ImGuiTreeNodeFlags_DefaultOpen |
ImGuiTreeNodeFlags_Bullet |
ImGuiTreeNodeFlags_Leaf;
ImGui::Begin("Scene");
if (ImGui::IsItemClicked())
LOG_TRACE("Scene window tab was clicked");
if (ImGui::TreeNodeEx("root", rootFlag)){
if (ImGui::IsItemClicked())
LOG_TRACE("Scene root was clicked");
ImGui::PushStyleColor(ImGuiCol_Header, IM_COL32(55, 55, 55, 255)); // gray background
for (const auto& i : _entities)
if(i->transform->isRoot())
drawHierarchyTreeRecursive(i.get()); // Call recursively to populate each level of children
ImGui::PopStyleColor(1);
ImGui::TreePop(); // This is required at the end of the if block
}
// drawHierarchy Tree döngüsünün dışına, Begin/End arasına:
ImGui::Dummy(ImGui::GetContentRegionAvail()); // Boş bir alan yarat
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY_HIERARCHY_NODE")) {
Entity* draggedEntity = *(Entity**)payload->Data;
draggedEntity->transform->setParent(nullptr); // Bağımsız yap
}
ImGui::EndDragDropTarget();
}
// bos alana tiklamayi yakala:
if (ImGui::IsWindowFocused() &&
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
!ImGui::IsAnyItemHovered()
)
{
deselectAll();
}
ImGui::End();
// ...
}C++
Leave a Reply