GraphEditorUI.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. """
  2. Defines Graph Editor
  3. """
  4. import wx
  5. import math
  6. from . import ObjectGlobals as OG
  7. from . import AnimGlobals as AG
  8. from wx.lib.embeddedimage import PyEmbeddedImage
  9. property = [
  10. "translateX",
  11. "translateY",
  12. "translateZ"
  13. ]
  14. #----------------------------------------------------------------------
  15. ZoomIn = PyEmbeddedImage(
  16. "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACgklE"
  17. "QVRIid3VW0vjQBQA4DlJMziZlCKCSB/9Bf4a3wRtNU6SHyXK6pay2nVbQbasskXFO15SqmwL"
  18. "LtYnn7Zg20zSyT50wZikXsCHxXk9Z74ZZuacgebtLXrvIb27+PFQjDEADIoqiiLL8htQAMAY"
  19. "Hx4dPTw8SHEuIaRWqzWbzUQi8SoUAIaGhgqFgn15SSn1Iwmqqh4fH5c2NpLJpO8/xhORzEeR"
  20. "EJLL5VqtViaT8TxPCBFMoJTu7e1tb28zxpLJpOu6L6D9PS6vrHQ6nWw267puVNzZ2alUKqZh"
  21. "UE0LivFoX/y0vOxynpmZ4ZxHxZ+Vyu7urmmaqqqGxBhUkiSM8eLiIgDMTE87EVHTtB9bW4cH"
  22. "B5ZpEkKiYhjt3/XCwoKiKFNTU47jRPf4vVw+PTmxLAtjHCs+QQEAAJaWljRNm5yc7Ha7wQtF"
  23. "CGGMy+WybduWZSmK4nlerIiCTwoAOOfX19cTExMSgPDDT0iSJNu2x8fHU6nUM+ITVAhBCLFM"
  24. "83MuV63VKCGhVM65ruv1RqNYLFJKX4UihFzXTafTc7Oz+XzerlZVVQ1GhRCyLJuGcXV1VSqV"
  25. "QtGBKEKo6zhjY2Pzur66tnZxcRGa2ev1AMA0zXqj8W3wfmPK1HGc0dFRNj//dX397Ows6iKE"
  26. "DMZ+39wUCgVKabTXxNe+4zgjIyMGY8VS6eT0NOr6vs8Yu7u7+7K6SggJuQMbCud8eHjYYGxz"
  27. "c3N/f19RlJDb6/V0Xb+/v8/n829ofZzzVCqlz82dn5//abUk6UmyEEIIkc1k2u32r3o9uCq8"
  28. "+PHJsuz7vud5IfTffABZljnnwejLnb9/grEiQih2vVd9J36kup4fH+w3/S/QvwejQg8ibHgo"
  29. "AAAAAElFTkSuQmCC")
  30. #----------------------------------------------------------------------
  31. ZoomOut = PyEmbeddedImage(
  32. "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACmUlE"
  33. "QVRIieXVz0sbQRQH8NmdH8smh3jwEIIlB+tNEW1NVps0WxPBv0BQXKQx4N2/xR2xTYQ9iIHc"
  34. "/A+shyqevHiQVBGLeqgoxM1kNjHTQ8DayWb14KX0Hfe9+fDd4bGr/Ly4AK9d6quL/y6qKIqm"
  35. "aQHThBBVfT7HnwlFUTjn3/f3MUKKoviMqurh4WG9XkcIvRQVQoRCodPT0+1yWdO0bhchxD2v"
  36. "WCxyzjHGL0IBAA8PD9biIgDAcRxN06Q39Tzvk2kahmHbNmMswP3rmBCi0WhYlkUI2dzcxBhL"
  37. "ruu6mUwmnU6v2bbrur1c+dY77sLCQjgcLpVKGKFuN5VKmaZpU1qr1Qghz6OP7vz8fF9f39di"
  38. "Efq5H6amcrkcpfTu7q7b9d8PIQRjbG5urr+//8vGBoSw200mErOzs3R9/fb2VnLh6uqqrwsA"
  39. "aLVao6OjV9fX3/b2RkZGJLfZbMbj8UgkUqlU3g4NhcNhIURQ0k612+12u/1ufPxHtcoY6157"
  40. "z/OGh4fv7++vLi8hhI/Pg9ZY1/Xz83PHcVZWViKRSLPZfNpFCHmeRynNZrNjY2ONRuOx1TOp"
  41. "rutnZ2eO41iWNTg4KIkYY875mm2/n5iYnp5+KvZMqut6tVrd2tpaWlqKx+OMMUmsM0YpnZqc"
  42. "NE3TdV3puA+q6/rJycl2ufw5n38zMCClwBjXXdem9GMmk06lukUfNBQKHR8fVyqVwvJyLBaT"
  43. "REJIrVbr3KNhGL6ijGKMj46OdnZ2CoVCNBqVRAjhr5ubUqmUm5kxksleIpA+fYyxg4ODfD4f"
  44. "jUY559IohHB3dzebzSYTiQARAKA8/fEJIVRVhRC2Wi3faSEEIUTahKCknbAAgF4iAEBV1WdF"
  45. "Ge1kCZgO7vZEX6X+c/Q3Qy8zmmCLWqIAAAAASUVORK5CYII=")
  46. #----------------------------------------------------------------------
  47. OneTangent = PyEmbeddedImage(
  48. "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACKUlE"
  49. "QVRIia2Wz2saURDH5/3Yt6aVsE3SomArGO0phxCSU6A2EFgSklP+qPwrXkOQkBCoaG8eQrBQ"
  50. "KRYVU1tabUij3V1337weAtZI1FX3e9qF2c/OzJv9zpKbRgMGRAhRSsF8oo9uOCeUMk0LDEo1"
  51. "rVUuF46Pv2SzhDEgJBhoLZer5/OViwu32yWUjnlsvHj/SrluPJ222m3GORMC5ugsGTwoyjkT"
  52. "4nuxeFetvj06ko4zG/RRjeh5rmVFNjeZrt8UCnxhIQAoAIBSnm0n9vb+1Gq/y2Wm60FAAUAp"
  53. "UGr18LCRz9vtNuH8iZipoQAopW4Yb3Z2vmazgDjtJIyMlo7zIpUyksnq2RkTIhgoAHiWFdve"
  54. "RsTmx4IuNP/ZToiUvV7CNNt3natb61b57cKEMIXIOeu+N0uof5IaEl8f7+R3K1SG8sKc0FqF"
  55. "oPTjCZOhEiDF0Vyk8da3+occC4UCgAKAAhBe73X6Xa/T+VEs8klcv0eKCtD1kgcHP6+v7xsN"
  56. "OtZzp5hqhUh1PbG/Xz0/l5ZFGAsACgDous+j0cjWVuX0lI428qmdWNr2q/X10NJS/fJyVHNn"
  57. "sXfPtuO7u39brV+lkgiHmRBDKZOhbepThDHpOJ8zmZ7jLMZiq6YJhPSXxYyLSEkZMgx9ebl8"
  58. "clLKZO6bTTbgkFN7ZV+e47xcW4tubIQjkWcrKyjl/zpmK/9BlDH0vIfZUogBZAoAKCWhVCk1"
  59. "tHrnggLAk/9I/wC0eekA1bLbIQAAAABJRU5ErkJggg==")
  60. #----------------------------------------------------------------------
  61. TwoTangents = PyEmbeddedImage(
  62. "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACL0lE"
  63. "QVRIie3UzU8TQRQA8DczO1vatRgh1YhWD/WD+kG91FgOXLhx4+CpiYnE9L8g/gVwJHhp4lUP"
  64. "pPHgQRMOGiEaDabV1LRAtdjUAG23m3W/Znc8YEo/trRNOGjCO+7M++3MezODdopFOO7Axy6e"
  65. "oC0oAqAEY4QGyCcE4faVtaII7dQUy7b7dDEheq3GdB0R4o76KH2+kZ158uzxyzcO56iXS0Rx"
  66. "N5tdnZ9fW1w0FaXZPUQxRl/Le7+q8mruh2paQsem2kLweCq5XGVrq7K5adTruGk+ahx+AeOS"
  67. "rLz4ktctdtYvPYje0i3Gu22cUr1a3VheHg6FhoPBC9EoBwDO21EOQDH2igIALL39NOrz3r8z"
  68. "rppWp3jQmQ8LC5enp4NTU0zTmGG0/PJwKgBzHEU3VcN6eHfie7X++ltBEmknSoaG0snkSDg8"
  69. "Njmp12ptIrieU4dzAEjEIu8KPz8Wy14qNI9SScqvrHCA67Ozlqq6F8f1K3McL6WPYpFUOre9"
  70. "L3uEv50VfL7S+vpuJjMxN8cMo1HEvlAAMG37nF+KR28+fZ/e/62JBAuiWC8U8qlUJJFAhHDH"
  71. "6ZZ71LnRLXY1MDJzI5Rc+6wwR5PlTDIZjsd9gYBjuTSwEajneypR4dV2qXxq1F/dG5fLodg9"
  72. "U9OOThGOHgYAg7FrF8fKKqjng/4rl+xeYl+ozeEMsNsiwmCftnnXQg6EcgABICxyAGAcut2x"
  73. "wdADt+uFdYv/9OU/Qf9d9A9dhOgRU8MmewAAAABJRU5ErkJggg==")
  74. #----------------------------------------------------------------------
  75. class GraphEditorWindow(wx.Window):
  76. """
  77. This is the main graph editor window.
  78. """
  79. def __init__(self, parent, windowSize, property, xRange, yRange, curFrame, object):
  80. wx.Window.__init__(self, parent, size = windowSize, style = wx.SUNKEN_BORDER)
  81. self._mainDialog = wx.GetTopLevelParent(self)
  82. self.w,self.h = self.GetClientSize()
  83. self.zoom = 2.0
  84. self._mouseIn = False
  85. self._selectRec = False
  86. self._selectHandler = False
  87. self._OneTangent = True
  88. self.object = object
  89. self.curFrame = curFrame
  90. self.property = property
  91. self.zeroPos = (0.0, self.h / 2.0)
  92. self.zero = 0
  93. self.unitWidth = self.w / float(xRange)
  94. self.unitHeight = self.h / float(yRange)
  95. self.generateInfo()
  96. self.InitBuffer()
  97. self.Bind(wx.EVT_PAINT, self.OnPaint)
  98. self.Bind(wx.EVT_SIZE, self.OnSize)
  99. self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  100. self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  101. self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
  102. self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp)
  103. self.Bind(wx.EVT_MOTION, self.OnMotion)
  104. def refresh(self):
  105. self._mouseIn = False
  106. self._selectRec = False
  107. self._selectHandler = False
  108. self.generateInfo()
  109. def generateInfo(self):
  110. #generate the information for animation curve generation
  111. self.X = []
  112. self.Y = []
  113. self.Z = []
  114. if self._mainDialog.editor.animMgr.keyFramesInfo != {}:
  115. self.keyFramesInfo = self._mainDialog.editor.animMgr.keyFramesInfo
  116. for key in self.keyFramesInfo:
  117. if key == (self.object[OG.OBJ_UID], 'X'):
  118. for i in range(len(self.keyFramesInfo[key])):
  119. item = self.keyFramesInfo[key][i]
  120. handler = self.generateHandler(item)
  121. self.X.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
  122. if key == (self.object[OG.OBJ_UID], 'Y'):
  123. for i in range(len(self.keyFramesInfo[key])):
  124. item = self.keyFramesInfo[key][i]
  125. handler = self.generateHandler(item)
  126. self.Y.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
  127. if key == (self.object[OG.OBJ_UID], 'Z'):
  128. for i in range(len(self.keyFramesInfo[key])):
  129. item = self.keyFramesInfo[key][i]
  130. handler = self.generateHandler(item)
  131. self.Z.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
  132. def generateHandler(self, item):
  133. #generate the position for the control handler
  134. x1 = self.zeroPos[0] + float(item[AG.FRAME])*self.unitWidth
  135. y1 = self.zeroPos[1] - float(item[AG.VALUE])*self.unitHeight
  136. t1x = item[AG.INSLOPE][0]*self.unitWidth
  137. t1y = item[AG.INSLOPE][1]*self.unitHeight
  138. t2x = item[AG.OUTSLOPE][0]*self.unitWidth
  139. t2y = item[AG.OUTSLOPE][1]*self.unitHeight
  140. tanA = t1y / t1x
  141. temp1 = 1.0 / (tanA ** 2 + 1)
  142. if t1x < 0:
  143. cosA = -math.sqrt(abs(temp1))
  144. if t1x >= 0:
  145. cosA = math.sqrt(abs(temp1))
  146. temp2 = (tanA ** 2) * temp1
  147. if t1y < 0:
  148. sinA = -math.sqrt(abs(temp2))
  149. if t1y >= 0:
  150. sinA = math.sqrt(abs(temp2))
  151. x2 = x1-float(self.unitWidth*self.zoom)*cosA
  152. y2 = y1+float(self.unitWidth*self.zoom)*sinA
  153. tanA = t2y / t2x
  154. temp1 = 1.0 / (tanA ** 2 + 1)
  155. if t2x < 0:
  156. cosA = -math.sqrt(abs(temp1))
  157. if t2x >= 0:
  158. cosA = math.sqrt(abs(temp1))
  159. temp2 = (tanA ** 2) * temp1
  160. if t2y < 0:
  161. sinA = -math.sqrt(abs(temp2))
  162. if t2y >= 0:
  163. sinA = math.sqrt(abs(temp2))
  164. x3 = x1+float(self.unitWidth*self.zoom)*cosA
  165. y3 = y1-float(self.unitWidth*self.zoom)*sinA
  166. return [[(x1,y1),0],[(x2,y2),0],[(x3,y3),0],[t1x,t1y],[t2x,t2y]]
  167. def InitBuffer(self):
  168. self.buffer = wx.EmptyBitmap(self.w, self.h)
  169. dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
  170. self.DrawXCoord(dc)
  171. self.DrawYCoord(dc)
  172. self.DrawFrame(dc)
  173. self.DrawCurve(dc)
  174. self.DrawSelectRec(dc)
  175. def SetGraphEditorData(self, property, curFrame = 1):
  176. self.curFrame = curFrame
  177. self.property = property
  178. self.InitBuffer()
  179. def OnPaint(self, evt):
  180. dc = wx.BufferedPaintDC(self, self.buffer)
  181. def DrawXCoord(self,dc):
  182. dc.SetBackground(wx.Brush(wx.Colour(200, 200, 200)))
  183. dc.Clear()
  184. dc.SetPen(wx.BLACK_PEN)
  185. dc.SetBrush(wx.BLACK_BRUSH)
  186. dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
  187. dc.DrawLine(self.zeroPos[0], 0.0, self.zeroPos[0], self.h)
  188. st = str(self.zero)
  189. self.tw,self.th = dc.GetTextExtent(st)
  190. dc.DrawText(st, self.zeroPos[0]+1.0, self.h-self.th-0.5)
  191. dc.SetPen(wx.Pen(wx.Colour(150, 150, 150)))
  192. dc.SetBrush(wx.Brush(wx.Colour(150, 150, 150)))
  193. if self.unitWidth >= 25:
  194. posPos = self.zeroPos[0]+self.unitWidth
  195. posNum = self.zero + 1
  196. while posPos <= self.w:
  197. dc.DrawLine(posPos, 0.0, posPos, self.h)
  198. st = str(posNum)
  199. self.drawXNumber(dc, st, posPos)
  200. posPos += self.unitWidth
  201. posNum += 1
  202. negPos = self.zeroPos[0]-self.unitWidth
  203. negNum = self.zero - 1
  204. while negPos >= 0.0:
  205. dc.DrawLine(negPos, 0.0, negPos, self.h)
  206. st = str(negNum)
  207. self.drawXNumber(dc, st, negPos)
  208. negPos -= self.unitWidth
  209. posNum -= 1
  210. elif self.unitWidth >= 10 and self.unitWidth <= 25:
  211. posPos = self.zeroPos[0]+self.unitWidth*2.0
  212. posNum = self.zero + 2
  213. while posPos <= self.w:
  214. dc.DrawLine(posPos, 0.0, posPos, self.h)
  215. st = str(posNum)
  216. self.drawXNumber(dc, st, posPos)
  217. posPos += self.unitWidth*2.0
  218. posNum += 2
  219. negPos = self.zeroPos[0]-self.unitWidth*2.0
  220. negNum = self.zero - 2
  221. while negPos >= 0.0:
  222. dc.DrawLine(negPos, 0.0, negPos, self.h)
  223. st = str(negNum)
  224. self.drawXNumber(dc, st, negPos)
  225. negPos -= self.unitWidth*2.0
  226. posNum -= 2
  227. elif self.unitWidth >= 2 and self.unitWidth <= 10:
  228. posPos = self.zeroPos[0]+self.unitWidth*float(5)
  229. posNum = self.zero + 5
  230. while posPos <= self.w:
  231. dc.DrawLine(posPos, 0.0, posPos, self.h)
  232. st = str(posNum)
  233. self.drawXNumber(dc, st, posPos)
  234. posPos += self.unitWidth*float(5)
  235. posNum += 5
  236. negPos = self.zeroPos[0]-self.unitWidth*float(5)
  237. negNum = self.zero - 5
  238. while negPos >= 0.0:
  239. dc.DrawLine(negPos, 0.0, negPos, self.h)
  240. st = str(negNum)
  241. self.drawXNumber(dc, st, negPos)
  242. negPos -= self.unitWidth*float(5)
  243. posNum -= 5
  244. def DrawYCoord(self,dc):
  245. dc.SetPen(wx.BLACK_PEN)
  246. dc.SetBrush(wx.BLACK_BRUSH)
  247. dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
  248. dc.DrawLine(0.0, self.zeroPos[1], self.w, self.zeroPos[1])
  249. st = str(self.zero)
  250. dc.DrawText(st, 5.0, self.zeroPos[1]-1.0)
  251. dc.SetPen(wx.Pen(wx.Colour(150, 150, 150)))
  252. dc.SetBrush(wx.Brush(wx.Colour(150, 150, 150)))
  253. dc.SetLogicalFunction(wx.AND)
  254. posPos = self.zeroPos[1]-self.unitHeight*float(5)
  255. posNum = self.zero + 5
  256. while posPos >= 0.0:
  257. dc.DrawLine(0.0, posPos, self.w, posPos)
  258. st = str(posNum)
  259. self.drawYNumber(dc, st, posPos)
  260. posPos -= self.unitHeight*float(5)
  261. posNum += 5
  262. negPos = self.zeroPos[1]+self.unitHeight*float(5)
  263. negNum = self.zero - 5
  264. while negPos <= self.h:
  265. dc.DrawLine(0.0, negPos, self.w, negPos)
  266. st = str(negNum)
  267. self.drawYNumber(dc, st, negPos)
  268. negPos += self.unitHeight*float(5)
  269. negNum -= 5
  270. def drawXNumber(self, dc, st, pos):
  271. oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
  272. dc.SetPen(wx.BLACK_PEN)
  273. dc.SetBrush(wx.BLACK_BRUSH)
  274. dc.DrawText(st, pos+1.0, self.h-self.th-0.5)
  275. dc.SetPen(oldPen)
  276. dc.SetBrush(oldBrush)
  277. dc.SetLogicalFunction(oldMode)
  278. def drawYNumber(self, dc, st, pos):
  279. oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
  280. dc.SetPen(wx.BLACK_PEN)
  281. dc.SetBrush(wx.BLACK_BRUSH)
  282. dc.DrawText(st, 5.0, pos-1.0)
  283. dc.SetPen(oldPen)
  284. dc.SetBrush(oldBrush)
  285. dc.SetLogicalFunction(oldMode)
  286. def DrawFrame(self, dc):
  287. if self._mainDialog.editor.mode == self._mainDialog.editor.ANIM_MODE:
  288. curFramePos = self.zeroPos[0]+self.curFrame*self.unitWidth
  289. dc.SetPen(wx.Pen("red"))
  290. dc.SetBrush(wx.Brush("red"))
  291. dc.DrawLine(curFramePos, 0.0, curFramePos, self.h)
  292. else:
  293. pass
  294. def drawX(self, dc):
  295. dc.SetPen(wx.Pen("red"))
  296. dc.SetBrush(wx.Brush("red"))
  297. self.drawSingleCurve(self.X, dc)
  298. self.drawKeys(self.X, dc)
  299. self.drawHandler(self.X, dc)
  300. def drawY(self, dc):
  301. dc.SetPen(wx.Pen("green"))
  302. dc.SetBrush(wx.Brush("green"))
  303. self.drawSingleCurve(self.Y, dc)
  304. self.drawKeys(self.Y, dc)
  305. self.drawHandler(self.Y, dc)
  306. def drawZ(self, dc):
  307. dc.SetPen(wx.Pen("blue"))
  308. dc.SetBrush(wx.Brush("blue"))
  309. self.drawSingleCurve(self.Z, dc)
  310. self.drawKeys(self.Z, dc)
  311. self.drawHandler(self.Z, dc)
  312. def DrawCurve(self, dc):
  313. if self.property == self._mainDialog.namestr:
  314. self.drawX(dc)
  315. self.drawY(dc)
  316. self.drawZ(dc)
  317. return
  318. if self.property == property[AG.X]:
  319. self.drawX(dc)
  320. return
  321. if self.property == property[AG.Y]:
  322. self.drawY(dc)
  323. return
  324. if self.property == property[AG.Z]:
  325. self.drawZ(dc)
  326. return
  327. def drawSingleCurve(self, list, dc):
  328. if len(list) == 1:
  329. dc.DrawPoint(list[0][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[0][AG.KEYFRAME][AG.LOCAL_VALUE][1])
  330. return
  331. if len(list) == 2:
  332. dc.DrawLine(list[0][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[0][AG.KEYFRAME][AG.LOCAL_VALUE][1], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[1][AG.KEYFRAME][AG.LOCAL_VALUE][1])
  333. return
  334. if len(list)>=3 :
  335. for i in range(len(list)-1):
  336. x1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
  337. y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
  338. x4 = list[i+1][AG.KEYFRAME][AG.LOCAL_VALUE][0]
  339. y4 = list[i+1][AG.KEYFRAME][AG.LOCAL_VALUE][1]
  340. t1x = list[i][AG.OUT_SLOPE][0]
  341. t1y = list[i][AG.OUT_SLOPE][1]
  342. t2x = list[i+1][AG.IN_SLOPE][0]
  343. t2y = list[i+1][AG.IN_SLOPE][1]
  344. x2 = x1 + (x4 - x1) / 3.0
  345. scale1 = (x2 - x1) / t1x
  346. y2 = y1 - t1y * scale1
  347. x3 = x4 - (x4 - x1) / 3.0
  348. scale2 = (x4 - x3) / t2x
  349. y3 = y4 + t2y * scale2
  350. ax = - 1.0 * x1 + 3.0 * x2 - 3.0 * x3 + 1.0 * x4
  351. bx = 3.0 * x1 - 6.0 * x2 + 3.0 * x3 + 0.0 * x4
  352. cx = - 3.0 * x1 + 3.0 * x2 + 0.0 * x3 + 0.0 * x4
  353. dx = 1.0 * x1 + 0.0 * x2 - 0.0 * x3 + 0.0 * x4
  354. ay = - 1.0 * y1 + 3.0 * y2 - 3.0 * y3 + 1.0 * y4
  355. by = 3.0 * y1 - 6.0 * y2 + 3.0 * y3 + 0.0 * y4
  356. cy = - 3.0 * y1 + 3.0 * y2 + 0.0 * y3 + 0.0 * y4
  357. dy = 1.0 * y1 + 0.0 * y2 - 0.0 * y3 + 0.0 * y4
  358. preX = x1
  359. preY = y1
  360. t = 0.001
  361. while t <= 1.0:
  362. x = ax * t*t*t + bx * t*t + cx * t + dx
  363. y = ay * t*t*t + by * t*t + cy * t + dy
  364. curX = x
  365. curY = y
  366. dc.DrawLine(preX, preY, curX, curY)
  367. preX = curX
  368. preY = curY
  369. t += 0.001
  370. def drawKeys(self, list, dc):
  371. for i in range(len(list)):
  372. pointX = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
  373. pointY = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
  374. if list[i][AG.KEYFRAME][AG.SELECT] == 0:
  375. dc.SetPen(wx.Pen("black",3))
  376. dc.SetBrush(wx.Brush("black"))
  377. dc.DrawCircle(pointX, pointY, 2)
  378. if list[i][AG.KEYFRAME][AG.SELECT] == 1:
  379. dc.SetPen(wx.Pen("cyan",3))
  380. dc.SetBrush(wx.Brush("cyan"))
  381. dc.DrawCircle(pointX, pointY, 2)
  382. def drawHandler(self, list, dc):
  383. for i in range(len(list)):
  384. if list[i][AG.KEYFRAME][AG.SELECT] == 1:
  385. X1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
  386. Y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
  387. if self._OneTangent == True:
  388. for j in range(3,5):
  389. X = list[i][j][AG.LOCAL_VALUE][0]
  390. Y = list[i][j][AG.LOCAL_VALUE][1]
  391. if list[i][j][AG.SELECT] == 1:
  392. dc.SetPen(wx.Pen("cyan",3))
  393. dc.SetBrush(wx.Brush("cyan"))
  394. dc.DrawCircle(X, Y, 2)
  395. dc.SetPen(wx.Pen("cyan",1))
  396. dc.DrawLine(X1, Y1, X, Y)
  397. if list[i][j][AG.SELECT] == 0:
  398. dc.SetPen(wx.Pen("brown",3))
  399. dc.SetBrush(wx.Brush("brown"))
  400. dc.DrawCircle(X, Y, 2)
  401. dc.SetPen(wx.Pen("brown",1))
  402. dc.DrawLine(X1, Y1, X, Y)
  403. if self._OneTangent == False:
  404. if list[i][AG.IN_TANGENT][AG.SELECT] == 1:
  405. X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
  406. Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
  407. dc.SetPen(wx.Pen("cyan",3))
  408. dc.SetBrush(wx.Brush("cyan"))
  409. dc.DrawCircle(X, Y, 2)
  410. dc.SetPen(wx.Pen("cyan",1))
  411. dc.DrawLine(X1, Y1, X, Y)
  412. if list[i][AG.IN_TANGENT][AG.SELECT] == 0:
  413. X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
  414. Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
  415. dc.SetPen(wx.Pen("navy",3))
  416. dc.SetBrush(wx.Brush("navy"))
  417. dc.DrawCircle(X, Y, 2)
  418. dc.SetPen(wx.Pen("navy",1))
  419. dc.DrawLine(X1, Y1, X, Y)
  420. if list[i][AG.OUT_TANGENT][AG.SELECT] == 1:
  421. X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
  422. Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
  423. dc.SetPen(wx.Pen("cyan",3))
  424. dc.SetBrush(wx.Brush("cyan"))
  425. dc.DrawCircle(X, Y, 2)
  426. dc.SetPen(wx.Pen("cyan",1))
  427. dc.DrawLine(X1, Y1, X, Y)
  428. if list[i][AG.OUT_TANGENT][AG.SELECT] == 0:
  429. X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
  430. Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
  431. dc.SetPen(wx.Pen("brown",3))
  432. dc.SetBrush(wx.Brush("brown"))
  433. dc.DrawCircle(X, Y, 2)
  434. dc.SetPen(wx.Pen("brown",1))
  435. dc.DrawLine(X1, Y1, X, Y)
  436. def DrawSelectRec(self, dc):
  437. if self._selectRec == True:
  438. dc.SetPen(wx.Pen("navy", 1))
  439. dc.SetBrush(wx.Brush("navy"))
  440. ## dc.SetLogicalFunction(wx.AND)
  441. dc.DrawLine(self.pos[0], self.pos[1], self.pos[0], self.newPos[1])
  442. dc.DrawLine(self.pos[0], self.pos[1], self.newPos[0], self.pos[1])
  443. dc.DrawLine(self.newPos[0], self.newPos[1], self.pos[0], self.newPos[1])
  444. dc.DrawLine(self.newPos[0], self.newPos[1], self.newPos[0], self.pos[1])
  445. def OnSize(self,evt):
  446. self.InitBuffer()
  447. def OnLeftDown(self,evt):
  448. point = (evt.GetX(), evt.GetY())
  449. if point[1]>= 0.0 and point[1]<= float(self.h):
  450. if point[0]>= 0.0 and point[0]<= float(self.w):
  451. self._mouseIn = True
  452. if self._mouseIn:
  453. self.CaptureMouse()
  454. self.pos = point
  455. def OnLeftUp(self,evt):
  456. if self.GetCapture():
  457. self.ReleaseMouse()
  458. self._mouseIn = False
  459. self._selectRec = False
  460. self.setSelection()
  461. self.SetGraphEditorData(self.property, self.curFrame)
  462. def OnMiddleDown(self,evt):
  463. point = (evt.GetX(), evt.GetY())
  464. if point[1]>= 0.0 and point[1]<= float(self.h):
  465. if point[0]>= 0.0 and point[0]<= float(self.w):
  466. self._mouseIn = True
  467. if self._mouseIn:
  468. self.CaptureMouse()
  469. self.midPos = point
  470. def OnMiddleUp(self, evt):
  471. if self.GetCapture():
  472. self.ReleaseMouse()
  473. def OnMotion(self,evt):
  474. self._mouseIn = False
  475. if evt.Dragging() and evt.LeftIsDown():
  476. self.newPos = (evt.GetX(), evt.GetY())
  477. if self.newPos[1]>= 0.0 and self.newPos[1]<= float(self.h):
  478. if self.newPos[0]>= 0.0 and self.newPos[0]<= float(self.w):
  479. self._mouseIn = True
  480. if self._mouseIn:
  481. if self.newPos == self.pos:
  482. evt.Skip()
  483. self._mouseIn = False
  484. else:
  485. self._selectRec = True
  486. self.SetGraphEditorData(self.property, self.curFrame)
  487. if evt.Dragging() and evt.MiddleIsDown():
  488. self.newMidPos = (evt.GetX(), evt.GetY())
  489. if self.newMidPos[1]>= 0.0 and self.newMidPos[1]<= float(self.h):
  490. if self.newMidPos[0]>= 0.0 and self.newMidPos[0]<= float(self.w):
  491. self._mouseIn = True
  492. if self._mouseIn:
  493. if self.newMidPos == self.midPos:
  494. evt.Skip()
  495. self._mouseIn = False
  496. else:
  497. self.recalculateSlope()
  498. self.onAnimation()
  499. self.midPos = self.newMidPos
  500. evt.Skip()
  501. self._mouseIn = False
  502. self._selectRec = False
  503. def setExistKey(self, list):
  504. flag = False
  505. for i in range(len(list)):
  506. if list[i][AG.KEYFRAME][AG.SELECT] == 1:
  507. inside = self.inside(self.pos, self.newPos, (list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]))
  508. if inside == True:
  509. list[i][AG.KEYFRAME][AG.SELECT] = 0
  510. if inside == False:
  511. find = False
  512. for j in range(3,5):
  513. inside = self.inside(self.pos, self.newPos, (list[i][j][AG.LOCAL_VALUE][0], list[i][j][AG.LOCAL_VALUE][1]))
  514. if inside == False:
  515. list[i][j][AG.SELECT] = 0
  516. if inside == True:
  517. list[i][j][AG.SELECT] = 1
  518. find = True
  519. flag = True
  520. if find == False:
  521. list[i][AG.KEYFRAME][AG.SELECT] == 0
  522. return flag
  523. def setNewKey(self, list):
  524. for i in range(len(list)):
  525. inside = self.inside(self.pos, self.newPos, (list[i][2][0][0], list[i][2][0][1]))
  526. if inside == True:
  527. list[i][AG.KEYFRAME][AG.SELECT] = 1
  528. if inside == False:
  529. list[i][AG.KEYFRAME][AG.SELECT] = 0
  530. def setSelection(self):
  531. if self.property == self._mainDialog.namestr:
  532. self.setSelectionBase(self.X)
  533. self.setSelectionBase(self.Y)
  534. self.setSelectionBase(self.Z)
  535. return
  536. if self.property == property[AG.X]:
  537. self.setSelectionBase(self.X)
  538. return
  539. if self.property == property[AG.Y]:
  540. self.setSelectionBase(self.Y)
  541. return
  542. if self.property == property[AG.Z]:
  543. self.setSelectionBase(self.Z)
  544. return
  545. def setSelectionBase(self, list):
  546. self.setExistKey(list)
  547. if self.setExistKey(list) == True:
  548. return
  549. else:
  550. self.setNewKey(list)
  551. def inside(self, point0, point1, point):
  552. if point0[0]<=point1[0] and point0[1]<=point1[1]:
  553. if point0[0]<point[0] and point[0]<point1[0] and point0[1]<point[1] and point[1]<point1[1]:
  554. return True
  555. else:
  556. return False
  557. elif point1[0]<=point0[0] and point0[1]<=point1[1]:
  558. if point1[0]<point[0] and point[0]<point0[0] and point0[1]<point[1] and point[1]<point1[1]:
  559. return True
  560. else:
  561. return False
  562. elif point0[0]<=point1[0] and point1[1]<=point0[1]:
  563. if point0[0]<point[0] and point[0]<point1[0] and point1[1]<point[1] and point[1]<point0[1]:
  564. return True
  565. else:
  566. return False
  567. elif point1[0]<=point0[0] and point1[1]<=point0[1]:
  568. if point1[0]<point[0] and point[0]<point0[0] and point1[1]<point[1] and point[1]<point0[1]:
  569. return True
  570. else:
  571. return False
  572. else:
  573. return False
  574. def recalculateSlope(self):
  575. if self.property == self._mainDialog.namestr:
  576. self.recalculateSlopeBase(self.X)
  577. self.recalculateSlopeBase(self.Y)
  578. self.recalculateSlopeBase(self.Z)
  579. return
  580. if self.property == property[AG.X]:
  581. self.recalculateSlopeBase(self.X)
  582. return
  583. if self.property == property[AG.Y]:
  584. self.recalculateSlopeBase(self.Y)
  585. return
  586. if self.property == property[AG.Z]:
  587. self.recalculateSlopeBase(self.Z)
  588. return
  589. def recalculateSlopeBase(self, list):
  590. #recalculate the tangent slope
  591. moveX = self.newMidPos[0]-self.midPos[0]
  592. moveY = self.newMidPos[1]-self.midPos[1]
  593. for i in range(len(list)):
  594. if list[i][AG.KEYFRAME][AG.SELECT] == 1:
  595. if list[i][AG.IN_TANGENT][AG.SELECT] == 1:
  596. newPointX = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] + moveX
  597. newPointY = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] + moveY
  598. newSlope = [list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] - newPointX , newPointY - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]]
  599. temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0]
  600. temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1]
  601. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = newSlope[0]/self.unitWidth
  602. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = newSlope[1]/self.unitHeight
  603. handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
  604. if handler[1][0][0]>= list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
  605. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = temp0
  606. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = temp1
  607. return
  608. if handler[1][0][0] < list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
  609. if self._OneTangent == False:
  610. list[i][AG.IN_TANGENT][0] = handler[1][0]
  611. list[i][AG.IN_SLOPE][0] = handler[3][0]
  612. list[i][AG.IN_SLOPE][1] = handler[3][1]
  613. if self._OneTangent == True:
  614. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = newSlope[0]/self.unitWidth
  615. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = newSlope[1]/self.unitHeight
  616. handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
  617. list[i][AG.IN_TANGENT][0] = handler[1][0]
  618. list[i][AG.OUT_TANGENT][0] = handler[2][0]
  619. list[i][AG.IN_SLOPE][0] = handler[3][0]
  620. list[i][AG.IN_SLOPE][1] = handler[3][1]
  621. list[i][AG.OUT_SLOPE][0] = handler[4][0]
  622. list[i][AG.OUT_SLOPE][1] = handler[4][1]
  623. self.SetGraphEditorData(self.property, self.curFrame)
  624. if list[i][AG.OUT_TANGENT][AG.SELECT] == 1:
  625. newPointX = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] + moveX
  626. newPointY = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] + moveY
  627. newSlope = [newPointX - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] , list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] - newPointY]
  628. temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0]
  629. temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1]
  630. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = newSlope[0]/self.unitWidth
  631. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = newSlope[1]/self.unitHeight
  632. handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
  633. if handler[2][0][0] <= list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
  634. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = temp0
  635. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = temp1
  636. return
  637. if handler[2][0][0] > list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
  638. if self._OneTangent == False:
  639. list[i][AG.OUT_TANGENT][0] = handler[2][0]
  640. list[i][AG.OUT_SLOPE][0] = handler[4][0]
  641. list[i][AG.OUT_SLOPE][1] = handler[4][1]
  642. if self._OneTangent == True:
  643. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = newSlope[0]/self.unitWidth
  644. self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = newSlope[1]/self.unitHeight
  645. handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
  646. list[i][AG.IN_TANGENT][0] = handler[1][0]
  647. list[i][AG.OUT_TANGENT][0] = handler[2][0]
  648. list[i][AG.IN_SLOPE][0] = handler[3][0]
  649. list[i][AG.IN_SLOPE][1] = handler[3][1]
  650. list[i][AG.OUT_SLOPE][0] = handler[4][0]
  651. list[i][AG.OUT_SLOPE][1] = handler[4][1]
  652. self.SetGraphEditorData(self.property, self.curFrame)
  653. def selectHandler(self):
  654. self._selectHandler = False
  655. def onAnimation(self):
  656. if self._mainDialog.editor.mode == self._mainDialog.editor.ANIM_MODE:
  657. self._mainDialog.editor.ui.animUI.OnAnimation(self._mainDialog.editor.ui.animUI.curFrame)
  658. else:
  659. pass
  660. class GraphEditorUI(wx.Dialog):
  661. """
  662. This is the graph editor main class implementation.
  663. """
  664. def __init__(self, parent, editor, object):
  665. wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Graph Editor",
  666. pos=wx.DefaultPosition, size=(735, 535))
  667. self.editor = editor
  668. self.editor.GRAPH_EDITOR = True
  669. self.object = object
  670. self.xRange = 24+1
  671. self.yRange = 50
  672. if self.editor.mode == self.editor.ANIM_MODE:
  673. self.curFrame = self.editor.ui.animUI.curFrame
  674. self.curFrame = 1
  675. self.mainPanel1 = wx.Panel(self, -1)
  676. bmpZoomIn = ZoomIn.GetBitmap()
  677. bmpZoomOut = ZoomOut.GetBitmap()
  678. bmpOneTangent = OneTangent.GetBitmap()
  679. bmpTwoTangents = TwoTangents.GetBitmap()
  680. self.buttonZoomIn = wx.BitmapButton(self.mainPanel1, -1, bmpZoomIn, size = (30,30),style = wx.BU_AUTODRAW)
  681. self.buttonZoomOut = wx.BitmapButton(self.mainPanel1, -1, bmpZoomOut, size = (30,30),style = wx.BU_AUTODRAW)
  682. self.buttonOneTangent = wx.BitmapButton(self.mainPanel1, -1, bmpOneTangent, size = (30,30),style = wx.BU_AUTODRAW)
  683. self.buttonTwoTangents = wx.BitmapButton(self.mainPanel1, -1, bmpTwoTangents, size = (30,30),style = wx.BU_AUTODRAW)
  684. self.mainPanel2 = wx.Panel(self, -1)
  685. self.tree = self.tree = wx.TreeCtrl(self.mainPanel2, id=-1, pos=wx.DefaultPosition,size=wx.Size(200, 450), style=wx.TR_MULTIPLE|wx.TR_DEFAULT_STYLE,validator=wx.DefaultValidator, name="treeCtrl")
  686. self.namestr = "%s"%(object[OG.OBJ_DEF].name)
  687. self.root = self.tree.AddRoot(self.namestr)
  688. self.AddTreeNodes(self.root, property)
  689. self.tree.Expand(self.root)
  690. self.tree.SelectItem(self.root,select=True)
  691. self.str = self.tree.GetItemText(self.root)
  692. self.graphEditorWindow =GraphEditorWindow(self.mainPanel2, wx.Size(500, 450), str(object[OG.OBJ_DEF].name), self.xRange, self.yRange, self.curFrame, self.object)
  693. self.SetProperties()
  694. self.DoLayout()
  695. self.Bind(wx.EVT_BUTTON, self.OnZoomIn, self.buttonZoomIn)
  696. self.Bind(wx.EVT_BUTTON, self.OnZoomOut, self.buttonZoomOut)
  697. self.Bind(wx.EVT_BUTTON, self.OnOneTangent, self.buttonOneTangent)
  698. self.Bind(wx.EVT_BUTTON, self.OnTwoTangents, self.buttonTwoTangents)
  699. self.Bind(wx.EVT_CLOSE, self.OnExit)
  700. self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
  701. def SetProperties(self):
  702. pass
  703. def DoLayout(self):
  704. dialogSizer = wx.BoxSizer(wx.VERTICAL)
  705. mainSizer1 = wx.FlexGridSizer(1, 4, 0, 0)
  706. mainSizer2 = wx.FlexGridSizer(1, 2, 0, 0)
  707. mainSizer1.Add(self.buttonOneTangent, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 570)
  708. mainSizer1.Add(self.buttonTwoTangents, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
  709. mainSizer1.Add(self.buttonZoomIn, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
  710. mainSizer1.Add(self.buttonZoomOut, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
  711. mainSizer2.Add(self.tree, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
  712. mainSizer2.Add(self.graphEditorWindow, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
  713. self.mainPanel1.SetSizerAndFit(mainSizer1)
  714. self.mainPanel2.SetSizer(mainSizer2)
  715. dialogSizer.Add(self.mainPanel2, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 10)
  716. dialogSizer.Add(self.mainPanel1, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 5)
  717. self.SetSizer(dialogSizer)
  718. self.Layout()
  719. self.dialogSizer = dialogSizer
  720. def AddTreeNodes(self, parentItem, items):
  721. for item in items:
  722. if type(item) == str:
  723. self.tree.AppendItem(parentItem, item)
  724. def OnSelChanged(self, evt):
  725. item = evt.GetItem()
  726. if item:
  727. self.str = self.tree.GetItemText(item)
  728. self.graphEditorWindow.refresh()
  729. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  730. def OnZoomIn(self,evt):
  731. self.graphEditorWindow.zoom = self.graphEditorWindow.zoom/float(1.2)
  732. self.graphEditorWindow.unitWidth = self.graphEditorWindow.unitWidth*float(1.2)
  733. self.graphEditorWindow.unitHeight = self.graphEditorWindow.unitHeight*float(1.2)
  734. self.graphEditorWindow.generateInfo()
  735. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  736. def OnZoomOut(self,evt):
  737. self.graphEditorWindow.zoom = self.graphEditorWindow.zoom*float(1.2)
  738. self.graphEditorWindow.unitWidth = self.graphEditorWindow.unitWidth/float(1.2)
  739. self.graphEditorWindow.unitHeight = self.graphEditorWindow.unitHeight/float(1.2)
  740. self.graphEditorWindow.generateInfo()
  741. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  742. def OnOneTangent(self,evt):
  743. self.graphEditorWindow._OneTangent = True
  744. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  745. def OnTwoTangents(self,evt):
  746. self.graphEditorWindow._OneTangent = False
  747. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  748. def curFrameChange(self):
  749. if self.editor.mode == self.editor.ANIM_MODE:
  750. self.curFrame = self.editor.ui.animUI.curFrame
  751. self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
  752. else:
  753. pass
  754. def OnExit(self,evt):
  755. self.Destroy()
  756. self.editor.ui.graphEditorMenuItem.Check(False)
  757. self.object = None
  758. self.editor.GRAPH_EDITOR = False