# Change the selected parameter(s) via the mouse wheel v3.8
# and much more see http://neocron.lunarpages.com/alforum/index.php?topic=1511.0
# changes: 
#	return/enter doesn't deactivate panel, layout and position saved by room (if it can be guessed), 
#	LightAttenuation can be set, Undo/Redo and Value changes work for V4's chest rotation that cannot be called by it's Parameter name (Twist)
#	normals forwards not only for root node, 
#	decrease/increase Diffuse-Value by multiplier value diffuseMulti
#	SetGamma for Poser Pro
#	Checkbox to modify parented and conformed items, too (useful for changing properties/mats), Camera/Lighs checkboxes combined to one checkbox to save space
#	no more errors with multiple GoalCenterOfMass etc. props
#	added context menu for actor list: allows duplicating selected actors (will use Poser's duplicate feature) and if wished to select all duplicated actors
#	set the units used to display translation values to inches, foot, millimeter, centimeter, meter or a custom value ;-) (see setup tab)
#	can change the following properties: "Visible", "Visible in Raytrace", "Visible in Render", "Casts Shadows", "Bend", "Smooth Polygons", "Include in Boundingbox", "Static"
# - Python coding by Dizzi
import poser
import wx
import wx.aui
import os.path
import random
import wx.lib.masked.numctrl
import math
import pickle

class WheelPosing(wx.Panel):
	diffuseMulti=0.9 #set to the value you like...
	CustomUnit=1 # custom display unit for translations
	
	SavePath=os.path.join(poser.PrefsLocation(), "acb", "multiactor")
	PanelLayout={}
	selectedParamName=""
