Metasequoia BBS

| New message | Normal | Tree |
Status
Tag
Keyword
[4304] マテリアルを完全に削除できないバグ - mqsdk411 / tamachan
Done [Bug report] Response
SDK: mqsdk411(C++)
Metaseq: 4.1.1 (64bit)

マテリアルを1つ残らず削除することができません。削除してもマテリアルパネルにマテリアル1つ残った状態になり、そのマテリアルを開いた瞬間にクラッシュします。

サンプルコード(メタセコの初期状態から下のコード実行で再現可能):
      int numMat = doc->GetMaterialCount();
      for(int i=0;i<numMat;i++)
      {
        if(doc->GetMaterial(i))doc->DeleteMaterial(i);
      }
#ifdef _DEBUG
      numMat = doc->GetMaterialCount();
      for(int i=0;i<numMat;i++)
      {
        ATLTRACE(_T("DEBUG(Material-%d): 0x%08X\n"), i, doc->GetMaterial(i));
      }
#endif

上のコード(_DEBUG)のTRACE結果:

Show more...
2014-03-03 03:08
[4305] Re: マテリアルを完全に削除できないバグ - mqsdk411 / Administrator
マテリアルパネルに残るのはイベント時にFALSEを返しているのではないでしょうか?
ドキュメント内のものに変更を加えた場合、TRUEを返さないと更新処理が行われず、その後の動作にも影響を与えることになります。
2014-03-03 10:42
[4308] Re: Re: マテリアルを完全に削除できないバグ - mqsdk411 / tamachan
ExecuteCallbackが何故かfalseを返してたので、trueに書き換え直しましたが同症状で落ちます。

  void AllClearObj(MQDocument doc)
  {
    int numObj = doc->GetObjectCount();
    for(int i=0; i<numObj; i++)
    {
      if(doc->GetObject(i))doc->DeleteObject(i);
    }
  }

みたいなコードはちゃんとobjが全部削除されます。マテリアルだけ残ります。APIがリストビューから削除し忘れているっぽい症状です。
2014-03-03 17:12
[4309] Re: Re: Re: マテリアルを完全に削除できないバグ - mqsdk411 / tamachan
http://goz-metaseq.googlecode.com/archive/5920667803893f9b77548c4cb2f2d0931fa2df2d.zip
をダウンロードして、GoM.h、ImportGoZのCleanup4Import();以外の場所を適当にコメントアウトしてもらえれば再現できます。
2014-03-03 17:15
[4310] Re: Re: Re: Re: マテリアルを完全に削除できないバグ - mqsdk411 / tamachan
あと余談なのですが・・・これはAPIの仕様だとは思うのですが、マテリアルだけ(オブジェクト版はちゃんと削除できる)無限ループになってました。

こんなコード:
for(int i=0;i<doc->GetMaterialCount();i++)doc->DeleteMaterial(0);
2014-03-03 17:26
[4311] Re: Re: Re: Re: Re: マテリアルを完全に削除できないバグ - mqsdk411 / tamachan
コード間違えました
while(doc->GetMaterialCount())doc->DeleteMaterial(0);
2014-03-03 17:27
[4312] Re: Re: Re: Re: Re: Re: マテリアルを完全に削除できないバグ - mqsdk411 / Administrator
ImportGoZ()内の最後にあるMQ_RefreshView(NULL)の呼び出しをコメントアウトしてください。
これは本体に制御が戻る前に描画が行われると更新フラグが消えてしまう実装になっているためです。
まずい実装なので今後改善する可能性もありますが、RedrawAllScene()で再描画の予約がされているため、どのみちここではMQ_RefreshViewは不要かと。

また、Compact()を呼び出すまではインデックスの切り詰めは行われず、
DeleteMaterial()ではNULLに置き換わるだけなので、当該コードでは無限ループとなります。
2014-03-03 18:57