Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

エントリーポイント見直し #218

Open
lriki opened this issue Aug 9, 2022 · 0 comments
Open

エントリーポイント見直し #218

lriki opened this issue Aug 9, 2022 · 0 comments
Milestone

Comments

@lriki
Copy link
Collaborator

lriki commented Aug 9, 2022

Lumino はメインループを内部に持つスタンドアロンのアプリケーションフレームワークのほか、別の GUI フレームワークにレンダリングライブラリとして組み込む機能も持っている。

しかし最近は対応する言語や環境が増えてきたことで、暫定的に用意したグルーコードがかなり複雑になってきている。

エントリーポイントのシンプルさはそのままサンプルコードのとっつきやすさにつながってくるため、仕様を整理する。

基本方針

  • ユーザーが使うクラスを増やしすぎない。
  • スタンドアロンのアプリケーションフレームワークでサンプルを示すとき、コードが最小限になること。(驚き最小)
  • 別のフレームワークに組み込む時は、そちらの文化にできるだけ似た書き方ができるようにする。
  • ゲームアプリケーションを実装する用に、 Application クラスをオーバーライドできるようにする。
  • GUI アプリケーションを実装する用に、 Application クラス及び MainWindow クラスをオーバーライドできるようにする。

破壊的変更

これまで ln::Engine::initalize() で MainWindow を自動生成していたが、それをやめる。

v0.10.0 以降、 Lumino 単体で使う際は Application クラスを使う方法が基本となったため、自分で初期化 & メインループを各機会は外部アプリに組み込む時だけになっている。
サッと Lumino を使いたい人にとって ln::Engine::initalize() を使った初期化周りは隠蔽されることになるので、このあたりの仕様は外部アプリに組み込みたいケース向けに調整していく。

Application クラスと MainWindow クラスの関係

いくつかの GUI フレームワークでは Application が先にあって、MainWindow は後から作られる。
しかし Lumino は MainWindow が先となるので注意。

他の GUI アプリに組み込む場合、 Application はオプションとなる。
対して MainWindow は描画先サーフェスを表すものであり、単なるレンダリングライブラリとして使う場合でも必須である。
(Window と Surface を分離するのもありだが、いずれにしても Application よりも優先されるインスタンスとなる)

Standalone

C++ (with launcher)

class MyApp : public ln::Application {
    MyApp() {
    }

    void onInit() {
        // この時点で内部・外部問わず作成された MainWindow を ln::Engine::mainWindow() で取得できる。
    }
}

LN_APP(MyApp, MyMainWindow)
// Launcher例 (Libになっているので、基本はユーザーが書くことは無い)
LuminoConfigureApp();
ln::Engine::initialize();
ln::Engine::setupMainWindow(LuminoCreateMainWindow());
ln::Engine::setupApplication(LuminoCreateApp());
ln::Engine::run();

C++ (without launcher)

Launcher 未対応の環境で使う。あまり機会は無いかも。

class MyApp : public ln::Application {
    MyApp() {
    }

    void onInit() {
    }
}
ln::Engine::initialize();
auto app = makeObject<MyApp>();     // Application のコンストラクタで、MainWindow 未設定なら ln::Engine::setupMainWindow() 実行、でいいかも。
app->run();
ln::Engine::terminate();

C

// init
LNHandle mainWindow, app;
LNEngine_Initialize();
LNMainWindow_Create(&mainWindow);
LNMainWindow_SetPrototype_...(mainWindow, ...);
LNEngine_SetupMainWindow(mainWindow);
LNApplication_Create(&app);
LNApplication_SetPrototype_...(app, ...);
LNEngine_SetupApplication(app);

// run
LNEngine_Run();

Ruby

require "lumino"
Engine.initialize   # require の中で initialize してしまうと EngineSettings による設定ができないので、明示的な初期化が要る。(あるいは App のコンストラクタで呼んでもいいが)
app = new App()
app.run()
require "lumino"
Engine.initialize
Engine.setupMainWindow
app = new App();
app.run()
Engine.terminate

TypeScript

ExternalMainLoop 必須。

External main loop

C++

// init
ln::Engine::initialize();
ln::Engine::setupMainWindow(makeObject<MainWindow>(hWnd));  // ユーザー定義の MainWindow を登録。この仕組みは App とは直接関係は無い。
ln::Engine::setupApplication(makeObject<App>());

// update
ln::Engine::update();

// render
ln::Engine::render(ln::Engine::mainWindow());
swap(hWnd);

// terminate
ln::Engine::terminate();

C++ (External GraphicsAPI)

// init
ln::EngineSettings::setGraphicsBackend(GraphicsBackend::None);
ln::Engine::initialize();
auto renderer = ln::VulkanIntegration::createContext(device);
ln::Engine::setupGraphics(renderer);
ln::Engine::setupMainWindow(makeObject<MainWindow>(hWnd));
ln::Engine::setupApplication(makeObject<App>());

// update
ln::Engine::update();

// render
renderer->resetCommandList(...);
ln::Engine::render(renderer, ln::Engine::mainWindow());
swap(hWnd);

// terminate
ln::Engine::terminate();

Ruby

# init
require "lumino"  # この中で initialize() したいところだが、 require の前で EngineSettings を呼ぶことができないため断念。
Engine.setupMainWindow(new MainWindow(window_id))
Engine.setupApplication(new App)

# update
Engine.update

# render
Engine.render(ln::Engine::mainWindow());
swap(window_id)

TypeScript

// init
const renderer = WebGpuIntegration.getContext(device);
const mainWindow = new MainWindow(canvas);
Engine.setupMainWindow(mainWindow);
Engine.setupApplication(new App());

// update
Engine.update();

// render
renderer.resetCommandList(webgpuCommandList);
Engine.render(renderer, mainWindow, w, h);
@lriki lriki added this to v0.11.0 Aug 9, 2022
@lriki lriki moved this to 📋 Backlog in v0.11.0 Aug 9, 2022
@lriki lriki added this to the v0.11.0 milestone Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 📋 Backlog
Development

No branches or pull requests

1 participant