@luna-editor/engine 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Player.js CHANGED
@@ -361,9 +361,9 @@ export const Player = ({ scenario: scenarioProp, settings, plugins = EMPTY_PLUGI
361
361
  loadPlugins();
362
362
  return () => {
363
363
  isCancelled = true;
364
- // Strict Mode再マウント時にPluginManagerインスタンスが変わる場合に備えて
365
- // ロード済みリストをクリアし、新しいインスタンスで再ロードされるようにする
364
+ // Strict Mode再マウント時にプラグインが再ロード・再登録できるようにする
366
365
  loadedPluginNamesRef.current.clear();
366
+ pluginManager.resetForRemount();
367
367
  };
368
368
  }, [plugins, sounds]);
369
369
  // 初回レンダリング完了フラグ
@@ -517,7 +517,7 @@ export const Player = ({ scenario: scenarioProp, settings, plugins = EMPTY_PLUGI
517
517
  }, [pluginManager, branchState]);
518
518
  // ダイアログ表示とアクションノード実行のuseEffectを分離
519
519
  useEffect(() => {
520
- if (currentBlock) {
520
+ if (currentBlock && isFirstRenderComplete && pluginsLoaded) {
521
521
  // fullscreen_text は独自のタイプライターを使うので、displayTextをクリアしてスキップ
522
522
  if (currentBlock.blockType === "fullscreen_text") {
523
523
  startTyping("");
@@ -548,7 +548,7 @@ export const Player = ({ scenario: scenarioProp, settings, plugins = EMPTY_PLUGI
548
548
  startTyping(content, false);
549
549
  }
550
550
  }
551
- }, [currentBlock, previousBlock, startTyping, resetAccumulated]);
551
+ }, [currentBlock, previousBlock, startTyping, resetAccumulated, isFirstRenderComplete, pluginsLoaded]);
552
552
  // 分岐ブロック自動ロード処理
553
553
  useEffect(() => {
554
554
  if (currentBlock && currentBlock.blockType === "conversation_branch") {
@@ -433,6 +433,16 @@ export const GameScreen = memo(function GameScreen({ scenario, currentBlock, pre
433
433
  if (pendingEntranceRef.current.includes(image.objectId)) {
434
434
  opacity = 0;
435
435
  }
436
+ // useEffectが走る前の新キャラ(entranceFadesにもpendingEntranceにもまだない)を非表示
437
+ // これにより登場フェード開始前の1フレームでチラつくのを防ぐ
438
+ // ただし初回レンダリング時(prevが空)はフェードなしで即表示する
439
+ if (prevDisplayedCharIdsRef.current.size > 0 &&
440
+ entranceFadeOpacity === undefined &&
441
+ !pendingEntranceRef.current.includes(image.objectId) &&
442
+ !prevDisplayedCharIdsRef.current.has(image.objectId) &&
443
+ !isExitingChar) {
444
+ opacity = 0;
445
+ }
436
446
  // 明るさを決定
437
447
  let brightness = 1;
438
448
  if (displayedCharacters.length > 0 && displayedChar) {
@@ -77,6 +77,11 @@ export declare class PluginManager {
77
77
  executeActionNode(nodeType: string, context: unknown): Promise<void>;
78
78
  setPluginEnabled(packageName: string, enabled: boolean): void;
79
79
  cleanup(): void;
80
+ /**
81
+ * React Strict Mode の再マウント時に呼び出す。
82
+ * componentRegistry と plugins をクリアし、プラグインが再ロード・再登録できるようにする。
83
+ */
84
+ resetForRemount(): void;
80
85
  private findPluginByComponentType;
81
86
  getComponent(type: ComponentType): React.ComponentType<{
82
87
  dataAPI?: DataAPI;
@@ -975,6 +975,14 @@ export class PluginManager {
975
975
  this.storage.clear();
976
976
  this.componentRegistry.clear();
977
977
  }
978
+ /**
979
+ * React Strict Mode の再マウント時に呼び出す。
980
+ * componentRegistry と plugins をクリアし、プラグインが再ロード・再登録できるようにする。
981
+ */
982
+ resetForRemount() {
983
+ this.componentRegistry.clear();
984
+ this.plugins.clear();
985
+ }
978
986
  // Component registry helper methods
979
987
  findPluginByComponentType(type) {
980
988
  for (const [packageName, plugin] of this.plugins) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luna-editor/engine",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Luna Editor scenario playback engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",