- attached CardWirthPy.exe.log
バグ: 一部の条件を満たしたテキストセルを表示した後に非表示にするとセーブ時に異常終了
お疲れ様です。
β1のリリース後に本当に申し訳ございませんが、詰まったのでご教示をお願い致します……。
コモン変数を用い、再表示時の処理が「状態変数値を更新する」となっているテキストセルを表示した後に非表示にすると
セーブ時に異常終了する現象を確認しました。
検証に用いたシナリオを添付します。
最初は使用したカード名をテキストセルにした時に起きるかと思っていましたが……。
cw.sprite.background.TextCellData
のnamelist
にて、data
メンバは存在するがname
メンバがNoneであるためアサーションエラーとなります。
テキストセルを非表示する際の画面再構築コンテントで背景がリロードされ、_add_textcell
関数が呼ばれるのですが、
そこで再表示時の処理が「状態変数値を更新する」となっていて、フラグ・ステップ・コモンであるnamelist
のアイテムについて
name
メンバのみがNoneに書き換えられているためです。
いつもご迷惑をおかけする所ではあるのですが、僕は内部仕様に詳しくないので、この場合はどう修正すれば良いのでしょうか。
Comments (11)
-
reporter -
repo owner namelist
すなわちNameListItem
のリストはテキストセルやメッセージに表示される特殊文字の内容をリスト化して記録したものですが、その構造は基本的にはitem.name
には実際に表示される文字列が入るitem.data
にはその文字列の由来となったデータ(#M
や#R
なら該当キャラクターのインスタンス、状態変数値ならフラグやステップのインスタンス、等)が入る
……となっています。
が、コモンの場合は少々ややこしく、なぜそうしたのか自分でもよく分からないのですが(型情報が必要という事なのだろうが今見るとテキストとして表示するだけのデータの型情報を記録する必要が無さそうに思えるので単なる判断ミスの可能性もある)、コモンの場合は例外として
item.name
にコモン値そのもの(数値だったり真偽値だったりする)が入っており、そしてそれを型情報と共にセーブデータに保存しています。テキストセルをいちど表示したあと消すと、そのセルの設定にもよりますが、セルに表示されているコモン値は存在しない状態、すなわち
None
になります。これがセーブ処理の想定から抜けていた部分で、バグの原因です。これを解決するには
None
値をきちんとセーブデータに書き出す仕様が必要です。cw.xmlcreater.create_scenariolog()
から問題のアサーションを削除し、elif isinstance(item.data, cw.data.Variant): e_name.set("type", "Variant") e_name.set("variant", item.data.name) if isinstance(item.name, list): cw.data.Variant.value_to_element(item.name, e_name, typeattr="valuetype") elif isinstance(item.name, bool) or not isinstance(item.name, int) e_name.set("valuetype", cw.data.Variant.value_to_type(item.name)) e_name.text = cw.data.Variant.value_to_str(item.name) else: assert item.name is None
のように変更して、
valuetype
を書き出さない場合は値はNone
である、という事にするのがよさそうに思えます。読み出し側(
cw.sprite.background.BackGround._create_textcelldata()
では:elif vtype == "Variant": name2 = e_name.getattr(".", "variant", "") if e_name.getattr(".", "valuetype", None): name = cw.data.Variant.value_from_element(e_name, "valuetype", None) else: name = None if name2 in cw.cwpy.sdata.variants: data = cw.cwpy.sdata.variants[name2] else: data = None
のようになるでしょうか(
valuetype
がなかったらname
をNone
にする)。 -
reporter ご多忙の中、ご教示頂いた上、コードまで提示頂きまして誠に恐縮です。手許でも正常な動作を確認いたしました。
お手隙の際にご確認をよろしくお願いいたします。 -
repo owner マージしました。ありがとうございました。
-
reporter それで、すみません……今、非常に混乱しているのですが、
今朝方確認したところ、直っておりません。僕は一体昨日何を見たんだ。
後でエラーログも念の為もうひとたび添付いたしますが、
コードの場所を移動させたassert item.name is not None
でアサーションエラーになります。item.name
をNone
として書き出すべきという話でしたが、
str(None)
が"None"
となるため、文字列"None"
を書き出す必要があるのでしょうか。
その場合、実際のコモン変数の中身として"None"
が入っている場合、見分けがつかないので、どうしたものでしょう。申し訳ございませんがご助力お願いいたします……。ちょっと頭冷やしてきます。
-
reporter - attached CardWirthPy_20200724.exe.log
-
repo owner ありゃ、アサーションの条件が逆になってますね。ここに来る場合、
item.name
はNone
のはずです。 -
reporter 時間があき、申し訳ありません。
件のアサーションの部分は、`item.Name`が`None`の時も実文字列がある場合も通る箇所であり、アサーションというよりif文にした方がよいという形と認識しております。こうする事で、
None
が入る際も中身のないxmlになると思います。こんな時間で恐れ入りますが、お手隙の際にご確認いただきますよう、お願いいたします。 -
repo owner 上記マージしました。ありがとうございます。
構造体対応の問題があったので私の方で追加で修正しておきます。
-
repo owner -
reporter - changed status to resolved
お疲れ様です。時間が経ちまして恐れ入りますが本件解決済み&投稿者が僕につきクローズ操作いたします。
- Log in to comment