メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

FIDocScene.h

説明を見る。
00001 #ifndef FIDOCSCENE_H
00002 #define FIDOCSCENE_H
00003 #include "FIDocNode.h"
00004 #include "FIFileDoc.h"
00005 #include "FITypeDesc.h"
00006 #include <SceneGraph/SGScene.h>
00007 
00008 /** @file FIDocScene.h ドキュメントからシーングラフをロードする仕組み   */
00009 namespace Spr{;
00010 
00011 /** ある型のドキュメントノードのローダー    */
00012 class SPR_DLL FIBaseLoader:public UTRefCount{
00013 public:
00014     /// ローダが担当する型名
00015     virtual UTString GetNodeType() const =0;
00016     /// ロード関数.子ノードがロードされる前に呼ばれる.
00017     virtual void Load(class FILoadScene* context)=0;
00018     /// ロード後処理関数.子ノードがロードされた後呼ばれる.
00019     virtual void Loaded(class FILoadScene* context){}
00020 };
00021 template <class T, bool bAdd=true, bool bCont=true> class FIObjectLoader: public FIBaseLoader{
00022 public:
00023     typedef T TLoaded;
00024     void Create(class FILoadScene* context, UTRef<TLoaded>& t){
00025         t = new TLoaded;
00026         t->SetName(context->docs.Top()->GetName().c_str(), context->scene);
00027     }
00028     /// ローダが担当するノードの型名.C++クラスの型名から接頭辞2文字をなくしたもの.
00029     virtual UTString GetNodeType() const{
00030         return TLoaded::GetTypeInfoStatic()->ClassName()+2;
00031     }
00032     /// ロード関数.子ノードがロードされる前に呼ばれる.
00033     virtual void Load(class FILoadScene* context){
00034         UTRef<TLoaded> t=NULL;
00035         Create(context, t);
00036         t->doc = context->docs.Top();
00037         t->SetName(t->doc->GetName().c_str(), context->scene);
00038         if (bAdd) context->AddObject(t);
00039         if (bCont) context->AddContainer(t);
00040         if (!LoadData(context, t)){
00041             if (bAdd){
00042                 context->CancelAddObject();
00043             }
00044         }
00045     }
00046     /// ロードの実装
00047     virtual bool LoadData(class FILoadScene* context, TLoaded* t)=0;
00048 };
00049 
00050 template <class P=SGFrame> class FIOtherLoader: public FIBaseLoader{
00051 public:
00052     /// ロード関数.子ノードがロードされる前に呼ばれる.
00053     virtual void Load(class FILoadScene* context){
00054         P* p=NULL;
00055         context->objects.Find(p);
00056         Load(context, p);
00057     }
00058     virtual void Load(class FILoadScene* context, P* p)=0;
00059     /// ロード後処理関数.子ノードがロードされた後呼ばれる.
00060 };
00061 
00062 inline bool operator < (const FIBaseLoader& t1, const FIBaseLoader& t2){
00063     return t1.GetNodeType().compare(t2.GetNodeType()) < 0;
00064 }
00065 /// 各ノードのローダーのSet
00066 class SPR_DLL FILoders:public std::multiset<FIBaseLoader*, UTContentsLess<FIBaseLoader*> >{
00067 public:
00068     class FITypeLoaderKey:public FIBaseLoader{
00069         UTString* key;
00070     public:
00071         FITypeLoaderKey(UTString& k):key(&k){}
00072         virtual UTString GetNodeType() const{ return *key; }
00073         virtual void Load(FILoadScene* context){}
00074     };
00075     iterator LowerBound(UTString s){
00076         return lower_bound(&FITypeLoaderKey(s));
00077     }
00078     iterator UpperBound(UTString s){
00079         return upper_bound(&FITypeLoaderKey(s));
00080     }
00081     std::pair<iterator, iterator> EqualRange(UTString s){
00082         return equal_range(&FITypeLoaderKey(s));
00083     }
00084     void Erase(UTString s){
00085         std::pair<iterator, iterator> r = EqualRange(s);
00086         erase(r.first, r.second);
00087     }
00088 };
00089 
00090 class SPR_DLL FIReferenceBase:public UTRefCount{
00091 protected:
00092     SGObject* Find(SGScene* s);
00093     /// リファレンス先の名前
00094     UTString name;
00095 public:
00096     virtual ~FIReferenceBase(){}
00097     /// 参照の解決
00098     virtual void SolveReference(SGScene* s)=0;
00099 };
00100 class SPR_DLL FIReferences:public std::vector< UTRef<FIReferenceBase> >{
00101 };
00102 /** リファレンス保持クラス  */
00103 template <class T>
00104 class SPR_DLL FIReference:public FIReferenceBase{
00105     /// リファレンス元ポインタのアドレス.ここを書き換える.
00106     UTRef<T>* reference;
00107     /// 
00108 public:
00109     FIReference(UTRef<T>& t, UTString n): reference(&t) { name=n; }
00110     /// 参照の解決
00111     virtual void SolveReference(SGScene* s){
00112         T* t = (T*)Find(s);
00113         *reference = t;
00114 //      reference->ForceOverWrite(t);
00115 //      t->AddRef();
00116     }
00117 };
00118 template <class CT>
00119 class SPR_DLL FIReferenceVector:public FIReferenceBase{
00120     /// リファレンス元ポインタのアドレス.ここを書き換える.
00121     CT* container;
00122     typedef TYPENAME CT::value_type T;
00123     int pos;
00124 public:
00125     FIReferenceVector(CT& c, int p, UTString n): container(&c), pos(p) { name=n; }
00126     /// 参照の解決
00127     virtual void SolveReference(SGScene* s){
00128         T t = T(UTRef<SGObject>(Find(s)));
00129         (*container)[pos] = t;
00130     }
00131 };
00132 template <class T>
00133 FIReference<T>* createFIReference(UTRef<T>& t, UTString n){
00134     return new FIReference<T>(t, n);
00135 }
00136 template <class CT>
00137 FIReferenceVector<CT>* createFIReference(CT& ct, int p, UTString n){
00138     return new FIReferenceVector<CT>(ct, p, n);
00139 }
00140 
00141 class SPR_DLL FILink: public SGObject{
00142 public:
00143     SGOBJECTDEF(FILink);
00144     UTString linkName;
00145 };
00146 class SGObject;
00147 class SPR_DLL FIObjectAdder{
00148 public:
00149     /// 追加先のオブジェクト
00150     SGObjects containers;
00151     /// 追加するオブジェクト
00152     SGObjects objects;
00153     /// 参照を解決
00154     void Link(SGScene* scene);
00155     void Add(SGObject* obj);
00156     void Add(UTString name);
00157 };
00158 class SPR_DLL FIObjectAdders:public UTStack<FIObjectAdder>{
00159 public:
00160 };
00161 
00162 /** ドキュメントノードのツリーを読んでシーングラフを作る.
00163     コンテキストも保持する.
00164     ドキュメントノードには,型があり型ごとにローダが用意できる.
00165     型ごとのローダーはFIBaseLoaderを派生させて作る.
00166 */
00167 class SPR_DLL FILoadScene:public UTRefCount{
00168     /// 型ごとのローダー
00169     FILoders loaders;
00170     /** オブジェクトの追加リスト(参照解決後に追加する)
00171         追加すべきコンテナが途中で増えることがあるので,
00172         まずadderStackに入れておき,それをこちらに移す.*/
00173     FIObjectAdders adders;
00174     /** オブジェクトの追加リストのスタック.ノードごとにPush,Popする.
00175         ひとつのノードが複数のローダを持つ場合,ロード中にコンテナが増えることがある.
00176         そこで,ロード中の追加リストと,ロード先のコンテナをひとまずここに入れておく.
00177         Popするときに,追加リストをadders に移す.*/
00178     FIObjectAdders adderStack;
00179     /// 子ノードのためのコンテナリスト
00180     SGObjects containers;
00181 public:
00182     /// @name 各ノードのローダが使うメンバ
00183     //@{
00184     /// もとのファイル名
00185     UTString fileName;
00186     /// ロード元のドキュメントのスタック
00187     FIDocNodes docs;
00188     /// ロード先シーン
00189     UTRef<SGScene> scene;
00190     /// ロード中に使うオブジェクトのスタック
00191     SGObjects objects;
00192     /// ロードしたオブジェクトを現在のコンテナに追加
00193     void AddObject(SGObject* obj);
00194     /// ロードしたリファレンスを現在のコンテナに追加
00195     void AddObject(UTString name);
00196     /// 最後の追加をキャンセル
00197     void CancelAddObject();
00198     /// コンテナを追加
00199     void AddContainer(SGObject* cont){
00200         containers.Push(cont);
00201     }
00202     /// コンテナスタックをPush.成功するとtrueを返す.
00203     bool PushContainer();
00204     /// コンテナスタックをPop
00205     void PopContainer();
00206     //@}
00207 
00208     //@name 外部から呼び出す関数.
00209     //@{
00210     /// ドキュメントオブジェクトからシーングラフを作成
00211     virtual void Load(SGScene* s, SGObject* obj, FIFileDoc* fileDoc);
00212     virtual void Load(SGScene* s, FIFileDoc* fileDoc);
00213     virtual void Load(SGScene* s, SGObject* obj, FIDocNodes& docs);
00214     virtual void Load(SGScene* s, FIDocNodes& docs);
00215     /// ローダーを登録
00216     void Register(FIBaseLoader* l){ loaders.insert(l); }
00217     /// ローダーを削除
00218     void Erase(UTString k){ loaders.Erase(k); }
00219     /// ドキュメントオブジェクトからシーングラフを作成
00220     virtual void LoadRecursive();
00221     //@}
00222 
00223 
00224 protected:
00225     /// 参照の解決.
00226     void SolveReferences();
00227     /// オブジェクトの追加.
00228     void AddObjects();
00229 };
00230 
00231 /// ある型(SGFrame/Visual/..) を保存するセーバー
00232 class FIBaseSaver:public UTRefCount{
00233 public:
00234     virtual UTString GetType() const =0;
00235     virtual UTString GetNodeType() const { return GetType().substr(2); }
00236     virtual void Save(class FISaveScene* ctx, SGObject* target){}
00237 };
00238 inline bool operator < (const FIBaseSaver& t1, const FIBaseSaver& t2){
00239     return t1.GetType().compare(t2.GetType()) < 0;
00240 }
00241 /// SGObjectのためのセーバー
00242 template <class T, bool bAdd=true, bool bCont=true> class FIObjectSaver: public FIBaseSaver{
00243 public:
00244     typedef T TSaved;
00245     /// 型名
00246     virtual UTString GetType() const {
00247         return TSaved::GetTypeInfoStatic()->ClassName();
00248     }
00249     /// データのセーブ.オーバーライドしてください.
00250     virtual void SaveData(class FISaveScene* ctx, FIDocNodeBase* doc, TSaved* target)=0;
00251     /// セーブ
00252     virtual void Save(class FISaveScene* ctx, SGObject* target){
00253         TSaved* t = (TSaved*) target;
00254         UTRef<FIDocNodeBase> doc = t->doc;
00255         if (!doc) doc = ctx->CreateDocNode(GetNodeType(), t);
00256         doc->SetName(target->GetName());
00257         doc->ClearChildren();
00258         SaveData(ctx, doc, t);
00259         ctx->AddSavedObject(target);
00260         if (bAdd) ctx->docs.Top()->AddChild(doc);
00261         if (bCont){
00262             ctx->docs.Push(doc);
00263             for(unsigned i=0; i<t->NChildObjects(); ++i){
00264                 if(ctx->IsSavedObject(t->ChildObject(i))){
00265                     ctx->SaveReference(t->ChildObject(i));
00266                 }else{
00267                     ctx->SaveRecursive(t->ChildObject(i));
00268                 }
00269             }
00270             for(unsigned i=0; i<t->NReferenceObjects(); ++i){
00271                 ctx->SaveReference(t->ReferenceObject(i));
00272             }
00273             ctx->docs.Pop();
00274         }
00275     }
00276 };
00277 
00278 /// ある型(SGFrame/Visual/..) を保存するセーバーのSet
00279 class FISavers:public std::set<FIBaseSaver*, UTContentsLess<FIBaseSaver*> >{
00280 public:
00281     class FITypeSaverKey:public FIBaseSaver{
00282         UTString* key;
00283     public:
00284         FITypeSaverKey(UTString& k):key(&k){}
00285         virtual UTString GetType() const{ return *key; }
00286         virtual void Save(FISaveScene* context, SGObject* target){}
00287     };
00288     iterator Find(UTString s){
00289         return find(&FITypeSaverKey(s));
00290     }
00291 };
00292 /** シーングラフをドキュメントにセーブするセーバー
00293 */
00294 class SPR_DLL FISaveScene:public UTRefCount{
00295 protected:
00296     /// 型ごとのセーバー
00297     FISavers savers;
00298     /// ドキュメントノードの生成
00299     virtual UTRef<FIDocNodeBase> CreateDocNodeImp(UTString type)=0;
00300 public:
00301     /// セーブするシーン
00302     UTRef<SGScene> scene;
00303     /// ドキュメントノードのスタック
00304     FIDocNodes docs;
00305     /// セーブ済みオブジェクトの記録
00306     std::set<SGObject*> savedObjects;
00307     /// ドキュメントノードの作成
00308     virtual UTRef<FIDocNodeBase> CreateDocNode(UTString type, SGObject* o=NULL){
00309         UTRef<FIDocNodeBase> doc = CreateDocNodeImp(type);
00310         if (o){
00311             doc->SetName(o->GetName());
00312             if (type.compare("REF")!=0) o->doc = doc;
00313         }
00314         return doc;
00315     }
00316     /// シーングラフの特定のノード以下をセーブ
00317     virtual void Save(FIDocNodeBase* doc, SGScene* s, SGObject* obj=NULL);
00318     /// Saveの再帰部
00319     virtual void SaveRecursive(SGObject* obj);
00320     /// 参照をセーブ
00321     virtual void SaveReference(SGObject* obj);
00322     
00323     /// 特定の型のセーバーを登録
00324     void Register(FIBaseSaver* s){ savers.insert(s); }
00325     /// セーブ済みオブジェクトの登録
00326     void AddSavedObject(SGObject * o){
00327         if (!savedObjects.insert(o).second){
00328             DSTR << "Fail to insert " << o->GetTypeInfo()->ClassName() << ":" << o->GetName() << std::endl;
00329         }
00330     }
00331     /// セーブ済みオブジェクトかどうか判定
00332     bool IsSavedObject(SGObject * o){
00333         return savedObjects.find(o) != savedObjects.end();
00334     }
00335 };
00336 
00337 #define DEF_REGISTER_LOADER(cls)                \
00338 void RegisterLoaderFor##cls(FILoadScene* l){    \
00339     static cls##Loader load_##cls;              \
00340     l->Register(&load_##cls);                   \
00341 }
00342 
00343 #define DEF_REGISTER_SAVER(cls)             \
00344 void RegisterSaverFor##cls(FISaveScene* s){ \
00345     static cls##Saver save_##cls;           \
00346     s->Register(&save_##cls);               \
00347 }
00348 
00349 #define DEF_REGISTER_BOTH(cls)  DEF_REGISTER_SAVER(cls) DEF_REGISTER_LOADER(cls)
00350 
00351 #define REGISTER_LOADER(l, cls)                                 \
00352     extern void RegisterLoaderFor##cls(FILoadScene* ld);        \
00353     RegisterLoaderFor##cls(l);                                  \
00354 
00355 #define REGISTER_SAVER(s, cls)                                  \
00356     extern void RegisterSaverFor##cls(FISaveScene* sv);         \
00357     RegisterSaverFor##cls(s);                                   \
00358 
00359 }
00360 #endif

Springheadに対してSun Apr 16 01:57:51 2006に生成されました。  doxygen 1.4.1