#	multi=1
	value=1.0
	Amount="1"
	Digit=1
	Exponent=0
	Actors=[]
	RotTrans=[poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT, poser.kParmCodeXTRAN, poser.kParmCodeYTRAN, poser.kParmCodeZTRAN]
	RotTransString=["Rotate X", "Rotate Y", "Rotate Z", "Translate X", "Translate Y", "Translate Z"]
	InternalItems=["GoalCenterOfMass","CenterOfMass", "faceRoomActor", "faceRoomTexActor"]
	Undos=[]
	Redos=[]
	LastActor=None
	KeyActors={}
	changedMats=[]
	UnitDivisor=[]
	
	ReallyDoStatic=-1
	def __init__(self,parent,title, pane):
		wx.Panel.__init__(self, parent, -1, wx.Point(-1, -1), wx.DefaultSize, wx.WANTS_CHARS)
		self.dlgGamma=None
		self.dlgDuplicate=wx.NumberEntryDialog(self, "Please enter how often to duplicate the selected actors", "Amount: ", "Duplicate actors", 1, 1, 100)
	
		self.man=poser.WxAuiManager()
		
		if not os.path.exists(self.SavePath):
			os.makedirs(self.SavePath)
		
		self.PanelLayoutFile=os.path.join(self.SavePath, "PanelLayout_"+self.TryFindRoom()+".config")
		if os.path.exists(self.PanelLayoutFile):
			fd=open(self.PanelLayoutFile)
			self.PanelLayout=pickle.load(fd)
			fd.close()
			if self.PanelLayout.has_key("PanelLayout"):
				self.man.LoadPaneInfo(self.PanelLayout["PanelLayout"], pane)
		self.settingsFile=os.path.join(self.SavePath, "Settings.config")
		
		DefaultUnit=0
		self.settings={}
		if os.path.exists(self.settingsFile):
			fd=open(self.settingsFile)
			self.settings=pickle.load(fd)
			fd.close()
			if self.settings.has_key("diffuseMulti"):
				self.diffuseMulti=self.settings["diffuseMulti"]
			if self.settings.has_key("CustomUnit"):
				self.CustomUnit=self.settings["CustomUnit"]
			if self.settings.has_key("DefaultUnit"):
				DefaultUnit=self.settings["DefaultUnit"]
		
		
		self.CheckboxPropertyNames=["Visible", "Visible in Raytrace", "Visible in Render", "Casts Shadows", "Bend", "Smooth Polygons", "Include in Boundingbox", "Static"]
		self.CheckboxPropertyMethods=[self.SetVisible, self.SetVisibleInReflections, self.SetVisibleInRender, self.SetCastsShadows, self.SetBends, self.SetSmoothPolys, self.SetIncludeInBoundingBox, self.SetStatic]
		
		
		self.sizer = wx.BoxSizer(wx.VERTICAL)
		self.SetSizer(self.sizer)
		self.SetAutoLayout(1)
		#self.sizer.SetSizeHints(self)
		self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizer.Add(self.sizer2)
		l=self.GetActorParamList()
		list=self.GetActorParamList()[0]
		self.Params=l[1]
		radioList = ['Actor', 'Figure', 'All']
		self.rbType = wx.RadioBox(self, 40, "Type", wx.Point(-1, -1), wx.DefaultSize, radioList, 1, wx.RA_SPECIFY_COLS)
		self.Bind(wx.EVT_RADIOBOX, self.EvtRbType, self.rbType)
		self.sizer2.Add(self.rbType)
		
		staticBox = wx.StaticBox(self, -1, "Actors")
		self.szActorType = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
		self.cbCamLights = wx.CheckBox(self, 21, "Cam/Light")
		self.cbCamLights.Bind(wx.EVT_CHECKBOX, self.EvtChkboxActorType)
		self.szActorType.Add(self.cbCamLights)
		self.cbMagnets = wx.CheckBox(self, 23, "Magnet")
		self.cbMagnets.Bind(wx.EVT_CHECKBOX, self.EvtChkboxActorType)
		self.szActorType.Add(self.cbMagnets)
		self.cbProps = wx.CheckBox(self, 23, "Prop")
		self.cbProps.Bind(wx.EVT_CHECKBOX, self.EvtChkboxActorType)
		self.cbProps.SetValue(True)
		self.szActorType.Add(self.cbProps)
		self.cbHidden = wx.CheckBox(self, 24, "Hidden")
		self.cbHidden.Bind(wx.EVT_CHECKBOX, self.EvtChkboxActorType)
		#self.cbHidden.SetValue(True)
		self.szActorType.Add(self.cbHidden)
		self.cbParented = wx.CheckBox(self, 25, "Parented")
		self.cbParented.Bind(wx.EVT_CHECKBOX, self.EvtChkboxActorType)
		self.cbParented.Enable(False)
		self.szActorType.Add(self.cbParented)
		self.sizer2.Add(self.szActorType)
		self.sizer2.Hide(self.szActorType)
		
		self.rbTransType = wx.RadioBox(self, 44, "Translate", wx.Point(-1, -1), wx.DefaultSize, ["Equally", "N*A", "Random"], 1, wx.RA_SPECIFY_COLS)
		self.Bind(wx.EVT_RADIOBOX, self.EvtRbTransType, self.rbTransType)
		self.rbTransType.Show(0)
		self.sizer2.Add(self.rbTransType)

		self.lbActors = wx.ListBox(self, 50, (-1, -1), self.GetSize("lbActors", (175, 100)), [], wx.LB_EXTENDED|wx.LB_NEEDED_SB)
		self.lbActors.Multiselect=1
		self.sizer.Add(self.lbActors)
		self.lbActors.Show(0);
		
		self.tabs = wx.Notebook(self, -1, wx.DefaultPosition, wx.DefaultSize)
		self.sizer.Add(self.tabs)
		self.tabs.SetAutoLayout(True)
		
		self.tab1 = wx.Panel(self.tabs, -1, wx.Point(-1, -1), wx.DefaultSize, wx.WANTS_CHARS)
		self.tabs.AddPage(self.tab1, "Param", True)
		self.sizerTab1= wx.BoxSizer(wx.VERTICAL)
		self.tab1.SetSizer(self.sizerTab1)
		
		self.lbParams = wx.ListBox(self.tab1, 60, (-1, -1), self.GetSize("lbParams", (175, 100)), list, wx.LB_EXTENDED|wx.LB_NEEDED_SB)
		self.tab1.Bind(wx.EVT_LISTBOX, self.EvtListBoxClick, self.lbParams)
		self.sizerTab1.Add(self.lbParams)
		
		
		fgsGridInputs=wx.FlexGridSizer(2,3,2,1)
		self.sizerTab1.Add(fgsGridInputs)
		# input value
		lblValue = wx.StaticText(self.tab1, -1, "Value: ", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_RIGHT)
		self.txtValue = wx.lib.masked.NumCtrl(self.tab1, 0, "0.0")
		self.txtValue.SetFractionWidth(6)
		self.txtValue.SetIntegerWidth(6)
		self.txtValue.SetAllowNone(False)
		self.txtValue.SetAllowNegative(True)
		self.txtValue.SetGroupDigits(False)
		self.txtValue.SetEditable(False)
		fgsGridInputs.Add(lblValue, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
		fgsGridInputs.Add(self.txtValue)
		fgsGridInputs.Add(wx.StaticText(self.tab1, -1, ""))
		
		# amount label and input
		lblAmount = wx.StaticText(self.tab1, -1, "Amount: ", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_RIGHT)
		self.txtAmount = wx.lib.masked.NumCtrl(self.tab1, 0)
		self.txtAmount.SetFractionWidth(6)
		self.txtAmount.SetIntegerWidth(6)
		self.txtAmount.SetAllowNone(True)
		self.txtAmount.SetAllowNegative(True)
		self.txtAmount.SetGroupDigits(False)
		self.txtAmount.SetEditable(False)
		self.txtAmount.SetLimited(True)
		self.txtAmount.SetLimitOnFieldChange(True)
		self.txtAmount.SetMax("999999.999999")
		self.txtAmount.SetValue(self.Amount)
		self.lblDigit = wx.StaticText(self.tab1, -1, "+1", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_LEFT)
		fgsGridInputs.Add(lblAmount, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
		fgsGridInputs.Add(self.txtAmount)
		fgsGridInputs.Add(self.lblDigit, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
		
		#undo
		self.sizer3 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerTab1.Add(self.sizer3)
		self.btnInvert = wx.Button(self.tab1, 61, "Invert")
		self.sizer3.Add(self.btnInvert)
		self.btnSet = wx.Button(self.tab1, 62, "Set")
		self.sizer3.Add(self.btnSet)
		
		#undo
		self.sizerUndo = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerTab1.Add(self.sizerUndo)
		self.btnUndo = wx.Button(self.tab1, 71, "Undo")
		self.btnUndo.Enable(False)
		self.sizerUndo.Add(self.btnUndo)
		self.btnRedo = wx.Button(self.tab1, 72, "Redo")
		self.btnRedo.Enable(False)
		self.sizerUndo.Add(self.btnRedo)
		
		
		#
		self.tab2 = wx.Panel(self.tabs, -1, wx.Point(-1, -1), wx.DefaultSize, wx.WANTS_CHARS)
		self.tabs.AddPage(self.tab2, "Prop", False)
		self.sizerTab2= wx.BoxSizer(wx.HORIZONTAL)
		self.tab2.SetSizer(self.sizerTab2)
		
		staticBoxGeneral = wx.StaticBox(self.tab2, -1, "General")
		szGeneral = wx.StaticBoxSizer(staticBoxGeneral, wx.VERTICAL)
		self.lbCheckboxProperties = wx.ListBox(self.tab2, 50, (-1, -1), (120, 110), self.CheckboxPropertyNames, wx.LB_EXTENDED|wx.LB_NEEDED_SB)
		self.lbCheckboxProperties.Multiselect=1
		szGeneral.Add(self.lbCheckboxProperties)
		self.btnPropOn = wx.Button(self.tab2, 101, "Check")
		szGeneral.Add(self.btnPropOn)
		self.btnPropOff = wx.Button(self.tab2, 102, "Uncheck")
		szGeneral.Add(self.btnPropOff)
		self.sizerTab2.Add(szGeneral)
		
		staticBoxLight = wx.StaticBox(self.tab2, -1, "Light")
		szLight = wx.StaticBoxSizer(staticBoxLight, wx.VERTICAL)
		self.btnOn = wx.Button(self.tab2, 111, "On")
		szLight.Add(self.btnOn)
		self.btnOff = wx.Button(self.tab2, 112, "Off")
		szLight.Add(self.btnOff)
		self.btnRayTrace = wx.Button(self.tab2, 121, "Ray Trace")
		szLight.Add(self.btnRayTrace)
		self.btnDepthMap = wx.Button(self.tab2, 122, "Depth Map")
		szLight.Add(self.btnDepthMap)
		self.btnAttenConst = wx.Button(self.tab2, 123, "Constant")
		szLight.Add(self.btnAttenConst)
		self.btnAttenSqu = wx.Button(self.tab2, 124, "Inv Linear")
		szLight.Add(self.btnAttenSqu)
		self.btnAttenLin = wx.Button(self.tab2, 125, "Inv Square")
		szLight.Add(self.btnAttenLin)
		
		self.sizerTab2.Add(szLight)
		
		#Materials
		self.tab4 = wx.Panel(self.tabs, -1, wx.Point(-1, -1), wx.DefaultSize, wx.WANTS_CHARS)
		self.tabs.AddPage(self.tab4, "Mats", False)
		self.sizerTab4= wx.GridBagSizer(2,2)
		self.tab4.SetSizer(self.sizerTab4)
		
		staticBoxTexFilter = wx.StaticBox(self.tab4, -1, "Filtering")
		szTexFilter = wx.StaticBoxSizer(staticBoxTexFilter, wx.VERTICAL)
		self.sizerTab4.Add(szTexFilter, wx.GBPosition(0,0))
		self.btnMatFilterOff = wx.Button(self.tab4, 131, "Quality")
		szTexFilter.Add(self.btnMatFilterOff)
		self.btnMatFilterFast = wx.Button(self.tab4, 132, "Fast")
		szTexFilter.Add(self.btnMatFilterFast)
		self.btnMatFilterQuality = wx.Button(self.tab4, 133, "None")
		szTexFilter.Add(self.btnMatFilterQuality)
		
		staticBoxNForward = wx.StaticBox(self.tab4, -1, "N-Forward")
		szNForward = wx.StaticBoxSizer(staticBoxNForward, wx.VERTICAL)
		self.sizerTab4.Add(szNForward, wx.GBPosition(0,1))
		self.btnNForwardOn = wx.Button(self.tab4, 141, "On")
		szNForward.Add(self.btnNForwardOn)
		self.btnNForwardOff = wx.Button(self.tab4, 142, "Off")
		szNForward.Add(self.btnNForwardOff)

		staticBoxReflMult = wx.StaticBox(self.tab4, -1, "Refl_x_Mult")
		szReflMult = wx.StaticBoxSizer(staticBoxReflMult, wx.VERTICAL)
		self.sizerTab4.Add(szReflMult, wx.GBPosition(1,0))
		self.btnReflOn = wx.Button(self.tab4, 151, "On")
		szReflMult.Add(self.btnReflOn)
		self.btnReflOff = wx.Button(self.tab4, 152, "Off")
		szReflMult.Add(self.btnReflOff)

		staticBox = wx.StaticBox(self.tab4, -1, "Diffuse-Value")
		sz = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
		self.sizerTab4.Add(sz, wx.GBPosition(1,1))
		self.btnDiffuseDec = wx.Button(self.tab4, 161, "Decrease")
		sz.Add(self.btnDiffuseDec)
		self.btnDiffuseInc = wx.Button(self.tab4, 162, "Increase")
		sz.Add(self.btnDiffuseInc)
		self.SetDiffuseToolTips()
		
		if poser.IsPro():
			self.sizerTab4.Add(wx.Button(self.tab4, 990, "Set Gamma"), wx.GBPosition(2,0))
		
		# layout
		self.tab3 = wx.Panel(self.tabs, -1, wx.Point(-1, -1), wx.DefaultSize, wx.WANTS_CHARS)
		p=self.tab3
		self.tabs.AddPage(self.tab3, "Setup", False)
		self.sizerTab3= wx.BoxSizer(wx.VERTICAL)
		self.tab3.SetSizer(self.sizerTab3)
		fgsLayout=wx.FlexGridSizer(2,3,2,1)
		self.sizerTab3.Add(fgsLayout)
		
		# input value
		lbl = wx.StaticText(self.tab3, -1, "Object", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_CENTER)
		fgsLayout.Add(lbl, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL)
		lbl = wx.StaticText(self.tab3, -1, "Width", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_CENTER)
		fgsLayout.Add(lbl, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL)
		lbl = wx.StaticText(self.tab3, -1, "Height", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_CENTER)
		fgsLayout.Add(lbl, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL)
		
		lbl = wx.StaticText(self.tab3, -1, "Parameters", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_RIGHT)
		self.spLoPX  = wx.SpinCtrl(id=1, initial=self.lbParams.GetSizeTuple()[0], max=999, min=50, parent=self.tab3, pos=wx.Point(-1, -1), size=(60,-1), style=wx.SP_ARROW_KEYS)
		self.spLoPY  = wx.SpinCtrl(id=1, initial=self.lbParams.GetSizeTuple()[1], max=999, min=50, parent=self.tab3, pos=wx.Point(-1, -1), size=(60,-1), style=wx.SP_ARROW_KEYS)
		fgsLayout.Add(lbl, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
		fgsLayout.Add(self.spLoPX, 0, wx.ALIGN_CENTER)
		fgsLayout.Add(self.spLoPY, 0, wx.ALIGN_CENTER)

		lbl = wx.StaticText(self.tab3, -1, "Actors", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_RIGHT)
		self.spLoAX  = wx.SpinCtrl(id=2, initial=self.lbActors.GetSizeTuple()[0], max=999, min=50, parent=self.tab3, pos=wx.Point(-1, -1), size=(60,-1), style=wx.SP_ARROW_KEYS)
		self.spLoAY  = wx.SpinCtrl(id=2, initial=self.lbActors.GetSizeTuple()[1], max=999, min=50, parent=self.tab3, pos=wx.Point(-1, -1), size=(60,-1), style=wx.SP_ARROW_KEYS)
		fgsLayout.Add(lbl, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
		fgsLayout.Add(self.spLoAX, 0, wx.ALIGN_CENTER)
		fgsLayout.Add(self.spLoAY, 0, wx.ALIGN_CENTER)
		self.tab3.Bind(wx.EVT_SPINCTRL, self.EvtSpin)
		
		self.sizerTab3.AddSpacer(10)
		s=wx.BoxSizer(wx.HORIZONTAL)
		self.sizerTab3.Add(s)
		s.Add(wx.StaticText(p, -1, "Diffuse Multi: "))
		self.ncDiffuse=wx.lib.masked.numctrl.NumCtrl(parent=p, value=self.diffuseMulti, id=1000, integerWidth=1, fractionWidth=3,allowNegative=False, min=0.1, max=0.999, limitOnFieldChange=True)
		self.ncDiffuse.Bind(wx.EVT_TEXT, self.EvtText)
		s.Add(self.ncDiffuse)
		
		self.sizerTab3.AddSpacer(10)
		radioList = ['Poser native units', 'Inches', 'Feet', 'Millimeter', 'Centimeter', 'Meter', 'Custom (1 PNU=X Custom)']
		self.UnitMultiplier=[1.0, 0.009689922332760, 0.116279064941000, 0.000381492993164000, 0.00381492993164000, 0.381492993164000, self.CustomUnit]
		self.rbUnit = wx.RadioBox(p, 70, "Units used for Translations", wx.Point(-1, -1), wx.DefaultSize, radioList, 1, wx.RA_SPECIFY_COLS)
		self.rbUnit.SetSelection(DefaultUnit)
		self.sizerTab3.Add(self.rbUnit)
		self.Bind(wx.EVT_RADIOBOX, self.EvtUnit, self.rbUnit)
		s=wx.BoxSizer(wx.HORIZONTAL)
		self.sizerTab3.Add(s)
		s.Add(wx.StaticText(p, -1, "1 PNU=X Custom: "))
		self.ncCustomUnit=wx.lib.masked.numctrl.NumCtrl(parent=p, value=self.CustomUnit, id=1001, integerWidth=5, fractionWidth=10,allowNegative=False)
		self.ncCustomUnit.Bind(wx.EVT_TEXT, self.EvtText)
		s.Add(self.ncCustomUnit)
		
		#bind mousewheel on listboxes so moving the wheel without pressing will work
		self.Bind(wx.EVT_BUTTON, self.EvtButton)
		self.tab1.Bind(wx.EVT_BUTTON, self.EvtButton)
		self.tab2.Bind(wx.EVT_BUTTON, self.EvtButton)
		self.Bind(wx.EVT_MOUSEWHEEL, self.EvtWheel)
		self.lbParams.Bind(wx.EVT_MOUSEWHEEL, self.EvtWheel)
		self.lbActors.Bind(wx.EVT_MOUSEWHEEL, self.EvtWheel)

		#bind keyevents so Poser doesn't get them. Ha!
		self.Bind(wx.EVT_CHAR, self.EvtKey)
		self.lbParams.Bind(wx.EVT_CHAR, self.EvtKey)
		self.lbActors.Bind(wx.EVT_CHAR, self.EvtKey)
		self.rbType.Bind(wx.EVT_CHAR, self.EvtKey)
		self.rbTransType.Bind(wx.EVT_CHAR, self.EvtKey)
		self.txtValue.Bind(wx.EVT_CHAR, self.EvtKey)
		self.txtAmount.Bind(wx.EVT_CHAR, self.EvtKey)
		
#		self.Layout()
#		poser.Scene().SetEventCallback(self.EvcbParam)
		self.timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.EvtTimer, self.timer)
		self.timer.Start(100)  # x100 milliseconds
		
		self.Bind(wx.EVT_SIZE,self.EvtChildFocus)
		self.Bind(wx.EVT_CHILD_FOCUS, self.EvtChildFocus)
		self.Bind(wx.EVT_RIGHT_DOWN, self.ShowContextMenu)
		self.lbActors.Bind(wx.EVT_RIGHT_DOWN, self.ShowActorContextMenu)
		self.Bind(wx.EVT_MENU, self.ExecuteMenuCommand)
		self.lbActors.Bind(wx.EVT_MENU, self.ExecuteMenuCommand)

		self.Bind(wx.EVT_NAVIGATION_KEY, self.EvtDoNothing)
		
		self.KeyActorsFile=os.path.join(self.SavePath, "key_actor.config")
		if os.path.exists(self.KeyActorsFile):
			fd=open(self.KeyActorsFile)
			self.KeyActors=pickle.load(fd)
			fd.close()
	def __del__(self):
		try:
			fd=open(self.KeyActorsFile, "w")
			pickle.dump(self.KeyActors,fd)
			fd.close()
		except:
			pass
		try:
			fd=open(self.PanelLayoutFile, "w")
			pickle.dump(self.PanelLayout,fd)
			fd.close()
		except:
			pass
	def EvtDoNothing(self, event):
		print event
		return
#		poser.Scene().ClearEventCallback()
	def EvtChildFocus(self, event):
		self.SaveLayout()
		event.Skip()
	def SaveLayout(self):
		pane=self.man.GetPane(self)
		pane.BestSize(pane.floating_size)
		self.PanelLayout["PanelLayout"]=self.man.SavePaneInfo(pane)
	def TryFindRoom(self):
		for pane in self.man.GetAllPanes():
			if pane.name.startswith("Hair") and pane.IsShown():
				return "Hair"
			elif pane.name.startswith("Cloth") and pane.IsShown():
				return "Cloth"
			elif pane.name.startswith("Material") and pane.IsShown():
				return "Material"
		return "Default"

	def EvtText(self, event):
		if event.Id==1000:
			val=self.ncDiffuse.GetValue()
			if val>=1 or val<0.1:return
			self.diffuseMulti=val
			self.SetDiffuseToolTips()
			self.settings["diffuseMulti"]=val
			fd=open(self.settingsFile, "w")
			pickle.dump(self.settings,fd)
			fd.close()
		if event.Id==1001:
			val=self.ncCustomUnit.GetValue()
			self.CustomUnit=val
			self.settings["CustomUnit"]=val
			fd=open(self.settingsFile, "w")
			pickle.dump(self.settings,fd)
			fd.close()
	def SetDiffuseToolTips(self):
		self.btnDiffuseDec.SetToolTip(wx.ToolTip("Increase or decrease the Diffuse-Value\nValue will be multiplied/divided by "+str(self.diffuseMulti)))
		self.btnDiffuseInc.SetToolTip(wx.ToolTip("Increase or decrease the Diffuse-Value\nValue will be multiplied/divided by "+str(self.diffuseMulti)))
	
	def EvtKey(self,event):
		event.StopPropagation()
		code=event.GetKeyCode()
		if code==wx.WXK_F1:
			self.SetDigit(5)
		elif code==wx.WXK_F2:
			self.SetDigit(4)
		elif code==wx.WXK_F3:
			self.SetDigit(3)
		elif code==wx.WXK_F4:
			self.SetDigit(2)
		elif code==wx.WXK_F5:
			self.SetDigit(1)
		elif code==wx.WXK_F6:
			self.SetDigit(0)
		elif code==wx.WXK_F7:
			self.SetDigit(-1)
		elif code==wx.WXK_F8:
			self.SetDigit(-2)
		elif code==wx.WXK_F9:
			self.SetDigit(-3)
		elif code==wx.WXK_F10:
			self.SetDigit(-4)
		elif code==wx.WXK_F11:
			self.SetDigit(-5)
		elif code==wx.WXK_F12:
			self.SetDigit(-6)
		elif code==wx.WXK_LEFT:
			self.SetDigit(min(self.Exponent+1, 5))
		elif code==wx.WXK_RIGHT:
			self.SetDigit(max(self.Exponent-1, -6))
		elif code==wx.WXK_UP:
			self.SetAmount(self.txtAmount.GetValue()+self.Digit)
		elif code==wx.WXK_DOWN:
			val=self.txtAmount.GetValue()-self.Digit
			if (val>=0):
				self.SetAmount(val)
		elif code==wx.WXK_BACK:
			val=self.Amount
			if (len(val)>0):
				val=val[0:len(val)-1]
				self.SetAmount(val)
		elif code==wx.WXK_SPACE:
			self.SetAmount("")
		elif code==wx.WXK_RETURN:
			print 'x'
		elif code>255:
			return
		else:
			char=chr(code)
			if char.isdigit() or char==',' or char=='.':
				if char==',':
					char="."
				val=self.Amount
				if val=='' and char=='.':
					val="0.";
				else:
					val=val+char
				if self.IsNumber(val):
					self.SetAmount(val)
			elif char.isalpha():
				if char.isupper():
					l=[]
					for ix in self.lbActors.GetSelections():
						l.append(self.lbActors.GetString(ix))
					self.KeyActors[char.lower()]=l
				else:
					self.lbActors.DeselectAll()
					if self.KeyActors.has_key(char.lower()):
						for s in self.KeyActors[char.lower()]:
							i=self.lbActors.FindString(s)
							if i!=wx.NOT_FOUND:
								self.lbActors.Select(i)
	def EvtSpin(self, event):
		if event.Id==1:
			self.SetSizeParams(self.spLoPX.GetValue(), self.spLoPY.GetValue())
		elif event.Id==2:
			self.SetSizeActors(self.spLoAX.GetValue(), self.spLoAY.GetValue())
	def SetSizeParams(self, x, y):
		self.lbParams.SetSize((x,y))
		self.PanelLayout["lbParams"]=(x,y)
		self.sizerTab1.SetItemMinSize(self.lbParams, (x,y))
		self.tab1.Layout()
		self.tab1.Fit()
	def SetSizeActors(self, x, y):
		self.lbActors.SetSize((x,y))
		self.PanelLayout["lbActors"]=(x,y)
		self.sizer.SetItemMinSize(self.lbActors, (x,y))
		self.PanelLayout()
	def GetSize(self, component, defaultSize):
		if self.PanelLayout.has_key(component): 
			return self.PanelLayout[component]
		return defaultSize
#	def EvtEnter(self,event):
#		event.StopPropagation()
#		self.UpdateAmount()
#	def UpdateAmount(self):
#		val=self.txtNewAmount.GetValue()
#		if (self.IsNumber(val)):
#			self.txtAmount.SetValue(str(float(val)))
#		self.txtNewAmount.SetValue("")
	def SetAmount(self, val):
		val=str(val)
		self.Amount=val
		if len(val)==0:
			self.txtAmount.SetValue(None)
		else:
			if self.txtAmount.IsInBounds(val):
				self.txtAmount.SetValue(val)
	def SetDigit(self, exponent):
		self.Exponent=exponent
		self.Digit=math.pow(10, exponent)
		if (exponent>=0):
			self.lblDigit.SetLabel("+"+str(exponent+1))
		else:
			self.lblDigit.SetLabel(str(exponent))
	def SetValue(self, value):
		if value<0 and value>-0.000001: value=0.0
		self.txtValue.SetValue(value)
	def IsNumber(self, s):
		try:
			float(s)
			return True
		except ValueError:
			return False
	def EvtRbType(self, event):
		self.CheckList('T')
		self.lbParams.SetFocus()
	def EvtRbTransType(self, event):
		self.lbParams.SetFocus()
	def EvtListBoxClick(self, event):
		self.SelectedParametersChanged()
	def EvtChkboxActorType(self, event):
		self.CheckList('A')
	def CheckList(self, type):
		if self.rbType.GetSelection()==0 and (type=='C' or type=='T'):
			l=self.GetActorParamList()
			self.UpdateParams(l[0])
			self.Param=l[1]
			self.sizer2.Hide(self.szActorType)
			self.lbActors.Show(0)
			self.rbTransType.Show(0)
			self.cbParented.Enable(0)
		elif (self.rbType.GetSelection()==1):
			self.UpdateActors(self.GetFigureActors())
			self.UpdateParams(self.RotTransString[:3])
			self.Param=self.RotTrans[:3]
			self.sizer2.Show(self.szActorType)
			self.lbActors.Show(1)
			self.rbTransType.Show(0)
			self.cbParented.Enable(0)
		elif (self.rbType.GetSelection()==2):
			self.UpdateActors(self.GetUniverseActors())
			self.UpdateParams(self.RotTransString)
			self.Param=self.RotTrans
			self.sizer2.Show(self.szActorType)
			self.lbActors.Show(1)
			self.rbTransType.Show(1)
			self.cbParented.Enable(1)
		else:
			return
		self.sizer.Layout()
		self.Layout()
	def GetActorParamList(self):
		list=[]
		Param=[]
		Parameters=[]
		try:
			Parameters = poser.Scene().CurrentActor().Parameters()
		except:
			pass
		for parm in Parameters:
			if not parm.Hidden():
			   list = list + [parm.Name()]
			   Param = Param + [parm.InternalName()]
		return [list, Param]
	def UpdateParams(self, lNewNames):
		lCurrentNames=self.lbParams.GetItems()
		bSame=True #old==new actors?
		for param in lCurrentNames:
			if not param in lNewNames:
				bSame=False
				break
		for param in lNewNames:
			if not param in lCurrentNames:
				bSame=False
				break
		if bSame:
			return
		lSelectedIx=self.lbParams.GetSelections()
		self.lbParams.Set(lNewNames)
		for i in range(len(lSelectedIx)): #select the previous selected actors
			try:
				ix=lNewNames.index(lCurrentNames[lSelectedIx[i]])
			except ValueError:
				continue
			self.lbParams.Select(ix)
	def UpdateActors(self, lNewActors, lNewActorsToSelect=()):
		bSame=True #old==new actors?
		for actor in self.Actors:
			if not actor in lNewActors[0]:
				bSame=False
				break
		for actor in lNewActors[0]:
			if not actor in self.Actors:
				bSame=False
				break
		if bSame:
			return
		lSelectedIx=self.lbActors.GetSelections()
		self.lbActors.Clear() #clear list
		self.lbActors.AppendItems(lNewActors[1]) #add all new actors
		for i in range(len(lSelectedIx)): #select the previous selected actors
			try:
				ix=lNewActors[0].index(self.Actors[lSelectedIx[i]])
			except ValueError:
				continue
			self.lbActors.Select(ix)
		for sa in lNewActorsToSelect:
			self.lbActors.Select(lNewActors[0].index(sa))
		self.Actors=lNewActors[0]
		
	def SelectedParametersChanged(self):
		if (self.rbType.GetSelection()==0):
			list=self.lbParams.GetSelections()
#			for ix in self.lbParams.GetSelections():
#				list = list + [self.lbParams.GetString(ix)]
			if len(list)==1:
				self.selectedParamName=self.lbParams.GetString(list[0])
				#check by internal name, because V4's chest rotation parameter 'twist' cannot be called by its name
				try:
					param=self.GetParamByInternalName(poser.Scene().CurrentActor(), self.Params[list[0]])
					if (param.TypeCode() in self.RotTrans[3:]): #is translation type... adjust amount
						self.value=param.Value()/self.UnitMultiplier[self.rbUnit.GetSelection()]
					else:
						self.value=param.Value()
				except:
					self.value=0
			else:
				self.selectedParamName=""
				self.value=0
		elif (self.rbType.GetSelection()==1):
			self.value=0
		elif (self.rbType.GetSelection()==2):
			self.value=0
		self.SetValue(self.value)
	def GetParamByInternalName(self, actor, name):
		for param in actor.Parameters():
			if param.InternalName()==name:
				return param
		return None
	def GetFigureActors(self):
		list=([],[])
#		try:
		fig=poser.Scene().CurrentFigure()
		if fig==None:
			return list
		name=fig.Name()
		for actor in fig.Actors():
			if self.IsInternalItem(actor.InternalName()):
				continue
			#print actor.InternalName()
			if (
				self.ActorIsBody(actor) 
				or (actor.InternalName()==actor.ItsFigure().InternalName())
				or (actor.IsCamera() and self.cbCamLights.GetValue()) 
				or (actor.IsLight() and self.cbCamLights.GetValue()) 
				or actor.IsBodyPart() 
				or ((actor.IsProp() or actor.IsHairProp()) and self.cbProps.GetValue()) 
				or ((actor.IsBase() or actor.IsDeformer() or actor.IsZone()) and self.cbMagnets.GetValue())
			) and (self.cbHidden.GetValue() or actor.OnOff()==1):
				list[0].append(actor.InternalName())
				list[1].append(actor.Name())
#		except:
#			pass
		return list
	def GetUniverseActors(self):
		l=self.GetAllChildActors(poser.Scene().Actor("UNIVERSE"))
		#print l
		return l
	def GetAllChildActors(self, parent, prefix=""):
		list=([],[])
		for actor in parent.Children():
			name=actor.Name()
			newprefix=prefix
			#print actor.Name(), actor.IsBodyPart(), actor.OnOff()
			if self.IsInternalItem(actor.InternalName()):
				continue
			if (
				(actor.IsCamera() and self.cbCamLights.GetValue()) 
				or (actor.IsLight() and self.cbCamLights.GetValue())
				or (actor.IsProp() and self.cbProps.GetValue())
				or ((actor.IsBase() or actor.IsDeformer() or actor.IsZone()) and self.cbMagnets.GetValue())
			) and (self.cbHidden.GetValue() or actor.OnOff()==1):
				list[0].append(actor.InternalName())
				list[1].append(prefix + name)
			elif actor.IsBodyPart():
				if actor.ItsFigure().ConformTarget()!=None and self.cbParented.GetValue()==False:
					continue
				parentBelongsToSameFigure=parent.IsBodyPart() and (parent.ItsFigure()!=None and parent.ItsFigure().InternalName()==actor.ItsFigure().InternalName())
				if not parentBelongsToSameFigure and self.IsFigurePartVisible(actor.ItsFigure())==1:
					name=actor.ItsFigure().Name()# + ">" +actor.Name()
					list[0].append(actor.InternalName())
					list[1].append(prefix + name)
					newprefix=prefix+name+" > "
			if self.cbParented.GetValue():
				l=self.GetAllChildActors(actor, newprefix)
				list[0].extend(l[0])
				list[1].extend(l[1])
		return list
	def IsFigurePartVisible(self, figure):
		for actor in figure.Actors():
			if (self.cbHidden.GetValue() or actor.OnOff()==1):
				return 1
		return 0
	def EvtWheel(self, event):
#		delta = event.GetWheelDelta()
		rotation = event.GetWheelRotation()
		
#		print 'delta: ' + repr(delta) + ' rotation:' + repr(rotation)
		if (event.ShiftDown() and not event.CmdDown()):
			if rotation>0:
				self.lbParams.ScrollLines(-1*event.GetLinesPerAction())
			else:
				self.lbParams.ScrollLines(event.GetLinesPerAction())
		elif (event.CmdDown() and not event.ShiftDown()):
			val=self.txtAmount.GetValue()
			if rotation>0:
				self.SetAmount(val+self.Digit)
			else:
				val=val-self.Digit
				if (val>=0):
					self.SetAmount(val)
		elif (event.CmdDown() and event.ShiftDown()):
			if not self.IsNumber(self.Amount):
				return
			if rotation>0:
				self.SetAmount(float(self.Amount)*10)
			else:
				self.SetAmount(float(self.Amount)/10)
		else:
			if not self.IsNumber(self.Amount):
				return
			amount=float(self.Amount)
			if rotation<0:
				amount=-1.0*amount
			if (self.rbType.GetSelection()==0):
				self.ChangeActorParams(2, amount)
			elif (self.rbType.GetSelection()==1):
				self.ChangeFigureRotations(2, amount)
			elif (self.rbType.GetSelection()==2):
				self.ChangeUniverseRotTrans(2, amount)
	def ChangeActorParams(self, type, amount):
		unitAmount=amount*self.UnitMultiplier[self.rbUnit.GetSelection()]
		l = self.lbParams.GetSelections()
		if len(l)==0:
			return
		Undo={}
		actor = poser.Scene().CurrentActor()
		frame = poser.Scene().Frame()
		UndoFrame={}
		Undo[frame]=UndoFrame
		UndoFrameActor={}
		UndoFrame[actor.InternalName()]=UndoFrameActor
		param = None
		value = 0
		amt=0.0
		for ix in self.lbParams.GetSelections():
			param=self.GetParamByInternalName(actor, self.Params[ix])
			UndoFrameActor[param.InternalName()]=param.Value()
			if (param.TypeCode() in self.RotTrans[3:]): #is translation type... adjust amount
				amt=unitAmount
			else:
				amt=amount
			if type==0:
				value=amt
			elif type==1:
				value=-1*param.Value()
			elif type==2:
				value=param.Value()+amt
			param.SetValue(value)

		if len(l)==1:
			if amt==unitAmount:
				self.value=param.Value()/self.UnitMultiplier[self.rbUnit.GetSelection()]
			else:
				self.value=param.Value()
		else:
			if type==0:
				self.value=value
			elif type==1:
				self.value=0
			elif type==2:
				self.value=self.value+amount
		self.SetValue(self.value)
		poser.Scene().Draw()
		self.SetUndo(Undo)
	def SetActorProperties(self, type):
		self.ReallyDoStatic=-1
		if len(self.changedMats)>0:
			self.changedMats=[]
		actor = poser.Scene().CurrentActor()
		self.SetProperty(type, actor)
		poser.Scene().Draw()
		poser.Scene().CurrentMaterial().ShaderTree().UpdatePreview()

	def ChangeFigureRotations(self, type, amount):
		selectedParams=self.lbParams.GetSelections()
		if (len(selectedParams)==0):
			return
		fig=poser.Scene().CurrentFigure()
		if fig==None:
			return
		frame = poser.Scene().Frame()
		Undo={}
		UndoFrame={}
		Undo[frame]=UndoFrame
		params=[]
		for ix in selectedParams:
			params = params + [self.RotTrans[ix]]
		value=0
		amount
		for actor in fig.Actors():
			if actor.IsCamera() or actor.IsLight() or actor.IsBodyPart() or actor.IsProp() or actor.IsHairProp():
				for ix in self.lbActors.GetSelections():
					if actor.InternalName()==self.Actors[ix]:
						UndoFrameActor={}
						UndoFrame[actor.InternalName()]=UndoFrameActor
						for param in params:
							parm=actor.ParameterByCode(param)
							UndoFrameActor[parm.InternalName()]=parm.Value()
							if type==0:
								value=amount
							elif type==1:
								value=-1*parm.Value()
							elif type==2:
								value=parm.Value()+amount
							parm.SetValue(value)
		poser.Scene().Draw()
		self.SetUndo(Undo)
		if type==0:
			self.value=value
		elif type==1:
			self.value=0
		elif type==2:
			self.value=self.value+amount
		self.SetValue(self.value)
	def SetFigureProperties(self, type):
		self.ReallyDoStatic=-1
		if len(self.changedMats)>0:
			self.changedMats=[]
		fig=poser.Scene().CurrentFigure()
		if fig==None:
			return
		for actor in fig.Actors():
			if actor.IsCamera() or actor.IsLight() or actor.IsBodyPart() or actor.IsProp() or actor.IsHairProp():
				for ix in self.lbActors.GetSelections():
					if actor.InternalName()==self.Actors[ix]:
						self.SetProperty(type, actor)
		poser.Scene().Draw()
		poser.Scene().CurrentMaterial().ShaderTree().UpdatePreview()
	def ChangeUniverseRotTrans(self, type, amount):
		unitAmount=amount*self.UnitMultiplier[self.rbUnit.GetSelection()]
		selectedParams=self.lbParams.GetSelections()
		if (len(selectedParams)==0):
			return
		frame = poser.Scene().Frame()
		Undo={}
		UndoFrame={}
		Undo[frame]=UndoFrame
		params=[]
		transtype=self.rbTransType.GetSelection()
		for ix in selectedParams:
			followTransType = 0
			if transtype==1 or transtype==2:
				followTransType = 1
			params = params + [[self.RotTrans[ix],followTransType]]
		selectedActors=self.lbActors.GetSelections()
		cntAct=len(selectedActors)
		amt=0.0
		for actor in poser.Scene().Actor("UNIVERSE").Children():
			ixAct=0
			for ix in selectedActors:
				if actor.InternalName()==self.Actors[ix]:
					UndoFrameActor={}
					UndoFrame[actor.InternalName()]=UndoFrameActor
					for param in params:
						parm=actor.ParameterByCode(param[0])
						if parm==None:
							continue
						UndoFrameActor[parm.InternalName()]=parm.Value()
						val=parm.Value()
						if (parm.TypeCode() in self.RotTrans[3:]): #is translation type... adjust amount
							amt=unitAmount
						else:
							amt=amount
						if type==0:
							val=amt
						elif type==1:
							val=-1*val
						elif type==2:
							if param[1]==1:
								if transtype==1:
									val=val+ixAct*amt
								if transtype==2:
									val=val+random.random()*amt
							else:
								val=val+amt
						parm.SetValue(val)
				ixAct=ixAct+1
		poser.Scene().Draw()
		self.SetUndo(Undo)
		if type==0:
			self.value=val
		elif type==1:
			self.value=0
		elif type==2:
			self.value=self.value+amount
		self.SetValue(self.value)
	def SetUniverseProperties(self, type):
		self.ReallyDoStatic=-1
		if len(self.changedMats)>0:
			self.changedMats=[]
		selectedActors=self.lbActors.GetSelections()
		if len(selectedActors)==0:
			return
		self.SetUniversePropertiesRec(type, poser.Scene().Actor("UNIVERSE"), selectedActors)
		poser.Scene().Draw()
		poser.Scene().CurrentMaterial().ShaderTree().UpdatePreview()
	def SetUniversePropertiesRec(self, type, parent, selectedActors):
		for actor in parent.Children():
			for ix in selectedActors:
				if actor.InternalName()==self.Actors[ix]:
					self.SetProperty(type, actor)
			self.SetUniversePropertiesRec(type, actor, selectedActors)
	def SetProperty(self, type, actor):
		if type==101:
			for selectedProperty in self.lbCheckboxProperties.GetSelections():
				if self.CheckboxPropertyMethods[selectedProperty]==self.SetStatic:
					if self.ReallyDoStatic==0: return
					if self.ReallyDoStatic<0:
						dlg=wx.MessageDialog(self, "Do you really want to set static? That means that the Parameters of an actor cannot change throughout an animation. The values will be the same in every frame. If you change one frame, all frames are changed!", "Really set static?", wx.YES_NO|wx.NO_DEFAULT|wx.ICON_QUESTION)
						if (dlg.ShowModal()!=wx.ID_YES):
							self.ReallyDoStatic=0
							return
					self.ReallyDoStatic=1
				self.CheckboxPropertyMethods[selectedProperty](actor, 1)
		elif type==102:
			for selectedProperty in self.lbCheckboxProperties.GetSelections():
				self.CheckboxPropertyMethods[selectedProperty](actor, 0)
		elif type==111:
			if (actor.IsLight()):
				actor.SetLightOn(1)
		elif type==112:
			if (actor.IsLight()):
				actor.SetLightOn(0)
		elif type==121:
			if (actor.IsLight()):
				actor.SetRayTraceShadows(1)
		elif type==122:
			if (actor.IsLight()):
				actor.SetRayTraceShadows(0)
		elif type==123:
			if (actor.IsLight()):
				actor.SetLightAttenType(0)
		elif type==124:
			if (actor.IsLight()):
				actor.SetLightAttenType(poser.kLightCodeINVLINEARATTEN)
		elif type==125:
			if (actor.IsLight()):
				actor.SetLightAttenType(poser.kLightCodeINVSQUAREATTEN)
		elif type==131: #Quality
			self.SetMaterialProperties(actor, self.SetMaterialFilter, 3)
		elif type==132: #Fast
			self.SetMaterialProperties(actor, self.SetMaterialFilter, 2)
		elif type==133: #None
			self.SetMaterialProperties(actor, self.SetMaterialFilter, 1)
		elif type==141: #N-Forward on
			self.SetMaterialProperties(actor, self.SetNormalsForward, 1)
		elif type==142: #N-Forward off
			self.SetMaterialProperties(actor, self.SetNormalsForward, 0)
		elif type==151: #Refl-x-Mult on
			self.SetMaterialProperties(actor, self.SetReflXMult, 1)
		elif type==152: #Refl-x-Mult off
			self.SetMaterialProperties(actor, self.SetReflXMult, 0)
		elif type==161: #Diffuse-Multi
			self.SetMaterialProperties(actor, self.MultiDiffuse, self.diffuseMulti)
		elif type==162: #Diffuse-Divide
			self.SetMaterialProperties(actor, self.MultiDiffuse, 1/self.diffuseMulti)
		elif type==990: 
			self.SetMaterialProperties(actor, self.SetGammaValue, None)
	
	def SetVisible(self, actor, on): 
		try:
			actor.SetVisible(on)
			if (self.ActorIsBody(actor)):
				actor.ItsFigure().SetVisible(on)
		except:
			pass
	def SetVisibleInReflections(self, actor, on):
		try:
			actor.SetVisibleInReflections(on)
		except:
			pass
	def SetVisibleInRender(self, actor, on):  
		try:
			actor.SetVisibleInRender(on)
		except:
			pass
	def SetCastsShadows(self, actor, on): 
		try:
			actor.SetCastsShadows(on)
		except:
			pass
	def SetBends(self, actor, on): 
		try:
			actor.SetBends(on)
		except:
			pass
	def SetSmoothPolys(self, actor, on): 
		try:
			actor.SetSmoothPolys(on)
		except:
			pass
	def SetIncludeInBoundingBox(self, actor, on): 
		try:
			actor.SetIncludeInBoundingBox(on)
		except:
			pass
	def SetStatic(self, actor, on):
		try:
			actor.SetStatic(on)
		except:
			pass
	
	def SetMaterialProperties(self, actor, nodeMethod, value):
		if (actor.Materials()):
			for material in actor.Materials():
				id=self.GetMaterialId(actor, material)
				if id in self.changedMats:
					continue
				else:
					tree = material.ShaderTree()
					for node in tree.Nodes():
						nodeMethod(node, value)
					self.changedMats.append(id)
	def GetMaterialId(self, actor, material):
		fig=actor.ItsFigure()
		if fig==None:
			return actor.InternalName()+":"+material.Name()
		else:
			return fig.InternalName()+":"+material.Name()
	def SetGammaValue(self, node, value):
		self.dlgGamma.SetGamma(node)
	def SetMaterialFilter(self, node, value):
		if node.Type() == poser.kNodeTypeCodeIMAGEMAP:
			inp = node.Input(13)
			if inp!=None:
				inp.SetFloat(value)
	def SetReflXMult(self, node, value):
		if node.Type() ==  poser.kNodeTypeCodePOSERSURFACE:
			inp = node.Input(20)
			if inp!=None:
				inp.SetFloat(value)
			inp = node.Input(21)
			if inp!=None:
				inp.SetFloat(value)
	def MultiDiffuse(self, node, value):
		if node.Type() ==  poser.kNodeTypeCodePOSERSURFACE:
			inp = node.Input(1)
			if inp!=None:
				inp.SetFloat(inp.Value()*value)
		elif node.Type() == poser.kNodeTypeCodeDIFFUSE:
			inp = node.Input(1)
			if inp!=None:
				inp.SetFloat(inp.Value()*value)
	
	def SetNormalsForward(self, node, value):
		if node.Type() ==  poser.kNodeTypeCodePOSERSURFACE:
			inp = node.Input(25)
			if inp!=None:
				inp.SetFloat(value)
		elif node.Type() in [poser.kNodeTypeCodeVELVET, poser.kNodeTypeCodeTOON, poser.kNodeTypeCodeSPECULAR, poser.kNodeTypeCodePHONG, poser.kNodeTypeCodeGLOSSY, poser.kNodeTypeCodeDIFFUSE, poser.kNodeTypeCodeBLINN, poser.kNodeTypeCodeANISOTROPIC]:
			inp=node.InputByInternalName("Normals_Forward")
			if inp!=None:
				inp.SetFloat(value)
		
	def EvtUnit(self, event):
		try:
			self.settings["DefaultUnit"]=self.rbUnit.GetSelection()
			fd=open(self.settingsFile, "w")
			pickle.dump(self.settings,fd)
			fd.close()
		except:
			pass
	def EvtButton(self, event):
		if (event.Id==62):
			val=self.txtAmount.GetValue()
			if (self.rbType.GetSelection()==0):
				self.ChangeActorParams(0,val)
			elif (self.rbType.GetSelection()==1):
				self.ChangeFigureRotations(0,val)
			elif (self.rbType.GetSelection()==2):
				self.ChangeUniverseRotTrans(0,val)
		elif (event.Id==61):
			if (self.rbType.GetSelection()==0):
				self.ChangeActorParams(1,0)
			elif (self.rbType.GetSelection()==1):
				self.ChangeFigureRotations(1,0)
			elif (self.rbType.GetSelection()==2):
				self.ChangeUniverseRotTrans(1,0)
		elif (event.Id==71):
			if wx.GetKeyState(wx.WXK_ALT):
				self.Undos=[]
				self.SetUndoRedoButtons()
			else:
				self.Undo()
		elif (event.Id==72):
			self.Redo()
		elif (event.Id>100):
			if (event.Id==990):
				if (self.dlgGamma==None):
					self.dlgGamma=self.SetGamma(self)
				res=self.dlgGamma.ShowModal()
				if res==wx.ID_CANCEL:
					return
			if (self.rbType.GetSelection()==0):
				self.SetActorProperties(event.Id)
			elif (self.rbType.GetSelection()==1):
				self.SetFigureProperties(event.Id)
			elif (self.rbType.GetSelection()==2):
				self.SetUniverseProperties(event.Id)
		else:
			return
	def SetUndo(self, Undo):
		self.Redos=[]
		self.Undos.append(Undo)
		self.SetUndoRedoButtons()
	def Undo(self):
		self.UndoOrRedo(self.Undos, self.Redos)
	def Redo(self):
		self.UndoOrRedo(self.Redos, self.Undos)
	def UndoOrRedo(self, Prevs, Nexts):
		Prev=Prevs[-1]
		Next={}
		currentFrame=poser.Scene().Frame()
		frames=poser.Scene().NumFrames()
		for PrevFrame in Prev.items():
			if PrevFrame[0]<=frames:
				poser.Scene().SetFrame(PrevFrame[0])
				NextFrame={}
				Next[PrevFrame[0]]=NextFrame
				PrevFrameActor=PrevFrame[1]
				for actor in poser.Scene().Actors():
					if actor.InternalName() in PrevFrameActor:
						NextFrameActor={}
						NextFrame[actor.InternalName()]=NextFrameActor
						for kv in PrevFrameActor[actor.InternalName()].items():
							param=self.GetParamByInternalName(actor, kv[0])
							if param==None:
								continue
							NextFrameActor[kv[0]]=param.Value()
							param.SetValue(kv[1])
		Nexts.append(Next)
		del Prevs[-1]
		self.SetUndoRedoButtons()
		self.SetValue(0.0)
		poser.Scene().SetFrame(currentFrame)
		poser.Scene().Draw()
	def SetUndoRedoButtons(self):
		self.btnUndo.Enable(len(self.Undos)>0)
		self.btnUndo.SetLabel("Undo "+str(len(self.Undos)))
		self.btnRedo.Enable(len(self.Redos)>0)
		self.btnRedo.SetLabel("Redo "+str(len(self.Redos)))
#	def EvcbParam(self, iScene, iEventType):
#		if (iEventType & poser.kEventCodeACTORSELECTIONCHANGED):
#			self.CheckList('C')
#		if (iEventType & poser.kEventCodeACTORDELETED):
#			self.CheckList('D')
#		if (iEventType & poser.kEventCodeITEMRENAMED):
#			self.CheckList('R')
	def EvtTimer(self, id):
		try:
			lastAct=poser.Scene().CurrentActor().InternalName()
			if (self.LastActor != lastAct):
				self.LastActor = lastAct
				self.CheckList('C')
		except:
			self.LastActor=None
	def IsInternalItem(self, internalName):
		return internalName.replace(" ",":").split(":")[0] in self.InternalItems # replace(" ", ":") to catch CenterOfMass 2:x objects...
	def ActorIsBody(self, actor):
		return actor.InternalName().split(":")[0]=="BODY"
	def Duplicate(self, bSelectDuplicates):
		res=self.dlgDuplicate.ShowModal()
		if res==wx.ID_CANCEL:
			return
		duplicateCnt=self.dlgDuplicate.GetValue()
		selectedActors=self.lbActors.GetSelections()
		newActors=[]
		for actor in poser.Scene().Actor("UNIVERSE").Children():
			for ix in selectedActors:
				if actor.InternalName()==self.Actors[ix]:
					for i in range(duplicateCnt):
						poser.Scene().SelectActor(actor)
						poser.ProcessCommand(1568)
						a=poser.Scene().CurrentActor()
						if (a.IsBodyPart()):
							a=a.ItsFigure()
						newActors.append(a.InternalName())
		if not bSelectDuplicates:
			newActors=[]
		self.UpdateActors(self.GetUniverseActors(), newActors)
	
	
	def ShowActorContextMenu(self, event):
		if (self.rbType.GetSelection()!=2):	return
		pane = self.man.GetPane(self)
		menu = wx.Menu()
		menu.Append(11, "Duplicate Selected")
		menu.Append(12, "Duplicate && Select Selected")
		self.PopupMenu(menu)
		menu.Destroy()
		
	def ShowContextMenu(self, event):
		pane = self.man.GetPane(self)
		menu = wx.Menu()
				
		dock = menu.Append(1, "Docked", kind=wx.ITEM_CHECK)
		float = menu.Append(2, "Floating", kind=wx.ITEM_CHECK)
		if pane.IsDocked():
			dock.Check()
		else: 
			float.Check()
		menu.AppendSeparator()
		drag = menu.Append(3, "Drag-Docking Enabled", kind=wx.ITEM_CHECK)
		if pane.IsLeftDockable():
			drag.Check()
		self.PopupMenu(menu)
		menu.Destroy()

	def ExecuteMenuCommand(self, e):
		pane = self.man.GetPane(self)
		id = e.GetId()
		if id == 1:
			if pane.IsDocked():
				return
			pane.Dock()
			self.man.Update()
		elif id == 2:
			if pane.IsFloating():
				return
			pane.Float()
			self.man.Update()
		elif id == 3:
			pane.Dockable(e.IsChecked())
		elif id == 11:
			self.Duplicate(False)
		elif id == 12:
			self.Duplicate(True)
	
	class SetGamma(wx.Dialog):
		SavePath=os.path.join(poser.PrefsLocation(), "acb", "gamma")
		DicSelection={}
		
		def __init__(self,parent):
			wx.Dialog.__init__(self, parent, -1, "Set Gamma", wx.Point(-1, -1), wx.DefaultSize)
			
			self.sizer = wx.BoxSizer(wx.VERTICAL)
			self.SetSizer(self.sizer)
			
			staticBox = wx.StaticBox(self, -1, "Inputs")
			self.szInput = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
			self.sizer.Add(self.szInput)
			self.cbDisplacement = wx.CheckBox(self, -1, "Displacement")
			self.szInput.Add(self.cbDisplacement)
			self.cbBump = wx.CheckBox(self, -1, "Bump")
			self.szInput.Add(self.cbBump)
			self.cbGradient = wx.CheckBox(self, -1, "Gradient_Bump")
			self.szInput.Add(self.cbGradient)
			self.cbTransparency = wx.CheckBox(self, -1, "Transparency")
			self.szInput.Add(self.cbTransparency)
			self.cbOther = wx.CheckBox(self, -1, "Other")
			self.szInput.Add(self.cbOther)
			
			fgsGridInputs=wx.FlexGridSizer(2,2,2,1)
			self.sizer.Add(fgsGridInputs)
			lblGamma = wx.StaticText(self, -1, "Value: ", wx.Point(-1, -1), wx.DefaultSize, wx.ALIGN_RIGHT)
			self.txtGamma = wx.lib.masked.NumCtrl(self, 20)
			self.txtGamma.SetFractionWidth(2)
			self.txtGamma.SetIntegerWidth(1)
			self.txtGamma.SetValue(2.2)
			self.txtGamma.SetMax(5.0)
			self.txtGamma.SetMin(0.2)
			self.txtGamma.SetAllowNone(False)
			self.txtGamma.SetAllowNegative(False)
			self.txtGamma.SetGroupDigits(False)
			
			fgsGridInputs.Add(lblGamma, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
			fgsGridInputs.Add(self.txtGamma)
			
			self.btnReset = wx.Button(self, 1, "Reset", wx.Point(-1,-1), (50,-1))
			self.btnReset.SetToolTip(wx.ToolTip("use global gamma setting"))
			fgsGridInputs.Add(self.btnReset)
			self.btnSet = wx.Button(self, 2, "Set", wx.Point(-1,-1), (50,-1))
			self.btnSet.SetToolTip(wx.ToolTip("use entered gamma value"))
			fgsGridInputs.Add(self.btnSet)
			
			self.sizer.Add(self.CreateStdDialogButtonSizer(wx.CANCEL))
			
			self.Layout()
			
			self.Bind(wx.EVT_BUTTON, self.EvtButton)
			
			if not os.path.exists(self.SavePath):
				os.makedirs(self.SavePath)

			self.MemoryFile=os.path.join(self.SavePath, "memory.config")
			if os.path.exists(self.MemoryFile):
				fd=open(self.MemoryFile)
				dic=pickle.load(fd)
				self.DicSelection=dic
				if (dic.has_key("inputs_d")):
					self.cbDisplacement.SetValue(dic["inputs_d"])
				if (dic.has_key("inputs_b")):
					self.cbBump.SetValue(dic["inputs_b"])
				if (dic.has_key("inputs_g")):
					self.cbGradient.SetValue(dic["inputs_g"])
				if (dic.has_key("inputs_t")):
					self.cbTransparency.SetValue(dic["inputs_t"])
				if (dic.has_key("inputs_o")):
					self.cbOther.SetValue(dic["inputs_o"])
				if (dic.has_key("gamma")):
					self.txtGamma.SetValue(dic["gamma"])
				fd.close()
			
		def __del__(self):
			try:
				fd=open(self.MemoryFile, "w")
				pickle.dump(self.DicSelection,fd)
				fd.close()
			except:
				pass

		def EvtButton(self, event):
			dic=self.DicSelection
			dic["inputs_d"]=self.cbDisplacement.GetValue()
			dic["inputs_b"]=self.cbBump.GetValue()
			dic["inputs_g"]=self.cbGradient.GetValue()
			dic["inputs_t"]=self.cbTransparency.GetValue()
			dic["inputs_o"]=self.cbOther.GetValue()
			dic["gamma"]=self.txtGamma.GetValue()
			
			self.EndModal(event.Id)
			return
			
		def SetGamma(self, node):
			code=self.GetReturnCode()
			if code==1:
				self.SetGammaStart(node, 0, True)
			elif code==2:
				self.SetGammaStart(node, self.txtGamma.GetValue(), False)
					
		def SetGammaStart(self, node, value, useGlobalGamma):
			for input in node.Inputs():
				name = input.InternalName()
				if input.InNode():
					if name == "Transparency_Max":
						if self.cbTransparency.GetValue():
							self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)
					elif name == "Displacement":
						if self.cbDisplacement.GetValue():
							self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)
					elif name == "Bump":
						if self.cbBump.GetValue():
							self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)
					elif name == "Gradient_Bump":
						if self.cbGradient.GetValue():
							self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)
					else:
						if self.cbOther.GetValue():
							self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)
		def SetGammaPerNode(self, node, value, useGlobalGamma):
			if node!=None:
				for input in node.Inputs():
					if input.InternalName() == "Image_Source":
						texture = input.Texture()
						if texture!=None:
							if useGlobalGamma==True:
								texture.SetUseSceneGamma(1)
							else:
								texture.SetGamma(value)
					self.SetGammaPerNode(input.InNode(), value, useGlobalGamma)

		

name = "Wheel Posing & Tools"
man = poser.WxAuiManager()
root = man.GetManagedWindow()

pane = wx.aui.AuiPaneInfo()
pane.Caption(name).CaptionVisible().CloseButton().Resizable().DestroyOnClose()
pane.BestSize(wx.Size(50, 50)).Right().PinButton().Dock()
win = WheelPosing(root, name, pane)
man.AddPane(win, pane)
pane.Show()
man.Update()


