2008.12.28 作成 -----------------------------------------------------------------   エクスプレッションのサンプルまとめ for コピペプログラミング ----------------------------------------------------------------- ●エクスプレッションとは、キーフレームを打つかわりに、C#のプログラムで   マテリアルやエフェクトのパラメータ(プロパティ)を制御するという仕組みのことです。   プログラミングの知識があれば、キーフレームだけでは実現できないような   処理を行わせることもできます。 ●これは、     「C#はよく知らないけど、サンプルソースがあれば多分それなりにコピペ応用はできるよ!」   という人(例えば私とか)のためのエクスプレッションサンプルまとめです。     「やべっ、ここってどうやって書くんだっけ?」     「あれ?この情報ってどうやって取ればいいんだっけ?」   というボケが多い自分のために、覚え書き代わりに作ってみました。   よく使うコードの例や、便利に応用できるコードなどを自分なりにまとめています。 ●NiVEのエクスプレッションの仕様については、NiVE本体に付属している     プラグイン開発について.txt     エクスプレッションについて.txt   などを参照して下さい。 ●掲載しているエクスプレッションサンプルの多くは、NiVEサンプルとして公開されている   サンプルプロジェクトから抜粋し、自分なりの改造や説明の追記を行っています。   サンプルプロジェクト作者様、ありがとうございます。 ●説明の都合上、どこに書くエクスプレッションなのかを以下の呼び方で分類しています。     エフェクトエクスプレッション・・・エフェクトのところに書くもの     マテリアルエクスプレッション・・・マテリアルのところに書くもの     テキストエクスプレッション・・・テキストトラックのテキストマテリアルのところに書くもの     アニメータエクスプレッション・・・テキストトラックのテキストアニメータのところに書くもの ●ソース内の【】で囲まれた部分は、状況にあわせた内容を記述する必要がある部分です。   【】内の説明にあわせて適切な内容に置き換えて下さい。 ●サンプルプロジェクトの内容について、     「変えないといけないかも」   と思って変更した部分には「★」をつけてコメントをしています。 ●ここの説明だけではよくわからない部分もあると思うので、   ベースとなるNiVEサンプルのサンプルプロジェクトのほうも、必ず参照して下さい。   NiVEサンプルのサンプルプロジェクトは、     http://www.geocities.jp/goldenhige/NiVE/sample_backup.html   にまとめて置いてあります。 ●細かいデバッグなどはしていないので、バグが含まれている可能性もあります。   冒頭に書いたように、私はまだC#をちゃんと理解していませんので・・・。   内容を理解していただいたうえで、自己責任でご利用願います。 ●いずれはもっとちゃんとした形でまとめたいと思いますが、とりあえずテキスト形式で公開。   ちょくちょく変更するかもしれません。 ■■■■■■■■■■■■■■■■■ 配列の作り方 ■■■■■■■■■■■■■■■■■ // 説明 // 基本だけど、時々書き方忘れるオイラって・・・ int[] i_array = new int[10]; int[] i_array2 = new int[] {1,2,3,4}; ■■■■■■■■■■■■■■■■■ リストの作成・要素の追加・配列化 ■■■■■■■■■■■■■■■■■ // リストの作成 List tracks = new List(); // リストの要素追加 tracks.Add(【IExpressionItem型の要素】); // リストを配列化する IExpressionItem[] items = tracks.ToArray(); ■■■■■■■■■■■■■■■■■ プロパティモニタの使い方 ■■■■■■■■■■■■■■■■■ // 説明 // プロパティモニタは、プロパティの型や値などを調べるための仕組み。 // MonitorPropertyというリストに、調べたいプロパティを挿入しておくと、 // 「プロパティモニタ」のタブで、そのプロパティの型や値を見ることができる。 // Add()に渡すプロパティのプログラム表現は、該当プロパティのところで // 右クリックメニューから「エクスプレッションにコピー」などを行うことで取得できます。 // // 下の例は、マテリアルエクスプレッションで「位置」のプロパティを調べる例。 MonitorProperty.Add(ExpressionUtils.GetProperty(Property.ThisProperty, "位置")); ■■■■■■■■■■■■■■■■■ フレーム番号の取得 ■■■■■■■■■■■■■■■■■ // 説明 // Property.Indexは、「フレーム番号−1」が入っています。 int frameno = Property.Index +1; ■■■■■■■■■■■■■■■■■■■■ コンポジションのサイズ(外枠)・fps・長さの取得 ■■■■■■■■■■■■■■■■■■■■ // 説明 // コンポジションのサイズ・fps・長さの情報は、Property.Hostから取得できる。 // 名前に"Project"がついてるのは、v1.50以前は // 1プロジェクトで1コンポジションしか扱えなかった名残かな? // コンポジションのサイズ Size comp_size = Property.Host.ProjectSize; // コンポジションのfps double comp_fps = Property.Host.ProjectFrameRate; // コンポジションの長さ int com_len = Property.Host.ProjectLength; ■■■■■■■■■■■■■■■■■■■■■■■■ 構造型(?)のTypeSafeValueをまとめて変更する例  (sm2930149「3D空間移動」より) ■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // OpenGLレンダラ時のカメラ用のマテリアルエクスプレッション。 // ここでは、注視点を現在位置から見てZ方向に-2ずらした点にしている。 // (つまりカメラの視線が常にZ軸のマイナス方向を向くように固定される) VertexProperty tgt = (VertexProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "注視点"); VertexProperty pos = (VertexProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "位置"); tgt.TypeSafeValue = new Vertex(pos.X, pos.Y, pos.Z - 2); ■■■■■■■■■■■■■■■■■ ColorProperty(色)の設定例 ■■■■■■■■■■■■■■■■■ // 説明 // Colorクラスについては.NETのSystem.Drawing.Colorの定義を参照。 // 色指定 ColorProperty color = (ColorProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "色"); color.TypeSafeValue= Color.FromArgb(255,0,0,0); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ フォントの設定(FontProperyの使い方と注意点)(「名前空間」「参照」タブの使い方)  (sm3258040「sm3155828のNiVEエフェクトの説明」を参考に作成) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // テキストトラックや「テキスト(基本)」などのエフェクトでフォントのプロパティを設定する。 // // ★注意 //   ひとくちにFontPropertyといっても、複数の定義があるので使い分けが必要。 //   普通に使えるのは下記1のnicoAE.Plugin.Propert.FontPropertyだが、 //   それ以外のものは、エクスプレッションの「高度」にチェックを入れ、 //   「名前空間」や「参照」タブに追記を行う必要がある。 // //     1.nicoAE.Plugin.Propert.FontProperty //        テキストトラックおよびテキストアニメータで使われているもの。 //        名前空間や参照の記述なしで使用できるのはこれ。 // //     2.nicoAE.PresetEffects.FontProperty //        「テキスト(基本)」「テキスト(拡張)」で使われているもの。 //        エクスプレッションで使用するには、「名前空間」にnicoAE.PresetEffects、 //        「参照」に絶対パスでplugins\nicoAE.PresetEffects.dllを指定する必要がある。 // //     3.NiveSh5TextRangePlugin.FontProperty //        拡張プラグインの「テキスト(範囲)」で使われているもの。 //        エクスプレッションで使用するには、「名前空間」にNiveSh5TextRangePlugin、 //        「参照」に絶対パスでplugins\plugintextrange.dllを指定する必要がある。 // //   3のように、拡張プラグインの作者さんが独自に定義していることもあるので注意。 //   探せばまだ他にもあるかもしれない。 // //   また、2や3のように別の名前空間を取り込んだ場合、FontPropertyの定義があいまいになるので //   型やキャストでは、名前空間を明示的に指定してやる必要がでてくる。 // // ★サンプル作成時のNiVE(たぶんv1.50くらい)では、テキストトラックが //   実装されていなかったので、多分nicoAE.Plugin.Propert.FontPropertyも無かったと思われる。 //   そのため、nicoAE.PresetEffects.FontPropertyを使う場合も、 //   定義があいまいになることはなく、型宣言やキャストに名前空間を明示指定する必要はなかった。 //   v1.70でテキストトラックが実装されたのにともない、名前空間の明示が必要になったと思われる。 // // Fontクラスの仕様については.NETのSystem.Drawing.Fontの仕様を参照。 // // 以下の例は、上記2のケースでフォントを設定するもの。 // 「名前空間」と「参照」タブの設定を忘れずに。 // 「テキスト(基本)」「テキスト(拡張)」のエフェクトエクスプレッションに記述。 // フォントスタイルの指定。必要なものの論理和をとって使う。 //  太字: FontStyle.Bold //  斜体: FontStyle.Italic //  標準: FontStyle.Regular //  取り消し線:FontStyle.Strikeout //  下線: FontStyle.Underline FontStyle f_style = FontStyle.Bold | FontStyle.Italic | FontStyle.Strikeout | FontStyle.Underline; // ★型宣言やキャストには名前空間を明示的に含めないと、あいまいになってしまう nicoAE.PresetEffects.FontProperty font = (nicoAE.PresetEffects.FontProperty)ExpressionUtils.GetProperty(items[i].Properties, "フォント"); // フォント名とサイズ、フォントスタイルを指定して値を設定 font.TypeSafeValue = new Font("MS UI Gothic",72,f_style); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ トランスフォームやマスク(基本図形)などで、基準位置を左上ではなく中心にする  (sm4840455「アピールさせてみた3」より) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // 「トランスフォーム」「マスク(基本図形)」といったエフェクトでは、 // イメージやマスクの左上を「位置」の基準として、そこからの「サイズ」を指定して領域を決めている。 // そのため、サイズを変えて拡大縮小しようとすると、左上を基準に拡大縮小してしまう。 // これだと「中心位置を固定したままマスクを拡大縮小する」ということができない。 // // エフェクトエクスプレッションにこのコードを書いておくと、 // 「位置」の数値が指す位置は、イメージやマスクの中心位置を表すようになる。 // 中心を基準に拡大縮小できるようになるので便利。 PointFProperty pos = (PointFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "位置"); SizeFProperty sz = (SizeFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "サイズ"); pos.X = pos.X - sz.Width / 2.0F; pos.Y = pos.Y - sz.Height / 2.0F; ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 常に映像を正面を向けたまま回転させる例(三角関数の使用例)  (sm3078184の「amazonぽい回転」を、NiVE v1.73でのZ軸方向仕様修正にあわせて改造) ■■■■■■■■■■■■■■■■■■■■■■■■■■■ //説明 // OpenGLレンダラ用のマテリアルエクスプレッション。 // アンカーポイントをずらしてマテリアルを回転させるというのはよく使われる手法だが、 // 普通にやると、回転にしたがってトラック映像も傾いてしまう。 // このコードをマテリアルエクスプレッションに書いておくと、 // トラック映像が正面を向いたまま回転するようになる。 // // 行っている内容は、マテリアルの「アンカーポイント」と「回転」の // パラメータから座標値を計算し、その座標にトラック映像を配置するというもの。 // (配置は「位置」ではなく「アンカーポイント」の数値操作で行っている) // nullオブジェクトや親子を使っても似たような動きは可能ですが、 // こちらもシンプルで便利そうです。 // // ★NiVE v1.73で、Z軸の方向が逆になったので、 //   それにあわせて計算式を変更してみました。 //   合ってる・・・かな? VertexRotationProperty rot = (VertexRotationProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "回転"); VertexProperty ac = (VertexProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "アンカーポイント"); double x,y,z, rad; // X軸回転 rad = Math.PI*rot.XAngle/180; z = ac.Z; y = ac.Y; ac.Z = z*Math.Cos(rad)+y*Math.Sin(rad); ac.Y = -z*Math.Sin(rad)+y*Math.Cos(rad); rot.XAngle = 0; // Y軸回転 rad = Math.PI*rot.YAngle/180; x = ac.X; z = ac.Z; ac.X = x*Math.Cos(rad)+z*Math.Sin(rad); ac.Z = -x*Math.Sin(rad)+z*Math.Cos(rad); rot.YAngle = 0; // Z軸回転 rad = Math.PI*rot.ZAngle/180; x = ac.X; y = ac.Y; ac.X = x*Math.Cos(rad)-y*Math.Sin(rad); ac.Y = x*Math.Sin(rad)+y*Math.Cos(rad); rot.ZAngle = 0; ■■■■■■■■■■■■■■■■■■■■■■■ ExpressionUtils.Wiggle()を使って値を振動させる例  (sm3033353nvp「Wiggle」より) ■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // ExpressionUtils.Wiggle()は、値を一定の範囲内で振動させる関数。 // 詳細はNiVE本体に付属している「エクスプレッションについて.txt」を参照。 // ここではint型を返すタイプを使っているが、PointFやVertexなどを返すタイプもある。 // //   int Wiggle(int seed, int oct, int value, int amp) //      int seed: 乱数のシード値。 //      int oct: 0〜100までの振動の複雑性。 //      value: 元となる値。 //      amp: 振動の振幅。 // // サンプルプロジェクトでは、「加減算」エフェクトのエクスプレッションに記述し、 // 色を振動させている。 Int32Property aka = (Int32Property)ExpressionUtils.GetProperty(Property.ThisProperty, "赤値"); aka.TypeSafeValue = ExpressionUtils.Wiggle(Property.Index,100,192,256); ■■■■■■■■■■■■■■■■■■■■■■■ ExpressionUtils.Ease()を使って値を加減速させる例  (sm3641119「エクスプレッションで加速度的な制御」より) ■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // ExpressionUtils.Ease()は、数値を開始値から終了値まで加速度的に変化させる関数。 // 詳細はNiVE本体に付属している「エクスプレッションについて.txt」を参照。 // ここではint型を返すタイプを使っているが、PointFやVertexなどを返すタイプもある。 // //   int Ease(int frame1, int value1, int frame2, int value2, int index, double ease) //        frame1: 開始するフレーム位置。 //        value1: 開始時の値。 //        frame2: 終了するフレーム位置。 //        value2: 終了時の値。 //        index: 現在のフレーム位置。 //        ease: 実数を入力します。1で等速、1未満の時は減速、1以上の時は加速します。 // // サンプルプロジェクトでは、マテリアルのエクスプレッションに記述し、 // 位置パラメータを加速度的に制御している。 PointFProperty pos = (PointFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "位置"); // 1〜30フレームの間に 減速しながらX座標を-256から256まで変更 pos.X = ExpressionUtils.Ease(1, -256, 30, 256, Property.Index, 0.5); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ トラックの一覧を取得して、各トラックのマテリアルを操作する例  (sm2908999「螺旋階段」に改造・追記) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //説明 // OpenGLレンダラ用のエクスプレッション。 // コンポジションに存在するトラック一覧を取得し、映像トラックを // Y軸に絡みつくような螺旋状に配置し、回転させる。 // // サンプルプロジェクトでは、コンポジションに8枚のカラーイメージと1つのカメラ、 // 1つのnullオブジェクトを作成し、カメラの親にはnullオブジェクトを指定。 // それ以外のパラメータは一切さわらず、 // nullオブジェクトのマテリアルエクスプレッションに、このプログラムを記述し、 // 全てのカラーイメージを螺旋状に自動配置するよう制御している。 // また、カメラの制御(実際にはカメラの親であるnullオブジェクト自身の制御)も // ここで行っている。 // コンポジションに存在するトラック一覧の取得 IExpressionItem[] items = ExpressionUtils.CastToExpressionItem(Property.TimelineTracks); // 処理対象とするトラックを覚えておくためのリスト List tracks = new List(); // 選別 for(int i = 0; i < items.Length; i++) { // 自分自身と、カメラ、オーディオトラックは処理対象外とする。 // ★サンプルプロジェクトではMediaTypeの判定を"(論理積 == 0)"で判定していたが、 //   単純に"!="で直接判定するのが正解っぽい。 if (!items[i].Equals(Property.This) && ( ((ITimeline)items[i]).Info.Type != MediaType.Audio ) && ( ((ITimeline)items[i]).Info.Type != MediaType.Camera ) ) { tracks.Add(items[i]); } } //螺旋配置の各パラメータを指定を指定 int rasen_hankei = 2; // トラックを配置する螺旋の半径 int rasen_tatekankaku = 2; // トラックを螺旋配置する際の縦方向の間隔 int rasen_zurashikakudo = 45; // トラックを螺旋配置する際のY回転間隔 int rasen_kaiten = 10; //1フレーム毎の螺旋回転の単位度数 items = tracks.ToArray(); for(int i = 0; i < items.Length; i++) { VertexProperty ap = (VertexProperty)ExpressionUtils.GetProperty(items[i].Properties, "アンカーポイント"); VertexProperty vp = (VertexProperty)ExpressionUtils.GetProperty(items[i].Properties, "位置"); VertexRotationProperty rp = (VertexRotationProperty)ExpressionUtils.GetProperty(items[i].Properties, "回転"); // アンカーポイントを螺旋半径分Z方向にずらすことで、螺旋の半径を指定。 ap.Z = rasen_hankei; // 縦(Y軸)方向の配置。トラックが増減しても螺旋の高さの中心がY=0になるように。 vp.Y = -(rasen_tatekankaku * (items.Length-1) / 2) + i * rasen_tatekankaku; // 少しずつY軸回転でずらして配置。また、フレーム毎に単位度数回転させる。 rp.YAngle = -rasen_zurashikakudo * i + Property.Index * rasen_kaiten; } // ここからカメラの制御(正確にはカメラの親であるnullオブジェクト自身の制御) VertexProperty n_anc = (VertexProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "アンカーポイント"); VertexRotationProperty n_kaiten = (VertexRotationProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "回転"); // 螺旋全体が見えるよう、カメラを遠めにしています。 // 実際には、親であるnullオブジェクトのアンカーポイントをずらすことでカメラ位置を調節。 // また、ここで指定した数値が半円軌道の半径となる。 // (ただ、デフォルトのカメラ位置は(0,0,2)なので、実際のカメラの半円軌道の半径は22となる。) n_anc.Z = -20; // 半円軌道上を移動させる速度。(Sin波の変化速度) int n_speed = 5; // X軸回転の半円軌道を、指定した速度で往復させる。 // (Sin関数を使うことで、X回転の数値を-90〜90°の範囲で往復させている) n_kaiten.XAngle = 90 * Math.Sin(Math.PI / 180 * Property.Index * n_speed); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 「トランスフォーム」エフェクトで、縦横の比率を自動的に保ったままサイズ変更できるようにする例  (sm4840455「アピールさせてみた3」を参考にして作成)  (自トラックのアイテムコードを明示的に指定しないやり方) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // 縮尺をパーセントで指定するマテリアルと違って、トランスフォームエフェクトでは、 // 「サイズ」というプロパティでイメージサイズを変更し、拡大縮小を行うことになる。 // しかし、この方法だと、縦横の比率を保ったまま拡大縮小するのは難しいという問題がある。 // このエクスプレッションでは、「サイズ」プロパティの横幅値と、トラックのアイテムサイズを基準にして // 「サイズ」の縦幅を自動計算することで、縦横比率を保ったままの変形を可能にしている。 // トランスフォームのエフェクトエクスプレッションとして記述する。 // // ★注意1 //   比率計算のために自トラックのアイテムサイズを取得していますが、 //   sm4840455のサンプルプロジェクトでは、 //       1.トラック一覧を取得。 //       2.トラックを1つ取り出し、エフェクト一覧を取得。 //       3.エフェクト一覧のエフェクトのItemCodeを調べていき、 //         自エフェクトのコード(Property.ThisCode)と一致するものがあれば、 // そのトラックが自トラックだと判断し、アイテムサイズを取得。 //         トランスフォームの数値を比率にあわせて設定。 //       4.2〜3を全てのトラックについて繰り返す。 //   という流れで処理を行っていました。 //   しかしながら、エフェクトのItemCodeはトラックをまたいで重複する可能性があるので、 //   この方法では自トラックを厳密に特定することはできない模様。 //   つまり全然違うトラックのアイテムサイズにあわせて変形を行ってしまう可能性もある。 // //   そこで、Wikiのプラグインページでアドバイスをいただき、Property.ThisCodeではなく //   Property.Thisで自エフェクトを探すようにしてみました。これなら一意に特定できるかな? // サイズプロパティの取得 SizeFProperty s = (SizeFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "サイズ"); // トラックの一覧を取得 IExpressionItem[] items = ExpressionUtils.CastToExpressionItem(Property.TimelineTracks); bool found = false; // 自トラックの特定 for(int i = 0; i < items.Length; i++) { // トラックのエフェクト一覧の取得 IExpressionItem[] es = ((IExpressionTrack)items[i]).GetEffect(); // 自エフェクトを探す for (int j = 0; j < es.Length; j++) { // ★自エフェクトかどうかの判定はProperty.Thisで行う if (es[j].Equals(Property.This)) { // トラックの情報から、アイテムサイズを取得する。 // 縦横比率はこの数値に基づく。 Size mediaSize = ((ITimeline)items[i]).Info.Size; //幅を基準に高さを調整 s.Height = (s.Width / mediaSize.Width) * mediaSize.Height; found = true; break; } } if (found) break; } MonitorProperty.Add(s); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 「トランスフォーム」エフェクトで、縦横の比率を自動的に保ったままサイズ変更できるようにする例  (sm4840455「アピールさせてみた3」を参考にして作成)  (自トラックのアイテムコードを明示的に指定するやり方) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // 上の例を、自トラックのアイテムコードを明示指定する方法で書いたもの。 // // ※注意 //   【】の部分は、タイムラインウィンドウの自トラック名の部分の右クリックメニューから、 //   「アイテムコードをコピー」した結果に置き換えて下さい。 // サイズプロパティの取得 SizeFProperty s = (SizeFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "サイズ"); // トラックの一覧を取得 IExpressionItem[] items = ExpressionUtils.CastToExpressionItem(Property.TimelineTracks); // 自トラックを取得 IExpressionItem track = ExpressionUtils.GetItem(items,【自トラックのアイテムコード】); // トラックの情報から、アイテムサイズを取得する。 // 縦横比率はこの数値に基づく。 Size mediaSize = ((ITimeline)track).Info.Size; // 「サイズ」の幅を基準に、「サイズ」の高さを調整 s.Height = (s.Width / mediaSize.Width) * mediaSize.Height; MonitorProperty.Add(s); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ トラックの開始位置・終了位置で自動的にフェードイン・フェードアウト  (sm4840455「アピールさせてみた3」に一部改造・追記) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // トラックの開始位置・終了位置を自動検出し、トランスフォームの // 「不透明度」によるフェードイン・フェードアウトを行う。 // トランスフォームのエフェクトエクスプレッションに記述する。 // // ★注意 //   上にある「縦横の比率を自動的に保ったままサイズ変更できるようにする例」と同様、 //   自エフェクトの検出をProperty.ItemCodeではなくProperty.Thisで判断するように変えています。 // 不透明度のプロパティ SingleProperty tp = (SingleProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "不透明度"); // トラック一覧 IExpressionItem[] items = ExpressionUtils.CastToExpressionItem(Property.TimelineTracks); // 現在のフレーム位置 int index = Property.Index + 1; // フェードイン・アウトの期間(フレーム数) int range = 30; bool found = false; // 選別 for(int i = 0; i < items.Length; i++) { // トラックのエフェクト一覧の取得 IExpressionItem[] es = ((IExpressionTrack)items[i]).GetEffect(); // 自エフェクトを探す for (int j = 0; j < es.Length; j++) { // ★自エフェクトかどうかの判定はProperty.Thisで行う if (es[j].Equals(Property.This)) { // アイテムの開始位置 int mediaStart = ((ITimeline)items[i]).MediaPosition; // トラックの有効範囲の開始位置(「s」の位置) int start = mediaStart + ((ITimeline)items[i]).StartPoint + 1; // トラックの有効範囲の終了位置(「e」の位置) int end = mediaStart + ((ITimeline)items[i]).EndPoint + 1; // フェードインの処理 if (index >= start && index < start + range) { tp.TypeSafeValue = ((index - start) / (float)range) * 100F; } // フェードアウトの処理 if (end - range < index && index <= end) { tp.TypeSafeValue = ((end - index) / (float)range) * 100F; } found = true; break; } if (found) break; } } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 「確認用図形」エフェクトで、マテリアルのアンカーポイントの位置に「+」を表示する例  (sm4840455「アピールさせてみた3」に改造・追記) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // 自トラックのマテリアルのアンカーポイントの数値を取得し、 // それを「確認用図形」エフェクトの「位置」に代入する。 // 「確認用図形」エフェクトのエフェクトエクスプレッションに記述する。 // // ★注意 //   上にある「縦横の比率を自動的に保ったままサイズ変更できるようにする例」と同様、 //   自エフェクトの検出をProperty.ItemCodeではなくProperty.Thisで判断するように変えています。 PointProperty lp = (PointProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "位置"); // 全アイテム IExpressionItem[] items = ExpressionUtils.CastToExpressionItem(Property.TimelineTracks); bool found = false; // 選別 for (int i = 0; i < items.Length; i++) { // トラックのエフェクト一覧の取得 IExpressionItem[] es = ((IExpressionTrack)items[i]).GetEffect(); // 自エフェクトを探す for (int j = 0; j < es.Length; j++) { // ★自エフェクトかどうかの判定はProperty.Thisで行う if (es[j].Equals(Property.This)) { PointFProperty alp = (PointFProperty)ExpressionUtils.GetProperty(items[i].Properties, "アンカーポイント"); lp.X = (int)alp.X; lp.Y = (int)alp.Y; found = false; break; } } if (found) break; } MonitorProperty.Add(lp); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 空気抵抗や重力などを考慮して放物運動をシミュレーションした例。  (sm3051029「空気抵抗のある放物運動シミュレーション」に少し追記・改造) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // GDIまたは拡張2D用のマテリアルエクスプレッション。 // 空気抵抗や重力などを考慮して放物運動をシミュレーションした例。 // サンプルではカラーイメージのマテリアルに記述しています。 // 作者さんのコメントには //   「とりあえず動くように書いただけなので実装効率とかは気にしないで下さい」 // とありますが、わかりやすく、色々と面白く使えると思います。 // 位置情報を取得 PointFProperty p = (PointFProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "位置"); // -------------- // 各種変数の宣言 // -------------- float m, kx, ky, pos_x, pos_y, vel_x, vel_y, acc_x, acc_y, g; int start, end; // -------------------- // 各種パラメータ定義 // -------------------- // 物体の質量を定義 m = 1.0f; // 物体のx方向空気抵抗を定義 kx = 0.1f; // 物体のy方向空気抵抗を定義 ky = 0.1f; // x方向初期位置を定義 pos_x = 180.0f; // y方向初期位置を定義 pos_y = 240.0f; // x方向初速を定義 vel_x = 0.0f; // y方向初速を定義 vel_y = 0.0f; // x方向加速度初期値を定義 acc_x = 0.0f; // y方向加速度初期値を定義 acc_y = 0.0f; // 重力加速度を定義 g = 9.8f; // シミュレーションを行う範囲(最初のフレーム・最後のフレーム) start = 15; end = 300; // -------------------- //    力の入力 // -------------------- float[] F_x = new float[end]; float[] F_y = new float[end]; // ここでは、シミュレーションを行う最初のフレームで、 //   x方向右向きへ800.0f、y方向上向きへ500.0f // の力を加え、ふっとばすことにする。 F_x[start-1] = 800.0f; F_y[start-1] = -500.0f; // あらかじめF_x[]、F_y[]の適切な要素に力の数値を代入しておけば、 // 放物運動の途中で新たな力が加わった場合の動きもシミュレーションできる。 // ここでは40フレーム目で左上方向の力を加えてみる。 F_x[39] = -800.0f; F_y[39] = -800.0f; //メインループ for(int i = start; i < Property.Index; i++) { // 終了フレームに達していたら、メインループを抜ける if (i == end) break; // 運動方程式を記述 acc_x = - kx * vel_x / m + F_x[i-1] / m; acc_y = - ky * vel_y / m + F_y[i-1] / m + 9.8f; // 現在速度の更新 vel_x += acc_x; vel_y += acc_y; // 現在位置の更新 pos_x += vel_x * (1.0f / 30.0f); pos_y += vel_y * (1.0f / 30.0f); } // 最終的に値を代入する p.X = pos_x; p.Y = pos_y; ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ トラックのイメージを取得して、それを元に処理を行う例。  (sm5018535「グラデーションワイプで文字を描く」に少し改造・追記) ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 説明 // トラック名をキーにして自トラックを取得し、そのイメージを取得して // アルファの分布を元にイメージの重心位置を計算している。 // サンプルではnShineのエフェクトエクスプレッションに記述し、 // 「光源」プロパティの位置を重心位置にあわせている。 // // なお、ここにはわかりやすさ重視で低速版のプログラムを載せていますが、 // サンプルには同じ処理を高速化したプログラムも含まれています。 // // また、エクスプレッションからはトラックのイメージを取得することはできますが、 // トラックのイメージを直接書き換えたりすることはできないようです。 int no; double ax = 0; double ay = 0; // 初期処理(元画像取得版) // "筆の先端抽出"という名前のトラックを探し、そのトラックのイメージを取得する。 // // ★見つからなかった時のためにLengthによるループ中断判定を追加 for (no = 0; (no < Property.TimelineTracks.Length) && (Property.TimelineTracks[no].TimelineName != "筆の先端抽出"); no++); if (no < Property.TimelineTracks.Length) { Bitmap image = Property.TimelineTracks[no].GetImage(Property.Index,false).Image; int lx = image.Width; int ly = image.Height; int x = 0; int y = 0; Color c; int ct = 0; // アルファの分布を元に重心を計算 for (y = 0; y < ly; y++) { for (x = 0; x < lx; x++) { c = image.GetPixel(x,y); if (c.A != 0) { ax += x; ay += y; ct++; } } } ax /= ct; ay /= ct; image.Dispose(); } PointProperty light = (PointProperty)ExpressionUtils.GetProperty(Property.ThisProperty, "光源"); light.X = (int)ax; light.Y = (int)ay; //デバック表示 StringProperty dbg = new StringProperty("Debug",""); dbg.TypeSafeValue = "["+light.X+","+light.Y+"]"; MonitorProperty.Add(dbg); ■■■■■■■■■■■■■■■■■■■■■■■■■■■ トラックのオーディオデータを取得する例 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ sm4352133「レベルメータ」を参照。 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 拡張プラグイン「なめらか移動」の元になった曲線補間式の関数 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ sm3020415「曲線補間解説編」を参照。 ■■■■■■■■■■■■■■■■■ ブロック崩しのような衝突判定プログラム ■■■■■■■■■■■■■■■■■ sm2945827「バウンディングボックス」を参照。