gltf_viewer: add support for drag-and-drop.
You can now drop gltf or glb files into the app. Note that we will soon be migrating from SDL to GLFW, which also has support for drag-and-drop.
This commit is contained in:
@@ -68,6 +68,13 @@ public:
|
||||
*/
|
||||
void setAsset(FilamentAsset* asset, utils::NameComponentManager* names);
|
||||
|
||||
/**
|
||||
* Removes the current asset from the viewer.
|
||||
*
|
||||
* This removes all the asset entities from the Scene, but does not destroy them.
|
||||
*/
|
||||
void removeAsset();
|
||||
|
||||
/**
|
||||
* Sets or changes the current scene's IBL to allow the UI manipulate it.
|
||||
* NOTE: this could be removed if we add a getter method to Scene.
|
||||
@@ -179,13 +186,7 @@ SimpleViewer::~SimpleViewer() {
|
||||
|
||||
void SimpleViewer::setAsset(FilamentAsset* asset, utils::NameComponentManager* names) {
|
||||
using namespace filament::math;
|
||||
if (mAsset) {
|
||||
const auto begin = mAsset->getEntities();
|
||||
const auto end = begin + mAsset->getEntityCount();
|
||||
for (auto entity = begin; entity != end; ++entity) {
|
||||
mScene->remove(*entity);
|
||||
}
|
||||
}
|
||||
removeAsset();
|
||||
mAsset = asset;
|
||||
mAnimator = asset->getAnimator();
|
||||
mNames = names;
|
||||
@@ -196,6 +197,19 @@ void SimpleViewer::setAsset(FilamentAsset* asset, utils::NameComponentManager* n
|
||||
mScene->addEntities(mAsset->getEntities(), mAsset->getEntityCount());
|
||||
}
|
||||
|
||||
void SimpleViewer::removeAsset() {
|
||||
if (mAsset) {
|
||||
const auto begin = mAsset->getEntities();
|
||||
const auto end = begin + mAsset->getEntityCount();
|
||||
for (auto entity = begin; entity != end; ++entity) {
|
||||
mScene->remove(*entity);
|
||||
}
|
||||
}
|
||||
mAsset = nullptr;
|
||||
mAnimator = nullptr;
|
||||
mNames = nullptr;
|
||||
}
|
||||
|
||||
void SimpleViewer::setIndirectLight(filament::IndirectLight* ibl) {
|
||||
using namespace filament::math;
|
||||
mIndirectLight = ibl;
|
||||
|
||||
@@ -194,6 +194,8 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
|
||||
int sidebarWidth = mSidebarWidth;
|
||||
|
||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||
|
||||
while (!mClosed) {
|
||||
|
||||
if (mSidebarWidth != sidebarWidth) {
|
||||
@@ -284,6 +286,12 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback,
|
||||
if (!io || !io->WantCaptureMouse)
|
||||
window->mouseMoved(event.motion.x, event.motion.y);
|
||||
break;
|
||||
case SDL_DROPFILE:
|
||||
if (mDropHandler) {
|
||||
mDropHandler(event.drop.file);
|
||||
}
|
||||
SDL_free(event.drop.file);
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
filament::Scene*, filament::Renderer*)>;
|
||||
using ImGuiCallback = std::function<void(filament::Engine*, filament::View*)>;
|
||||
using AnimCallback = std::function<void(filament::Engine*, filament::View*, double now)>;
|
||||
using DropCallback = std::function<void(std::string)>;
|
||||
|
||||
static FilamentApp& get();
|
||||
|
||||
@@ -64,6 +65,8 @@ public:
|
||||
|
||||
void animate(AnimCallback animation) { mAnimation = animation; }
|
||||
|
||||
void setDropHandler(DropCallback handler) { mDropHandler = handler; }
|
||||
|
||||
void run(const Config& config, SetupCallback setup, CleanupCallback cleanup,
|
||||
ImGuiCallback imgui = ImGuiCallback(), PreRenderCallback preRender = PreRenderCallback(),
|
||||
PostRenderCallback postRender = PostRenderCallback(),
|
||||
@@ -203,6 +206,7 @@ private:
|
||||
filament::MaterialInstance* mDepthMI = nullptr;
|
||||
std::unique_ptr<filagui::ImGuiHelper> mImGuiHelper;
|
||||
AnimCallback mAnimation;
|
||||
DropCallback mDropHandler;
|
||||
int mSidebarWidth = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -43,10 +43,11 @@ using namespace gltfio;
|
||||
using namespace utils;
|
||||
|
||||
struct App {
|
||||
Engine* engine;
|
||||
SimpleViewer* viewer;
|
||||
Config config;
|
||||
AssetLoader* loader;
|
||||
FilamentAsset* asset;
|
||||
FilamentAsset* asset = nullptr;
|
||||
NameComponentManager* names;
|
||||
MaterialSource materialSource = GENERATE_SHADERS;
|
||||
};
|
||||
@@ -138,46 +139,41 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
auto setup = [&app, filename](Engine* engine, View* view, Scene* scene) {
|
||||
app.names = new NameComponentManager(EntityManager::get());
|
||||
app.viewer = new SimpleViewer(engine, scene, view);
|
||||
app.loader = AssetLoader::create({engine, app.names, app.materialSource});
|
||||
if (filename.isEmpty()) {
|
||||
app.asset = app.loader->createAssetFromBinary(GLTF_DAMAGEDHELMET_DATA,
|
||||
GLTF_DAMAGEDHELMET_SIZE);
|
||||
} else {
|
||||
// Peek at the file size to allow pre-allocation.
|
||||
long contentSize = static_cast<long>(getFileSize(filename.c_str()));
|
||||
if (contentSize <= 0) {
|
||||
std::cerr << "Unable to open " << filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Consume the glTF file.
|
||||
std::ifstream in(filename.c_str(), std::ifstream::in);
|
||||
std::vector<uint8_t> buffer(static_cast<unsigned long>(contentSize));
|
||||
if (!in.read((char*) buffer.data(), contentSize)) {
|
||||
std::cerr << "Unable to read " << filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Parse the glTF file and create Filament entities.
|
||||
if (filename.getExtension() == "glb") {
|
||||
app.asset = app.loader->createAssetFromBinary(buffer.data(), buffer.size());
|
||||
} else {
|
||||
app.asset = app.loader->createAssetFromJson(buffer.data(), buffer.size());
|
||||
}
|
||||
buffer.clear();
|
||||
buffer.shrink_to_fit();
|
||||
auto loadAsset = [&app](utils::Path filename) {
|
||||
// Peek at the file size to allow pre-allocation.
|
||||
long contentSize = static_cast<long>(getFileSize(filename.c_str()));
|
||||
if (contentSize <= 0) {
|
||||
std::cerr << "Unable to open " << filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Consume the glTF file.
|
||||
std::ifstream in(filename.c_str(), std::ifstream::in);
|
||||
std::vector<uint8_t> buffer(static_cast<unsigned long>(contentSize));
|
||||
if (!in.read((char*) buffer.data(), contentSize)) {
|
||||
std::cerr << "Unable to read " << filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Parse the glTF file and create Filament entities.
|
||||
if (filename.getExtension() == "glb") {
|
||||
app.asset = app.loader->createAssetFromBinary(buffer.data(), buffer.size());
|
||||
} else {
|
||||
app.asset = app.loader->createAssetFromJson(buffer.data(), buffer.size());
|
||||
}
|
||||
buffer.clear();
|
||||
buffer.shrink_to_fit();
|
||||
|
||||
if (!app.asset) {
|
||||
std::cerr << "Unable to parse " << filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
auto loadResources = [&app] (utils::Path filename) {
|
||||
// Load external textures and buffers.
|
||||
utils::Path assetFolder = filename.getParent();
|
||||
gltfio::ResourceLoader({engine, assetFolder, true, false}).loadResources(app.asset);
|
||||
gltfio::ResourceLoader({app.engine, assetFolder, true, false}).loadResources(app.asset);
|
||||
|
||||
// Load animation data then free the source hierarchy.
|
||||
app.asset->getAnimator();
|
||||
@@ -185,7 +181,23 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Add the renderables to the scene.
|
||||
app.viewer->setAsset(app.asset, app.names);
|
||||
|
||||
app.viewer->setIndirectLight(FilamentApp::get().getIBL()->getIndirectLight());
|
||||
};
|
||||
|
||||
auto setup = [&](Engine* engine, View* view, Scene* scene) {
|
||||
app.engine = engine;
|
||||
app.names = new NameComponentManager(EntityManager::get());
|
||||
app.viewer = new SimpleViewer(engine, scene, view);
|
||||
app.loader = AssetLoader::create({engine, app.names, app.materialSource});
|
||||
if (filename.isEmpty()) {
|
||||
app.asset = app.loader->createAssetFromBinary(GLTF_DAMAGEDHELMET_DATA,
|
||||
GLTF_DAMAGEDHELMET_SIZE);
|
||||
} else {
|
||||
loadAsset(filename);
|
||||
}
|
||||
|
||||
loadResources(filename);
|
||||
|
||||
// Leave FXAA enabled but we also enable MSAA for a nice result. The wireframe looks
|
||||
// much better with MSAA enabled.
|
||||
@@ -212,6 +224,14 @@ int main(int argc, char** argv) {
|
||||
|
||||
FilamentApp& filamentApp = FilamentApp::get();
|
||||
filamentApp.animate(animate);
|
||||
|
||||
filamentApp.setDropHandler([&] (std::string path) {
|
||||
app.viewer->removeAsset();
|
||||
app.loader->destroyAsset(app.asset);
|
||||
loadAsset(path);
|
||||
loadResources(path);
|
||||
});
|
||||
|
||||
filamentApp.run(app.config, setup, cleanup, gui);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user