元記事:Global Undo


Global Undo


Ton Roosendaal氏


Blender2.35では「グローバルなUndo」も使用できるようになりました。これがグローバルと呼ばれるのは、一時的な編集モード(Mesh編集やVertexPaint等)の外で働き、'Undo'をBlender全体のデータベースで行う物だからです。

ホットキー
すべてのUndoの操作は[Ctrl]+[Z](Undo)と、[Shift]+[Ctrl]+[Z](Redo)もしくは[Ctrl]+[Y](Redo)で行います。Macユーザは[Ctrl]をAppleキーで置き換えて下さい。ただし、EditModeでは旧[U]キーと[Shift]+[U]キーもまだ動作します。
[Alt]+[U]は現在のUndoレベルを表示します。

注意:3DWindow中の旧[Ctrl]+[Z](Shading DrawModeの再計算)は、[Shift]+[Alt]+[Z]になりました。Shaded drawmode([Shift]+[Z])がすでに多くのシチュエーションで再計算されるため、これは実際にはほとんど不要なオプションになってしまいました。

設定
UserPreference(InfoWindow)中の[Global Undo]で使用可能になります。これはデフォルトではONになっています。UserPreferenceではまた、保存するUndoステップの量を設定できます。常に要求されるUndoメモリの量は少なくとも現在の.blendファイルのサイズ分で、プラスUndoステップごとにその2-5%が必要になります。

UIの非復元
Undo操作でUIもしくはビューの設定は、Blenderのファイル保存時のようには保存(復活)されません。これはUIを変更した後、どんな状況でもUndo/Redoのステップが明らかに目で確認できるとは限らないことを意味します。
例:新しい画像をUV Editorで読み込み、Undo、Redoをすると、新しい画像は戻りますが、UV Editorはそれを表示しません。

二つのUndoシステム
- 非常に重要な事です。EditModeのUndoスタックは'GlobalUndo'スタックからは切り離されています。これはもしEditModeに入ったとき、UndoステップはEditModeに入ったときまでしか戻れないことを意味します。EditModeを出たとき、さらにUndoできますが、これはEditModeをそっくりそのままスキップします。
この機構は実際に決定されたデザインではなく、EditModeのUndoのみ利用可能だった過去からの成長の結果です。
しかし、Global Undoのステップとは独立しているため、EditModeに帰れば常に完全なオリジナルのUndoスタックが利用できる利点があります。我々がこちらを採用しようが、完全なUndoの融合を採用しようが、次のリリースになります。

Quit時の保存
- 実際に「現在のファイル」がメモリ上にあるので、ディスクにもすぐ保存できます。これでもしBlenderから抜けても、今はデフォルトで「セッションのリカバリ」ファイルができるようになります。そのファイルはメインのFileメニューで読み込むことができます。
この機能は間違えてBlenderをquitしてしまった時の、作業の損失を解決するでしょう。

Todo
BlenderのほとんどのエディタとEditModeはUndoを持つようになりましたが、例外を以下にリストアップします。

- PoseModeはGlobal Undoの一部です。
- ArmatureのEditModeはUndoがまだありません。
- FileSelect、Audio、OopsWindowもUndoはありません。
- TextWindowは自身にデザインされたUndoをすでに持っており、Global Undoでクリアされます。

Undo実装の概要
一般的なUndoシステムは例えば、「ヒストリリスト(何行かのスクリプトのようなもの)」によって、もしくは変更点についてのイベントリストを構築する別の関数ですべてのデータ変更をラップすることによって、データ内の変更された場所を追跡する、という原理を元にしています。

私の考えでは、BlenderはUndoを使用するようにはデザインされていません。さらにそのコードでは、変更を得るための一切の抽象レイヤもなしに、コード中のいたるところでデータのアクセス・変更を行うため、一般的なソフトウェアアーキテクチャのルールを完全に破っています。
もちろん、このようなアプローチには恩恵も…特にコーディングのしやすさと実行スピードがあります。

しかし、Blenderでも力押しのアプローチ ― Blender2.3xのMeshEditのUndoのようなもの ― は可能で、作業の完全なデータセットを格納・キャッシュしています。一般的なMeshはメモリ内で1MBの半分以下にしかならず、システムの速度低下が目立つようなことはないでしょう。

