omni/kit/IApp.h

File members: omni/kit/IApp.h

// Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

#pragma once

#include "../../carb/Interface.h"
#include "../../carb/events/EventsUtils.h"
#include "../../carb/events/IEvents.h"
#include "../../carb/extras/Timer.h"
#include "../../carb/profiler/Profile.h"
#include "../String.h"

namespace omni
{

namespace ext
{
class ExtensionManager;
}

namespace kit
{

class IRunLoopRunner;

struct AppDesc
{
    const char* carbAppName;
    const char* carbAppPath;
    int argc;
    char** argv;
};

struct BuildInfo
{
    omni::string kitVersion;
    omni::string kitVersionShort;
    omni::string kitVersionHash;

    omni::string kernelVersion;
};

struct PlatformInfo
{
    const char* config;

    const char* platform;
    const char* pythonVersion;
};

struct AppInfo
{
    omni::string filename;
    omni::string name;
    omni::string version;
    omni::string versionShort;

    omni::string environment;
    bool isExternal;
};

class RunLoop
{
public:
    carb::events::IEventStream* preUpdate;
    carb::events::IEventStream* update;
    carb::events::IEventStream* postUpdate;

    carb::events::IEventStream* messageBus;
};

enum class RestartArgsPolicy
{
    eAppend,
    eReplace,
};

// Few predefined run loop names. Serve as hints, doesn't have to use only those.

constexpr char kRunLoopDefault[] = "main";
constexpr char kRunLoopSimulation[] = "simulation";
constexpr char kRunLoopRendering[] = "rendering";
constexpr char kRunLoopUi[] = "ui";

class IAppScripting;

// App shutdown events pumped into IApp::getShutdownEventStream():
constexpr const carb::events::EventType kPostQuitEventType = 0;

constexpr const carb::events::EventType kPreShutdownEventType = 1;

const carb::events::EventType kEventAppStarted = CARB_EVENTS_TYPE_FROM_STR("APP_STARTED");
const carb::events::EventType kEventAppReady = CARB_EVENTS_TYPE_FROM_STR("APP_READY");

class IApp
{
public:
    CARB_PLUGIN_INTERFACE("omni::kit::IApp", 1, 3);

    virtual void startup(const AppDesc& desc) = 0;

    virtual void update() = 0;

    virtual bool isRunning() = 0;

    virtual int shutdown() = 0;

    int run(const AppDesc& desc);

    virtual void postQuit(int returnCode = 0) = 0;

    virtual carb::events::IEventStream* getLogEventStream() = 0;

    virtual void replayLogMessages(carb::logging::Logger* target) = 0;

    virtual void toggleLogMessageRecording(bool logMessageRecordingEnabled) = 0;

    virtual RunLoop* getRunLoop(const char* name) = 0;

    virtual bool isRunLoopAlive(const char* name) = 0;

    virtual void terminateRunLoop(const char* name, bool block) = 0;

    carb::events::IEventStream* getPreUpdateEventStream(const char* runLoopName = kRunLoopDefault)
    {
        return getRunLoop(runLoopName)->preUpdate;
    }

    carb::events::IEventStream* getUpdateEventStream(const char* runLoopName = kRunLoopDefault)
    {
        return getRunLoop(runLoopName)->update;
    }

    carb::events::IEventStream* getPostUpdateEventStream(const char* runLoopName = kRunLoopDefault)
    {
        return getRunLoop(runLoopName)->postUpdate;
    }

    carb::events::IEventStream* getMessageBusEventStream(const char* runLoopName = kRunLoopDefault)
    {
        return getRunLoop(runLoopName)->messageBus;
    }

    virtual void setRunLoopRunner(IRunLoopRunner* runner) = 0;

    virtual omni::ext::ExtensionManager* getExtensionManager() = 0;

    virtual IAppScripting* getPythonScripting() = 0;

    virtual const char* getBuildVersion() = 0;

    virtual bool isDebugBuild() = 0;

    virtual PlatformInfo getPlatformInfo() = 0;

    virtual double getTimeSinceStart(carb::extras::Timer::Scale timeScale = carb::extras::Timer::Scale::eMilliseconds) = 0;

    virtual double getLastUpdateTime() = 0;

    virtual uint32_t getUpdateNumber() = 0;

    virtual void printAndLog(const char* message) = 0;

    virtual carb::events::IEventStream* getShutdownEventStream() = 0;

    virtual bool tryCancelShutdown(const char* reason) = 0;

    virtual void postUncancellableQuit(int returnCode) = 0;

    virtual carb::events::IEventStream* getStartupEventStream() = 0;

    virtual bool isAppReady() = 0;

    virtual void delayAppReady(const char* requesterName) = 0;

    virtual const BuildInfo& getBuildInfo() = 0;

    virtual const AppInfo& getAppInfo() = 0;

    virtual void restart(const char* const* args = nullptr,
                         size_t argCount = 0,
                         RestartArgsPolicy argsPolicy = RestartArgsPolicy::eAppend,
                         bool uncancellable = false) = 0;
};

// TODO(anov): switch back to using string hash when fix for IEventStream.push binding is merged in from Carbonite.

const carb::events::EventType kScriptingEventCommand = 0; // CARB_EVENTS_TYPE_FROM_STR("SCRIPT_COMMAND");
const carb::events::EventType kScriptingEventStdOut = 1; // CARB_EVENTS_TYPE_FROM_STR("SCRIPT_STDOUT");
const carb::events::EventType kScriptingEventStdErr = 2; // CARB_EVENTS_TYPE_FROM_STR("SCRIPT_STDERR");

class IAppScripting
{
public:
    virtual bool executeString(const char* str, const char* commandName = nullptr, bool executeAsFile = false) = 0;

    virtual bool executeFile(const char* path, const char* const* args, size_t argCount) = 0;

    virtual bool addSearchScriptFolder(const char* path) = 0;

    virtual bool removeSearchScriptFolder(const char* path) = 0;

    virtual carb::events::IEventStream* getEventStream() = 0;
};

//                                                Inline Functions                                                    //

inline int IApp::run(const AppDesc& desc)
{
    this->startup(desc);
    while (this->isRunning())
    {
        this->update();
    }
    return this->shutdown();
}

} // namespace kit
} // namespace omni