TreeView コントロールは、3ds Max のスクリプト ツールの中でももっとも広く使用される ActiveX コントロールです。TreeView コントロールを使用したスクリプトを DotNet TreeView コントロールを使用するように変換するプロセスは、比較的単純です。
ここでは、「チュートリアル - TreeView ActiveX コントロールを使用したシーン ブラウザの開発 - 第 1 部」のトピックで紹介されている単純なスクリプトを変換の一例として取り上げてみましょう。
次のスクリプトは、元の ActiveX コードをコメント アウトして緑色のフォントで示し、新たにコメント付きの DotNet コードを追加したものです。2 つのコードを比較してみましょう。
スクリプトの変換 - 第 1 部
|
macroScript SceneTreeView category:"DotNet"
(
rollout treeview_rollout "TreeView Scene Browser"
(
/* ActiveXVersion:
fn initTreeView tv =
(
tv.Indentation = 28*15
tv.LineStyle = #tvwRootLines
)
*/
fn initTreeView tv =
(
tv.Indent= 28 --プロパティ名を変更し、値をピクセル単位で指定します。
--ルート ラインは既定値のスタイルに含まれています。
)
/* ActiveXVersion:
fn addChildren tv theNode theChildren =
(
for c in theChildren do
(
newNode = tv.Nodes.add theNode.index 4 "" c.name 0
addChildren tv newNode c.children
)
)
*/
fn addChildren theNode theChildren =
(
for c in theChildren do
(
newNode = theNode.Nodes.add c.name -- 親に追加します。
newNode.tag = dotNetMXSValue c --..tag に MXS 値を含ませることができます。
addChildren newNode c.children --新しいノードを再帰的に呼び出します。
)
)
/* ActiveX Version:
fn fillInTreeView tv =
(
theRoot = tv.Nodes.add()
theRoot.text = "WORLD ROOT"
rootNodes = for o in objects where o.parent == undefined collect o
addChildren tv theRoot rootNodes
)
*/
fn fillInTreeView tv =
(
theRoot = tv.Nodes.add "WORLD ROOT" --親ノードを追加します。
rootNodes = for o in objects where o.parent == undefined collect o
addChildren theRoot rootNodes --TreeView を渡す必要はありません。
)
/*ActiveX Version:
activeXControl tv "MSComctlLib.TreeCtrl" width:190 height:290 align:#center
*/
dotNetControl tv "TreeView" width: 190 height:290 align:#center
spinner spn_indent "Indentation" range:[0,100,28] type:#integer fieldwidth:40
/*ActiveX Version:
on tv nodeClick theNode do try(select (getNodeByName theNode.text))catch()
*/
on tv Click arg do
(
--まずマウス カーソルの下にある TreeView ノードを取得します。
--arg 引数には現在の位置に関する .x および .y の 2 つのプロパティがあります。
----内容を確認する場合は showProperties 引数を使用します。
--TreeView のメソッド GetNodeAt を使用して、クリックされたものが何かを確認します。
hitNode = tv.GetNodeAt (dotNetObject "System.Drawing.Point" arg.x arg.y)
if hitNode != undefined do --TreeView ノードがクリックされた場合には、
try(select hitNode.tag.value)catch(max select none)
--.tag の値として保管されているオブジェクトの選択を試みます。
)
--.indentation を .indent に変更します。
on spn_indent changed val do tv.indent = val
-- 以降のスクリプトは変更する必要はありません。
on treeview_rollout open do
(
initTreeView tv
fillInTreeView tv
)
)
try(destroyDialog treeview_rollout)catch()
createDialog treeview_rollout200 320
)
|
続いて、「チュートリアル - TreeView ActiveX コントロールを使用したシーン ブラウザの開発 - 第 2 部」トピックで紹介されている TreeView のサンプルの後半を見てみましょう。この例では、ActiveX の ImageList コントロールを DotNet の ImageList オブジェクトに変換し、TreeView にアイコンを追加し、ノードのカラーをシーン
オブジェクトのワイヤフレーム カラーに設定し、オブジェクトの表示状態を制御するためのチェックボックスを追加しています。
スクリプトの変換 - 第 2 部
|
macroScript SceneTreeView category:"DotNet"
(
--TreeView で使用するすべてのアイコンを保持するための ImageList オブジェクトを、
--MacroScript のローカル スコープに作成します。ActiveX では、
--ImageList はロールアウト内の UI コントロールでなくてはなりませんでした。
--ロールアウト内に ローカル DotNet オブジェクトを作成して
--ImageList をパラーメータとして関数に渡すことはできますが、
--手順は複雑です。ここでは、すべての関数は
--さらに上位のスコープで ImageList DotNet オブジェクトを「参照」します。
ilTv = dotNetObject "System.Windows.Forms.ImageList"
ilTv.imageSize = dotNetObject "System.Drawing.Size" 16 15
rollout treeview_rollout "TreeView Scene Browser"
(
/* ActiveX Version:
fn getIconFromBitmap thePath number =
(
tempBmp = openBitmap thePath
iconBmp = bitmap 16 15
for v = 0 to 14 do
setPixels iconBmp [0,v] (getPixels tempBmp [(number-1)*16, v] 16)
iconBmp.filename = getDir #image +"/_temp.bmp"
save iconBmp
close iconBmp
close tempBmp
getDir #image +"/_temp.bmp"
)
*/
--DotNet で使用するアイコンを作成する場合には、アイコンごとに 1 つのビットマップを
--作成する必要があります。DotNet のイメージ リストでは
--スクリプトの実行中はファイルがロックされるからです。
--元のスクリプトでは、単一のファイルを使用してすべてのアイコン ビットマップを
--一時的に書き出していました。このバージョンでは、3 個目の引数として渡す名前を使用して、
--個別のビットマップを書き出します。ビットマップがまだ存在しない場合は、
--アクセス エラーを回避するために、ビットマップファイルの作成のみを実行します。
fn getIconFromBitmap thePath number iconFileName =
(
theFileName = getDir #image +"\\icon_"+ iconFileName +".bmp"
if not doesFileExist theFileName do
(
tempBmp = openBitmap thePath
iconBmp = bitmap 16 15
for v = 0 to 14 do
setPixels iconBmp [0,v] (getPixels tempBmp [(number-1)*16, v] 16)
iconBmp.filename = theFileName
save iconBmp
close iconBmp
close tempBmp
)
img = dotNetClass "System.Drawing.Image" --イメージを作成します。
ilTv.images.add (img.fromFile theFileName) --リストに追加します。
)
/* ActiveX Version:
fn initTreeView tv ilTv =
(
tv.Indentation = 28*15
tv.LineStyle = #tvwRootLines
tv.checkboxes = true
tv.sorted = true
ilTv.imagewidth = 16
ilTv.imageheight = 15
iconDir = (getDir #ui) + "\\icons"
ilTv.listImages.add 1 #root (loadPicture (getIconFromBitmap (iconDir + "\\Standard_16i.bmp") 2))
ilTv.listImages.add 2 #geomnode (loadPicture (getIconFromBitmap (iconDir + "\\Standard_16i.bmp") 1))
ilTv.listImages.add 3 #light (loadPicture (getIconFromBitmap (iconDir + "\\Lights_16i.bmp") 3))
ilTv.listImages.add 4 #camera (loadPicture (getIconFromBitmap (iconDir + "\\Cameras_16i.bmp") 2))
ilTv.listImages.add 5 #helper (loadPicture (getIconFromBitmap (iconDir + "\\Helpers_16i.bmp") 1))
tv.imageList = ilTv
)
*/
fn initTreeView tv =
(
tv.Indent= 28
tv.CheckBoxes = true --ActiveX の場合と同様です。
--アイコン ディレクトリです。
--新しい colorman.resolveIconFolder() メソッドを使用して、実際の
--システム アイコンへのパスを取得することもできます。
iconDir = (getDir #ui) + "\\icons\\"
--完成した関数を各アイコンについて呼び出します。このとき、
--3 個目の引数としてアイコン名のサフィックスを渡します。
getIconFromBitmap (iconDir + "Standard_16i.bmp") 2 "Sphere"
getIconFromBitmap (iconDir + "Standard_16i.bmp") 1 "Box"
getIconFromBitmap (iconDir + "Lights_16i.bmp") 3 "Light"
getIconFromBitmap (iconDir + "Cameras_16i.bmp") 2 "Camera"
getIconFromBitmap (iconDir + "Helpers_16i.bmp") 1 "Helper"
--最後に、TreeView に ImageList を割り当てます。
tv.imageList = ilTv
)
/* ActiveX Version:
fn addChildren tv theNode theChildren =
(
for c in theChildren do
(
theIcon = case superclassof c of
(
GeometryClass: 2
Light: 3
Camera: 4
Helper: 5
Default:2
)
newNode = tv.Nodes.add theNode.index 4 "" c.name theIcon
theNode.sorted = true
newNode.checked = not c.isHidden
newNode.forecolor = color c.wirecolor.b c.wirecolor.g c.wirecolor.r
addChildren tv newNode c.children
)
)
*/
fn addChildren theNode theChildren =
(
for c in theChildren do
(
newNode = theNode.Nodes.add c.name
newNode.tag = dotNetMXSValue c
--既定値では、.iconIndex プロパティおよび .selectedIconIndex プロパティで
--具体的に指定しない限り、すべてのノードでアイコン 0(1 個目のアイコン)が
--使用されます。 ここでは、シーン オブジェクトのスーパークラスに対応する
--アイコンに対してこの 2 つのプロパティを設定します。
newNode.imageIndex = newNode.selectedImageIndex = case superclassof c of
(
Default: 1
Light: 2
Camera: 3
Helper: 4
)
newNode.checked = not c.isHidden--ActiveX の場合と同様です。
--カラーについては、オブジェクトのワイヤカラーから DotNet カラー クラスを
--作成して、TreeView ノードの .forecolor に
--割り当てます。
newNode.forecolor = (dotNetClass "System.Drawing.Color").fromARGB c.wirecolor.r c.wirecolor.g c.wirecolor.b
addChildren newNode c.children
)
)
--特に指定しない限りは、各ノードでインデックス 0 のアイコンが使用されるので、
--既定値ではルート ノードでは 1 個目のアイコンが使用されます。
fn fillInTreeView tv =
(
theRoot = tv.Nodes.add "WORLD ROOT"
rootNodes =for o in objects where o.parent == undefined collect o
addChildren theRoot rootNodes
)
dotNetControl tv "TreeView" width:290 height:490 align:#center
on tv Click arg do
(
hitNode = tv.GetNodeAt (dotNetObject "System.Drawing.Point" arg.x arg.y)
if hitNode != undefined do
try(select hitNode.tag.value)catch(max select none)
)
/*
on tv NodeCheck theNode do
(
theSceneNode = (getNodeByName theNode.text)
if theSceneNode != undefined do
theSceneNode.isHidden = not theNode.checked
)
*/
--ActiveX コントロールの場合には、TreeView ノードによって表示される名前を
--使用していました。DotNet では、
--シーン オブジェクトをポイントする実際の MAXScript の値を使用しています。
-- arg 引数は、チェックされたノードが含まれているノード プロパティを
--提供します。.tag プロパティを使用して TreeView ノード内に保存されている
--DotNetMXSValue にアクセスし、.value プロパティを使用して DotNetMXSValue に保存されている
-- MAXScript 値にアクセスします。次に、シーン オブジェクトの isHidden
--プロパティを TreeView ノードのチェック状態の反対に
--設定します。
on tv AfterCheck arg do
try (arg.node.tag.value.isHidden = not arg.node.checked)catch()
on treeview_rollout open do
(
initTreeView tv
fillInTreeView tv
)
)
try (destroyDialog treeview_rollout)catch()
createDialog treeview_rollout 300 500
)
|