# MorphScale v1.0
# Set/reset the "include morphs when conforming" and "include scales when conforming" checkboxes for all selected items
# tell me if you found the properties to set, so I don't need to load a pose file ;-)
# - poor python coding by Dizzi
import poser
import wx
import wx.aui
import os.path
import wx.lib.masked.numctrl
import math
import pickle

class SetGamma(wx.Panel):
	SavePath=os.path.join(poser.PrefsLocation(), "acb", "morphscale")
	PanelLayout={}
	DicSelection={}
	
	Actors=[]
	def __init__(self,parent,title, pane):
		wx.Panel.__init__(self, parent, -1, wx.Point(-1, -1), wx.DefaultSize)
		
		self.man=poser.WxAuiManager()
		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.sizer = wx.BoxSizer(wx.VERTICAL)
		self.SetSizer(self.sizer)
		
		self.lbActors = wx.ListBox(self, 50, (-1, -1), (100, 75), [], wx.LB_EXTENDED|wx.LB_NEEDED_SB)
		self.lbActors.Multiselect=1
		self.sizer.Add(self.lbActors)
		
		self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizer.Add(self.sizer2)
		self.sizer3 = wx.BoxSizer(wx.VERTICAL)
		self.sizer2.Add(self.sizer3)
		
		self.cbMorph = wx.CheckBox(self, -1, "Morph")
		self.sizer3.Add(self.cbMorph)
		self.cbScale = wx.CheckBox(self, -1, "Scale")
		self.sizer3.Add(self.cbScale)
		
		self.btnApply = wx.Button(self, 12, "Apply", wx.Point(-1,-1), (50,-1))
		self.sizer2.Add(self.btnApply)
		
		self.Update()
		
		self.Layout()
		
		self.timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.EvtTimer, self.timer)
		self.timer.Start(1000)  # 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.Bind(wx.EVT_MENU, self.ExecuteMenuCommand)

		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("Morph")):
				self.cbMorph.SetValue(dic["Morph"])
			if (dic.has_key("Scale")):
				self.cbScale.SetValue(dic["Scale"])
			fd.close()
		
	def __del__(self):
		try:
			fd=open(self.MemoryFile, "w")
			pickle.dump(self.DicSelection,fd)
			fd.close()
		except:
			pass
		try:
			fd=open(self.PanelLayoutFile, "w")
			pickle.dump(self.PanelLayout,fd)
			fd.close()
		except:
			pass
	def EvtTimer(self, event):
		self.Update()
	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 EvtButton(self, event):
		dic=self.DicSelection
		dic["Morph"]=self.cbMorph.GetValue()
		dic["Scale"]=self.cbScale.GetValue()
		
		if (event.Id==12):
			self.Apply()
	
	def Apply(self):
		file=os.path.join(self.SavePath, "morphscale.pz2")
		fd=open(file, "w")
		fd.write('{\n')
		fd.write('version\n')
		fd.write('{\n')
		fd.write('number 8.2\n')
		fd.write('}\n')
		fd.write('figure\n')
		fd.write('{\n')
		if self.cbScale.GetValue(): 
			fd.write('conformScale 1\n')
		else:
			fd.write('conformScale 0\n')
		if self.cbMorph.GetValue(): 
			fd.write('conformMorphs 1\n')
		else:
			fd.write('conformMorphs 0\n')
		fd.write('}\n')
		fd.write('}\n')
		fd.close()
		
		currentFigure=poser.Scene().CurrentFigure()
		if currentFigure==None: return
		for ix in self.lbActors.GetSelections():
			#try:
				figures=poser.Scene().Figures()
				for fig in figures:
					if fig.Name()==self.lbActors.GetString(ix):
						poser.Scene().SelectFigure(fig)
						poser.Scene().LoadLibraryPose(file)
			#except:
			#	pass
		poser.Scene().SelectFigure(currentFigure)
	
	def Update(self):
		l=[]
		for figure in poser.Scene().Figures():
			l.append(figure.Name())
		self.UpdateActors(l)
		
	def UpdateActors(self, lNewActors):
		bSame=True #old==new actors?
		for actor in self.Actors:
			if not actor in lNewActors:
				bSame=False
				break
		for actor in lNewActors:
			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) #add all new actors
		for i in range(len(lSelectedIx)): #select the previous selected actors
			try:
				ix=lNewActors.index(self.Actors[lSelectedIx[i]])
			except ValueError:
				continue
			self.lbActors.Select(ix)
		self.Actors=lNewActors

	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 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())
				
name = "Set Morph/Scale"
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 = SetGamma(root, name, pane)
man.AddPane(win, pane)
pane.Show()
man.Update()


