チュートリアル - 面領域 xView チェッカーの開発 - 第 2 部

以下のチュートリアルでは、第 1 部で作成した xView チェッカーのスクリプトを、カスタム テキスト、表示の上書き、テスト オプションの追加により拡張します。

xView チェッカーは、 3ds Max 2010 以降で使用可能です。

関連トピック:

xView ジオメトリ チェッカーへのアクセス

インタフェース: XViewChecker

全体の流れ:

新しいモード プロパティを追加し、各モードに 1 つずつ表示カラーの配列を追加します。

xView チェッカーを新しい比較モードで拡張します。

新しいモードをコントロールするドロップダウン リストをダイアログ ボックスに追加します。

テキスト上書き関数を定義します。

表示上書き関数を定義します。

xViewChecker を新しい関数に登録します。

スクリプト:

    (
    global FaceAreaChecker
    struct FaceAreaCheckerStruct
    (
    FaceAreaThresholdMin = 1,
    FaceAreaThresholdMax = 10,
    FaceAreaMode = 1,
    faceAreaDialog = undefined,
    InteractiveUpdates = true,
    iniFileName = (getDir #plugcfg +"\\FaceAreaXViewChecker.ini"),
    resultColors = #(green, blue+green*0.5, red+yellow*0.5, blue, yellow, red),

    fn geomCheck theTime theNode theResults =
    (
      local theCount = case classof theNode of
      (
        Editable_Poly: getNumFaces theNode
        Editable_Mesh: theNode.numfaces
      )
      local theAreaMethod = case classof theNode of
      (
        Editable_Poly: polyOp.getFaceArea
        Editable_Mesh: meshOp.getFaceArea
      )

      for f = 1 to theCount do
      (
        local theArea = theAreaMethod theNode f
        case FaceAreaChecker.FaceAreaMode of
        (
          default:if theArea >= FaceAreaChecker.FaceAreaThresholdMin and theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
          2: if theArea <= FaceAreaChecker.FaceAreaThresholdMin do append theResults f
          3: if theArea >= FaceAreaChecker.FaceAreaThresholdMin do append theResults f
          4: if theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
          5: if theArea >= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
          6: if theArea <= FaceAreaChecker.FaceAreaThresholdMin or theArea >= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
        )
      )
    3
    ),

    fn supportedCheck theNode =
    (
      classof theNode == Editable_Mesh or classof theNode == Editable_Poly
    ),

    fn configDlg =
    (
      try(destroyDialog FaceAreaChecker.faceAreaDialog)catch()
      rollout faceAreaDialog "Face Area Checker"
      (
        dropdownlist ddl_FaceAreaMode width:150 align:#left offset:[-10,-3] items:#("Between Min. and Max","Less Than Min.","Greater Than Min.","Less Than Max.","Greater Than Max.","Not Between Min. and Max") selection:FaceAreaChecker.FaceAreaMode across:2
        colorpicker clr_resultsColor fieldwidth:10 align:#right offset:[7,-3] color:FaceAreaChecker.resultColors[FaceAreaChecker.FaceAreaMode]
        spinner spn_FaceAreaThresholdMin "Min. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMin] offset:[7,-3] type:#worldUnits
        spinner spn_FaceAreaThresholdMax "Max. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMax] offset:[7,-3] type:#worldUnits
        checkbox chk_InteractiveUpdates "Interactive" checked:FaceAreaChecker.InteractiveUpdates offset:[0,-3] across:2
        button btn_selectResults "Selection" align:#right width:72 height:18 offset:[7,-3]

        fn updateDisplay =
        (
          if FaceAreaChecker.InteractiveUpdates do
          (
            XViewChecker.runCheck CurrentTime
            maxviews redraw
          )
        )
        on ddl_FaceAreaMode selected itm do
        (
          FaceAreaChecker.FaceAreaMode = itm
          updateDisplay()
          clr_resultsColor.color = FaceAreaChecker.resultColors[itm]
        )
        on clr_resultsColor changed val do
        (
          FaceAreaChecker.resultColors[ddl_FaceAreaMode.selection] = val
          updateDisplay()
        )
        on chk_InteractiveUpdates changed state do
        (
          FaceAreaChecker.InteractiveUpdates = state
          updateDisplay()
        )
        on spn_FaceAreaThresholdMin changed val do
        (
          FaceAreaChecker.FaceAreaThresholdMin = val
          updateDisplay()
        )
        on spn_FaceAreaThresholdMax changed val do
        (
          FaceAreaChecker.FaceAreaThresholdMax = val
          updateDisplay()
        )   
        on btn_selectResults pressed do
        (
          XViewChecker.selectResults CurrentTime
          maxviews redraw
        )
        on faceAreaDialog moved pos do setIniSetting FaceAreaChecker.iniFileName "Dialog" "Position"(pos as string)
      )--end rollout

      local thePos = execute (getIniSetting FaceAreaChecker.iniFileName "Dialog" "Position")
      if classof thePos != Point2 do thePos = mouse.screenpos
      createDialog faceAreaDialog 170 82 thePos.x thePos.y
      FaceAreaChecker.faceAreaDialog = faceAreaDialog
    ),

    fn textOverride =
    (
      case FaceAreaChecker.FaceAreaMode of
      (
        1: "Between "+FaceAreaChecker.FaceAreaThresholdMin as string +" and "+FaceAreaChecker.FaceAreaThresholdMax as string
        2: "Less Than "+FaceAreaChecker.FaceAreaThresholdMin as string
        3: "Greater Than "+FaceAreaChecker.FaceAreaThresholdMin as string
        4: "Less Than "+FaceAreaChecker.FaceAreaThresholdMax as string
        5: "Greater Than "+FaceAreaChecker.FaceAreaThresholdMax as string
        6: "Not Between "+FaceAreaChecker.FaceAreaThresholdMin as string +" and "+FaceAreaChecker.FaceAreaThresholdMax as string
      )
    ),

    fn dispOverride theTime theNode theHwnd theResults=
    (
      local theColor = FaceAreaChecker.resultColors[FaceAreaChecker.FaceAreaMode]
      XViewChecker.displayResults theColor theTime theNode theHwnd 3 (for o in theResults collect o+1)
    )
    )--end struct

    try(destroyDialog FaceAreaChecker.faceAreaDialog)catch()
    FaceAreaChecker = FaceAreaCheckerStruct()

    XViewChecker.unRegisterChecker "Face Area Checker"
    XViewChecker.registerChecker FaceAreaChecker.geomCheck FaceAreaChecker.supportedCheck #Faces "Face Area Checker" FaceAreaChecker.configDlg FaceAreaChecker.textOverride FaceAreaChecker.dispOverride
    )--end script

ステップごとの解説

--code in italic has not changed since Part 1
(
global FaceAreaChecker
struct FaceAreaCheckerStruct
(
FaceAreaThresholdMin = 1,
FaceAreaThresholdMax = 10, FaceAreaMode = 1,

ここでは、このチェッカーに 6 つのモードを追加します。 このため、現在のモードを格納するプロパティが必要になります。

faceAreaDialog = undefined, InteractiveUpdates = true,

新しいプロパティにより、UI コントロールへの変更がチェッカーおよびビューポートへの更新をトリガするかどうかをコントロールします。重いメッシュで作業している場合、更新を無効にすると効果的な場合があります。

iniFileName = (getDir #plugcfg +"\\FaceAreaXViewChecker.ini"),

INI ファイルに、設定ダイアログ ボックスが最後に開いていた場所を格納します。

resultColors = #(green, blue+green*0.5, red+yellow*0.5, blue, yellow, red),

各チェック モードは、この手順で追加する表示上書き関数を使用して、結果をそれぞれ異なる色で表示します。このプロパティには、表示に使用する 6 個のカラーの配列が含まれます。青に 50% の緑を足すことでシアンを、赤に 50% の黄色を足すことでオレンジを作成できます。あらかじめ定義されているグローバルの「オレンジ」を使用して同じ処理もできますが、この方法では、色合いをより細かくコントロールできます。たとえばこれを赤 + 黄色*0.75 に変えれば簡単により明るい色にすることができます。シアンにはあらかじめ定義されたグローバルはありません。

fn geomCheck theTime theNode theResults =
(
local theCount = case classof theNode of
(
Editable_Poly: getNumFaces theNode
Editable_Mesh: theNode.numfaces
)
local theAreaMethod = case classof theNode of
(
Editable_Poly: polyOp.getFaceArea
Editable_Mesh: meshOp.getFaceArea
)

for f = 1 to theCount do
(
local theArea = theAreaMethod theNode f case FaceAreaChecker.FaceAreaMode of

(
default:if theArea >= FaceAreaChecker.FaceAreaThresholdMin and theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
2: if theArea <= FaceAreaChecker.FaceAreaThresholdMin do append theResults f
3: if theArea >= FaceAreaChecker.FaceAreaThresholdMin do append theResults f
4: if theArea <= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
5: if theArea >= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
6: if theArea <= FaceAreaChecker.FaceAreaThresholdMin or theArea >= FaceAreaChecker.FaceAreaThresholdMax do append theResults f
)

チェッカーに、面領域の値を各しきい値と比較する 6 個のモードを追加します。既定値のモードは、領域が 2 つのしきい値間にある面にフラグを設定するオリジナルのモードです。その他のモードでは、領域が最小より小さい、最小より大きいけれど最大を無視する、最大より小さいけれど最小を無視する、最大より大きい、およびしきい値範囲内にない (最小より小さいまたは最大より大きい)という場合にフラグを立てます。

)
3
),

fn supportedCheck theNode =
(
classof theNode == Editable_Mesh or classof theNode == Editable_Poly
),

fn configDlg =
(
try (destroyDialog FaceAreaChecker.faceAreaDialog)catch()
rollout faceAreaDialog "Face Area Checker"
( dropdownlist ddl_FaceAreaMode width:150 align:#left offset:[-10,-3] items:#("Between Min. and Max","Less Than Min.", "Greater Than Min.","Less Than Max.", "Greater Than Max.","Not Between Min. and Max") selection:FaceAreaChecker.FaceAreaMode across:2

このドロップダウン リストは、設定ダイアログ ボックスに 6 個のチェック モードを公開します。これを構造体インスタンスのプロパティの現在値に初期化します。

colorpicker clr_resultsColor fieldwidth:10 align:#right offset:[7,-3] color:FaceAreaChecker.resultColors[FaceAreaChecker.FaceAreaMode]

ドロップダウン リストの横に、現在モードのカラーをコントロールする小さなカラー ピッカーを配置します。

spinner spn_FaceAreaThresholdMin "Min. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMin] offset:[7,-3] type:#worldUnits
spinner spn_FaceAreaThresholdMax "Max. Threshold:" range:[0,1000000,FaceAreaChecker.FaceAreaThresholdMax] offset:[7,-3] type:#worldUnits
checkbox chk_InteractiveUpdates "Interactive" checked:FaceAreaChecker.InteractiveUpdates offset:[0,-3] across:2

このチェックボックスは、ツールのインタラクティブな動作をコントロールします。

button btn_selectResults "Selection" align:#right width:72 height:18 offset:[7,-3]

このボタンは、チェッカーのメニューを表示することなく、ダイアログ ボックスから直接チェッカーのフラグをスタック上のサブオブジェクト選択に変換します。

fn updateDisplay =
( if FaceAreaChecker.InteractiveUpdates do ( XViewChecker.runCheck CurrentTime
max views redraw )

インタラクティブ/非インタラクティブ モードを実装するため、単にプロパティが true かfalse かを調べるテストを追加します。false の場合、テストとビューポートを更新しません。

) on ddl_FaceAreaMode selected itm do
(
 FaceAreaChecker.FaceAreaMode = itm
 updateDisplay()
 clr_resultsColor.color = FaceAreaChecker.resultColors[itm]
)

ドロップダウン リスト選択が変更されたら、新しい選択インデックスを構造体インスタンスの新しいプロパティに格納し、表示を更新して、さらにカラー ピッカーを現在のモードに合ったカラーに更新します。

on clr_resultsColor changed val do
(
 FaceAreaChecker.resultColors[ddl_FaceAreaMode.selection] = val
 updateDisplay()
)

カラー ピッカーが変更された場合、構造体インスタンスの配列内の現在のカラーを更新し、表示も更新します。

on chk_InteractiveUpdates changed state do
(
 FaceAreaChecker.InteractiveUpdates = state
 updateDisplay()
)

インタラクティブ モードが変更された場合、現在の状態を構造体インスタンスのプロパティに格納し、表示を更新します。

on spn_FaceAreaThresholdMin changed val do
(
 FaceAreaChecker.FaceAreaThresholdMin = val
 updateDisplay()
)
on spn_FaceAreaThresholdMax changed val do
(
 FaceAreaChecker.FaceAreaThresholdMax = val
 updateDisplay()
)   
 on btn_selectResults pressed do
(
 XViewChecker.selectResults CurrentTime
 max views redraw
)

新しいボタンが押された場合、現時点の結果を選択するためのメソッドを呼び出します。このメソッドは、XViewChecker インタフェースによって実装されているため、選択の変更を実際に表示するビューポートの再描画だけを行います。

on faceAreaDialog moved pos do setIniSetting FaceAreaChecker.iniFileName "Dialog" "Position" (pos as string)

ユーザが設定ダイアログ ボックスを移動した場合、INI ファイルに新しい位置を格納します。

)--end rollout

local thePos = execute (getIniSetting FaceAreaChecker.iniFileName "Dialog" "Position")

ダイアログ ボックスを開く前に、INI ファイルから最後に開かれていた場所を読み込みます。

if classof thePos != Point2 do thePos = mouse.screenpos

返された値が実際の位置の値ではない場合 (INI ファイルが作成されていないか、削除されている場合)、マウスの画面位置を使用します。

createDialog faceAreaDialog170 82 thePos.x thePos.y

ダイアログ ボックスを最後に開かれていた場所またはマウスの位置に開きます。さらに、最初の 2 つの引数でダイアログ ボックスの正確なサイズを指定します。

FaceAreaChecker.faceAreaDialog = faceAreaDialog
),

fn textOverride =
(
case FaceAreaChecker.FaceAreaMode of
(
1: "Between "+FaceAreaChecker.FaceAreaThresholdMin as string +" and " +FaceAreaChecker.FaceAreaThresholdMax as string
2: "Less Than "+FaceAreaChecker.FaceAreaThresholdMin as string
3: "Greater Than "+FaceAreaChecker.FaceAreaThresholdMin as string
4: "Less Than "+FaceAreaChecker.FaceAreaThresholdMax as string
5: "Greater Than "+FaceAreaChecker.FaceAreaThresholdMax as string
6: "Not Between "+FaceAreaChecker.FaceAreaThresholdMin as string +" and " +FaceAreaChecker.FaceAreaThresholdMax as string
)
),

このテキスト上書き関数は引数を取らず、ビューポートの現在のチェッカーの名前の横に表示する文字列を返します。ここでは、現在のモードと関連するしきい値だけを返すようにします。

fn dispOverride theTime theNode theHwnd theResults=
(
local theColor = FaceAreaChecker.resultColors[FaceAreaChecker.FaceAreaMode]
XViewChecker.displayResults theColor theTime theNode theHwnd 3 theResults
)

この表示上書き関数は、チェッカーのユーザ定義表示を実装するのに使用できます。引数として、時間、ノード、現在のビューポートのウィンドウ ハンドル、およびチェッカー関数によって生成される結果配列の 4 つを受け取ります。

XViewChecker インタフェースの displayResults メソッドを呼び出します。これには、カラーの配列と現在のモードに基づく結果表示に使用するカラー、時間、ノード、この関数に渡されたウィンドウ ハンドル、表示のタイプ(面の場合は 3 )、および結果の配列の 6 個の引数を渡します。

)--end struct

try (destroyDialog FaceAreaChecker.faceAreaDialog)catch()
FaceAreaChecker = FaceAreaCheckerStruct()

xViewChecker.unRegisterChecker "Face Area Checker"
xViewChecker.registerChecker FaceAreaChecker.geomCheck FaceAreaChecker.supportedCheck #Faces "Face Area Checker" FaceAreaChecker.configDlgFaceAreaChecker.textOverride FaceAreaChecker.dispOverride

チェッカーの登録時に、テキストの上書きと表示の上書きの 2 つの関数を追加する必要があります。

)--end script

スクリプトの使い方

面領域 xView チェッカーにはすべてのチェック モードが追加されましたが、設定は保持されません。次のチュートリアル 第 3 部では、INI ファイルを使用して設定を保持する機能を追加します。

新しいチェッカーを使用するには、再度シェーディング ビューポート メニュー (左から 3 番目) をクリックし、xView サブメニューから標準の xView チェッカーのいずれかを選択します。次に、ビューポート下部に表示されているチェッカーの名前をクリックし、代わりに[Face Area]を選択します。xView チェッカーをビューポート メニューに登録する方法は、チュートリアル第 4 部で説明します。

設定ダイアログ ボックスを開いて各種モードを切り替えるには、ビューポートの下部にある[ここをクリックして設定](Click Here To Configure)ラベルをクリックします。

以下の例は、編集ポリゴンに集約された 4 つのセグメントを持つ半径 40 のティーポットに、6 つすべての面領域 xView チェッカーを適用したものです。

ビューポートでの xView チェッカーの結果 設定ダイアログ ボックス モード
20 ~ 108 平方単位の領域を持つポリゴン
20 平方単位よりも大きい領域を持つポリゴン
108 平方単位未満の領域を持つポリゴン
108 平方単位よりも大きい領域を持つポリゴン
20 平方単位よりも小さい領域または 108 平方単位よりも大きい領域を持つポリゴン

チュートリアル - 面領域 xView チェッカーの開発 - 第 1 部

チュートリアル - 面領域 xView チェッカーの開発 - 第 3 部