2015年3月20日金曜日

UE4 : Shader : Hair

https://forums.unrealengine.com/showthread.php?63555-FREE-Hair-Material 髪の良いシェーダー メモ

2015年3月17日火曜日

カテナリー曲線



電線を自動化できないかと思って調査
思った以上に難易度高い orz

はいぽりっく関数って何よ・・・。

とりあえず、SketchUPのRubyをみて、
SIのPythonに移植まではできた。

だけどやってることはほとんどわからないです orz


参考サイト



Houdini Hip
http://www.sidefx.com/index.php?option=com_forum&Itemid=172&page=viewtopic&p=103132&sid=85aa23c1c1eb2cce0b5f59a635c71c45

Houdini
http://forums.odforce.net/topic/1322-challenge-helical-cable/

懸垂曲線 Math
http://www.epii.jp/articles/note/math/catenary

プログラム
ソースは無し?
http://demonstrations.wolfram.com/CatenaryTheHangingChain/

SketchUP Plugin Simple
Ruby Sorceつき
http://sketchucation.com/forums/viewtopic.php?t=22472

双曲線関数が必要になる(汗
http://21.xmbs.jp/shindou-287823-ch.php?guid=on

コードあり
http://sky.geocities.jp/lite_and_seen_lite/gaihen_hello_7.html

鉄塔
http://www.fair-sky.net/wada/souden/index.html

2015年3月16日月曜日

Softimage Script : 円状に集める2 等間隔

SIを使う人はもうないだろうから、
付け焼き刃的なスクリプトのままメモ

とりあえず、円周上に等間隔に整列するようにしてみました。



ズレる時はローカルで回転させてあわせてます。


Sorce

#AligenCircle
#
# 02 28 2015 ver 0.1
#
# 選択がまだ甘いがポイント選択状態だと動く
#
# ベクトルは選択したポイントの平均
# 中心はBBOX ,半径は一番遠いポイントまでの距離の設定になっている



app = Application; log = app.LogMessage
oCmdLog = app.Dictionary.GetObject( "preferences.scripting" )
userPref = oCmdLog.cmdlog.value
oCmdLog.cmdlog.value = False

import math
from win32com.client import constants as c
DEBUG = True
CUSTOM_RAD = False
CUSTOM_CENTER = False
CUSTOM_NORMAL = False
NORMAL = [1,0,0]


#Select
#Application.SelectGeometryComponents("grid.pnt[30-32,39-41,48-50]")

CENTER = (3,0,-1)
def vLog(v):
 return str(str(v.X) + ", " + str(v.Y) + ", " + str(v.Z) + "")
 
def dLog( str ):
 if DEBUG == True:
  log(str)


#サークルデータのソート

#---------------------------------------------------
# circleSort
#---------------------------------------------------
def circleSort(Center,pnts):
 o = XSIMath.CreateVector3(CENTER[0],CENTER[1],CENTER[2])
 v = XSIMath.CreateVector3()
 
 idRad = []
 
 for pnt in pnts:
  p = pnt.Position
  
  #中心点からのベクトル
  v.Sub(p,o)
  #vlog(v)
  r = math.atan2(-v.Z,v.X)
  
  if DEBUG:#Debg時にはわかりやすいように度表記で
   r = int( r / 3.141519 * 180)
  idRad.append( [r, pnt.Index] ) 
 idRad.sort()
 
 sortedIDs = []
 for i in idRad:
  sortedIDs.append(i[1])
  dLog(str(i))
  
 dLog("circleSortIDs : " + str(sortedIDs))
 return sortedIDs



#---------------------------------------------------
# getWorldPos
#---------------------------------------------------
def getWorldPos( pts, m4 ):
 posArray = []
 for pnt in pts:
  p = pnt.Position
  p.MulByMatrix4InPlace(m4)
  posArray.append([p.X,p.Y,p.Z])
 
 return posArray

#---------------------------------------------------
# getAveNormal
#---------------------------------------------------
def getAveNormal(pts,m4):
 n = XSIMath.CreateVector3()
 x = 0
 y = 0
 z = 0
 
 for pnt in pts:
  n = pnt.Normal
  
  #ノーマル座標(逆行列の転地をつかう)
  #m4.InvertInPlace()
  m4.TransposeInverseInPlace()
  n.MulByMatrix4InPlace(m4)
  x = x + n.X
  y = y + n.Y
  z = z + n.Z
  
 
 num = pts.Count
 n.Set( x / num, y / num, z / num)
 n.NormalizeInPlace()
 return n


#---------------------------------------------------
# getCenter
#---------------------------------------------------
def getCenter():
 center = XSIMath.CreateVector3()
 bbox = Application.GetBBox()
 rad = 0.01

 xLength = bbox(3) - bbox(0)
 yLength = bbox(4) - bbox(1)
 zLength = bbox(5) - bbox(2)
 xMid = xLength / 2 + bbox(0)
 yMid = yLength / 2 + bbox(1)
 zMid = zLength / 2 + bbox(2)
 center.Set(xMid,yMid,zMid)

 return center
 
#---------------------------------------------------
# getBBOXRadius
#---------------------------------------------------
def getBBOXRadius():
 bbox = Application.GetBBox()
 tmp = 0.01

 xLength = bbox(3) - bbox(0)
 yLength = bbox(4) - bbox(1)
 zLength = bbox(5) - bbox(2)
 
 if xLength > tmp:
  tmp = xLength
 if yLength > tmp:
  tmp = yLength
 if zLength > tmp:
  tmp = zLength
 rad = tmp * 0.5
 return rad
 
 

#---------------------------------------------------
# createCircleMatrix
#---------------------------------------------------
def createCircleMatrix(aID,aPos,normal,center):
 circleMatrix = XSIMath.CreateMatrix4()
 p = XSIMath.CreateVector3()
 v = XSIMath.CreateVector3()
 farPos = XSIMath.CreateVector3()
 offsetCount = 0
 maxLength = 0
 
 for i in range(len(aID)):
  p.Set(aPos[i][0],aPos[i][1],aPos[i][2])
  v.Sub(p,center)
  if maxLength < v.Length():
   maxLength = v.Length()
   farPos = p
   offsetCount = i

 x = XSIMath.CreateVector3()
 y = XSIMath.CreateVector3()   
 x.Sub(p,center)
 x.NormalizeInPlace()
 y.Cross(normal,x)
 y.NormalizeInPlace()
 
 circleMatrix.Set(
 x.X, x.Y, x.Z, 0,
 y.X, y.Y, y.Z, 0,
 normal.X, normal.Y, normal.Z, 0,
 center.X, center.Y, center.Z, 1)
 
 return circleMatrix,offsetCount


def circleSort2(aID,aPos):

 xID = 0
 yID = 1
 zID = 2
 
 idRad = []
 for i in range(len(aID)):
  r = math.atan2(aPos[i][yID],aPos[i][xID]) #y,x
  r += 0.01
  
  if DEBUG:#Debg時にはわかりやすいように度表記で
   r = int( r / 3.141519 * 180)
  idRad.append( [r, aID[i],i] ) 
 idRad.sort()
 
 sortedIDs = []
 
 for i in idRad:
  sortedIDs.append(i[2])
  dLog(str(i))
  
 dLog("circleSortIDs : " + str(sortedIDs))
 return sortedIDs


#---------------------------------------------------
# getWorldCirclePointsPositionArray
#---------------------------------------------------
def getWorldCirclePointsPositionArray(aID,aPos,center,radius,circleMatrix,offset):
 m4 = XSIMath.CreateMatrix4()
 im = XSIMath.CreateMatrix4()
 p = XSIMath.CreateVector3()
 m4.Invert(circleMatrix)
 im.Invert(m4)
 
 circlePositionArray = []
 
 #world to circle
 for i in aPos:
  p.Set(i[0],i[1],i[2])
  p.MulByMatrix4InPlace(m4)
  circlePositionArray.append([p.X,p.Y,p.Z])

 sortedID = circleSort2(aID,circlePositionArray)
 
 #AligenToLocalCircle
 dLog(offset)
 segment = len(aID)
 for i in range(len(sortedID)):
  j = (i + len(sortedID) / 2 ) % len(sortedID)
  x = radius * math.cos( j * 1.0 / segment * 2 * math.pi) 
  y = radius * math.sin( j * 1.0 / segment * 2 * math.pi)
  z = 0.0
  circlePositionArray[sortedID[i]] = [x,y,z]

 #Circle to World 
 newCirclePositionArray = []
 for i in circlePositionArray:
  p.Set(i[0],i[1],i[2])
  p.MulByMatrix4InPlace(im)
  newCirclePositionArray.append([p.X,p.Y,p.Z])
  
 return newCirclePositionArray 

#---------------------------------------------------
# main
#---------------------------------------------------
def main():

 #Defalt
 radius = 1.0
 center = XSIMath.CreateVector3(0,0,0)
 
 #if app.Selection().Count < 0:
 # return
 oSel = app.Selection(0)
 oSub = oSel.Subcomponent
 obj = oSub.Parent3DObject
 oColl = oSub.ComponentCollection
 
 #VertexCollectionから、IndexArrayを取得できないので一度ポイント選択にする
 if oSub.Type != "pntSubComponent":#point#
  Application.SelectFilter("Edge")
  Application.SelectAdjacent("", "Point", False)
  oSel = app.Selection(0)  
  oSub = oSel.Subcomponent
  obj = oSub.Parent3DObject
  pts = oSub.ComponentCollection
  
 else :
  pts = oColl

 if pts.Count < 3:
  log("selection error")
  return
  
 aID = pts.IndexArray
 pointNum = pts.Count
 
 normal = XSIMath.CreateVector3(NORMAL[0],NORMAL[1],NORMAL[2]) 
 circleMatrix = XSIMath.CreateMatrix4()
 m4 = XSIMath.CreateMatrix4()
 im4 = XSIMath.CreateMatrix4()
 tm4 = XSIMath.CreateMatrix4()
 objectMatrix = obj.Kinematics.Global.Transform.GetMatrix4(m4)
 im4.Invert(m4)
 offsetCount = 0
 
 
 #Center
 if CUSTOM_CENTER == False:
  center = getCenter()
 dLog("Center : " + vLog(center))
 
 #Radius
 if CUSTOM_RAD == False:
  radius = getBBOXRadius()
  
 #Local to Global
 aPos = getWorldPos(pts,m4)
 
 #Normal)
 if CUSTOM_NORMAL == False:
  normal = getAveNormal(pts,m4)
 
 #CircleMatrix,offdetCount(IndexArray)
 circleMatrix,offsetCount = createCircleMatrix(aID,aPos,normal,center)
 dLog("offsetCount : " + str(offsetCount))
 
 #getNewWorldPos newPositionArray[[x,y,z],[x,y,z]///]
 newPosA = getWorldCirclePointsPositionArray(aID,aPos,center,radius,circleMatrix,offsetCount)
 
 #setNewPosition
 for i in range(pointNum):
  app.Translate(oSel.Name + ".pnt[" + str(aID[i]) + "]", newPosA[i][0], newPosA[i][1], newPosA[i][2], 0, "siView", "siObj", "siXYZ", "", "", "", "", "", "", "", "", "", 0, "")

  
 #dLog(str(aPos))
 #dLog("Normal : " + vLog(normal))

 
 return
main()

近況

仕事
・リダクション作業が半分終わり
・キャラクター遅延気味

スクリプト挫折中
・屋根の処理
・電線の処理(カテナリー曲線)

心うきうき成分が足りない :p

2015年3月5日木曜日

Memo : 背景 The Order 1886

https://www.artstation.com/artist/bobbyjrice
http://www.polycount.com/forum/showthread.php?t=149706

the order 1886の背景さんらしいです。
スバラシイ。ああ、スバラシイ


2015年2月26日木曜日

円上にあつめる


Houdiniのチュートリアルで、
ポイントを円状に整列する
VOPSOP(ICEみたいなもの)があったので、
SI(Python)で確認してみた
確認しただけでコードは屑ですのであしからず

SIにはプラグインがあるので、
それを利用すればいいんだけどね
mx_Roundish

手順

1.中心点の作成
今回はBBOXを作成した

2.平面化する
(平面化で無い場合は球になります)


3.同距離に収める

・中心から、選択ポイントのベクトルを作成
・ベクトルをノーマライズ
・半径を掛ける
・中心とベクトルを足す

の順、スクリプトは
いろいろ適当なことやってるけど、
こんな感じ。

Houdiniはすでに平面状のポイントをそろえる
サンプルだったけど、

平面じゃなければ、平面化すれば良いんじゃね?
ってことで確認してみた

最初に平面化するのが味噌だったのか。

実作業としては、等間隔に収めたいと思います
円周でのソートは今後の課題ですな


追記
ぐぐったらコードをはけん。
二つのベクトルがわかってればAtan2で角度がでるので、
それで、比較してるんですな。
座標を平面座標に変換する必要がありそうだけど。
すでに並んでいるから問題ないのかな?

3点の座標から簡単に角度と回転方向を求める. (2・3・N次元,外積を用いる方法)

この辺りも覚えておきたい所

近況

Houdiniの勉強をしてるんだけど、

・必要そうな機能を洗い出し>習得

と言うわけにはいかないっぽい。
前提条件がノードだし、
データの扱いは特殊だし
(普通のモデリングソフトとはいかない)

リアルタイムの扱いは少ないし

基本、チュートリアルをやってみて、
何が出来るか把握してからじゃないと
工程の途中で詰んでしまいます orz

かと言って
歴史は長いのでチュートリアルは多いし

今回みたいに応用の利く技術が多いので、
幅は広がりそうですね

プロシージャルモデリングのように
あとでジワジワ利くタイプです


■最近買った本
・Maya実戦 ハードサーフェースモデリング
・ウェザリングの教科書
・背景CG実戦テクニック

背景充

どの本もお値段以上の良本でした(吐血 orz

2015年2月11日水曜日

Softimage Script : VCTool(Softimage用、頂点カラー塗りツール)

背景用の頂点カラーツールです

開発途中で、SI終了の報がきたので、
投げちゃったのですが、
要望があったのでさらしてみます

グラデーションの塗りを緩和します

どうやら、複数のオブジェクトにはまだバギーな動きをしてますが、
リペイントで対応してください :p

自分が必要であれば対応しますw


使用の想定

・ハイトマップ、多メッシュでの一様なグラデーション
・手作業での頂点へのライティング
・選択したオブジェクトの明るさなどの調整(未完


つかいかたっぽいもの

選択した、オブジェクト、エッジ、頂点に対し
頂点カラーを設定、調整します
※頂点カラーはあらかじめ設定してやってください





コード

ScriptEditorにコピペして、
実行してください
・・・すごい適当ですみません

from win32com.client import constants as c
app = Application; log = app.LogMessage

BUTTONSIZE_LW = 50
BUTTONSIZE_LH = 48

def createLayout(cp,ColorList,FCurveColorList):
 log(cp)
 oly = cp.PPGLayout

 oly.AddTab( "Main" ) 
 oly.AddItem("ToPntSamples")
 
 oly.AddGroup("PerCent",False,10)
 oItem = oly.AddItem("Percent")
 #oItem.SetAttribute("cx",30)
 #oItem.SetAttribute("cy",30)
 oItem = oItem.SetAttribute("NoLabel",True)
 oly.EndGroup()
 
 #SetColor
 #--------------------------------------------
 oly.AddGroup("SetColor")
 oly.AddRow()
 oItem = oly.AddButton("Pick_SetColor","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("cy",BUTTONSIZE_LH)
 oItem = oly.AddColor( ColorList[0] + "_red", ColorList[0],True)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddButton("SetColor","Set")
 oItem.SetAttribute("cx",50)
 oItem.SetAttribute("cy",48)
 oly.EndRow()
 oly.AddRow()
 oly.EndRow()
 oly.EndGroup()
# 
# #UpperLayer 
# #--------------------------------------------
# oly.AddGroup("UpperLayer")
# oly.AddRow()
# oItem = oly.AddButton("Pick_UpperLayer","Pick")
# oItem.SetAttribute("cx",BUTTONSIZE_LW)
# oItem.SetAttribute("cy",BUTTONSIZE_LH)
# oItem = oly.AddColor( ColorList[1] + "_red", ColorList[1],False)
# oItem.SetAttribute("NoLabel",True)
# oly.EndRow()
# 
# oly.AddGroup("Darken")
# oly.AddRow()
# oly.AddButton("Multiple")
# oly.AddButton("HardLight") 
# oly.AddButton("Burn")
# oly.EndRow() 
# oly.EndGroup()
#
# oly.AddGroup("Lightn")
# oly.AddRow()
# oly.AddButton("Screen")
# oly.AddButton("ColorDodge") 
# oly.AddButton("LinerDodge")
# oly.EndRow() 
# oly.EndGroup()
#
# oly.AddGroup("Contrast")
# oly.AddRow()
# oly.AddButton("OverLay") 
# oly.AddButton("SoftLight")
# oly.EndRow()
# oly.EndGroup()
# 
# oly.EndGroup()

 #ColorMath
 #--------------------------------------------
 oly.AddGroup("ColorMath")
 oly.AddRow()
 oItem = oly.AddButton("Pick_ColorMath","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("cy",BUTTONSIZE_LH)
 oItem = oly.AddColor( ColorList[2] + "_red", ColorList[2],False)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddButton("ColorMath_Sub","Sub")
 oItem.SetAttribute("cx",30)
 oItem.SetAttribute("cy",48)
 oItem = oly.AddButton("ColorMath_Add","Add")
 oItem.SetAttribute("cx",30)
 oItem.SetAttribute("cy",48)
 oly.EndRow()
 
 oly.AddRow()
 oly.AddGroup("SetColor")
 oly.AddRow()
 oly.AddButton("ColorMath_00","|0|")
 oly.AddButton("ColorMath_x05","x0.5")
 oly.AddButton("ColorMath_x08","x0.8")
 oly.AddButton("ColorMath_05","|0.5|")
 oly.AddButton("ColorMath_x12","x1.2")
 oly.AddButton("ColorMath_x20","x2")
 oly.AddButton("ColorMath_10","|1.0|")
 oly.EndRow()
 oly.EndGroup()
 oly.EndRow()
 oly.EndGroup()


 #+ Gra ++++++++++++++++++++++++++++++++++++++++++
 oly.AddTab( "Grad" )
 
 oly.AddItem("ToPntSamples")

 #-Percent------------------- 
 oly.AddGroup("PerCent",False,10)
 oItem = oly.AddItem("Percent")
 oItem = oItem.SetAttribute("NoLabel",True)
 oly.EndGroup()
  
 oly.AddGroup("Gradation") 
 #oly.AddButton("test")
 oly.AddRow()
 oItem = oly.AddButton("Gradation_Exe","Paint")
 oItem.SetAttribute("cx",100)
 oItem.SetAttribute("cy",48)
 oItem = oly.AddButton("RePaint","Re Paint")
 oItem.SetAttribute("cx",100)
 oItem.SetAttribute("cy",48)
 oly.EndRow()

 
 #-Type
 oly.AddGroup("Composit")
 Array = ["Normal",0,"Multiple",1]
 oItem = oly.AddEnumControl("GraComposition",Array,"Comp",c.siControlCombo)
 oItem.SetAttribute("NoLabel", True)
 oly.EndGroup()
 
 oly.AddRow()
 oly.AddGroup("Color")
 Array = ["Color1 > Bace",0,"Color1 > Color2",1]
 oItem = oly.AddEnumControl("GraColorPattern",Array,"ColorPattern",c.siControlCombo)
 oItem.SetAttribute("NoLabel", True)
 oly.EndGroup()
 
 oly.AddGroup("Form")
 oItem = oly.AddEnumControl("GraForm",["Linear",0,"Radial",1],"Comp",c.siControlCombo)
 oItem.SetAttribute("NoLabel", True)
 oly.EndGroup()
 oly.EndRow()
 
 #- FCurve Color -------------------
 oly.AddGroup("Color1")
 oly.AddRow()
 oItem = oly.AddButton("Pick_FCurveColor1","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("cy",BUTTONSIZE_LH)
 oItem = oly.AddColor( FCurveColorList[0] + "_red", FCurveColorList[0],True)
 oItem.SetAttribute("NoLabel",True)
 oly.EndRow()
 oly.AddRow()
 oly.EndRow()
 oly.EndGroup()
 
 oly.AddGroup("Color2")
 oly.AddRow()
 oItem = oly.AddButton("Pick_FCurveColor2","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("cy",BUTTONSIZE_LH)
 oItem = oly.AddColor( FCurveColorList[1] + "_red", FCurveColorList[1],True)
 oItem.SetAttribute("NoLabel",True)
 oly.EndRow()
 oly.AddRow()
 oly.EndRow()
 oly.EndGroup()



 #-Position-------------------  
 oly.AddGroup("Start_Position")
 oly.AddRow()
 oItem = oly.AddButton("pick_aPosButton","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW) 
 oItem = oly.AddItem("aPosX","x")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddItem("aPosY","y")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddItem("aPosZ","z")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True) 
 oly.EndRow()
 oly.EndGroup() 
 oly.AddGroup("End_Position")
 oly.AddRow()
 oItem = oly.AddButton("pick_bPosButton","Pick")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem = oly.AddItem("bPosX","x")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddItem("bPosY","y")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True)
 oItem = oly.AddItem("bPosZ","z")
 oItem.SetAttribute("cx",BUTTONSIZE_LW)
 oItem.SetAttribute("noslider",True)
 oItem.SetAttribute("NoLabel",True)
 oly.EndRow()
 oly.EndGroup()

 #-FCurve-------------------
 oly.AddGroup("PaintGradation")
 oly.AddFCurve("FCurve",150)
 oly.EndGroup()
 
 oly.EndGroup()
 
 return oly
 

#---------------------------------------------------
# addColorParam3
#---------------------------------------------------
def addColorParam3(cp,inName):
 colorList = ["red","green","bule","alpha"]
 colorList = [inName + "_" + i for i in colorList]
 for i in colorList:
  cp.AddParameter3( i, c.siDouble,1,0,1 ,False)


#---------------------------------------------------
# addColorParam
#---------------------------------------------------
def addColorParam(cp,colorList):
 #SetColor
 for i in colorList:
  addColorParam3(cp,i)
  
#---------------------------------------------------
# addOtherParam
#--------------------------------------------------- 
def addOtherParam(cp):
  
 cp.AddParameter3("Percent",c.siDouble,100,0.01,100,False)
 cp.AddParameter3("ToPntSamples",c.siBool,False,"","",False)
 
 oFCParam = cp.AddFCurveParameter("FCurve")
 oFCurve = oFCParam.Value
 oFCurve.BeginEdit()
 oFCurve.RemoveKeys()

 oFCurve.AddKey( 100, 0)
 oFCurve.AddKey( 0, 1)
 
 oFCurve.Interpolation = 2
 
 oFCurve.EndEdit();

 
 
 #Gradation
 cp.AddParameter3("GraComposition", c.siInt4, 0,0,1,False)
 cp.AddParameter3("GraColorPattern", c.siInt4,0,0,1,False)
 cp.AddParameter3("GraForm", c.siInt4, 0,0,1,False)
 cp.AddParameter3("GraPercentage", c.siDouble,100,0.01,100,False)
 
 cp.AddParameter3("aPosX",c.siDouble,0,-10000,10000,False)
 cp.AddParameter3("aPosY",c.siDouble,0,-10000,10000,False)
 cp.AddParameter3("aPosZ",c.siDouble,0,-10000,10000,False)
 cp.AddParameter3("bPosX",c.siDouble,0,-10000,10000,False)
 cp.AddParameter3("bPosY",c.siDouble,10,-10000,10000,False)
 cp.AddParameter3("bPosZ",c.siDouble,0,-10000,10000,False)
 
 oFCurve.EndEdit()

def lyLogic(ly):
 ly.Language = "Python"
 ly.Logic = """
app = Application; log = app.LogMessage

def test_OnClicked():
 fc = PPG.FCurve.Value
 log("Test")
 log(fc.Eval(20))

def getMixPercentage(inA,inB,inPercentage):
 aValue = inA * inPercentage / 100
 bValue = inB * ( 100 - inPercentage) / 100
 return aValue + bValue


# pickVertexRGBA
#---------------------------------
def pickVertexRGBA():
 oSel = app.Selection
 currentFilter = oSel.Filter
 app.SetSelFilter("SampledPoint")
 oPick = app.PickElement()
 #log(oPick(2))
 
 if oPick(0) != 0:
  pickSample = oPick(2).SubComponent.ComponentCollection(0).Index
  
 else :
  log(Cancel)
  app.SetSelFilter(currentFilter)
  pickSample = -1
  return False
 app.SetSelFilter(currentFilter)
 getVArray = oPick(2).SubComponent.Parent3DObject.ActivePrimitive.Geometry.CurrentVertexColor
 
 if getVArray == None:
  return False
 aRGBAs = getVArray.Elements.Array
 return [ aRGBAs[0][pickSample], aRGBAs[1][pickSample], aRGBAs[2][pickSample], aRGBAs[3][pickSample] ]
 
 
def Up_OnClicked():
 Inspects = PPG.Inspected
 for Inspected in Inspects:
  log(Inspected.Parameters("base_red") )
  Inspected.Parameters("base_red").Value = .1
  for oPrames in Inspected.Parameters:
   log(oPrames)
   #oParams("base_red").Value = .1
 return

def SetColorMathParam(in_Vale):
 PPG.Math_red.Value = in_Vale
 PPG.Math_green.Value = in_Vale
 PPG.Math_bule.Value = in_Vale
 #PPG.Math_alpha.Value = in_Vale
 return

#------------------------------------------------------
def minmax(inValue):
 if inValue < 0:
  return 0.0
 elif inValue > 1:
  #log("a")
  return 1.0
 else :
  return inValue


def SetColorMulMathParam(in_Vale):
 PPG.Math_red.Value   = minmax( PPG.Math_red.Value * in_Vale )
 PPG.Math_green.Value = minmax( PPG.Math_green.Value * in_Vale )
 PPG.Math_bule.Value  = minmax( PPG.Math_bule.Value  * in_Vale )
 #PPG.Math_alpha.Value  = minmax( PPG.Math_alpha.Value  * in_Vale )
 return
 
#------------ScalerAlglithm--------------------------

def ScalerSub(inA,inB):
 return inA - inB
 
def ScalerAdd(inA,inB):
 return inA + inB

#
def scalerMultiple(bg,fg):
 return fg * bg
 
#スクリーン
def scalerScreen(bg,fg):
 return 1 - ( ( 1 - bg ) * ( 1 - fg ) )

#オーバーレイ
def scalerOverLay(bg,fg):
 if bg < 0.5:
  return 2.0 * bg * fg
 if bg >= 0.5:
  return 1 - 2 * ( ( 1- bg ) * ( 1- fg ) )

#ソフトライト
def scalerSoftLight(bg,fg):
 if fg < 0.5:
  return bg ** ( 2 * ( 1 - fg ) )
 if fg >= 0.5:
  return bg ** ( 1 / ( 2 * fg ) )
  
#ハードライト
def scalerHardLight( bg, fg ):
 if fg < 0.5:
  return bg * fg * 2
 if fg >= 0.5:
  return 1 - 2 * ( 1 - bg) * ( 1 - fg )
  
#焼き込み
def scalerBurn(bg,fg):
 if fg == 0:
  return 1
 return 1.0 - ( 1.0 + bg ) / fg
 
#覆いカラー
def scalerDodge(bg,fg):
 if bg + fg > 1.0:
  return 1.0
 elif bg > 0:
  return bg  /(1.0 - fg )
 else :
  return 0.0
  
#覆い焼きリニア   
def scalerLinearDodge(bg,fg):
 if bg + fg > 1.0:
  return 1
 else :
  return bg + fg
  
#------------------------------------------


def setRGB(aVC,sID,inPercent):
 #R
 aVC[0][sID] = getMixPercentage( PPG.Set_red.Value , aVC[0][sID],inPercent)
 #G
 aVC[1][sID] = getMixPercentage( PPG.Set_green.Value , aVC[1][sID],inPercent)
 #B
 aVC[2][sID] = getMixPercentage( PPG.Set_bule.Value , aVC[2][sID],inPercent)
 #A
 aVC[3][sID] = getMixPercentage( PPG.Set_alpha.Value , aVC[3][sID],inPercent)


def Set_ColorMath_Sub_RGB(aVC,sID,inPercent):
 #R
 aVC[0][sID] = minmax ( getMixPercentage( ScalerSub(aVC[0][sID],PPG.Math_red.Value) , aVC[0][sID],inPercent) )
 #G
 aVC[1][sID] = minmax (  getMixPercentage( ScalerSub(aVC[1][sID],PPG.Math_green.Value) , aVC[1][sID],inPercent) )
 #B
 aVC[2][sID] = minmax (  getMixPercentage( ScalerSub(aVC[2][sID],PPG.Math_bule.Value) , aVC[2][sID],inPercent) )
 #A
 #aVC[3][sID] = minmax (  getMixPercentage( ScalerSub(aVC[3][sID],PPG.Math_alpha.Value) , aVC[3][sID],inPercent) )



def Set_ColorMath_Add_RGB(aVC,sID,inPercent):
 #R
 aVC[0][sID] = minmax ( getMixPercentage( ScalerAdd(aVC[0][sID],PPG.Math_red.Value) , aVC[0][sID],inPercent) )
 #G
 aVC[1][sID] = minmax (  getMixPercentage( ScalerAdd(aVC[1][sID],PPG.Math_green.Value) , aVC[1][sID],inPercent) )
 #B
 aVC[2][sID] = minmax (  getMixPercentage( ScalerAdd(aVC[2][sID],PPG.Math_bule.Value) , aVC[2][sID],inPercent) )
 #A
 #aVC[3][sID] = minmax (  getMixPercentage( ScalerAdd(aVC[3][sID],PPG.Math_alpha.Value) , aVC[3][sID],inPercent) )


#Set
#----------------------------------------

#----------------------------------
# getSelectSampleIDs
#----------------------------------
def getSelectSampleIDs(oSel,gToPntSmps):
 #oGeo = oSel.ActivePrimitive.Geometry
 #VC = oGeo.CurrentVertexColor
 log(oSel.Type)

 oSmpIDs = []

 #Obj
 if oSel.Type == "polymsh":
  oGeo = oSel.ActivePrimitive.Geometry
  VC = oGeo.CurrentVertexColor
  if VC == None:
   return -1
  oSmpIDs = range(oGeo.Samples.Count)
 
 #poly
 elif oSel.Type == "polySubComponent":
  oSub = oSel.SubComponent
  oColl = oSel.SubComponent.ComponentCollection
  
  #PolygonPnt Poly > pnt > sample
  if gToPntSmps:
   for oPoly in oColl:
    oPnts = oPoly.Points    
    for oPnt in oPnts:
     oSamples = oPnt.Samples
     for oSmp in oSamples:
      oSmpIDs.append(oSmp.Index)
      
  #Poly > Sampe
  else :    
   for oPoly in oColl:
    oSamples = oPoly.Samples
    for oSmp in oSamples:
     oSmpIDs.append(oSmp.Index)
 
 #Edge
 elif oSel.Type == "edgeSubComponent":
  oSub = oSel.SubComponent
  oColl = oSel.SubComponent.ComponentCollection
  
  #PolygonPnt Edge > pnt > sample
  if gToPntSmps:
   for oEdge in oColl:
    oPnts = oEdge.Points    
    for oPnt in oPnts:
     oSamples = oPnt.Samples
     for oSmp in oSamples:
      oSmpIDs.append(oSmp.Index)
      
  #Poly > Sampe
  else :    
   for oEdge in oColl:
    oSamples = oEdge.Samples
    for oSmp in oSamples:
     oSmpIDs.append(oSmp.Index)
     
 #Point   
 elif oSel.Type == "sampleSubComponent":
  oColl = oSel.SubComponent.ComponentCollection
  for oSmp in oColl:
   oSmpIDs.append(oSmp.Index)
    
 #Sample   
 elif oSel.Type == "pntSubComponent":
  oColl = oSel.SubComponent.ComponentCollection
  for oPnt in oColl:
   oSamples = oPnt.Samples
   for oSmp in oSamples:
    oSmpIDs.append(oSmp.Index)
 
 else :
  log("Pls Select Poly or Pnt")
  return -1
 
 return oSmpIDs

# SetColor
#-------------------------------
def SetColor(DrawingMode):

 gToPntSmps = PPG.ToPntSamples.Value
 gPacentege = PPG.Percent.Value
 
 oSels = app.Selection
 
 for oSel in oSels:
  
  oSmpIDs = getSelectSampleIDs(oSel,gToPntSmps)
  
  if oSmpIDs == -1:
   continue
   
  if oSel.Type != "polymsh":
   oSub = oSel.SubComponent
   oObj = oSub.Parent3DObject
  else:
   oObj = oSel
   
  oGeo = oObj.ActivePrimitive.Geometry
  Clusters = oGeo.Clusters.Filter("sample")
  for Cls in Clusters:
   for oProp in Cls.Properties:
    if(oProp.Name == "Vertex_Color"):

     aVC = oProp.Elements.Array
     aVC = [list(aVC[0]),list(aVC[1]),list(aVC[2]),list(aVC[3])]
     
     #SetColor
     if DrawingMode == "Set": 
      for i in oSmpIDs:
       setRGB(aVC,i,gPacentege)
       
     #ColorMath_Sub
     if DrawingMode == "ColorMath_Sub": 
      for i in oSmpIDs:
       Set_ColorMath_Sub_RGB(aVC,i,gPacentege)
       
     #ColorMath_Add
     if DrawingMode == "ColorMath_Add": 
      for i in oSmpIDs:
       Set_ColorMath_Add_RGB(aVC,i,gPacentege)
     
     #Burn
     if DrawingMode == "Burn":
      for i in oSmpIDs:
       rgbBurn(aVC,i)
       
     #Dodge
     if DrawingMode == "Dodge":
      for i in oSmpIDs:
       rgbDodge(aVC,i)
       
     #Multiple
     if DrawingMode == "Multiple":
      for i in oSmpIDs:
       rgbMultiple(aVC,i)
          
     oProp.Elements.Array = aVC

def SetColor_OnClicked():
 SetColor("Set")
 return
 
def ColorMath_Sub_OnClicked():
 log("Sub")
 SetColor("ColorMath_Sub")
 return 
 
def ColorMath_Add_OnClicked():
 log("Add")
 SetColor("ColorMath_Add")
 return
 

def ColorMath_00_OnClicked():
 SetColorMathParam(0.0)
 return 
def ColorMath_x05_OnClicked():
 SetColorMulMathParam(0.5)
 return 
def ColorMath_x08_OnClicked():
 SetColorMulMathParam(0.8)
 return
def ColorMath_05_OnClicked():
 SetColorMathParam(0.5)
 return 
def ColorMath_x12_OnClicked():
 SetColorMulMathParam(1.2)
 return 
def ColorMath_x20_OnClicked():
 SetColorMulMathParam(2.0)
 return
def ColorMath_10_OnClicked():
 SetColorMathParam(1.0)
 return


#----------------------------------------
#Pick VertexColor
#----------------------------------------
def Pick_FCurveColor1_OnClicked():
 rgba = pickVertexRGBA()
 if rgba == False:
  return
 PPG.FCurve1_red.Value = rgba[0]
 PPG.FCurve1_green.Value = rgba[1]
 PPG.FCurve1_bule.Value = rgba[2]
 PPG.FCurve1_alpha.Value = rgba[3]
 return

def Pick_FCurveColor2_OnClicked():
 rgba = pickVertexRGBA()
 if rgba == False:
  return
 PPG.FCurve2_red.Value = rgba[0]
 PPG.FCurve2_green.Value = rgba[1]
 PPG.FCurve2_bule.Value = rgba[2]
 PPG.FCurve2_alpha.Value = rgba[3]
 return

def Pick_SetColor_OnClicked():
 rgba = pickVertexRGBA()
 if rgba == False:
  return
 PPG.Set_red.Value = rgba[0]
 PPG.Set_green.Value = rgba[1]
 PPG.Set_bule.Value = rgba[2]
 PPG.Set_alpha.Value = rgba[3]
 return
 
def Pick_UpperLayer_OnClicked():
 rgba = pickVertexRGBA()
 if rgba == False:
  return
 PPG.UpperLayer_red.Value = rgba[0]
 PPG.UpperLayer_green.Value = rgba[1]
 PPG.UpperLayer_bule.Value = rgba[2]
 PPG.UpperLayer_alpha.Value = rgba[3]
 return
 
def Pick_ColorMath_OnClicked():
 rgba = pickVertexRGBA()
 if rgba == False:
  return
 PPG.Math_red.Value = rgba[0]
 PPG.Math_green.Value = rgba[1]
 PPG.Math_bule.Value = rgba[2]
 PPG.Math_alpha.Value = rgba[3]
 return
 
#-Gra--------------------------------------

def pickPosition():
 oPos = XSIMath.CreateVector3()
 oPick = app.PickPosition()
 if oPick(0) == 0:
  log("Pick Cancel")
  return -1
 oPos.X = oPick(1)
 oPos.Y = oPick(2)
 oPos.Z = oPick(3)
 return oPos


def setAPosition():
 oPos = pickPosition()
 if oPos == -1:
  return 
 PPG.aPosX.Value = oPos.X
 PPG.aPosY.Value = oPos.Y
 PPG.aPosZ.Value = oPos.Z
 return

def setBPosition():
 oPos = pickPosition()
 if oPos == -1:
  return 
 PPG.bPosX.Value = oPos.X
 PPG.bPosY.Value = oPos.Y
 PPG.bPosZ.Value = oPos.Z
 return
 
def pick_aPosButton_OnClicked():
 log("pick_aPos")
 setAPosition()
 return
 
def pick_bPosButton_OnClicked():
 log("pick_bPos")
 setBPosition()
 return

#----------------------------------
# pickPosition
#----------------------------------
def pickPosition():
 oPos = XSIMath.CreateVector3()
 oPick = app.PickPosition()
 if oPick(0) == 0:
  log("Pick Cancel")
  return -1
 oPos.X = oPick(1)
 oPos.Y = oPick(2)
 oPos.Z = oPick(3)
 return oPos
 
 
#------------------------------
# getGlobalPntsPositions
#------------------------------
def getGlobalPntsPositions(oObj,activePoints):
 oGeo = oObj.ActivePrimitive.Geometry
 oPnts = oGeo.Points
 aPos = oPnts.PositionArray
 aPos = [list(aPos[0]),list(aPos[1]),list(aPos[2])]
 v = XSIMath.CreateVector3()
 m = XSIMath.CreateMatrix4()
 oTrans = oObj.Kinematics.Global.Transform
 oTrans.GetMatrix4(m)
 
 for i in range(oPnts.Count):
  if activePoints[i]:
   v.Set(aPos[0][i],aPos[1][i],aPos[2][i])
   v.MulByMatrix4InPlace(m)
   aPos[0][i] = v.X
   aPos[1][i] = v.Y
   aPos[2][i] = v.Z
  
 return aPos

 
#------------------------------
# getSmp2Pnt
#------------------------------
def getSmp2Pnt(oGeo):
 smp2pnt = []
 
 oSmps = oGeo.Samples
 oPnts = oGeo.Points
 
 for i in oSmps:
  smp2pnt.append(-1)
  
 for oPnt in oPnts:
  for smp in oPnt.Samples:
   smp2pnt[smp.Index] = oPnt.Index
   
 return smp2pnt


#------------------------------
# getActivePoints
#------------------------------
def getActivePoints(nbPnts,smp2pnt,oSmpIDs):
 activePnts = []
 
 for i in range(nbPnts):
  activePnts.append(False)  
 for i in oSmpIDs:
  activePnts[ smp2pnt [ i ] ] = True
 
 return activePnts

#------------------------------
# getDistanceArray
#------------------------------
def getDistanceArray(gradientType,nbPnts,p1,p2,aPos,activePoints):
 distanceArray = []
 for i in range(nbPnts):
  distanceArray.append( -1.0 )

 v = XSIMath.CreateVector3()
 
 if gradientType == 0: #Linear Plane to Point
  n = XSIMath.CreateVector3()
  n.Sub(p2,p1)
  n.NormalizeInPlace()
  for i in range(nbPnts):
   if activePoints[i]:
    v.Set(aPos[0][i],aPos[1][i],aPos[2][i])
    v.SubInPlace(p1)
    len = v.Dot( n )
    #log(len)
    distanceArray[i] =  abs( len )  
 
 if gradientType == 1: # Distance
  for i in range(nbPnts):
   if activePoints[i]:
    v.Set(aPos[0][i],aPos[1][i],aPos[2][i])
    v.SubInPlace(p1)
    #log(v.Length())
    distanceArray[i] =  v.Length()
 return distanceArray
 

#------------------------------
# getDistanceArray
#------------------------------
def  getPercentage(nbPnts,p1,p2,distanceArray,activePoints):
 percentageArray =[]
 for i in range(nbPnts):
  percentageArray.append(100)
 p1.SubInPlace(p2)
 length = p1.Length()
 if length == 0:
  log("Plz Select2Pnt")
  return
 
 for i in range(nbPnts):
  if activePoints[i]:
   per = abs( distanceArray[i]/ length * 100 )
   if per > 100:
    per = 100
   per = 100 - per
   #log(per)
   percentageArray[i] =  per
 return percentageArray


#------------------------------
# perArrayToFCurvePerArray
#------------------------------
def perArrayToFCurvePerArray(percentageArray):

 fc = PPG.FCurve.Value
 for i,per in enumerate( percentageArray ):
  percentageArray[i] = 100 - ( minmax( fc.Eval( per ) ) * 100 )
 return  percentageArray


#------------------------------
# gradationExe
#------------------------------
def gradationExe(rePaint):
 gradientType = PPG.GraForm.Value
 gradientColorType = PPG.GraColorPattern.Value
 gToPntSmps = PPG.ToPntSamples.Value

 #Color
 c1 = [PPG.FCurve1_red.Value,
    PPG.FCurve1_green.Value,
    PPG.FCurve1_bule.Value,
    PPG.FCurve1_alpha.Value]
  
 c2 = [PPG.FCurve2_red.Value,
    PPG.FCurve2_green.Value,
    PPG.FCurve2_bule.Value,
    PPG.FCurve2_alpha.Value]
    
 #Position
 if rePaint:
  p1 = XSIMath.CreateVector3()
  p1.Set(
  PPG.aPosX.Value,
  PPG.aPosY.Value,
  PPG.aPosZ.Value )
  
  p2 = XSIMath.CreateVector3()
  p2.Set(
  PPG.bPosX.Value,
  PPG.bPosY.Value,
  PPG.bPosZ.Value )  
 
 else:
  p1 = pickPosition()
  if p1 == -1:
   return

  PPG.aPosX.Value = p1.X
  PPG.aPosY.Value = p1.Y
  PPG.aPosZ.Value = p1.Z
   
  p2 = pickPosition()
  if p2 == -1:
   return
  
  PPG.bPosX.Value = p2.X
  PPG.bPosY.Value = p2.Y
  PPG.bPosZ.Value = p2.Z

 oSels = app.Selection
  
 for oSel in oSels:
 
  oSmpIDs = getSelectSampleIDs(oSel,gToPntSmps)
  if oSmpIDs == -1:
   continue
   
  if oSel.Type != "polymsh":
   oSub = oSel.SubComponent
   oObj = oSub.Parent3DObject
  else:
   oObj = oSel
   
  oGeo = oObj.ActivePrimitive.Geometry
  oPnts = oGeo.Points
  nbPnts = oPnts.Count
  
  smp2pnt = getSmp2Pnt(oGeo)
  activePoints = getActivePoints(nbPnts,smp2pnt,oSmpIDs)
  aPos = getGlobalPntsPositions(oObj,activePoints)
  distanceArray = getDistanceArray(gradientType,nbPnts,p1,p2,aPos,activePoints)
  percentageArray = getPercentage(nbPnts,p1,p2,distanceArray,activePoints)
  percentageArray = perArrayToFCurvePerArray(percentageArray)
  
  Clusters = oGeo.Clusters.Filter("sample")
  for Cls in Clusters:
   for oProp in Cls.Properties:
    if(oProp.Name == "Vertex_Color"):

     aVC = oProp.Elements.Array
     aVC = [list(aVC[0]),list(aVC[1]),list(aVC[2]),list(aVC[3])]
     
     #Normal
     if PPG.GraComposition.Value == 0:
     
      #Color1 > Bace
      if gradientColorType == 0:
       for i in oSmpIDs:
        r = getMixPercentage( c1[0],aVC[0][i],percentageArray[smp2pnt[i]])
        g = getMixPercentage( c1[1],aVC[1][i],percentageArray[smp2pnt[i]])
        b = getMixPercentage( c1[2],aVC[2][i],percentageArray[smp2pnt[i]])
        a = getMixPercentage( c1[3],aVC[3][i],percentageArray[smp2pnt[i]])
        aVC[0][i] = getMixPercentage( r, aVC[0][i], PPG.Percent.Value )
        aVC[1][i] = getMixPercentage( g, aVC[1][i], PPG.Percent.Value )
        aVC[2][i] = getMixPercentage( b, aVC[2][i], PPG.Percent.Value )
        aVC[3][i] = getMixPercentage( a, aVC[3][i], PPG.Percent.Value )
        
      #Color1 > Color2
      if gradientColorType == 1:
       for i in oSmpIDs:
        r = getMixPercentage( c1[0], c2[0], percentageArray[smp2pnt[i]])
        g = getMixPercentage( c1[1], c2[1], percentageArray[smp2pnt[i]])
        b = getMixPercentage( c1[2], c2[2], percentageArray[smp2pnt[i]])
        a = getMixPercentage( c1[3], c2[3], percentageArray[smp2pnt[i]])
        aVC[0][i] = getMixPercentage( r, aVC[0][i], PPG.Percent.Value )
        aVC[1][i] = getMixPercentage( g, aVC[1][i], PPG.Percent.Value )
        aVC[2][i] = getMixPercentage( b, aVC[2][i], PPG.Percent.Value )
        aVC[3][i] = getMixPercentage( a, aVC[3][i], PPG.Percent.Value )
        
     #Multiple
     if PPG.GraComposition.Value == 1:
     
      #Color1 > Bace
      if gradientColorType == 0:
       for i in oSmpIDs:
        #r = getMixPercentage( c1[0],aVC[0][i],percentageArray[smp2pnt[i]])
        #g = getMixPercentage( c1[1],aVC[1][i],percentageArray[smp2pnt[i]])
        #b = getMixPercentage( c1[2],aVC[2][i],percentageArray[smp2pnt[i]])
        #a = getMixPercentage( c1[3],aVC[3][i],percentageArray[smp2pnt[i]])
        r = getMixPercentage( c1[0],1,percentageArray[smp2pnt[i]])
        g = getMixPercentage( c1[1],1,percentageArray[smp2pnt[i]])
        b = getMixPercentage( c1[2],1,percentageArray[smp2pnt[i]])
        a = getMixPercentage( c1[3],1,percentageArray[smp2pnt[i]])
        r = scalerMultiple(r,aVC[0][i])
        g = scalerMultiple(g,aVC[1][i])
        b = scalerMultiple(b,aVC[2][i])
        a = scalerMultiple(a,aVC[3][i])
        aVC[0][i] = getMixPercentage( r, aVC[0][i], PPG.Percent.Value )
        aVC[1][i] = getMixPercentage( g, aVC[1][i], PPG.Percent.Value )
        aVC[2][i] = getMixPercentage( b, aVC[2][i], PPG.Percent.Value )
        aVC[3][i] = getMixPercentage( a, aVC[3][i], PPG.Percent.Value )
        
      #Color1 > Color2
      if gradientColorType == 1:
       for i in oSmpIDs:
        r = getMixPercentage( c1[0], c2[0], percentageArray[smp2pnt[i]])
        g = getMixPercentage( c1[1], c2[1], percentageArray[smp2pnt[i]])
        b = getMixPercentage( c1[2], c2[2], percentageArray[smp2pnt[i]])
        a = getMixPercentage( c1[3], c2[3], percentageArray[smp2pnt[i]])
        r = minmax( scalerMultiple(r,aVC[0][i]) )
        g = minmax( scalerMultiple(g,aVC[1][i]) )
        b = minmax( scalerMultiple(b,aVC[2][i]) )
        a = minmax( scalerMultiple(a,aVC[3][i]) )
        aVC[0][i] = getMixPercentage( r, aVC[0][i], PPG.Percent.Value )
        aVC[1][i] = getMixPercentage( g, aVC[1][i], PPG.Percent.Value )
        aVC[2][i] = getMixPercentage( b, aVC[2][i], PPG.Percent.Value )
        aVC[3][i] = getMixPercentage( a, aVC[3][i], PPG.Percent.Value )
        


     oProp.Elements.Array = aVC
     

#------------------------------
def Gradation_Exe_OnClicked():
 gradationExe(False)

#------------------------------
def RePaint_OnClicked():
 log("RePaint")
 gradationExe(True)

"""

def main():

 cp = XSIFactory.CreateObject("CustomProperty")
 cp.Name = "VertexColorTools"
 
 colorList = ["Set","UpperLayer","Math"]
 addColorParam(cp,colorList)
 addOtherParam(cp)
 FCurveColorList = ["FCurve1","FCurve2"]
 addColorParam(cp,FCurveColorList)
 
 oly = createLayout(cp,colorList,FCurveColorList)
 lyLogic(oly)
 
 app.InspectObj(cp,"","",3)

main()