Visual検索の方法 後編
皆さんこんにちは、Emulate3Dの技術担当の大竹です。
今回は、前回に引き続きEmulate3D で利用頻度の高いVisual検索についてご紹介します。
前編・後編に分かれているため、よろしければこちらもご一緒にご覧ください。
目次
□「指定した条件」に一致する全ての子Visualを取得する方法
対象Visualの子供から検索
対象Visualの子供から検索する方法での特徴は、
シーン上に存在する他のVisualを気にせず、対象Visualから特定のVisualを検索出来る点です。
以下のモデルをサンプルとして、動作を確認します。
こちらのサンプルモデルでは、対象Visualはコンベヤに流れる「Pallet」です。
「Pallet」の子供に「Tote」があり、「Tote」の子供に「Box」があります。
対象Visualの子供からVisualを検索する方法は、
大きく分けて以下の4種類あります。
●「名前」で1個の子Visualを取得する方法
●「名前」で複数の子Visualを取得する方法
●「タイプ」で複数の子Visualを取得する方法
●「指定した条件」に一致する全ての子Visualを取得する方法
「名前」で1個の子Visualを取得する方法
1つ目は対象Visualから「名前」で1個の子Visualを取得する方法です。
対象Visual内で一意に存在する子Visualを取得したい時に便利です。
C#の場合
var yellowBox = load.FindChild("YellowBox");
var yellowBox = load.FindImmediateChild("YellowBox");
JScriptの場合
var yellowBox : Visual = load.FindChild("YellowBox");
var yellowBox : Visual = load.FindImmediateChild("YellowBox");
各2つの処理では、検索したいVisual名を渡して一致するVisualを取得出来ます。
もし、同じ名前のVisualが複数対象Visualの子供として存在する場合は、どれか1個のみを取得します。
また、FindChild関数とFindImmediateChild関数は、同じように対象Visualの子供を取得しますが、大きな違いが1つあります。
それは「全ての子供から検索」するか「直下の子供から検索」するかの違いです。
図に表すとこんな感じですね。
対象Visualの構成は上図のようになっています。
FindChild関数の場合、対象Visualの「Pallet」の全ての子供は「Tote」と「Box」が検索対象であるのに対し、
FindImmediateChild関数の場合は直下の「Tote」のみ検索対象です。
先ほどの図に加えると、こんな感じです。
今回のサンプルコードの場合、検索する名前が「YellowBox」だったため、
FindImmediateChild関数での取得は無し、
FindChild関数では以下の4個のうち1個を取得します。
「名前」で複数の子Visualを取得する方法
2つ目は対象Visualから「名前」で複数の子Visualを取得する方法です。
対象Visual内で複数の同じ名前の子Visualに対して何か実行したい時に便利です。
C#の場合
var tobox-03-blue = load.FindImmediateChildren("BlueTote");
JScriptの場合
var tobox-03-blue : IEnumerable<Visual> = load.FindImmediateChildren("BlueTote");
FindImmediateChildren関数では、直下に存在する子供から指定された名前のVisualを全て取得出来ます。
サンプルモデルで搬送されているPallet上のToteの名前を全て一緒の「BlueTote」にした場合、「BlueTote」の以下の4個のVisualが取得出来ます。
「タイプ」で複数の子Visualを取得する方法
3つ目は対象Visualの「タイプ」で複数の子Visualを取得する方法です。
対象Visual内で複数の同じTypeの子Visualに対して何か実行したい時に便利です。
C#の場合
var boxs = load.FindType(typeof(BoxVisual));
var importedMeshes = load.FindImmediateType(typeof(ImportedMeshVisual));
JScriptの場合
var boxs : ArrayList = load.FindType(BoxVisual);
var importedMeshes : ArrayList = load.FindImmediateType(ImportedMeshVisual);
各2つの処理では、検索したいTypeを渡して一致するVisualを全て取得出来ます。
FindType関数とFindImmediateType関数の違いは、1つ目で紹介した関数同様
「全ての子供から検索」するか、「直下の子供から検索」するかの違いです。
また、2つの処理は今まで紹介した関数と異なり、対象Visualも検索対象になります。
サンプルコードのFindType関数の場合、16個のBoxVisualを取得出来ます。
サンプルコードのFindImmediateType関数の場合、直下の「Tote」そして「Pallet」の5個を取得出来ます。
「指定した条件」に一致する全ての子Visualを取得する方法
4つ目は対象Visualから「指定した条件」に一致する全ての子Visualを取得する方法です。
「名前」や「Type」以外に詳細な条件を指定してVisualを取得したい時に便利です。
C#の場合
var loads = load.FilteredDescendants(
vis => (vis as PhysicsObject) is null ?
false : (vis as PhysicsObject).BodyType == PhysicsBodyType.Load
);
var loads = load.FilteredChildren(
vis => (vis as PhysicsObject) is null ?
false : (vis as PhysicsObject).BodyType == PhysicsBodyType.Load
);
JScriptの場合
var loads : IEnumerable<Visual> = load.FilteredDescendants(
vis -> defined(vis.BodyType) &&
vis.BodyType == PhysicsBodyType.Load
);
var loads : IEnumerable<Visual> = load.FilteredChildren(
vis -> defined(vis.BodyType) &&
vis.BodyType == PhysicsBodyType.Load
);
各2つの処理では、検索したい条件式を渡して一致する全てのVisualを取得出来ます。
サンプルコードでの条件は対象の子Visualが「物理オブジェクトである」かつ「BodyTypeがLoadである」の2点です。
また、今回の書き方はラムダ式と三項演算子を組み合わせています。
ラムダ式って?
関数定義を呼び出し元に書く方式です。 要は使い捨て・その場限りの処理のことです。
三項演算子って?
条件を指定し、真偽の分岐処理を簡単に書く方式です。if文を簡略化したものです。
FilteredDescendants関数とFilteredChildren関数の違いは、1つ目で紹介した関数同様「全ての子供から検索」するか、「直下の子供から検索」するかの違いです。
サンプルモデルで搬送されているPallet上のLoadの中で灰色のVisualのBodyTypeを「Visual Only」にして2つの処理を実行してみます。
サンプルコードのFilteredDescendants関数の場合、「Box」 8個、「Tote」2個の合計10個を取得出来ます。
サンプルコードのFilteredChildren関数の場合、「Tote」2個を取得出来ます。
対象のVisualの子供から検索が可能なため、
一部のVisualに対して固有の操作を行いたい場合に4つの検索方法を利用してはいかがでしょうか。
まとめ
いかがでしたでしょうか。
Emulate3D で数多くのVisual検索方法があることが分かったと思いますが、
状況によっての使い分けが難しいと感じたと思います。
最後に前編・後編でご紹介した各検索方法をまとめます。
★「シーン上に置かれたVisualから検索」は、全てのVisualから検索する。
★「対象Visualの子供から検索」は、検索範囲を子供に絞って検索する。
★「プロパティから検索」は、名前や親子関係が変わっても同じVisualを検索する。
今回ご紹介した内容が、少しでも皆様のお役に立てれば幸いです。
今後もブログによりEmulate3D の操作や技術をご紹介していきますので、ご活用ください。