mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2025-12-31 00:10:44 -06:00
Add the ability to run as task file at startup. Add new model conversion task that requires an OpenGL context. Add ability to use FileVerifier and DirectoryVerifier on files that don't exist (#3612)
This commit is contained in:
@@ -29,6 +29,9 @@
|
||||
#include <openspace/engine/settings.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/interaction/joystickinputstate.h>
|
||||
#include <openspace/util/progressbar.h>
|
||||
#include <openspace/util/task.h>
|
||||
#include <openspace/util/taskloader.h>
|
||||
#include <openspace/openspace.h>
|
||||
#include <ghoul/format.h>
|
||||
#include <ghoul/ghoul.h>
|
||||
@@ -100,6 +103,11 @@ glm::ivec2 currentDrawResolution;
|
||||
Window* FirstOpenVRWindow = nullptr;
|
||||
#endif
|
||||
|
||||
// This value is specified from the commandline options and kept around to be run after
|
||||
// everything has been initialized. It's going to be std::nullopt unless a user wants to
|
||||
// run a task
|
||||
std::optional<std::string> taskToRun;
|
||||
|
||||
//
|
||||
// SPOUT-support
|
||||
//
|
||||
@@ -401,6 +409,40 @@ void mainInitFunc(GLFWwindow*) {
|
||||
// Query joystick status, those connected before start up
|
||||
checkJoystickStatus();
|
||||
|
||||
if (taskToRun.has_value()) {
|
||||
// If a task was specified on the commandline line, we are loading that file and
|
||||
// executing everything within
|
||||
|
||||
TaskLoader loader;
|
||||
std::vector<std::unique_ptr<Task>> tasks = loader.tasksFromFile(*taskToRun);
|
||||
|
||||
size_t nTasks = tasks.size();
|
||||
if (nTasks == 1) {
|
||||
LINFO("Task queue has 1 item");
|
||||
}
|
||||
else {
|
||||
LINFO(std::format("Task queue has {} items", tasks.size()));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < tasks.size(); i++) {
|
||||
Task& task = *tasks[i].get();
|
||||
LINFO(std::format(
|
||||
"Performing task {} out of {}: {}",
|
||||
i + 1, tasks.size(), task.description()
|
||||
));
|
||||
ProgressBar progressBar = ProgressBar(100);
|
||||
auto onProgress = [&progressBar](float progress) {
|
||||
progressBar.print(static_cast<int>(progress * 100.f));
|
||||
};
|
||||
task.perform(onProgress);
|
||||
}
|
||||
std::cout << "Done performing tasks" << std::endl;
|
||||
|
||||
// Done with the tasks, so we can terminate
|
||||
Engine::instance().terminate();
|
||||
}
|
||||
|
||||
|
||||
LTRACE("main::mainInitFunc(end)");
|
||||
}
|
||||
|
||||
@@ -1142,41 +1184,56 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
CommandlineArguments commandlineArguments;
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.configuration, "--file", "-f",
|
||||
commandlineArguments.configuration,
|
||||
"--file",
|
||||
"-f",
|
||||
"Provides the path to the OpenSpace configuration file. Only the '${TEMPORARY}' "
|
||||
"path token is available and any other path has to be specified relative to the "
|
||||
"current working directory"
|
||||
));
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.windowConfig, "--config", "-c",
|
||||
commandlineArguments.windowConfig,
|
||||
"--config",
|
||||
"-c",
|
||||
"Specifies the window configuration file that should be used to start OpenSpace "
|
||||
"and that will override whatever is specified in the `openspace.cfg` or the "
|
||||
"settings. This value can include path tokens, so for example "
|
||||
"`${CONFIG}/single.json` is a valid value."
|
||||
));
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.profile, "--profile", "-p",
|
||||
commandlineArguments.profile,
|
||||
"--profile",
|
||||
"-p",
|
||||
"Specifies the profile that should be used to start OpenSpace and that overrides "
|
||||
"the profile specified in the `openspace.cfg` and the settings."
|
||||
));
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.propertyVisibility, "--propertyVisibility", "",
|
||||
commandlineArguments.propertyVisibility,
|
||||
"--propertyVisibility",
|
||||
"",
|
||||
"Specifies UI visibility settings for properties that this OpenSpace is using. "
|
||||
"This value overrides the values specified in the `openspace.cfg` and the "
|
||||
"settings and also the environment variable, if that value is provided. Allowed "
|
||||
"values for this parameter are: `Developer`, `AdvancedUser`, `User`, and "
|
||||
"`NoviceUser`."
|
||||
));
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.task,
|
||||
"--task",
|
||||
"-t",
|
||||
"Specifies a task that will be run after OpenSpace has been initialized. Once "
|
||||
"the task finishes, the application will automatically close again. All other "
|
||||
"commandline arguments are ignored, if a task is specified."
|
||||
));
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommandZeroArguments>(
|
||||
commandlineArguments.bypassLauncher, "--bypassLauncher", "-b",
|
||||
commandlineArguments.bypassLauncher,
|
||||
"--bypassLauncher",
|
||||
"-b",
|
||||
"Specifies whether the Launcher should be shown at startup or not. This value "
|
||||
"overrides the value specified in the `openspace.cfg` and the settings."
|
||||
));
|
||||
|
||||
// setCommandLine returns a reference to the vector that will be filled later
|
||||
const std::vector<std::string>& sgctArguments = parser.setCommandLine(
|
||||
{ argv, argv + argc }
|
||||
);
|
||||
parser.setCommandLine({ argv, argv + argc });
|
||||
|
||||
try {
|
||||
const bool showHelp = parser.execute();
|
||||
@@ -1189,8 +1246,16 @@ int main(int argc, char* argv[]) {
|
||||
LFATALC(e.component, e.message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Take an actual copy of the arguments
|
||||
std::vector<std::string> arguments = sgctArguments;
|
||||
|
||||
if (commandlineArguments.task.has_value()) {
|
||||
// If a task was specified, we want to overwrite the used window and profile and
|
||||
// not display the launcher
|
||||
commandlineArguments.windowConfig = "${CONFIG}/single.json";
|
||||
commandlineArguments.profile = "empty";
|
||||
commandlineArguments.bypassLauncher = true;
|
||||
|
||||
taskToRun = *commandlineArguments.task;
|
||||
}
|
||||
|
||||
//
|
||||
// Set up SGCT functions for window delegate
|
||||
|
||||
7
data/tasks/convertmodel.task
Normal file
7
data/tasks/convertmodel.task
Normal file
@@ -0,0 +1,7 @@
|
||||
return {
|
||||
{
|
||||
Type = "ConvertModelTask",
|
||||
InputFilePath = "< in path >",
|
||||
OutputFilePath = "< out path >"
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,8 @@ struct CommandlineArguments {
|
||||
std::optional<std::string> profile;
|
||||
std::optional<std::string> propertyVisibility;
|
||||
std::optional<bool> bypassLauncher;
|
||||
|
||||
std::optional<std::string> task;
|
||||
};
|
||||
|
||||
class OpenSpaceEngine : public properties::PropertyOwner {
|
||||
|
||||
@@ -87,6 +87,7 @@ set(HEADER_FILES
|
||||
scale/staticscale.h
|
||||
scale/timedependentscale.h
|
||||
scale/timelinescale.h
|
||||
task/convertmodeltask.h
|
||||
timeframe/timeframeinterval.h
|
||||
timeframe/timeframeunion.h
|
||||
translation/globetranslation.h
|
||||
@@ -161,6 +162,7 @@ set(SOURCE_FILES
|
||||
scale/staticscale.cpp
|
||||
scale/timedependentscale.cpp
|
||||
scale/timelinescale.cpp
|
||||
task/convertmodeltask.cpp
|
||||
timeframe/timeframeinterval.cpp
|
||||
timeframe/timeframeunion.cpp
|
||||
translation/globetranslation.cpp
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#include <modules/base/scale/staticscale.h>
|
||||
#include <modules/base/scale/timedependentscale.h>
|
||||
#include <modules/base/scale/timelinescale.h>
|
||||
#include <modules/base/task/convertmodeltask.h>
|
||||
#include <modules/base/translation/timelinetranslation.h>
|
||||
#include <modules/base/translation/globetranslation.h>
|
||||
#include <modules/base/translation/luatranslation.h>
|
||||
@@ -227,13 +228,20 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
|
||||
ghoul::TemplateFactory<Translation>* fTranslation =
|
||||
FactoryManager::ref().factory<Translation>();
|
||||
ghoul_assert(fTranslation, "Ephemeris factory was not created");
|
||||
ghoul_assert(fTranslation, "Translation factory was not created");
|
||||
|
||||
fTranslation->registerClass<GlobeTranslation>("GlobeTranslation");
|
||||
fTranslation->registerClass<LuaTranslation>("LuaTranslation");
|
||||
fTranslation->registerClass<MultiTranslation>("MultiTranslation");
|
||||
fTranslation->registerClass<StaticTranslation>("StaticTranslation");
|
||||
fTranslation->registerClass<TimelineTranslation>("TimelineTranslation");
|
||||
|
||||
|
||||
ghoul::TemplateFactory<Task>* fTask =
|
||||
FactoryManager::ref().factory<Task>();
|
||||
ghoul_assert(fTask, "Task factory was not created");
|
||||
|
||||
fTask->registerClass<ConvertModelTask>("ConvertModelTask");
|
||||
}
|
||||
|
||||
void BaseModule::internalDeinitializeGL() {
|
||||
@@ -316,7 +324,9 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
|
||||
LuaTranslation::Documentation(),
|
||||
MultiTranslation::Documentation(),
|
||||
StaticTranslation::Documentation(),
|
||||
TimelineTranslation::Documentation()
|
||||
TimelineTranslation::Documentation(),
|
||||
|
||||
ConvertModelTask::Documentation()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
80
modules/base/task/convertmodeltask.cpp
Normal file
80
modules/base/task/convertmodeltask.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/base/task/convertmodeltask.h>
|
||||
|
||||
#include <ghoul/io/model/modelgeometry.h>
|
||||
#include <ghoul/io/model/modelreaderassimp.h>
|
||||
|
||||
namespace {
|
||||
// This task converts a 3D model format from a format that is natively supported both
|
||||
// by OpenSpace and common 3D modelling tools and converts it into an OpenSpace
|
||||
// proprietary format that can be loaded more efficiently, but more important can be
|
||||
// distributed without violating terms of service for various 3D model hosting
|
||||
// websites.
|
||||
//
|
||||
// The resulting output file can be used everywhere in OpenSpace in place of the
|
||||
// source material.
|
||||
//
|
||||
// The list of supported files can be found here:
|
||||
// https://github.com/assimp/assimp/blob/master/doc/Fileformats.md
|
||||
struct [[codegen::Dictionary(ConvertModelTask)]] Parameters {
|
||||
// The path to the source file
|
||||
std::filesystem::path inputFilePath;
|
||||
// The path to the output file
|
||||
std::filesystem::path outputFilePath [[codegen::mustexist(false)]];
|
||||
};
|
||||
#include "convertmodeltask_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation ConvertModelTask::Documentation() {
|
||||
return codegen::doc<Parameters>("base_convert_model_task");
|
||||
}
|
||||
|
||||
ConvertModelTask::ConvertModelTask(const ghoul::Dictionary& dictionary) {
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_inFilePath = p.inputFilePath;
|
||||
_outFilePath = p.outputFilePath;
|
||||
}
|
||||
|
||||
std::string ConvertModelTask::description() {
|
||||
return "This task converts a 3D model format from a format that is natively "
|
||||
"supported both by OpenSpace and common 3D modelling tools and converts it into "
|
||||
"an OpenSpace proprietary format that can be loaded more efficiently, but more "
|
||||
"important can be distributed without violating terms of service for various 3D "
|
||||
"model hosting websites";
|
||||
}
|
||||
|
||||
void ConvertModelTask::perform(const Task::ProgressCallback&) {
|
||||
ghoul::io::ModelReaderAssimp reader;
|
||||
|
||||
std::unique_ptr<ghoul::modelgeometry::ModelGeometry> geometry =
|
||||
reader.loadModel(_inFilePath, false, true);
|
||||
geometry->saveToCacheFile(_outFilePath);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
52
modules/base/task/convertmodeltask.h
Normal file
52
modules/base/task/convertmodeltask.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2025 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___CONVERTMODELTASK___H__
|
||||
#define __OPENSPACE_CORE___CONVERTMODELTASK___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ConvertModelTask : public Task {
|
||||
public:
|
||||
explicit ConvertModelTask(const ghoul::Dictionary& dictionary);
|
||||
~ConvertModelTask() override = default;
|
||||
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& processCallback) override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
std::filesystem::path _inFilePath;
|
||||
std::filesystem::path _outFilePath;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_CORE___CONVERTMODELTASK___H__
|
||||
Reference in New Issue
Block a user