//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #include "BsScriptDragDropManager.h" #include "BsMonoManager.h" #include "BsMonoClass.h" #include "BsMonoMethod.h" #include "BsMonoUtil.h" #include "Wrappers/BsScriptSceneObject.h" #include "BsScriptGameObjectManager.h" #include "GUI/BsGUISceneTreeView.h" #include "GUI/BsGUIResourceTreeView.h" #include "Utility/BsTime.h" using namespace std::placeholders; namespace bs { ScriptDragDrop::ScriptDragDrop(MonoObject* instance) :ScriptObject(instance) { } void ScriptDragDrop::initRuntimeData() { metaData.scriptClass->addInternalCall("Internal_IsDragInProgress", (void*)&ScriptDragDrop::internal_IsDragInProgress); metaData.scriptClass->addInternalCall("Internal_IsDropInProgress", (void*)&ScriptDragDrop::internal_IsDropInProgress); metaData.scriptClass->addInternalCall("Internal_GetData", (void*)&ScriptDragDrop::internal_GetData); metaData.scriptClass->addInternalCall("Internal_GetDragType", (void*)&ScriptDragDrop::internal_GetDragType); metaData.scriptClass->addInternalCall("Internal_StartSceneObjectDrag", (void*)&ScriptDragDrop::internal_StartSceneObjectDrag); metaData.scriptClass->addInternalCall("Internal_StartResourceDrag", (void*)&ScriptDragDrop::internal_StartResourceDrag); } bool ScriptDragDrop::internal_IsDragInProgress() { return DragAndDropManager::instance().isDragInProgress(); } bool ScriptDragDrop::internal_IsDropInProgress() { return ScriptDragDropManager::instance().isDropInProgress(); } MonoObject* ScriptDragDrop::internal_GetData() { return ScriptDragDropManager::instance().getDropData(); } ScriptDragDropType ScriptDragDrop::internal_GetDragType() { return ScriptDragDropManager::instance().getDragType(); } void ScriptDragDrop::internal_StartSceneObjectDrag(ScriptSceneObjectDragDropData* value) { const Vector& sceneObjects = value->getSceneObjects(); DraggedSceneObjects* draggedSceneObjects = bs_new((UINT32)sceneObjects.size()); UINT32 idx = 0; for (auto& so : sceneObjects) { draggedSceneObjects->objects[idx] = so; idx++; } DragAndDropManager::instance().startDrag((UINT32)DragAndDropType::SceneObject, draggedSceneObjects, &ScriptDragDrop::sceneObjectDragDropFinalize, false); } void ScriptDragDrop::internal_StartResourceDrag(ScriptResourceDragDropData* value) { DraggedResources* draggedResources = bs_new(); draggedResources->resourcePaths = value->getPaths(); DragAndDropManager::instance().startDrag((UINT32)DragAndDropType::Resources, draggedResources, &ScriptDragDrop::resourceDragDropFinalize, false); } void ScriptDragDrop::sceneObjectDragDropFinalize(bool processed) { DraggedSceneObjects* draggedSceneObjects = reinterpret_cast(DragAndDropManager::instance().getDragData()); bs_delete(draggedSceneObjects); } void ScriptDragDrop::resourceDragDropFinalize(bool processed) { DraggedResources* draggedResources = reinterpret_cast(DragAndDropManager::instance().getDragData()); bs_delete(draggedResources); } ScriptSceneObjectDragDropData::ScriptSceneObjectDragDropData(MonoObject* instance, const Vector& sceneObjects) :ScriptObject(instance), mSceneObjects(sceneObjects) { } void ScriptSceneObjectDragDropData::initRuntimeData() { metaData.scriptClass->addInternalCall("Internal_CreateInstance", (void*)&ScriptSceneObjectDragDropData::internal_CreateInstance); metaData.scriptClass->addInternalCall("Internal_GetObjects", (void*)&ScriptSceneObjectDragDropData::internal_GetObjects); } MonoObject* ScriptSceneObjectDragDropData::create(const Vector& sceneObjects) { ScriptArray arrSceneObjects = ScriptArray::create((UINT32)sceneObjects.size()); UINT32 idx = 0; for (auto& so : sceneObjects) { ScriptSceneObject* scriptSceneObject = ScriptGameObjectManager::instance().getOrCreateScriptSceneObject(so); arrSceneObjects.set(idx, scriptSceneObject->getManagedInstance()); idx++; } void* params[1] = { arrSceneObjects.getInternal() }; MonoObject* instance = metaData.scriptClass->createInstance(params, 1); return instance; } void ScriptSceneObjectDragDropData::internal_CreateInstance(MonoObject* managedInstance, MonoArray* objects) { ScriptArray objectsArray = ScriptArray(objects); Vector sceneObjects(objectsArray.size()); for (UINT32 i = 0; i < objectsArray.size(); i++) { ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(objectsArray.get(i)); if (scriptSO != nullptr) sceneObjects[i] = scriptSO->getHandle(); } new (bs_alloc()) ScriptSceneObjectDragDropData(managedInstance, sceneObjects); } MonoArray* ScriptSceneObjectDragDropData::internal_GetObjects(ScriptSceneObjectDragDropData* instance) { ScriptArray objectsArray = ScriptArray::create((UINT32)instance->mSceneObjects.size()); for (UINT32 i = 0; i < (UINT32)instance->mSceneObjects.size(); i++) { ScriptSceneObject* scriptSO = ScriptGameObjectManager::instance().getOrCreateScriptSceneObject(instance->mSceneObjects[i]); if (scriptSO != nullptr) objectsArray.set(i, scriptSO->getManagedInstance()); } return objectsArray.getInternal(); } ScriptResourceDragDropData::ScriptResourceDragDropData(MonoObject* instance, const Vector& paths) :ScriptObject(instance), mPaths(paths) { } void ScriptResourceDragDropData::initRuntimeData() { metaData.scriptClass->addInternalCall("Internal_CreateInstance", (void*)&ScriptResourceDragDropData::internal_CreateInstance); metaData.scriptClass->addInternalCall("Internal_GetPaths", (void*)&ScriptResourceDragDropData::internal_GetPaths); } MonoObject* ScriptResourceDragDropData::create(const Vector& paths) { ScriptArray arrStrings(MonoUtil::getStringClass(), (UINT32)paths.size()); UINT32 idx = 0; for (auto& path : paths) { MonoString* managedPath = MonoUtil::stringToMono(path.toString()); arrStrings.set(idx, managedPath); idx++; } void* params[1] = { arrStrings.getInternal() }; MonoObject* instance = metaData.scriptClass->createInstance(params, 1); return instance; } void ScriptResourceDragDropData::internal_CreateInstance(MonoObject* managedInstance, MonoArray* monoPaths) { ScriptArray pathsArray = ScriptArray(monoPaths); Vector paths(pathsArray.size()); for (UINT32 i = 0; i < pathsArray.size(); i++) { MonoString* monoPath = pathsArray.get(i); paths[i] = MonoUtil::monoToString(monoPath); } new (bs_alloc()) ScriptResourceDragDropData(managedInstance, paths); } MonoArray* ScriptResourceDragDropData::internal_GetPaths(ScriptResourceDragDropData* instance) { ScriptArray arrStrings(MonoUtil::getStringClass(), (UINT32)instance->mPaths.size()); UINT32 idx = 0; for (auto& path : instance->mPaths) { MonoString* managedPath = MonoUtil::stringToMono(path.toString()); arrStrings.set(idx, managedPath); idx++; } return arrStrings.getInternal(); } ScriptDragDropManager::ScriptDragDropManager() :mIsDropInProgress(false), mDroppedFrameIdx(0), mDropType(ScriptDragDropType::None) { mDragEndedConn = DragAndDropManager::instance().onDragEnded.connect(std::bind(&ScriptDragDropManager::onMouseDragEnded, this, _1, _2)); } ScriptDragDropManager::~ScriptDragDropManager() { mDragEndedConn.disconnect(); } void ScriptDragDropManager::update() { // This only stays active for a single frame if (mIsDropInProgress && mDroppedFrameIdx < Time::instance().getFrameIdx()) mIsDropInProgress = false; } MonoObject* ScriptDragDropManager::getDropData() const { if (DragAndDropManager::instance().isDragInProgress()) { UINT32 nativeType = DragAndDropManager::instance().getDragTypeId(); if (nativeType == (UINT32)DragAndDropType::SceneObject) { DraggedSceneObjects* draggedData = reinterpret_cast(DragAndDropManager::instance().getDragData()); Vector draggedSceneObjects; for (UINT32 i = 0; i < draggedData->numObjects; i++) draggedSceneObjects.push_back(draggedData->objects[i]); return ScriptSceneObjectDragDropData::create(draggedSceneObjects); } else if (nativeType == (UINT32)DragAndDropType::Resources) { DraggedResources* draggedResources = reinterpret_cast(DragAndDropManager::instance().getDragData()); return ScriptResourceDragDropData::create(draggedResources->resourcePaths); } } else { if (mDropType == ScriptDragDropType::SceneObject) return ScriptSceneObjectDragDropData::create(mDroppedSceneObjects); else if (mDropType == ScriptDragDropType::Resource) return ScriptResourceDragDropData::create(mDroppedPaths); } return nullptr; } ScriptDragDropType ScriptDragDropManager::getDragType() const { if (DragAndDropManager::instance().isDragInProgress()) { UINT32 nativeType = DragAndDropManager::instance().getDragTypeId(); if (nativeType == (UINT32)DragAndDropType::SceneObject) return ScriptDragDropType::SceneObject; else if (nativeType == (UINT32)DragAndDropType::Resources) return ScriptDragDropType::Resource; return ScriptDragDropType::None; } else return mDropType; } void ScriptDragDropManager::onMouseDragEnded(const PointerEvent& evt, DragCallbackInfo& callbackInfo) { if (!DragAndDropManager::instance().isDragInProgress()) return; mDroppedPaths.clear(); mDroppedSceneObjects.clear(); mIsDropInProgress = false; mDropType = ScriptDragDropType::None; UINT32 nativeType = DragAndDropManager::instance().getDragTypeId(); if (nativeType == (UINT32)DragAndDropType::SceneObject) { DraggedSceneObjects* draggedSceneObjects = reinterpret_cast(DragAndDropManager::instance().getDragData()); for (UINT32 i = 0; i < draggedSceneObjects->numObjects; i++) mDroppedSceneObjects.push_back(draggedSceneObjects->objects[i]); mIsDropInProgress = true; mDropType = ScriptDragDropType::SceneObject; mDroppedFrameIdx = Time::instance().getFrameIdx(); } else if (nativeType == (UINT32)DragAndDropType::Resources) { DraggedResources* draggedResources = reinterpret_cast(DragAndDropManager::instance().getDragData()); mDroppedPaths = draggedResources->resourcePaths; mIsDropInProgress = true; mDropType = ScriptDragDropType::Resource; mDroppedFrameIdx = Time::instance().getFrameIdx(); } } }