この方法はまだBlender上にあり、Curve、Surface、3DText、MetaBall、Latticeの編集にも追加されています。

Global Undoの実装
Blenderのファイルの保存と読み込みが驚くほど早いため、これがBlenderの他の編集を満足にUndoできるか確認するためのテストが行われました。主な問題は急速に大きくなってしまうことです。今日では、Blender上の複雑なプロジェクトは簡単に数十MBにもなってしまいます。また、ディスクアクセスもボトルネックとなる可能性があり、メモリを使用する方がはるかに早いのです。

解決方法はストリーミングとコアのファイル保存ルーチンにありました。
Blenderのファイルが保存されるとき、あらかじめ、最小が50KBの作成された「チャンク」を集めており、これがディスクとネットワークのオーバーヘッドを最小限にしています。これらチャンクは現在'Undo save'のため、メモリに直接コピーされています。その結果、チャンクのリストを'Undo'の実行のための読み込みコードに簡単に供給できるようになりました。

Undo初期段階

この画像は最初の「Undoプッシュ」時のメモリの状態を表すものです。それぞれのチャンクは違った大きさであることに注意してください。

Blenderに何か変更があった場合、二つめのバッファが作成されます。一連のバッファが何百MBにもなってしまうのを防ぐため、簡単な圧縮のメカニズムを追加しています…。

ObjectをGrab

データ保存中、それぞれのチャンクは最初に以前のチャンクとバイナリ比較されます。もしそれが同じであれば、そのチャンクは保存(コピー)しない代わりに、以前のチャンクを参照します。

能率的なチャンクの組織化、そして新しい「ライブラリデータタイプ」の保存時にチャンクをフラッシュする合図を送るため、このシステムの一貫性は非常に良好です。
ここで新しいMesh Objectが追加されたとします。

MeshObject追加

そしてBlenderの一番多い変更 ― 編集 ― は非常に小さいため、Undoの変更の大部分は一つのチャンクのコピーが含まれているだけです。

Material変更

Blenderの多くの大きいチャンク(Vertex配列など)はこのプロセスの間ずっとコピーされず、比較のみが行われました。このすべては非常に効率的に起こります。

Undoバッファリングを行う間の新しいメモリを確保するオーバーヘッドも圧縮機構によって非常に小さいです。

次の重要な改良は(以前の、現Mesh Undoの代わりとして)編集コマンド実行後にUndoプッシュを行うことでした。これはユーザの行動の間の小さな空き時間を効率よく利用します。

そして最後だけど重要なこと:このシステムではそれぞれの「Undoレベル」において、直接読みこむことのできるチャンクのセットが完全に利用可能になっています。それぞれのUndoレベルは容易に削除もしくは前回の物と統合することができます。

結果
450MHzのG4システム上での遅延テストでは、20MBのデータセットまで対話的に動作していました。

このシステムは6週間以上も多くの問題の発見と修正を重ね、熟成とテストがされてきました。Undoシステムはまだ完全に作業が終了したわけではありません。いくつかのエリアについての作業があります。

- ボタンのON/OFFの変更は現在、自動的にUndoステップを生成するようになっており、単にそのボタンの名前もしくはTooltipを名前としてUndoスタックに格納します([Alt]+[U])。また、ボタンがUndoステップを追加することによるイベントの実行も起こります。

- Undoスタックはより綺麗に、より完全に、より適した名前にする必要がまだあります。

- UndoバッファはUIを格納しません(例:Screenチャンクの非保存)。これはUndo・Redoをビューやウィンドウの設定を変更せず行う可能性があります。 これはまた、Undoの変更が隠れて判らなくなることも付け加えておきます…しかし、私たちが新しいオプション、"load .blend without UI"ボタンをFileWindowへ追加できる様になりました。

- EditModeのUndoは(能率的で早い)自身のシステムを残すため、Global Undoとのミックスはできません。よってGlobal UndoはEditModeの作業を完全にスキップし、EditModeのUndoは常にEditModeの動作に専念しています。

このことについては、スムーズに二つをあわせて動作できる方法について更に研究を重ねる必要があります。