Added animation system

This commit is contained in:
Shuying Feng 2010-08-13 18:05:53 +00:00
parent debb5223cc
commit b18c13895c
12 changed files with 2616 additions and 4 deletions

View File

@ -0,0 +1,936 @@
"""
This is the GUI for the Animation Control Panel
"""
from direct.interval.IntervalGlobal import *
from direct.actor.Actor import *
from panda3d.core import VBase3,VBase4
import ObjectGlobals as OG
import AnimGlobals as AG
import os,wx, time
from wx.lib.embeddedimage import PyEmbeddedImage
#----------------------------------------------------------------------
FirstFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACh0lE"
"QVRIie2Uz08aQRTHd368CZzYGGNjPWkTlB7EK0QSewSSamL9R+upXmpko/LLskgqhrDGyqb4"
"Y40CB3dnd6aHMYBIjSZe2vhOk/2+93nf93Z3UOvsTHvtwK9OfIP+f1CEEKUUITRWJYQQQl4A"
"RQgBpQihVqvV6/UwflBCCGGM3XY6tm33H9JhGWPMOR9xFwhhnZzs7e21bPvL+rqu60KIe3eU"
"3tzcVCqVQqHwYW5ubW0tCIIBlDFmmmbTsjLptBoEADjnjUajWCodHx/3er2JiQklqWEdxzGr"
"1R8HB7/bbU3TotHoqFOMcfv8vFarZdJpxpjruvV6vVAs1ut1z/MopQBACAEAAGi32xXTLJfL"
"l5eXGGMAUJ3Gj88Y45w3LSu/v9+0LNd1AYAxpmlaEASE0uvr659HR+Vy2XEcla9pmpRS0zQy"
"tOsBFCEkhPi2tZXP533fD4VCqqY/iue6Xzc3r66uGGPDUr98kNw/SSkJIclE4tPKiq7rnHNl"
"QYUQIhwOp5aXF+bnlfERKKUDf3RYkFJOTk5ms9n40lJuZ6d6eOh5HgDcu5AyFoslk8liqWQY"
"xsXFxcjnOQYqhPB9PwgCzvn76emNjY3FeNzI5ZrNpjKMCQmCAACSicR8NLqfz5dLpU63q9Dk"
"sVMhRCQSmZmZQQhJKTnnCKGPsdjc7KxpmoZhtGxbCIEwVr11Xc9mMvHFxZ1crlarqfzBfp++"
"+THGlNLbTmd3d/fX6enn1dV3U1O+7ysVAIQQjUbj+/Z2bGEhlUqpXT+AKpuP0WpxjuOEw+FQ"
"KDScgxACgG63e3d3F4lEnuV0uFi1HNtVXQjq99VG3v4T8Tecij7uvsczoS+KN+g/Av0D3hpG"
"5dYDHHkAAAAASUVORK5CYII=")
#----------------------------------------------------------------------
PreFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACQ0lE"
"QVRIieWVzW4aMRSFbV+DCHTDJlkAYZMKAek2fQHYddElu/SteA+eoNk0iPA7BBBQgtQJI6Gi"
"ZoQKM2PP2F24P2RmKFGVRauenSX707nH99r4XtfRc4s8O/G/ghKMMcaHoQAAAIdxhFBKGeeM"
"MR/XDxVCrFYr0zQP4hzH0TStVqvpuk4p3d3waAEA6/W6Wq2m0ul3l5cIISmlDwcAm81mPp83"
"m827+ZwCFAoFn9NHUEXZWpZt20F3GGPLsiaTidbvz2Yzx3EQQvFkkgSy8kPVeUJ+xQIACjcc"
"DjudziddZ4ypBIQQyshh6C4OIWSa5sfZrNVqGYZh2zal9GeCUkq19KUUDsUIUUpN0xwOh71e"
"b2EYnHNCSCQSCe5EgZYKgWKMGefvr64Gt7f3i4XnebvuQhQoP7z5CSG2ZX15ePA8T2W6D+i7"
"gL1OpZQUoFwuF4vFD9fXo9HI2m6B0lA0CZuU8KJUPelM5u3Jyavz80ajMZ1OXdf9vesDUOXX"
"c10gpFAsZk5PB4NBvV5fLpdCiF1rT70oH5ozFj86en1x8fLsrN1ud7vdz6sVAKgo1UPxpJby"
"SQghhEgmk6VSKZ/PN25u+pq2tSzFCsYRMqacc9d1g2jP8xBCqVTqzfFxsVCo1+vj8Zgx9n2u"
"9kGFEIlEolKpJOJxGeg+Jdd1CSG5XC6bzbbabcMwghOFfR8fxjgajQohOOfhWfyQyvTrZgOE"
"xGKxXW5I+er5OSghBEboRSIhpfyTi9oniZAMBIr+0o/vH4d+A5itKwKTfnzPAAAAAElFTkSu"
"QmCC")
#----------------------------------------------------------------------
PreKeyFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACPUlE"
"QVRIib3Vz0/aYBgH8OfHiyTGgAsciJMl6A5j7OLO4+48eHT/qjflSDPlRweNEqPGrTF2hQwW"
"gbR9nx2Yi9Ii1bE9x7b55Pu87/Ok+PXqChZdtHDxv6FEsLS0UJQZXVcdHIBSi0OJ0HXV4aHE"
"QJmZmGOgML99BCAipZTjOPVard/vE00jT2gTEYkIEV3XbZpms9HwfP/T3l4mk9FaPwdVSmmt"
"v7uuaZqmaV5fX2utX66tEbOIPC0pIjIzANi23basRqPR7XaDIGBmRAQACImPoZNmtda2bbda"
"raZpOo4zeaiUAgARYebwgUajiJhIJPzR6Jtt12u1k5OTG8f5Y90vVgrjoIQ4Ho/Pz87ax8df"
"TLM/GABAIpGIbkckVvtE9PP2dn9//8KyiFkp9fvsogoRI99Ohw+CIJ1K7e7ulsvllZWVIAim"
"xuVBIqVinakAIFE+n8/t7LwtlarVauf0dDgaRUeeMQDRt+95HiG+3tx8lc+32m2jWr24vASA"
"yfDPCj4HBQAR8X2fmd9vbW0UCs1m8/PRkXNzowH4buUnIxW+qTnDLyKe56VSqQ/l8pti0TCM"
"Rr3+o9+fuDwjeKw1DYIAAbKZzMft7WKxaBiGZVnD4XDWHcbdfZnQiBuFwvr6eqfTqVQqAhBe"
"/Blo1Hd3b8T3fSZ6Vyrlcrler7eUTIbzhlBEmLU/92jP816srqbTaREJh8UHv2hEGI9xMJBs"
"9pG8c+thUhFIJmV5GXz/2SJE/E5E/lKMQhdR/wT9BR51CSZZ1VE7AAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
PrePlay = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACV0lE"
"QVRIic2Vz1PaUBDHs5tkH9jROv4LDhUHrLXOlOml/p3+H/VYg6YJQz3UWkDDAJlob8J4AUxq"
"3tse4lBKEIV6cI9vdz7vuz/eW/h1daU9t+GzE18kFBERpxAWhAJAJpO5u7sbDodp7iJQIjIM"
"o16v7+/vtzsdk2giwJgLZxqGYZqXl5eWZf04O4ui6NPeHqTCngpFRCFEr9f76jjVarXf7wsh"
"hBBKqXTw41BEFETD21vbtstHR9fX10SUzWaZmZmllHNDiYiZz2q1Q8vyfV9HzGazIy9r2nxQ"
"0zR1XQ+CwLKsn7WaUkoQAUwWUEqpMT8O1XWdiLrdrm3b305OBoOBEMI0zSk3M7NSWuqmf6BJ"
"NwaDgeO69vFxt9dLyvdQNolSnqEUAKSU309PLcsKgkDX9dm4ETR9aIyIiFgulz8fHEgpl5eX"
"ETEtYdyS+iYjBZo2HnoPZWal1IdS6fXqarVaDYKAmWlaZyYsTpQCjLfrb/rM/Gpp6WOp9G57"
"u1GvO67rBwErNQP9pDlVSt2Goa7r73d3C8Vio9GoVCrtTkc9gAYAfuKLklJKKRFxZ2enUChc"
"eJ7rOK12W0ppEuEYmpnlXM9UKRWGISK+3drazOc9z6tUKl6z+TuOiWj03ck4ngM6jgaAYrG4"
"sbHRarVc1/WazTAMiUjTNKnUrDmdYcycqN7M59/kcu1Ox3Hd8/PzMAzjOF7867tXHUUAkMvl"
"1tfXfd//cniIACqlFBZb0QBARHEc39zcrKysTHgX3FHMHEWRUmptbS3t/a9tyszxtO6/vL3/"
"kP0BhtFQnDqk9wIAAAAASUVORK5CYII=")
#----------------------------------------------------------------------
Play = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACTUlE"
"QVRIidXWzU7bQBAH8JmxLW8SbglXLCchTsKFElEUu4aaHnhSnoInoBeEihoSwodEz5wKya67"
"Oz24UAiOgQhV6p5sy/r5v7OztvHH9TW896B3F/8hats2Ir4zenNzQ0Su6y5M249PENG27YOD"
"g5+3t192d33fJyKlFDMvjgIAIRrmo6Oj8/PzTqcThWGjXrcsS6WpMWZBlAFs2xZCAMDx8fFg"
"MAharTAMm82mEEJK+ZrUsygiWkQAQERCCGPMt5OTwelp0Gr1+/0gCBzHUUoVp55FAcCy/178"
"QzN/HwyGo1Gz0QijqB0EQogCOg8lmll3QnRdl5mHo9HZeNyo1/v9frfbFUKkaaq1fhlFotzC"
"4T19Nh6PLy58z4vCsLu2VhJCPk2dl9SyCjr0gb64vLy8uvI8b2trKwiCcqn0EOVp8zMDgG1Z"
"88THtBDCcZzhcLi/v//18JAeFe1J0uxBRAQAzFy8o5RSWuvV1dUkSYJWyxjzkDR/+sUxtdZK"
"qVq1Gm9vf9zcrFQqUsqimiJiAWqMkVJWKpUoDOM4rtVqSqnJZDJz27OkzEgEzybOzEopIvqw"
"vp4kied5Wuvn3Bw0L2maptoY3/d3k6Tb6SDidDqdN5s8NGup++OsfMvLy593dnq9XrlUki/t"
"0fkoIjNPp9OlpaU4jj9FUbValVJOCgMWoUQkpXRdt7exkSTJysrKrzSdV75XoQyAiHXf39vb"
"a7fbiPgmLhs484kmoru7O8dxsu576zs/P6kxplwuA0Dx+r4NzdyFuWz8Pz8TvwFpng4ClVur"
"2QAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
NextKeyFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACNUlE"
"QVRIic2Vy27aQBSGj+3xBQNRlSJlQWhwSKPUSMkQmcu+Sl8zW56AVfMCTQgLVEQSbxCELhFi"
"wcUzc7qwihQ8NiTNImdny/P5/89tlNFwCO8d6rsTPyAUEXQdCAHE7VBFUXaCmqZ2d6c9PIBh"
"bIEi4nK5VFVVVbeYQMMg9/fq4yNGoGRDI2Os2+0yziuVim3bnDGMuFv/P87+JhQBRs/PnU7H"
"9/1Go+E4jqHrnPNYtCzIxrMCYOg6IPZ6vcFgUHbdWr1+mM8DAOf8jdC1ZELIYrH4dXv75PtV"
"z6OUfs7lBOdCiFdDETFgLLQalms6nf68ufnd63med3F+nk6nhRDJaEn18eUBTdNUVR2Px61W"
"q9ls9vt9xhghJKHzJDmNRpgNRHzy/eFo5LpurVr9Ui4rMW0XsQ8QZy1Er1ardrvt+75bq32f"
"TD4dHES/lNgPGJNC12wAmM/nf8bj2WwmFSuvvjTC+pim+bVUopSeXl5mr6+5TMFO0DXupFSi"
"lJaOj9OZDLMsBUA6ErKWWq3g31oRQnDObdt2HKdRrxcKBdu2OedBEERHPklpOJGhumwmUzo5"
"oZQWj44syxJCBEGw1ZkEyjhnjNm2/e3s7ILSYrFo6LoQgiUXMBmaSqUqlHrV6mE+b1kWY2x3"
"nASKiLqu/7i6yu7tWaYZ5i7pNGJ070mgmqblcrldzRICmhZ9rbz9ilZVZTIBQjCbhZdD+Irm"
"3wwhcH8fECEy1v8BBYCYtf3R7v34+AuNHRpDa7trrwAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
NextFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACOUlE"
"QVRIidWVS2/aQBSFZ8ZjYxkTFmSBRFAgpk1CJTIgE/orq/wMJFbNAjbNLqsgxAKVh+INgrhL"
"HkK8PI8urCKCx01bsWju+vrTuef6noHj0Qgcu9DRie8dCiE8MlQIsdlsEEIIvT0EQkhV1WAn"
"PtBIKe10OpSxYrFoGAajVAghJUIIF4vFdDqNx+OxWIxzLlcKIRQAjF9eGo1GrVYbDAaMc4yx"
"1BBN03q93pe7u3a7HdG0UKUAAAiApqpAiG63OxwOP+Xzt5XKWSoFAGCMHTRzzj3P29coh+4k"
"Y4zX6/VTs/nsOGXbJoQkTk85Y/sICCFCKDjHIVQI4VHqu+ivazabfXt4+N7t2rZ9UyhEo1HO"
"eVDdfkm2L15/oCgKQsh13Xq9Xq1W+/0+pTTMaLlSaaPvhhDi2XFG43E+n78tlz9eXob9doHx"
"AQgbzUdvt9tWq+U4TqlUAkJIuXJPpdAdGwCwWq1+uK5pmkhmgnz70vL3E4lEPlgWIaRQKDw1"
"m/Tx8R+hO1zOsggh1sVF1DQxxmGbko2/3YJfscI5Z4wZhpHNZj9XKul02jAMxpjneb8JB4lS"
"/9h9dTHTtHI5Qkjm/FzXdf+Egs1vQyljlFLDMK6vrm4IyWQymqpyzmlggUIIznmQC/ffKITQ"
"crn8en+PFcUul89SKV3XaUhQIYQmk4nruslkMpFIvDrffagfffP5PHZyokcijLGw3NtxMcaM"
"sYOsgcHXVFEU6VB/XhJPgxH3t/WuX9P/FPoTFHYunoRw1IsAAAAASUVORK5CYII=")
#----------------------------------------------------------------------
LastFrame = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAAClElE"
"QVRIie2VT0sbQRjG950/Gw8mW4QgCWxaMSdjwkq60YDmYD+A/QBiP5keq2IuHuKxxUNFqoI2"
"UuOlInahHpYkHhLdmXmnh5VNiLFS8CL4nhZm3t/zzvMsM/D76sp47iLPTnyFvkQoABDyqAYh"
"BAD+DwoA3W632WwyxiilA5u01r7vCyE454+B+iXvoZTSVru9Va1++fq10+2aphltAgAA+H5w"
"sL6xcXl5yRhjjD2Eaq0HoWHzzc1NrVZbXV09OjoytOacR2iNeHp6ura2tr297ft+LBaLvOKc"
"Hx4efl5fD+UNw+hpIiIhhHPued5WtXpycjI/P5+dnARChBBaa9M0AyG+7e01zs/nZmeLxWIi"
"kZBSEkJarZbneRGqB9WIiAgAjDGt9c+zs18XF47jVBYWkskkIhqGQQgxTbPZatV2dn7U65VK"
"JTc1xTkf8GSIO6EVpmlKKff39xuNhuu6t7e3kRWMUoNSz/M2Nzez2eyHxUWlVH9QLKIopcJx"
"en4TwhjzfX93d/eNZVFK+9NgjAkh6vX63d2dlUjQvt+x96W17u9BxCAIGGMzMzPLy8uZTEZK"
"Ga1KKYUQ4+PjH5eWPq2sJJNJqdSQ4yOi1toAQEQp5cjISCGfL5VK7yYmCMDx8XEoHKLTqZTr"
"uvl83rIsxphSKgiCYVCtpZQiCOLxuOM4ruu+zWQopUqpQIhwNM65bdvvi8VcLmdZllQqCAJE"
"TKVS07ncEKhSKmaaJdedK5cztg0AIQgAtNaolG3b5XI5Pz09OjoqhIhGk1IWCgXHcYQQ9wmF"
"zwkhpN1udzqddDodhjbg75/r67GxsUQ8LqUcyPNhQfRGEUIIIQO43okYQ8QncQ88/WdPf/RP"
"1ku8pF+hz1V/AVdHWFTfbzsRAAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
Key = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACl0lE"
"QVRIie2Uv0sbYRjH3x+X9/JGk9wlYkg6icbJMf0LHCxo/QuKUCfR0TFqB/dKHSztYKHBYHCp"
"kIIFqZM6ODho3Y2tQ44EMRffu3tz79vhlcNGC5I4+h2/L3yen+8Df19cgKcWenLiM7RbKITw"
"vql1g6OUAikhQowxIUTw1GGmEEKdkEKh8GZq6v3KCgAAY9wttKen58Pqan5hwTCMcrm8sLhI"
"COkKSgg5Ozv79PlzcWPjy/r6j50du9HY3d2llHYO1XV9s1R6NTY2OjpqWRbGeG5u7uDwMGjr"
"LRRCiB4tz/N+nZ6OT0y4rgsAcBwnm82GNK1WqyGEQDB9IYTv+wAAhBDGmHOuaZqUUpl3hRBq"
"NBp2szk0OOh5HgBASkkpTSSTVcsyTVMIoakeHR8fb5ZKGsYN2242m5l0ulqtYozNROLurqia"
"GGPX19eGYUgplSmljEQiruOotdUAAJzz4eHh+fl5Sun3cvnn3t7y8nI+n0/29c3MzDRtuz1T"
"256dnXUcJxKJBJG45yGEVBhNxSGE6LpOKTUMIxqNJpPJWCwWi8USpklCoTZoPB4nhPy5vOzv"
"71f98X2/Vq8bhqHKQkH+QgghBOfccRwhhOu6nucFfiDf9ymlqVTqYH8/HA4DADDGlmVdXV2l"
"Uql/oEq+72cymZe5HGNsZGQkOzTEOW8blCpwYnz8a6FQr9ej0ahpmltbWy8ymd7eXvUK2y4/"
"xhhj7LouIURKyTm/fzIQQhDC15OTmqa9W1o6Ojr6tr1dLBaNeLzVaj0AfaR0Xa9UKm+np09O"
"TgYGBj6ureVyOcbY7dw6g0opw+Fw8+amcn6eTqdN02SMBTV1CFVCCIVCoVar1fZHOr+nAAC1"
"JA8E6wb6Pz1Dn15/AQsQSZkYzgBNAAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
Stop = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAAAvklE"
"QVRIie3VMQ6DMAwF0G9CEUxMzAwch4NwCEbuxyXoygiBkMQd2KoUM7Cg4tFSnixZ/qH3MODq"
"ii4XHzQO9IiQpvJTIlgLY06gRFgW3/dwDkRHqHMoiqiq4L2ExjGPo+k6TBOUOkK1VnUdtS2M"
"AfMhug+bZfBeQAEkSbB9n+0/6IPeAQ2dKTO0htbi7QcjKoQ6hzx/NQ22TUgpa6ksYe1XmgCg"
"wMe3B4pYe56u64lJATBjnmX0d91n+3+OfgDGM0GplgNFhQAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
DeleteKey = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAAEXUlE"
"QVRIibWWX0hUWRzHf+ece4/3TjPjvTMOrqM+lH9KmQhEszCC2OifLRRF+LKwb8X66Eug0UOP"
"Cz22+7JIGwxmEGmTWUahkhapLQSbwQZFm6iDOubM3DPn3nvOPozT6jhKQft7u/f+zuf3O7/v"
"+f3ORf98+ADf2vA3JxaC4q8Mg9DGJeufpUSWBYryxSlhcBy0spLHXQ9VFOXxY/z2LWjal+Qo"
"CaGxGI7HgZDNoQDOwYPqyAianQVV3ZopNY0+eCBDIXfXLrDtzaGuK02THztGYzFIp/PiryPq"
"Oh0f34ax0tq6jRC81fYBgHNRWens30/v3AEorJvUNPXNG/39+98TiR/b2q5evQoAZE0GBdYg"
"xpxIRFRV0f5+qaqA0LrPqorn5oqnpn55966zq8vw+WL37nVdukQp3QoKAMiy7JYW6fHQoSG5"
"VjRCgDHfw4d/VlT81tMTvX69u7v7weBgcmXl0aNHuq5vBc3my48eRcvLyvPnMuuNEGBM+/pw"
"S0t0bOz4oUPfHz4cj8cJIe3t7WPj40KIdVCEEM4zhLAQzqlT6vS0Oj0Nug6aVjQ4iCoqUvX1"
"f01Otp48mclkAIAxVlNToyrKwsJCVrFVqBCCc845dxxHSsk5F0II2+aOk2xtxcPD7uwsfvbM"
"tizrwIHEx4/JVKq6qopzDgBSSk3TAsHgfDyelUsBAErpy5cve27eVAhZSSZTqVS4rGx+fp4Q"
"YgYCLsZFyeQPg4NzlD7dvh2mpqx0+tOnT4ZhSClXz4OUHo8nwxhCaBVq23ZtbW1HR4eu6/di"
"scdPnly5cqWzszNYUnLh/Pkk57C0FIhGeSjUdOYMwXhlefnn9nbGmMfj+Vw9m3OMcTYMzsah"
"lAZMM2CahmH4fL5gMOj3+/1+fyAUCup6eHQULlzQmpu/GxkxQqGKykpK6ceZGSU3JVzXXVhc"
"NAwjqxX+nL8Q2TLajDEhRCaT4bYtAZTbtzMNDSIUshsaXK8XDwxohlFaWjr29KmmaQBACInH"
"44lEorS0dB30c8BwONzU2GhZViQSqY5E0N27orzc2bMHGEOM8SNHUCqljI+3nj37x40bi4uL"
"Pp/PNM1bt26Vh8Nerze7fZQ3+QkhhJBMJkOLi8noqDszw0+fRozlegUDgNbbK5qaTly8qNj2"
"5cuXX7x4caevLxqNGsXFjuMUgK5Wo6hIef1amZxkbW1ICMipvNpUluXv6/u7vv6nrq5XExPb"
"d+z49dq1xsZGy7JWdSsAVVU0N0cHBjLnzoGug+sWcJif9w4NJU6ceL+0VFZSYpqmZVkoNyU2"
"tCkhkE7T+/f58ePS6y1ABADbFmVlqX37vAMDddXVXr+f5U5oIShCAED7+53mZlFejjgvQMw6"
"Mubu3GnX1cneXjfX8ptAVVUdHhaVlc7u3f+JsxnXsuy9e2VJiTIxAWvmHuTXFCG0vCwNAzYE"
"39QwRum01PW1Yubfpl9HBAAh8ogboABfR8ylkvfif/lD+Rcv7QbV/D7nwgAAAABJRU5ErkJg"
"gg==")
class TimeSlider(wx.Window):
"""
This is the Time Slider Panel.
"""
def __init__(self, parent, slidersize, sliderStartFrame, sliderEndFrame, curFrame):
wx.Window.__init__(self, parent, size = slidersize, style = wx.SUNKEN_BORDER)
self._mainDialog = wx.GetTopLevelParent(self)
self._mouseIn = False
self.points = []
self.numbers = []
self.curFrame = curFrame
self.sliderStartFrame = sliderStartFrame
self.sliderEndFrame = sliderEndFrame
self.frameNum = self.sliderEndFrame-self.sliderStartFrame+1
self.InitBuffer()
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMotion)
def InitBuffer(self):
self.w,self.h = self.GetClientSize()
self.buffer = wx.EmptyBitmap(self.w, self.h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
self.DrawTimeSlider(dc)
self.DrawNumber(dc)
self.DrawFrame(dc)
self.DrawKeys(dc)
def SetTimeSliderData(self, sliderStartFrame = 1, sliderEndFrame = 24, curFrame = 0):
self.curFrame = curFrame
self.sliderStartFrame = sliderStartFrame
self.sliderEndFrame = sliderEndFrame
self.frameNum = self.sliderEndFrame-self.sliderStartFrame+1
self.points = []
self.numbers = []
self.InitBuffer()
self.Refresh()
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self, self.buffer)
def DrawTimeSlider(self,dc):
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
self.unitWidth = self.w/float(self.frameNum)
if self.frameNum <= 20:
self.points.append(((float(0),self.h),(float(0),self.h-15)))
for i in range(1,self.frameNum):
temp = self.points[i-1][0][0]+self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(self.frameNum):
self.numbers.append(self.sliderStartFrame+i)
for i in range(self.frameNum):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 70:
self.points.append(((self.unitWidth,self.h),(self.unitWidth,self.h-15)))
for i in range(1,int((self.frameNum+1)/2)):
temp = self.points[i-1][0][0]+2*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/2+1):
self.numbers.append(self.sliderStartFrame-1+i*2)
for i in range(int((self.frameNum+1)/2)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/2):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 150:
self.points.append(((self.unitWidth*4.0,self.h),(self.unitWidth*4.0,self.h-15)))
for i in range(1,int(self.frameNum/5)):
temp = self.points[i-1][0][0]+5*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/5+1):
self.numbers.append(self.sliderStartFrame-1+i*5)
for i in range(int(self.frameNum/5)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/5):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 250:
self.points.append(((self.unitWidth*9.0,self.h),(self.unitWidth*9.0,self.h-15)))
for i in range(1,int(self.frameNum/10)):
temp = self.points[i-1][0][0]+10*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/10+1):
self.numbers.append(self.sliderStartFrame+i*10)
for i in range(int(self.frameNum/10)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/10):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 1000:
self.points.append(((self.unitWidth*49.0,self.h),(self.unitWidth*49.0,self.h-15)))
for i in range(1,int(self.frameNum/50)):
temp = self.points[i-1][0][0]+50*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/50+1):
self.numbers.append(self.sliderStartFrame-1+i*50)
for i in range(int(self.frameNum/50)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/50):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 2000:
self.points.append(((self.unitWidth*99.0,self.h),(self.unitWidth*99.0,self.h-15)))
for i in range(1,int(self.frameNum/100)):
temp = self.points[i-1][0][0]+100*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/100+1):
self.numbers.append(self.sliderStartFrame-1+i*100)
for i in range(int(self.frameNum/100)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/100):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
elif self.frameNum <= 10000:
self.points.append(((self.unitWidth*999.0,self.h),(self.unitWidth*999.0,self.h-15)))
for i in range(1,int(self.frameNum/1000)):
temp = self.points[i-1][0][0]+1000*self.unitWidth
self.points.append(((temp,self.h),(temp,self.h-15)))
for i in range(1,self.frameNum/1000+1):
self.numbers.append(self.sliderStartFrame-1+i*1000)
for i in range(int(self.frameNum/1000)):
dc.DrawLine(self.points[i][0][0], self.points[i][0][1], self.points[i][1][0], self.points[i][1][1])
for i in range(self.frameNum/1000):
st = str(self.numbers[i])
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, self.points[i][0][0]+2, 0.5)
else:
pass
def DrawNumber(self, dc):
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
i = self.curFrame-self.sliderStartFrame
st = str(self.curFrame)
tw,th = dc.GetTextExtent(st)
dc.DrawText(st, float(self.unitWidth)*float(i)+2, self.h-th-0.5)
def DrawFrame(self, dc):
i = self.curFrame-self.sliderStartFrame
pos = float(self.unitWidth)*float(i)
self.curRect = wx.Rect(pos, float(0), self.unitWidth, self.h)
oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
gray = wx.Colour(200, 200, 200)
grayPen = wx.Pen(gray)
grayBrush = wx.Brush(gray)
dc.SetPen(grayPen)
dc.SetBrush(grayBrush)
dc.SetLogicalFunction(wx.XOR)
dc.DrawRectangleRect(self.curRect)
dc.SetPen(oldPen)
dc.SetBrush(oldBrush)
dc.SetLogicalFunction(oldMode)
def DrawKeys(self, dc):
if len(self._mainDialog.keys) != 0:
for key in self._mainDialog.keys:
keyFrame = key
i = keyFrame-self.sliderStartFrame
pos = float(self.unitWidth)*float(i)
oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
dc.SetPen(wx.Pen("red"))
dc.SetBrush(wx.Brush("red"))
dc.SetLogicalFunction(wx.AND)
dc.DrawLine(pos, float(0), pos, self.h)
dc.SetPen(oldPen)
dc.SetBrush(oldBrush)
dc.SetLogicalFunction(oldMode)
else:
pass
def OnSize(self,evt):
self.InitBuffer()
def OnLeftDown(self,evt):
point = (evt.GetX(), evt.GetY())
if point[1]>= float(0) and point[1]<= (float(self.h)-2.0):
if point[0]>= float(0) and point[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
self.CaptureMouse()
self.curFrame = int(float(point[0])/self.unitWidth)+self.sliderStartFrame
self._mainDialog.curFrame = self.curFrame
self._mainDialog.curFrameSpin.SetValue(self.curFrame)
self._mainDialog.OnAnimation(self.curFrame)
self.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
def OnLeftUp(self,evt):
if self.GetCapture():
self.ReleaseMouse()
self._mouseIn = False
def OnMotion(self,evt):
self._mouseIn = False
if evt.Dragging() and evt.LeftIsDown():
point = (evt.GetX(), evt.GetY())
if point[1]>= float(0) and point[1]<= (float(self.h)-2.0):
if point[0]>= float(0) and point[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
self.curFrame = int(float(point[0])/self.unitWidth)+self.sliderStartFrame
self._mainDialog.curFrame = self.curFrame
self._mainDialog.curFrameSpin.SetValue(self.curFrame)
self._mainDialog.OnAnimation(self.curFrame)
self.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
evt.Skip()
self._mouseIn = False
class TimeRange(wx.Window):
"""
This is the Time Range Panel.
"""
def __init__(self, parent, rangesize, startFrame, endFrame, sliderStartFrame, sliderEndFrame):
wx.Window.__init__(self, parent, size = rangesize, style = wx.SUNKEN_BORDER)
self._mainDialog = wx.GetTopLevelParent(self)
self._mouseIn = False
self.startFrame = startFrame
self.endFrame = endFrame
self.sliderStartFrame = sliderStartFrame
self.sliderEndFrame = sliderEndFrame
self.frameNum = self.endFrame-self.startFrame+1
self.InitBuffer()
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMotion)
def InitBuffer(self):
self.w,self.h = self.GetClientSize()
self.buffer = wx.EmptyBitmap(self.w, self.h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
self.DrawTimeRange(dc)
def SetTimeRangeData(self, startFrame = 1, endFrame = 24, sliderStartFrame = 1, sliderEndFrame = 24):
self.startFrame = startFrame
self.endFrame = endFrame
self.sliderStartFrame = sliderStartFrame
self.sliderEndFrame = sliderEndFrame
self.frameNum = self.endFrame-self.startFrame+1
self.InitBuffer()
self.Refresh()
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self, self.buffer)
def DrawTimeRange(self,dc):
dc.SetBackground(wx.Brush(wx.Colour(150, 150, 150)))
dc.Clear()
dc.SetPen(wx.Pen(self.GetBackgroundColour()))
dc.SetBrush(wx.Brush(self.GetBackgroundColour()))
self.unitWidth = (self.w-6.0)/float(self.frameNum)
self.rangePosX = 3.0+(float(self.sliderStartFrame-self.startFrame))*self.unitWidth
self.rangePosY = 2.0
self.rangeWidth = float(self.sliderEndFrame-self.sliderStartFrame+1)*self.unitWidth
self.rangeHeight = self.h-4.0
self.curRect = wx.Rect(self.rangePosX, self.rangePosY, self.rangeWidth, self.rangeHeight)
dc.DrawRoundedRectangleRect(self.curRect, radius = 2)
def OnSize(self,evt):
self.InitBuffer()
def OnLeftDown(self,evt):
point = (evt.GetX(), evt.GetY())
self.pos = 0
if point[1]>= self.rangePosY and point[1]<= self.rangePosY+self.rangeHeight:
if point[0]>= self.rangePosX and point[0]<= self.rangePosX+self.rangeWidth:
self._mouseIn = True
if self._mouseIn:
self.CaptureMouse()
self.pos = point
def OnLeftUp(self,evt):
if self.GetCapture():
self.ReleaseMouse()
self._mouseIn = False
def OnMotion(self,evt):
self._mouseIn = False
if evt.Dragging() and evt.LeftIsDown():
newPos = (evt.GetX(), evt.GetY())
if newPos[1]>= self.rangePosY and newPos[1]<= self.rangePosY+self.rangeHeight:
if newPos[0]>= self.rangePosX and newPos[0]<= self.rangePosX+self.rangeWidth:
self._mouseIn = True
if self._mouseIn:
if newPos[0] == self.pos[0]:
evt.Skip()
self._mouseIn = False
if newPos[0] > self.pos[0]:
if float(newPos[0]-self.pos[0]) >= self.unitWidth:
if self.sliderEndFrame < self.endFrame:
self.sliderStartFrame += 1
self.sliderEndFrame += 1
self.SetTimeRangeData(self.startFrame, self.endFrame, self.sliderStartFrame, self.sliderEndFrame)
self.MainPanelUpdate()
self.pos = newPos
evt.Skip()
self._mouseIn = False
if newPos[0] < self.pos[0]:
if float(self.pos[0]-newPos[0]) >= self.unitWidth:
if self.sliderStartFrame > self.startFrame:
self.sliderStartFrame -=1
self.sliderEndFrame -=1
self.SetTimeRangeData(self.startFrame, self.endFrame, self.sliderStartFrame, self.sliderEndFrame)
self.MainPanelUpdate()
self.pos = newPos
evt.Skip()
self._mouseIn = False
evt.Skip()
self._mouseIn = False
def MainPanelUpdate(self):
self._mainDialog.sliderStartFrame = self.sliderStartFrame
self._mainDialog.sliderEndFrame = self.sliderEndFrame
self._mainDialog.timeSliderStartSpin.SetValue(self.sliderStartFrame)
self._mainDialog.timeSliderEndSpin.SetValue(self.sliderEndFrame)
self._mainDialog.timeSlider.SetTimeSliderData(self._mainDialog.sliderStartFrame, self._mainDialog.sliderEndFrame, self._mainDialog.curFrame)
class AnimControlUI(wx.Dialog):
"""
This is the Animation Control main class implementation.
"""
def __init__(self, parent, editor):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Animation Controller",
pos=wx.DefaultPosition, size=(920, 110))
self.editor = editor
self._initOver = False
self.parallel = []
if self.editor.animMgr.keyFramesInfo != []:
self.editor.animMgr.generateKeyFrames()
self.keys = self.editor.animMgr.keyFrames
self.editor.objectMgr.findActors(render)
self.editor.objectMgr.findNodes(render)
self.prePlay = False
self.play = False
self.stop = True
self.curFrame = 1
self.startFrame = 1
self.sliderStartFrame = 1
self.endFrame = 24
self.sliderEndFrame = 24
self.mainPanel1 = wx.Panel(self, -1)
self.timeSlider = TimeSlider(self.mainPanel1, wx.Size(560, 35), self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
self.curFrameSpin = wx.SpinCtrl(self.mainPanel1, -1, "",size = (70,25),min=self.startFrame, max=self.endFrame)
bmpFirstFrame = FirstFrame.GetBitmap()
bmpPreFrame = PreFrame.GetBitmap()
bmpPreKeyFrame = PreKeyFrame.GetBitmap()
self.bmpPrePlay = PrePlay.GetBitmap()
self.bmpPlay = Play.GetBitmap()
bmpNextKeyFrame = NextKeyFrame.GetBitmap()
bmpNextFrame = NextFrame.GetBitmap()
bmpLastFrame = LastFrame.GetBitmap()
bmpKey = Key.GetBitmap()
self.bmpStop = Stop.GetBitmap()
bmpDeleteKey = DeleteKey.GetBitmap()
self.buttonFirstFrame = wx.BitmapButton(self.mainPanel1, -1, bmpFirstFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonPreFrame = wx.BitmapButton(self.mainPanel1, -1, bmpPreFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonPreKeyFrame = wx.BitmapButton(self.mainPanel1, -1, bmpPreKeyFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonPrePlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpPrePlay, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonPlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpPlay, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonNextKeyFrame = wx.BitmapButton(self.mainPanel1, -1, bmpNextKeyFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonNextFrame = wx.BitmapButton(self.mainPanel1, -1, bmpNextFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonLastFrame = wx.BitmapButton(self.mainPanel1, -1, bmpLastFrame, size = (30,30),style = wx.BU_AUTODRAW)
self.mainPanel2 = wx.Panel(self, -1)
self.timeStartSpin = wx.SpinCtrl(self.mainPanel2, -1, "",size = (70,25),min=0, max=self.sliderEndFrame)
self.timeSliderStartSpin = wx.SpinCtrl(self.mainPanel2, -1, "",size = (70,25),min=self.startFrame, max=self.sliderEndFrame)
self.timeRange = TimeRange(self.mainPanel2, wx.Size(450, 25), self.startFrame, self.endFrame, self.sliderStartFrame, self.sliderEndFrame)
self.timeSliderEndSpin = wx.SpinCtrl(self.mainPanel2, -1, "",size = (70,25),min=self.sliderStartFrame, max=self.endFrame)
self.timeEndSpin = wx.SpinCtrl(self.mainPanel2, -1, "",size = (70,25),min=self.sliderStartFrame, max=10000)
self.buttonDeleteKey = wx.BitmapButton(self.mainPanel2, -1, bmpDeleteKey, size = (30,30),style = wx.BU_AUTODRAW)
self.SetProperties()
self.DoLayout()
self.Bind(wx.EVT_SPINCTRL, self.OnCurrentTime, self.curFrameSpin)
self.Bind(wx.EVT_BUTTON, self.OnFirstFrame, self.buttonFirstFrame)
self.Bind(wx.EVT_BUTTON, self.OnPreFrame, self.buttonPreFrame)
self.Bind(wx.EVT_BUTTON, self.OnPreKeyFrame, self.buttonPreKeyFrame)
self.Bind(wx.EVT_BUTTON, self.OnPrePlay, self.buttonPrePlay)
self.Bind(wx.EVT_BUTTON, self.OnPlay, self.buttonPlay)
self.Bind(wx.EVT_BUTTON, self.OnNextKeyFrame, self.buttonNextKeyFrame)
self.Bind(wx.EVT_BUTTON, self.OnNextFrame, self.buttonNextFrame)
self.Bind(wx.EVT_BUTTON, self.OnLastFrame, self.buttonLastFrame)
self.Bind(wx.EVT_SPINCTRL, self.OnTimeStartSpin, self.timeStartSpin)
self.Bind(wx.EVT_SPINCTRL, self.OnTimeSliderStartSpin, self.timeSliderStartSpin)
self.Bind(wx.EVT_SPINCTRL, self.OnTimeSliderEndSpin, self.timeSliderEndSpin)
self.Bind(wx.EVT_SPINCTRL, self.OnTimeEndSpin, self.timeEndSpin)
self.Bind(wx.EVT_BUTTON, self.OnDeleteKey, self.buttonDeleteKey)
self.Bind(wx.EVT_CLOSE, self.OnExit)
self.OnPropKey()
self.OnAnimation(self.curFrame)
self.timeUnit = float(1)/float(24)*float(1000)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self._initOver = True
def SetProperties(self):
self.curFrameSpin.SetValue(self.curFrame)
self.timeStartSpin.SetValue(self.startFrame)
self.timeSliderStartSpin.SetValue(self.sliderStartFrame)
self.timeSliderEndSpin.SetValue(self.sliderEndFrame)
self.timeEndSpin.SetValue(self.endFrame)
def DoLayout(self):
dialogSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer1 = wx.FlexGridSizer(1, 10, 0, 0)
mainSizer2 = wx.FlexGridSizer(1, 6, 0, 0)
mainSizer1.Add(self.timeSlider, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
mainSizer1.Add(self.curFrameSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 3)
mainSizer1.Add(self.buttonFirstFrame, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 3)
mainSizer1.Add(self.buttonPreFrame, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonPreKeyFrame, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonPrePlay, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonPlay, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonNextKeyFrame, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonNextFrame, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
mainSizer1.Add(self.buttonLastFrame, 0, wx.ALIGN_CENTER_VERTICAL)
mainSizer2.Add(self.timeStartSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer2.Add(self.timeSliderStartSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer2.Add(self.timeRange, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer2.Add(self.timeSliderEndSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer2.Add(self.timeEndSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer2.Add(self.buttonDeleteKey, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 3)
self.mainPanel1.SetSizerAndFit(mainSizer1)
self.mainPanel2.SetSizerAndFit(mainSizer2)
dialogSizer.Add(self.mainPanel1, 1, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 5)
dialogSizer.Add(self.mainPanel2, 1, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 7)
self.SetSizer(dialogSizer)
self.Layout()
self.dialogSizer = dialogSizer
def OnCurrentTime(self, evt):
self.curFrame = evt.GetInt()
self.timeSlider.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
self.OnAnimation(self.curFrame)
def OnControl(self):
self.curFrameSpin.SetValue(self.curFrame)
self.timeSlider.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
self.OnAnimation(self.curFrame)
def OnFirstFrame(self,evt):
self.curFrame = self.sliderStartFrame
self.OnControl()
def OnPreFrame(self,evt):
if self.curFrame-1 >= self.startFrame:
self.curFrame -= 1
self.OnControl()
else:
evt.Skip()
def sortKey(self):
for i in range(0, len(self.keys)-1):
for j in range(i+1, len(self.keys)):
if self.keys[i]>self.keys[j]:
temp = self.keys[i]
self.keys[i] = self.keys[j]
self.keys[j] = temp
def OnPreKeyFrame(self,evt):
self.sortKey()
if self.curFrame <= self.keys[0] or self.curFrame > self.keys[len(self.keys)-1]:
self.curFrame = self.keys[len(self.keys)-1]
else:
for i in range(1, len(self.keys)):
if self.curFrame <= self.keys[i] and self.curFrame > self.keys[i-1]:
self.curFrame = self.keys[i-1]
break
self.OnControl()
def OnTimer(self,evt):
if self.prePlay == True and self.stop == False and self.play == False:
if self.curFrame-1>=self.sliderStartFrame:
self.curFrame -= 1
self.OnControl()
elif self.curFrame == self.sliderStartFrame:
self.curFrame = self.sliderEndFrame
self.OnControl()
if self.play == True and self.stop == False and self.prePlay == False:
if self.curFrame+1<=self.sliderEndFrame:
self.curFrame += 1
self.OnControl()
elif self.curFrame == self.sliderEndFrame:
self.curFrame = self.sliderStartFrame
self.OnControl()
def OnPrePlay(self,evt):
if self.prePlay == False and self.stop == True and self.play == False:
self.buttonPrePlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpStop, size = (30,30),style = wx.BU_AUTODRAW)
self.DoLayout()
self.prePlay = True
self.stop = False
self.timer.Start(self.timeUnit)
evt.Skip()
elif self.prePlay == True and self.stop == False and self.play == False:
self.buttonPrePlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpPrePlay, size = (30,30),style = wx.BU_AUTODRAW)
self.DoLayout()
self.prePlay = False
self.stop = True
self.timer.Stop()
evt.Skip()
else:
evt.Skip()
def OnPlay(self,evt):
if self.play == False and self.stop == True and self.prePlay == False:
self.buttonPlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpStop, size = (30,30),style = wx.BU_AUTODRAW)
self.DoLayout()
self.play = True
self.stop = False
self.timer.Start(self.timeUnit)
evt.Skip()
elif self.play == True and self.stop == False and self.prePlay == False:
self.buttonPlay = wx.BitmapButton(self.mainPanel1, -1, self.bmpPlay, size = (30,30),style = wx.BU_AUTODRAW)
self.DoLayout()
self.play = False
self.stop = True
self.timer.Stop()
evt.Skip()
else:
evt.Skip()
def OnNextKeyFrame(self,evt):
self.sortKey()
if self.curFrame < self.keys[0] or self.curFrame >= self.keys[len(self.keys)-1]:
self.curFrame = self.keys[0]
else:
for i in range(0, len(self.keys)-1):
if self.curFrame >= self.keys[i] and self.curFrame < self.keys[i+1]:
self.curFrame = self.keys[i+1]
break
self.OnControl()
def OnNextFrame(self,evt):
if self.curFrame+1 <= self.endFrame:
self.curFrame += 1
self.OnControl()
else:
evt.Skip()
def OnLastFrame(self,evt):
self.curFrame = self.sliderEndFrame
self.OnControl()
def OnTime(self):
preFrame = self.curFrame
self.curFrameSpin.SetRange(self.startFrame,self.endFrame)
self.curFrame = preFrame
self.timeSlider.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
self.timeRange.SetTimeRangeData(self.startFrame, self.endFrame, self.sliderStartFrame, self.sliderEndFrame)
self.parallel = self.editor.animMgr.createParallel(self.startFrame,self.endFrame)
def OnTimeStartSpin(self,evt):
self.startFrame = evt.GetInt()
self.timeSliderStartSpin.SetRange(self.startFrame, self.sliderEndFrame)
if self.startFrame >= self.sliderStartFrame:
self.sliderStartFrame = self.startFrame
self.timeSliderStartSpin.SetValue(self.sliderStartFrame)
self.OnTime()
else:
self.OnTime()
def OnTimeSliderStartSpin(self,evt):
self.sliderStartFrame = evt.GetInt()
self.timeEndSpin.SetRange(self.sliderStartFrame, 10000)
self.OnTime()
def OnTimeSliderEndSpin(self,evt):
self.sliderEndFrame = evt.GetInt()
self.timeStartSpin.SetRange(0, self.sliderEndFrame)
self.OnTime()
def OnTimeEndSpin(self,evt):
self.endFrame = evt.GetInt()
self.timeSliderEndSpin.SetRange(self.sliderStartFrame, self.endFrame)
if self.endFrame <= self.sliderEndFrame:
self.sliderEndFrame = self.endFrame
self.timeSliderEndSpin.SetValue(self.sliderEndFrame)
self.OnTime()
else:
self.OnTime()
def OnDeleteKey(self,evt):
for i in range(0,len(self.keys)):
if self.curFrame == self.keys[i]:
del self.keys[i]
break
for j in self.editor.animMgr.keyFramesInfo.keys():
for k in range(0,len(self.editor.animMgr.keyFramesInfo[j])):
if self.curFrame == self.editor.animMgr.keyFramesInfo[j][k][0]:
del self.editor.animMgr.keyFramesInfo[j][k]
break
for l in self.editor.animMgr.keyFramesInfo.keys():
if len(self.editor.animMgr.keyFramesInfo[l]) == 0:
del self.editor.animMgr.keyFramesInfo[l]
self.OnPropKey()
self.OnAnimation(self.curFrame)
def OnPropKey(self):
self.parallel = self.editor.animMgr.createParallel(self.startFrame, self.endFrame)
self.timeSlider.SetTimeSliderData(self.sliderStartFrame, self.sliderEndFrame, self.curFrame)
def OnAnimation(self, curFrame):
time = float(curFrame-1)/float(24)
self.parallel.setT(time)
if self.editor.GRAPH_EDITOR == True:
self.editor.ui.graphEditorUI.curFrameChange()
def OnExit(self,evt):
for actor in self.editor.objectMgr.Actor:
actorAnim = os.path.basename(actor[OG.OBJ_ANIM])
actor[OG.OBJ_NP].loop(actorAnim)
self.parallel = None
self.Destroy()
self.editor.ui.editAnimMenuItem.Check(False)
self.editor.mode = self.editor.BASE_MODE

View File

@ -0,0 +1,53 @@
"""
This contains data structure and constants related with animation handling.
"""
# index for keyFramesInfo list structure
# data strucrure: {[nodeUID, propertyName] : [frameNum,
# value,
# [inSlopeX, inSlopeY],
# [outSlopeX, outSlopeY]]}
UID = 0
PROP_NAME = 1
FRAME = 0
VALUE = 1
INSLOPE = 2
OUTSLOPE = 3
# index for curveAnimation list structure
# data strucrure: {[nodeUID, curveUID] : [nodeUID,
# curveUID,
# time]}
NODE = 0
CURVE = 1
NODE = 0
CURVE = 1
TIME = 2
# index for animation curve generation information list structure(self.X, self.Y, self.Z in GraphEditorUI)
# data structur: [key,
# i ,
# [[keyFrameX, keyFrameY], keyFrame_select],
# [[inTangentX, inTangentY], inTangent_select],
# [[outTangentX, outTangentY], outTangent_select],
# [inSlopeX, inSlopeY],
# [outSlopeX, outSlopeY]]
KEY = 0
I = 1
KEYFRAME = 2
IN_TANGENT = 3
OUT_TANGENT = 4
IN_SLOPE = 5
OUT_SLOPE = 6
LOCAL_VALUE = 0
SELECT = 1
#index for coordinate
X = 0
Y = 1
Z = 2

View File

@ -0,0 +1,10 @@
"""
Defines AnimMgr
"""
from AnimMgrBase import *
class AnimMgr(AnimMgrBase):
""" Animation will create, manage, update animations in the scene """
def __init__(self, editor):
AnimMgrBase.__init__(self, editor)

View File

@ -0,0 +1,367 @@
"""
Defines AnimMgrBase
"""
import os, wx, math
from direct.interval.IntervalGlobal import *
from panda3d.core import VBase3,VBase4
import ObjectGlobals as OG
import AnimGlobals as AG
class AnimMgrBase:
""" AnimMgr will create, manage, update animations in the scene """
def __init__(self, editor):
self.editor = editor
self.graphEditorCounter = 0
self.keyFramesInfo = {}
self.curveAnimation = {}
#normal properties
self.lerpFuncs={
'H' : self.lerpFuncH,
'P' : self.lerpFuncP,
'R' : self.lerpFuncR,
'SX' : self.lerpFuncSX,
'SY' : self.lerpFuncSY,
'SZ' : self.lerpFuncSZ,
'CR' : self.lerpFuncCR,
'CG' : self.lerpFuncCG,
'CB' : self.lerpFuncCB,
'CA' : self.lerpFuncCA
}
#Properties which has animation curves
self.curveLerpFuncs={
'X' : [ self.lerpFuncX, self.lerpCurveFuncX ],
'Y' : [ self.lerpFuncY, self.lerpCurveFuncY ],
'Z' : [ self.lerpFuncZ, self.lerpCurveFuncZ ]
}
def reset(self):
self.keyFramesInfo = {}
self.curveAnimation = {}
def generateKeyFrames(self):
#generate keyFrame list
self.keyFrames = []
for property in self.keyFramesInfo.keys():
for frameInfo in self.keyFramesInfo[property]:
frame = frameInfo[AG.FRAME]
exist = False
for keyFrame in self.keyFrames:
if frame == keyFrame:
exist = True
break
if exist == False:
self.keyFrames.append(frame)
def generateSlope(self, list):
#generate handler slope of every keyframe for animation curve
listLen = len(list)
if listLen == 2:
slope =[float(list[1][AG.FRAME]-list[0][AG.FRAME]),(float(list[1][AG.VALUE])-float(list[0][AG.VALUE]))]
list[0][AG.INSLOPE] = slope
list[1][AG.INSLOPE] = slope
list[0][AG.OUTSLOPE] = list[0][AG.INSLOPE]
list[1][AG.OUTSLOPE] = list[1][AG.INSLOPE]
return
if listLen >= 3:
list[0][AG.INSLOPE] = [float(list[1][AG.FRAME] - list[0][AG.FRAME]),(float(list[1][AG.VALUE]) - float(list[0][AG.VALUE]))]
list[0][AG.OUTSLOPE] = list[0][AG.INSLOPE]
for i in range(1, listLen-1):
list[i][AG.INSLOPE] = [float(list[i+1][AG.FRAME] - list[i-1][AG.FRAME]),(float(list[i+1][AG.VALUE]) - float(list[i-1][AG.VALUE]))]
list[i][AG.OUTSLOPE] = list[i][AG.INSLOPE]
list[listLen-1][AG.INSLOPE] = [float(list[listLen-1][AG.FRAME] - list[listLen-2][AG.FRAME]),(float(list[listLen-1][AG.VALUE]) - float(list[listLen-2][AG.VALUE]))]
list[listLen-1][AG.OUTSLOPE] = list[listLen-1][AG.INSLOPE]
return
def removeAnimInfo(self, uid):
for property in self.keyFramesInfo.keys():
if property[AG.UID] == uid:
del self.keyFramesInfo[property]
self.generateKeyFrames()
if self.editor.mode == self.editor.ANIM_MODE:
self.editor.ui.animUI.OnPropKey()
def singleCurveAnimation(self, nodePath, curve, time):
rope = curve[OG.OBJ_NP]
self.points = rope.getPoints(time)
self.hprs = []
temp = render.attachNewNode("temp")
temp.setHpr(0,0,0)
for i in range(len(self.points)-1):
temp.setPos(self.points[i])
temp.lookAt(self.points[i+1])
hpr = temp.getHpr()
## self.hprs.append(hpr)
self.hprs.append(VBase3(hpr[0]+180,hpr[1],hpr[2]))
self.hprs.append(self.hprs[len(self.points)-2])
curveSequenceName = str(nodePath[OG.OBJ_UID])+' '+str(curve[OG.OBJ_UID])+' '+str(time)
self.curveSequence = Sequence(name = curveSequenceName)
for i in range(len(self.points)-1):
myLerp = LerpPosHprInterval(nodePath[OG.OBJ_NP], float(1)/float(24), self.points[i+1], self.hprs[i+1], self.points[i], self.hprs[i])
self.curveSequence.append(myLerp)
return self.curveSequence
def createParallel(self, startFrame, endFrame):
self.parallel = []
self.parallel = Parallel(name="Current Parallel")
self.createCurveAnimation(self.parallel)
self.createActorAnimation(self.parallel, startFrame, endFrame)
self.createKeyFrameAnimation(self.parallel, startFrame, endFrame)
self.createCurveKeyFrameAnimation(self.parallel, startFrame, endFrame)
return self.parallel
def createCurveAnimation(self, parallel):
for key in self.curveAnimation:
curveInfo = self.curveAnimation[key]
nodePath = self.editor.objectMgr.findObjectById(curveInfo[AG.NODE])
curve = self.editor.objectMgr.findObjectById(curveInfo[AG.CURVE])
time = curveInfo[AG.TIME]
sequence = self.singleCurveAnimation(nodePath, curve, time)
parallel.append(sequence)
def createActorAnimation(self, parallel, startFrame, endFrame):
self.editor.objectMgr.findActors(render)
for actor in self.editor.objectMgr.Actor:
actorAnim = os.path.basename(actor[OG.OBJ_ANIM])
myInterval = ActorInterval(actor[OG.OBJ_NP], actorAnim, loop=1, duration = float(endFrame-startFrame+1)/float(24))
parallel.append(myInterval)
def createKeyFrameAnimation(self, parallel, startFrame, endFrame):
#generate key frame animation for normal property
self.editor.objectMgr.findNodes(render)
for node in self.editor.objectMgr.Nodes:
for property in self.keyFramesInfo.keys():
if property[AG.UID] == node[OG.OBJ_UID] and property[AG.PROP_NAME] != 'X' and property[AG.PROP_NAME] != 'Y' and property[AG.PROP_NAME] != 'Z':
mysequence = Sequence(name = node[OG.OBJ_UID])
keyFramesInfo = self.keyFramesInfo[property]
if len(keyFramesInfo) == 1:
myLerp = LerpFunc(self.lerpFuncs[property[AG.PROP_NAME]],fromData=float(keyFramesInfo[0][AG.VALUE]),toData=float(keyFramesInfo[0][AG.VALUE]),duration = float(endFrame-startFrame)/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
parallel.append(mysequence)
if len(keyFramesInfo) != 1:
myLerp = LerpFunc(self.lerpFuncs[property[AG.PROP_NAME]],fromData=float(keyFramesInfo[0][AG.VALUE]),toData=float(keyFramesInfo[0][AG.VALUE]),duration = float(keyFramesInfo[0][AG.FRAME]-startFrame)/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
for key in range(0,len(keyFramesInfo)-1):
myLerp = LerpFunc(self.lerpFuncs[property[AG.PROP_NAME]],fromData=float(keyFramesInfo[key][AG.VALUE]),toData=float(keyFramesInfo[key+1][AG.VALUE]),duration = float(keyFramesInfo[key+1][AG.FRAME]-keyFramesInfo[key][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
myLerp = LerpFunc(self.lerpFuncs[property[AG.PROP_NAME]],fromData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),toData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),duration = float(endFrame-keyFramesInfo[len(keyFramesInfo)-1][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
parallel.append(mysequence)
def createCurveKeyFrameAnimation(self, parallel, startFrame, endFrame):
#generate key frame animation for the property which is controled by animation curve
self.editor.objectMgr.findNodes(render)
for node in self.editor.objectMgr.Nodes:
for property in self.keyFramesInfo.keys():
if property[AG.UID] == node[OG.OBJ_UID]:
if property[AG.PROP_NAME] == 'X' or property[AG.PROP_NAME] == 'Y' or property[AG.PROP_NAME] == 'Z':
mysequence = Sequence(name = node[OG.OBJ_UID])
keyFramesInfo = self.keyFramesInfo[property]
if len(keyFramesInfo) == 1:
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[0][AG.VALUE]),toData=float(keyFramesInfo[0][AG.VALUE]),duration = float(endFrame-startFrame)/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
parallel.append(mysequence)
if len(keyFramesInfo) == 2:
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[0][AG.VALUE]),toData=float(keyFramesInfo[0][AG.VALUE]),duration = float(keyFramesInfo[0][AG.FRAME]-startFrame)/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
for key in range(0,len(keyFramesInfo)-1):
self.keyFrameInfoForSingleLerp = keyFramesInfo
self.keyInfoForSingleLerp = key
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[key][AG.VALUE]),toData=float(keyFramesInfo[key+1][AG.VALUE]),duration = float(keyFramesInfo[key+1][AG.FRAME]-keyFramesInfo[key][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),toData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),duration = float(endFrame-keyFramesInfo[len(keyFramesInfo)-1][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
parallel.append(mysequence)
if len(keyFramesInfo) > 2:
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[0][AG.VALUE]),toData=float(keyFramesInfo[0][1]),duration = float(keyFramesInfo[0][AG.FRAME]-startFrame)/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
for key in range(0,len(keyFramesInfo)-1):
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][1],fromData=float(keyFramesInfo[key][AG.FRAME]),toData=float(keyFramesInfo[key+1][AG.FRAME]),duration = float(keyFramesInfo[key+1][AG.FRAME]-keyFramesInfo[key][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [[node[OG.OBJ_NP], keyFramesInfo, key]])
mysequence.append(myLerp)
myLerp = LerpFunc(self.curveLerpFuncs[property[AG.PROP_NAME]][0],fromData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),toData=float(keyFramesInfo[len(keyFramesInfo)-1][AG.VALUE]),duration = float(endFrame-keyFramesInfo[len(keyFramesInfo)-1][AG.FRAME])/float(24),blendType = 'noBlend',extraArgs = [node[OG.OBJ_NP]])
mysequence.append(myLerp)
parallel.append(mysequence)
def getPos(self, x, list, i):
#get the value from animation curve
x1 = float(list[i][AG.FRAME])
y1 = float(list[i][AG.VALUE])
x4 = float(list[i+1][AG.FRAME])
y4 = float(list[i+1][AG.VALUE])
t1x = list[i][AG.OUTSLOPE][0]
t1y = list[i][AG.OUTSLOPE][1]
t2x = list[i+1][AG.INSLOPE][0]
t2y = list[i+1][AG.INSLOPE][1]
x2 = x1 + (x4 - x1) / float(3)
scale1 = (x2 - x1) / t1x
y2 = y1 + t1y * scale1
x3 = x4 - (x4 - x1) / float(3)
scale2 = (x4 - x3) / t2x
y3 = y4 - t2y * scale2
ax = - float(1) * x1 + float(3) * x2 - float(3) * x3 + float(1) * x4
bx = float(3) * x1 - float(6) * x2 + float(3) * x3 + float(0) * x4
cx = - float(3) * x1 + float(3) * x2 + float(0) * x3 + float(0) * x4
dx = float(1) * x1 + float(0) * x2 - float(0) * x3 + float(0) * x4
ay = - float(1) * y1 + float(3) * y2 - float(3) * y3 + float(1) * y4
by = float(3) * y1 - float(6) * y2 + float(3) * y3 + float(0) * y4
cy = - float(3) * y1 + float(3) * y2 + float(0) * y3 + float(0) * y4
dy = float(1) * y1 + float(0) * y2 - float(0) * y3 + float(0) * y4
if ax == 0 and bx == 0 and cx == 0:
return 0
if ax == 0 and bx == 0 and cx != 0:
a = cx
b = dx-x
t = -b/a
y = ay * t*t*t + by * t*t + cy * t + dy
return y
if ax == 0 and bx!= 0:
a=bx
b=cx
c=dx-x
t=(-b+math.sqrt(b**2-4.0*a*c))/2*a
if t>=0 and t<=1:
y = ay * t*t*t + by * t*t + cy * t + dy
return y
else:
t=(-b-math.sqrt(b**2-4.0*a*c))/2*a
y = ay * t*t*t + by * t*t + cy * t + dy
return y
if ax != 0:
a = ax
b = bx
c = cx
d = dx - float(x)
t = self.calculateT(a, b, c, d, x)
y = ay * t*t*t + by * t*t + cy * t + dy
return y
def calculateT(self, a, b, c, d, x):
#Newton EQUATION
t = float(1)
t2 = t
t -= (a*t*t*t+b*t*t+c*t+d)/(float(3)*a*t*t+float(2)*b*t+c)
if abs(t-t2) <= 0.000001:
return t
else:
while abs(t - t2) > 0.000001:
t2 = t
t -= (a*t*t*t+b*t*t+c*t+d)/(float(3)*a*t*t+float(2)*b*t+c)
return t
def lerpFuncX(self,pos,np):
np.setX(pos)
def lerpFuncY(self,pos,np):
np.setY(pos)
def lerpFuncZ(self,pos,np):
np.setZ(pos)
def lerpCurveFuncX(self,t,extraArgs):
np = extraArgs[0]
pos = self.getPos(t, extraArgs[1], extraArgs[2])
np.setX(pos)
def lerpCurveFuncY(self,t,extraArgs):
np = extraArgs[0]
pos = self.getPos(t, extraArgs[1], extraArgs[2])
np.setY(pos)
def lerpCurveFuncZ(self,t,extraArgs):
np = extraArgs[0]
pos = self.getPos(t, extraArgs[1], extraArgs[2])
np.setZ(pos)
def lerpFuncH(self,angle,np):
np.setH(angle)
def lerpFuncP(self,angle,np):
np.setP(angle)
def lerpFuncR(self,angle,np):
np.setR(angle)
def lerpFuncSX(self,scale,np):
np.setSx(scale)
def lerpFuncSY(self,scale,np):
np.setSy(scale)
def lerpFuncSZ(self,scale,np):
np.setSz(scale)
def lerpFuncCR(self,R,np):
obj = self.editor.objectMgr.findObjectByNodePath(np)
r = obj[OG.OBJ_RGBA][0]
g = obj[OG.OBJ_RGBA][1]
b = obj[OG.OBJ_RGBA][2]
a = obj[OG.OBJ_RGBA][3]
self.colorUpdate(R,g,b,a,np)
def lerpFuncCG(self,G,np):
obj = self.editor.objectMgr.findObjectByNodePath(np)
r = obj[OG.OBJ_RGBA][0]
g = obj[OG.OBJ_RGBA][1]
b = obj[OG.OBJ_RGBA][2]
a = obj[OG.OBJ_RGBA][3]
self.colorUpdate(r,G,b,a,np)
def lerpFuncCB(self,B,np):
obj = self.editor.objectMgr.findObjectByNodePath(np)
r = obj[OG.OBJ_RGBA][0]
g = obj[OG.OBJ_RGBA][1]
b = obj[OG.OBJ_RGBA][2]
a = obj[OG.OBJ_RGBA][3]
self.colorUpdate(r,g,B,a,np)
def lerpFuncCA(self,A,np):
obj = self.editor.objectMgr.findObjectByNodePath(np)
r = obj[OG.OBJ_RGBA][0]
g = obj[OG.OBJ_RGBA][1]
b = obj[OG.OBJ_RGBA][2]
a = obj[OG.OBJ_RGBA][3]
self.colorUpdate(r,g,b,A,np)
def colorUpdate(self, r, g, b, a, np):
if base.direct.selected.last == None:
self.editor.objectMgr.updateObjectColor(r, g, b, a, np)
elif self.editor.objectMgr.findObjectByNodePath(np) == self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last):
self.editor.ui.objectPropertyUI.propCR.setValue(r)
self.editor.ui.objectPropertyUI.propCG.setValue(g)
self.editor.ui.objectPropertyUI.propCB.setValue(b)
self.editor.ui.objectPropertyUI.propCA.setValue(a)
self.editor.objectMgr.updateObjectColor(r, g, b, a, np)
else:
self.editor.objectMgr.updateObjectColor(r, g, b, a, np)

View File

@ -0,0 +1,159 @@
"""
This is the GUI for the Curve Animation
"""
import os, wx, time
from direct.interval.IntervalGlobal import *
from direct.actor.Actor import *
from direct.showutil.Rope import Rope
import ObjectGlobals as OG
class CurveAnimUI(wx.Dialog):
"""
This is the Curve Animation Panel implementation.
"""
def __init__(self, parent, editor):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Curve Animation",
pos=wx.DefaultPosition, size=(430, 140))
self.editor = editor
self.nodePath = None
self.curve = None
self.mainPanel = wx.Panel(self, -1)
self.chooseNode = wx.StaticText( self.mainPanel, -1, "Choose NodePath:")
self.chooseNodeTxt = wx.TextCtrl( self.mainPanel, -1, "")
self.chooseNodeButton = wx.Button( self.mainPanel, -1, "Choose..")
self.chooseCurve = wx.StaticText( self.mainPanel, -1, "Choose attch Curve:")
self.chooseCurveTxt = wx.TextCtrl( self.mainPanel, -1, "")
self.chooseCurveButton = wx.Button( self.mainPanel, -1, "Choose..")
self.duritionTime = wx.StaticText( self.mainPanel, -1, "Durition(Frame):")
self.duritionTimeSpin = wx.SpinCtrl( self.mainPanel, -1, "",size = (70,25), min=24, max=10000)
self.createAnimButton = wx.Button( self.mainPanel, -1, "Creat")
self.saveAnimButton = wx.Button( self.mainPanel, -1, "Save Animation")
self.SetProperties()
self.DoLayout()
self.Bind(wx.EVT_BUTTON, self.OnChooseNode, self.chooseNodeButton)
self.Bind(wx.EVT_BUTTON, self.OnChooseCurve, self.chooseCurveButton)
self.Bind(wx.EVT_BUTTON, self.OnCreateAnim, self.createAnimButton)
self.Bind(wx.EVT_BUTTON, self.OnSaveAnim, self.saveAnimButton)
self.Bind(wx.EVT_CLOSE, self.OnExit)
def SetProperties(self):
self.duritionTimeSpin.SetValue(24)
self.chooseNodeTxt.SetMinSize((200,21))
self.chooseCurveTxt.SetMinSize((200,21))
self.saveAnimButton.SetToolTipString("Save the animation to the global animation control")
def DoLayout(self):
dialogSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer = wx.FlexGridSizer(4, 3, 0, 0)
mainSizer.Add(self.chooseNode, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
mainSizer.Add(self.chooseNodeTxt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.chooseNodeButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.chooseCurve, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
mainSizer.Add(self.chooseCurveTxt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.chooseCurveButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.duritionTime, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
mainSizer.Add(self.duritionTimeSpin, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.createAnimButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
mainSizer.Add(self.saveAnimButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
self.mainPanel.SetSizerAndFit(mainSizer)
dialogSizer.Add(self.mainPanel, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.SetSizer(dialogSizer)
self.Layout()
def OnChooseNode(self, evt):
if base.direct.selected.last == None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'):
dlg = wx.MessageDialog(None, 'Please select an object.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
else:
obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
if obj[OG.OBJ_DEF].name == '__Curve__':
dlg = wx.MessageDialog(None, 'Please select an object, not a curve.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
else:
self.nodePath = obj
self.chooseNodeTxt.SetValue(str(self.nodePath[OG.OBJ_UID]))
def OnChooseCurve(self, evt):
if base.direct.selected.last == None or base.direct.selected.last.hasTag('Controller') or not base.direct.selected.last.hasTag('OBJRoot'):
dlg = wx.MessageDialog(None, 'Please select a curve.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
else:
obj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
if obj[OG.OBJ_DEF].name != '__Curve__':
dlg = wx.MessageDialog(None, 'Please select a curve, not an object.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
elif obj[OG.OBJ_DEF].name == '__Curve__':
self.curve = obj
self.chooseCurveTxt.SetValue(str(self.curve[OG.OBJ_UID]))
def OnCreateAnim(self, evt):
self.time = self.duritionTimeSpin.GetValue()
if self.nodePath == None or self.curve == None:
dlg = wx.MessageDialog(None, 'Please select an object and a curve first.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
else:
self.curveSequence = self.editor.animMgr.singleCurveAnimation(self.nodePath, self.curve, self.time)
self.curveSequence.start()
def OnSaveAnim(self,evt):
if not self.curveSequence:
dlg = wx.MessageDialog(None, 'Please create a animation first.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
else:
if self.editor.animMgr.curveAnimation == {}:
self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID])] = (self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID],self.time)
self.editor.updateStatusReadout('Sucessfully saved to global animation list')
return
hasKey = False
for key in self.editor.animMgr.curveAnimation.keys():
if key == (self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID]):
dlg = wx.MessageDialog(None, 'Already have the animation for this object attach to this curve.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
hasKey = True
return
elif self.nodePath[OG.OBJ_UID] == key[0]:
dlg = wx.MessageDialog(None, 'This object is already attached to a curve.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
hasKey = True
return
if hasKey == False and self.editor.animMgr.curveAnimation != {}:
self.editor.animMgr.curveAnimation[(self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID])] = (self.nodePath[OG.OBJ_UID],self.curve[OG.OBJ_UID],self.time)
self.editor.updateStatusReadout('Sucessfully saved to global animation list')
def OnExit(self,evt):
self.Destroy()
self.editor.ui.curveAnimMenuItem.Check(False)

View File

@ -19,12 +19,15 @@ class FileMgr:
f.write("from pandac.PandaModules import *\n")
f.write("\nif hasattr(base, 'le'):\n")
f.write(" objectMgr = base.le.objectMgr\n")
f.write(" animMgr = base.le.animMgr\n")
f.write(" ui = base.le.ui\n")
f.write(" ui.sceneGraphUI.reset()\n\n")
f.write("else:\n")
f.write(" objectMgr = base.objectMgr\n")
f.write("# temporary place holder for nodepath\n")
f.write("objects = {}\n")
f.write("animMgr.keyFramesInfo = "+str(self.editor.animMgr.keyFramesInfo)+"\n")
f.write("animMgr.curveAnimation = "+str(self.editor.animMgr.curveAnimation)+"\n")
saveData = self.editor.objectMgr.getSaveData()
for data in saveData:
f.write(data)

View File

@ -0,0 +1,918 @@
"""
Defines Graph Editor
"""
import os,wx
import math
import cPickle as pickle
from PaletteTreeCtrl import *
import ObjectGlobals as OG
import AnimGlobals as AG
from wx.lib.embeddedimage import PyEmbeddedImage
property = [
"translateX",
"translateY",
"translateZ"
]
#----------------------------------------------------------------------
ZoomIn = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACgklE"
"QVRIid3VW0vjQBQA4DlJMziZlCKCSB/9Bf4a3wRtNU6SHyXK6pay2nVbQbasskXFO15SqmwL"
"LtYnn7Zg20zSyT50wZikXsCHxXk9Z74ZZuacgebtLXrvIb27+PFQjDEADIoqiiLL8htQAMAY"
"Hx4dPTw8SHEuIaRWqzWbzUQi8SoUAIaGhgqFgn15SSn1Iwmqqh4fH5c2NpLJpO8/xhORzEeR"
"EJLL5VqtViaT8TxPCBFMoJTu7e1tb28zxpLJpOu6L6D9PS6vrHQ6nWw267puVNzZ2alUKqZh"
"UE0LivFoX/y0vOxynpmZ4ZxHxZ+Vyu7urmmaqqqGxBhUkiSM8eLiIgDMTE87EVHTtB9bW4cH"
"B5ZpEkKiYhjt3/XCwoKiKFNTU47jRPf4vVw+PTmxLAtjHCs+QQEAAJaWljRNm5yc7Ha7wQtF"
"CGGMy+WybduWZSmK4nlerIiCTwoAOOfX19cTExMSgPDDT0iSJNu2x8fHU6nUM+ITVAhBCLFM"
"83MuV63VKCGhVM65ruv1RqNYLFJKX4UihFzXTafTc7Oz+XzerlZVVQ1GhRCyLJuGcXV1VSqV"
"QtGBKEKo6zhjY2Pzur66tnZxcRGa2ev1AMA0zXqj8W3wfmPK1HGc0dFRNj//dX397Ows6iKE"
"DMZ+39wUCgVKabTXxNe+4zgjIyMGY8VS6eT0NOr6vs8Yu7u7+7K6SggJuQMbCud8eHjYYGxz"
"c3N/f19RlJDb6/V0Xb+/v8/n829ofZzzVCqlz82dn5//abUk6UmyEEIIkc1k2u32r3o9uCq8"
"+PHJsuz7vud5IfTffABZljnnwejLnb9/grEiQih2vVd9J36kup4fH+w3/S/QvwejQg8ibHgo"
"AAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
ZoomOut = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACmUlE"
"QVRIieXVz0sbQRQH8NmdH8smh3jwEIIlB+tNEW1NVps0WxPBv0BQXKQx4N2/xR2xTYQ9iIHc"
"/A+shyqevHiQVBGLeqgoxM1kNjHTQ8DayWb14KX0Hfe9+fDd4bGr/Ly4AK9d6quL/y6qKIqm"
"aQHThBBVfT7HnwlFUTjn3/f3MUKKoviMqurh4WG9XkcIvRQVQoRCodPT0+1yWdO0bhchxD2v"
"WCxyzjHGL0IBAA8PD9biIgDAcRxN06Q39Tzvk2kahmHbNmMswP3rmBCi0WhYlkUI2dzcxBhL"
"ruu6mUwmnU6v2bbrur1c+dY77sLCQjgcLpVKGKFuN5VKmaZpU1qr1Qghz6OP7vz8fF9f39di"
"Efq5H6amcrkcpfTu7q7b9d8PIQRjbG5urr+//8vGBoSw200mErOzs3R9/fb2VnLh6uqqrwsA"
"aLVao6OjV9fX3/b2RkZGJLfZbMbj8UgkUqlU3g4NhcNhIURQ0k612+12u/1ufPxHtcoY6157"
"z/OGh4fv7++vLi8hhI/Pg9ZY1/Xz83PHcVZWViKRSLPZfNpFCHmeRynNZrNjY2ONRuOx1TOp"
"rutnZ2eO41iWNTg4KIkYY875mm2/n5iYnp5+KvZMqut6tVrd2tpaWlqKx+OMMUmsM0YpnZqc"
"NE3TdV3puA+q6/rJycl2ufw5n38zMCClwBjXXdem9GMmk06lukUfNBQKHR8fVyqVwvJyLBaT"
"REJIrVbr3KNhGL6ijGKMj46OdnZ2CoVCNBqVRAjhr5ubUqmUm5kxksleIpA+fYyxg4ODfD4f"
"jUY559IohHB3dzebzSYTiQARAKA8/fEJIVRVhRC2Wi3faSEEIUTahKCknbAAgF4iAEBV1WdF"
"Ge1kCZgO7vZEX6X+c/Q3Qy8zmmCLWqIAAAAASUVORK5CYII=")
#----------------------------------------------------------------------
OneTangent = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACKUlE"
"QVRIia2Wz2saURDH5/3Yt6aVsE3SomArGO0phxCSU6A2EFgSklP+qPwrXkOQkBCoaG8eQrBQ"
"KRYVU1tabUij3V1337weAtZI1FX3e9qF2c/OzJv9zpKbRgMGRAhRSsF8oo9uOCeUMk0LDEo1"
"rVUuF46Pv2SzhDEgJBhoLZer5/OViwu32yWUjnlsvHj/SrluPJ222m3GORMC5ugsGTwoyjkT"
"4nuxeFetvj06ko4zG/RRjeh5rmVFNjeZrt8UCnxhIQAoAIBSnm0n9vb+1Gq/y2Wm60FAAUAp"
"UGr18LCRz9vtNuH8iZipoQAopW4Yb3Z2vmazgDjtJIyMlo7zIpUyksnq2RkTIhgoAHiWFdve"
"RsTmx4IuNP/ZToiUvV7CNNt3natb61b57cKEMIXIOeu+N0uof5IaEl8f7+R3K1SG8sKc0FqF"
"oPTjCZOhEiDF0Vyk8da3+occC4UCgAKAAhBe73X6Xa/T+VEs8klcv0eKCtD1kgcHP6+v7xsN"
"OtZzp5hqhUh1PbG/Xz0/l5ZFGAsACgDous+j0cjWVuX0lI428qmdWNr2q/X10NJS/fJyVHNn"
"sXfPtuO7u39brV+lkgiHmRBDKZOhbepThDHpOJ8zmZ7jLMZiq6YJhPSXxYyLSEkZMgx9ebl8"
"clLKZO6bTTbgkFN7ZV+e47xcW4tubIQjkWcrKyjl/zpmK/9BlDH0vIfZUogBZAoAKCWhVCk1"
"tHrnggLAk/9I/wC0eekA1bLbIQAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
TwoTangents = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAAA3NCSVQICAjb4U/gAAACL0lE"
"QVRIie3UzU8TQRQA8DczO1vatRgh1YhWD/WD+kG91FgOXLhx4+CpiYnE9L8g/gVwJHhp4lUP"
"pPHgQRMOGiEaDabV1LRAtdjUAG23m3W/Znc8YEo/trRNOGjCO+7M++3MezODdopFOO7Axy6e"
"oC0oAqAEY4QGyCcE4faVtaII7dQUy7b7dDEheq3GdB0R4o76KH2+kZ158uzxyzcO56iXS0Rx"
"N5tdnZ9fW1w0FaXZPUQxRl/Le7+q8mruh2paQsem2kLweCq5XGVrq7K5adTruGk+ahx+AeOS"
"rLz4ktctdtYvPYje0i3Gu22cUr1a3VheHg6FhoPBC9EoBwDO21EOQDH2igIALL39NOrz3r8z"
"rppWp3jQmQ8LC5enp4NTU0zTmGG0/PJwKgBzHEU3VcN6eHfie7X++ltBEmknSoaG0snkSDg8"
"Njmp12ptIrieU4dzAEjEIu8KPz8Wy14qNI9SScqvrHCA67Ozlqq6F8f1K3McL6WPYpFUOre9"
"L3uEv50VfL7S+vpuJjMxN8cMo1HEvlAAMG37nF+KR28+fZ/e/62JBAuiWC8U8qlUJJFAhHDH"
"6ZZ71LnRLXY1MDJzI5Rc+6wwR5PlTDIZjsd9gYBjuTSwEajneypR4dV2qXxq1F/dG5fLodg9"
"U9OOThGOHgYAg7FrF8fKKqjng/4rl+xeYl+ozeEMsNsiwmCftnnXQg6EcgABICxyAGAcut2x"
"wdADt+uFdYv/9OU/Qf9d9A9dhOgRU8MmewAAAABJRU5ErkJggg==")
#----------------------------------------------------------------------
class GraphEditorWindow(wx.Window):
"""
This is the main graph editor window.
"""
def __init__(self, parent, windowSize, property, xRange, yRange, curFrame, object):
wx.Window.__init__(self, parent, size = windowSize, style = wx.SUNKEN_BORDER)
self._mainDialog = wx.GetTopLevelParent(self)
self.w,self.h = self.GetClientSize()
self.zoom = float(2)
self._mouseIn = False
self._selectRec = False
self._selectHandler = False
self._OneTangent = True
self.object = object
self.curFrame = curFrame
self.property = property
self.zeroPos = (float(0), self.h/float(2))
self.zero = 0
self.unitWidth = self.w/float(xRange)
self.unitHeight = self.h/float(yRange)
self.generateInfo()
self.InitBuffer()
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp)
self.Bind(wx.EVT_MOTION, self.OnMotion)
def refresh(self):
self._mouseIn = False
self._selectRec = False
self._selectHandler = False
self.generateInfo()
def generateInfo(self):
#generate the information for animation curve generation
self.X = []
self.Y = []
self.Z = []
if self._mainDialog.editor.animMgr.keyFramesInfo != {}:
self.keyFramesInfo = self._mainDialog.editor.animMgr.keyFramesInfo
for key in self.keyFramesInfo.keys():
if key == (self.object[OG.OBJ_UID], 'X'):
for i in range(len(self.keyFramesInfo[key])):
item = self.keyFramesInfo[key][i]
handler = self.generateHandler(item)
self.X.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
if key == (self.object[OG.OBJ_UID], 'Y'):
for i in range(len(self.keyFramesInfo[key])):
item = self.keyFramesInfo[key][i]
handler = self.generateHandler(item)
self.Y.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
if key == (self.object[OG.OBJ_UID], 'Z'):
for i in range(len(self.keyFramesInfo[key])):
item = self.keyFramesInfo[key][i]
handler = self.generateHandler(item)
self.Z.append([key, i, handler[0], handler[1], handler[2], handler[3], handler[4]])
def generateHandler(self, item):
#generate the position for the control handler
x1 = self.zeroPos[0] + float(item[AG.FRAME])*self.unitWidth
y1 = self.zeroPos[1] - float(item[AG.VALUE])*self.unitHeight
t1x = item[AG.INSLOPE][0]*self.unitWidth
t1y = item[AG.INSLOPE][1]*self.unitHeight
t2x = item[AG.OUTSLOPE][0]*self.unitWidth
t2y = item[AG.OUTSLOPE][1]*self.unitHeight
tanA = t1y/t1x
temp1 = float(1)/(tanA**2+1)
if t1x <0 :
cosA = -math.sqrt(abs(temp1))
if t1x >=0:
cosA = math.sqrt(abs(temp1))
temp2 = (tanA**2)*temp1
if t1y <0 :
sinA = -math.sqrt(abs(temp2))
if t1y >=0:
sinA = math.sqrt(abs(temp2))
x2 = x1-float(self.unitWidth*self.zoom)*cosA
y2 = y1+float(self.unitWidth*self.zoom)*sinA
tanA = t2y/t2x
temp1 = float(1)/(tanA**2+1)
if t2x <0 :
cosA = -math.sqrt(abs(temp1))
if t2x >=0:
cosA = math.sqrt(abs(temp1))
temp2 = (tanA**2)*temp1
if t2y <0 :
sinA = -math.sqrt(abs(temp2))
if t2y >=0:
sinA = math.sqrt(abs(temp2))
x3 = x1+float(self.unitWidth*self.zoom)*cosA
y3 = y1-float(self.unitWidth*self.zoom)*sinA
return [[(x1,y1),0],[(x2,y2),0],[(x3,y3),0],[t1x,t1y],[t2x,t2y]]
def InitBuffer(self):
self.buffer = wx.EmptyBitmap(self.w, self.h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
self.DrawXCoord(dc)
self.DrawYCoord(dc)
self.DrawFrame(dc)
self.DrawCurve(dc)
self.DrawSelectRec(dc)
def SetGraphEditorData(self, property, curFrame = 1):
self.curFrame = curFrame
self.property = property
self.InitBuffer()
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self, self.buffer)
def DrawXCoord(self,dc):
dc.SetBackground(wx.Brush(wx.Colour(200, 200, 200)))
dc.Clear()
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
dc.DrawLine(self.zeroPos[0], float(0), self.zeroPos[0], self.h)
st = str(self.zero)
self.tw,self.th = dc.GetTextExtent(st)
dc.DrawText(st, self.zeroPos[0]+1.0, self.h-self.th-0.5)
dc.SetPen(wx.Pen(wx.Colour(150, 150, 150)))
dc.SetBrush(wx.Brush(wx.Colour(150, 150, 150)))
if self.unitWidth >= 25:
posPos = self.zeroPos[0]+self.unitWidth
posNum = self.zero + 1
while posPos <= self.w:
dc.DrawLine(posPos, float(0), posPos, self.h)
st = str(posNum)
self.drawXNumber(dc, st, posPos)
posPos += self.unitWidth
posNum += 1
negPos = self.zeroPos[0]-self.unitWidth
negNum = self.zero - 1
while negPos >= float(0):
dc.DrawLine(negPos, float(0), negPos, self.h)
st = str(negNum)
self.drawXNumber(dc, st, negPos)
negPos -= self.unitWidth
posNum -= 1
elif self.unitWidth >= 10 and self.unitWidth <= 25:
posPos = self.zeroPos[0]+self.unitWidth*float(2)
posNum = self.zero + 2
while posPos <= self.w:
dc.DrawLine(posPos, float(0), posPos, self.h)
st = str(posNum)
self.drawXNumber(dc, st, posPos)
posPos += self.unitWidth*float(2)
posNum += 2
negPos = self.zeroPos[0]-self.unitWidth*float(2)
negNum = self.zero - 2
while negPos >= float(0):
dc.DrawLine(negPos, float(0), negPos, self.h)
st = str(negNum)
self.drawXNumber(dc, st, negPos)
negPos -= self.unitWidth*float(2)
posNum -= 2
elif self.unitWidth >= 2 and self.unitWidth <= 10:
posPos = self.zeroPos[0]+self.unitWidth*float(5)
posNum = self.zero + 5
while posPos <= self.w:
dc.DrawLine(posPos, float(0), posPos, self.h)
st = str(posNum)
self.drawXNumber(dc, st, posPos)
posPos += self.unitWidth*float(5)
posNum += 5
negPos = self.zeroPos[0]-self.unitWidth*float(5)
negNum = self.zero - 5
while negPos >= float(0):
dc.DrawLine(negPos, float(0), negPos, self.h)
st = str(negNum)
self.drawXNumber(dc, st, negPos)
negPos -= self.unitWidth*float(5)
posNum -= 5
def DrawYCoord(self,dc):
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
dc.DrawLine(float(0), self.zeroPos[1], self.w, self.zeroPos[1])
st = str(self.zero)
dc.DrawText(st, 5.0, self.zeroPos[1]-1.0)
dc.SetPen(wx.Pen(wx.Colour(150, 150, 150)))
dc.SetBrush(wx.Brush(wx.Colour(150, 150, 150)))
dc.SetLogicalFunction(wx.AND)
posPos = self.zeroPos[1]-self.unitHeight*float(5)
posNum = self.zero + 5
while posPos >= float(0):
dc.DrawLine(float(0), posPos, self.w, posPos)
st = str(posNum)
self.drawYNumber(dc, st, posPos)
posPos -= self.unitHeight*float(5)
posNum += 5
negPos = self.zeroPos[1]+self.unitHeight*float(5)
negNum = self.zero - 5
while negPos <= self.h:
dc.DrawLine(float(0), negPos, self.w, negPos)
st = str(negNum)
self.drawYNumber(dc, st, negPos)
negPos += self.unitHeight*float(5)
negNum -= 5
def drawXNumber(self, dc, st, pos):
oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.DrawText(st, pos+1.0, self.h-self.th-0.5)
dc.SetPen(oldPen)
dc.SetBrush(oldBrush)
dc.SetLogicalFunction(oldMode)
def drawYNumber(self, dc, st, pos):
oldPen, oldBrush, oldMode = dc.GetPen(), dc.GetBrush(), dc.GetLogicalFunction()
dc.SetPen(wx.BLACK_PEN)
dc.SetBrush(wx.BLACK_BRUSH)
dc.DrawText(st, 5.0, pos-1.0)
dc.SetPen(oldPen)
dc.SetBrush(oldBrush)
dc.SetLogicalFunction(oldMode)
def DrawFrame(self, dc):
if self._mainDialog.editor.mode == self._mainDialog.editor.ANIM_MODE:
curFramePos = self.zeroPos[0]+self.curFrame*self.unitWidth
dc.SetPen(wx.Pen("red"))
dc.SetBrush(wx.Brush("red"))
dc.DrawLine(curFramePos, float(0), curFramePos, self.h)
else:
pass
def drawX(self, dc):
dc.SetPen(wx.Pen("red"))
dc.SetBrush(wx.Brush("red"))
self.drawSingleCurve(self.X, dc)
self.drawKeys(self.X, dc)
self.drawHandler(self.X, dc)
def drawY(self, dc):
dc.SetPen(wx.Pen("green"))
dc.SetBrush(wx.Brush("green"))
self.drawSingleCurve(self.Y, dc)
self.drawKeys(self.Y, dc)
self.drawHandler(self.Y, dc)
def drawZ(self, dc):
dc.SetPen(wx.Pen("blue"))
dc.SetBrush(wx.Brush("blue"))
self.drawSingleCurve(self.Z, dc)
self.drawKeys(self.Z, dc)
self.drawHandler(self.Z, dc)
def DrawCurve(self, dc):
if self.property == self._mainDialog.namestr:
self.drawX(dc)
self.drawY(dc)
self.drawZ(dc)
return
if self.property == property[AG.X]:
self.drawX(dc)
return
if self.property == property[AG.Y]:
self.drawY(dc)
return
if self.property == property[AG.Z]:
self.drawZ(dc)
return
def drawSingleCurve(self, list, dc):
if len(list) == 1:
dc.DrawPoint(list[0][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[0][AG.KEYFRAME][AG.LOCAL_VALUE][1])
return
if len(list) == 2:
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])
return
if len(list)>=3 :
for i in range(len(list)-1):
x1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
x4 = list[i+1][AG.KEYFRAME][AG.LOCAL_VALUE][0]
y4 = list[i+1][AG.KEYFRAME][AG.LOCAL_VALUE][1]
t1x = list[i][AG.OUT_SLOPE][0]
t1y = list[i][AG.OUT_SLOPE][1]
t2x = list[i+1][AG.IN_SLOPE][0]
t2y = list[i+1][AG.IN_SLOPE][1]
x2 = x1 + (x4 - x1) / float(3);
scale1 = (x2 - x1) / t1x;
y2 = y1 - t1y * scale1;
x3 = x4 - (x4 - x1) / float(3);
scale2 = (x4 - x3) / t2x;
y3 = y4 + t2y * scale2;
ax = - float(1) * x1 + float(3) * x2 - float(3) * x3 + float(1) * x4;
bx = float(3) * x1 - float(6) * x2 + float(3) * x3 + float(0) * x4;
cx = - float(3) * x1 + float(3) * x2 + float(0) * x3 + float(0) * x4;
dx = float(1) * x1 + float(0) * x2 - float(0) * x3 + float(0) * x4;
ay = - float(1) * y1 + float(3) * y2 - float(3) * y3 + float(1) * y4;
by = float(3) * y1 - float(6) * y2 + float(3) * y3 + float(0) * y4;
cy = - float(3) * y1 + float(3) * y2 + float(0) * y3 + float(0) * y4;
dy = float(1) * y1 + float(0) * y2 - float(0) * y3 + float(0) * y4;
preX = x1
preY = y1
t = 0.001
while t<=float(1):
x = ax * t*t*t + bx * t*t + cx * t + dx;
y = ay * t*t*t + by * t*t + cy * t + dy;
curX = x
curY = y
dc.DrawLine(preX, preY, curX, curY)
preX = curX
preY = curY
t += 0.001
def drawKeys(self, list, dc):
for i in range(len(list)):
pointX = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
pointY = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
if list[i][AG.KEYFRAME][AG.SELECT] == 0:
dc.SetPen(wx.Pen("black",3))
dc.SetBrush(wx.Brush("black"))
dc.DrawCircle(pointX, pointY, 2)
if list[i][AG.KEYFRAME][AG.SELECT] == 1:
dc.SetPen(wx.Pen("cyan",3))
dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(pointX, pointY, 2)
def drawHandler(self, list, dc):
for i in range(len(list)):
if list[i][AG.KEYFRAME][AG.SELECT] == 1:
X1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]
Y1 = list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]
if self._OneTangent == True:
for j in range(3,5):
X = list[i][j][AG.LOCAL_VALUE][0]
Y = list[i][j][AG.LOCAL_VALUE][1]
if list[i][j][AG.SELECT] == 1:
dc.SetPen(wx.Pen("cyan",3))
dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1))
dc.DrawLine(X1, Y1, X, Y)
if list[i][j][AG.SELECT] == 0:
dc.SetPen(wx.Pen("brown",3))
dc.SetBrush(wx.Brush("brown"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("brown",1))
dc.DrawLine(X1, Y1, X, Y)
if self._OneTangent == False:
if list[i][AG.IN_TANGENT][AG.SELECT] == 1:
X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("cyan",3))
dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1))
dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.IN_TANGENT][AG.SELECT] == 0:
X = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("navy",3))
dc.SetBrush(wx.Brush("navy"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("navy",1))
dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.OUT_TANGENT][AG.SELECT] == 1:
X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("cyan",3))
dc.SetBrush(wx.Brush("cyan"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("cyan",1))
dc.DrawLine(X1, Y1, X, Y)
if list[i][AG.OUT_TANGENT][AG.SELECT] == 0:
X = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0]
Y = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1]
dc.SetPen(wx.Pen("brown",3))
dc.SetBrush(wx.Brush("brown"))
dc.DrawCircle(X, Y, 2)
dc.SetPen(wx.Pen("brown",1))
dc.DrawLine(X1, Y1, X, Y)
def DrawSelectRec(self, dc):
if self._selectRec == True:
dc.SetPen(wx.Pen("navy", 1))
dc.SetBrush(wx.Brush("navy"))
## dc.SetLogicalFunction(wx.AND)
dc.DrawLine(self.pos[0], self.pos[1], self.pos[0], self.newPos[1])
dc.DrawLine(self.pos[0], self.pos[1], self.newPos[0], self.pos[1])
dc.DrawLine(self.newPos[0], self.newPos[1], self.pos[0], self.newPos[1])
dc.DrawLine(self.newPos[0], self.newPos[1], self.newPos[0], self.pos[1])
def OnSize(self,evt):
self.InitBuffer()
def OnLeftDown(self,evt):
point = (evt.GetX(), evt.GetY())
if point[1]>= float(0) and point[1]<= float(self.h):
if point[0]>= float(0) and point[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
self.CaptureMouse()
self.pos = point
def OnLeftUp(self,evt):
if self.GetCapture():
self.ReleaseMouse()
self._mouseIn = False
self._selectRec = False
self.setSelection()
self.SetGraphEditorData(self.property, self.curFrame)
def OnMiddleDown(self,evt):
point = (evt.GetX(), evt.GetY())
if point[1]>= float(0) and point[1]<= float(self.h):
if point[0]>= float(0) and point[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
self.CaptureMouse()
self.midPos = point
def OnMiddleUp(self, evt):
if self.GetCapture():
self.ReleaseMouse()
def OnMotion(self,evt):
self._mouseIn = False
if evt.Dragging() and evt.LeftIsDown():
self.newPos = (evt.GetX(), evt.GetY())
if self.newPos[1]>= float(0) and self.newPos[1]<= float(self.h):
if self.newPos[0]>= float(0) and self.newPos[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
if self.newPos == self.pos:
evt.Skip()
self._mouseIn = False
else:
self._selectRec = True
self.SetGraphEditorData(self.property, self.curFrame)
if evt.Dragging() and evt.MiddleIsDown():
self.newMidPos = (evt.GetX(), evt.GetY())
if self.newMidPos[1]>= float(0) and self.newMidPos[1]<= float(self.h):
if self.newMidPos[0]>= float(0) and self.newMidPos[0]<= float(self.w):
self._mouseIn = True
if self._mouseIn:
if self.newMidPos == self.midPos:
evt.Skip()
self._mouseIn = False
else:
self.recalculateSlope()
self.onAnimation()
self.midPos = self.newMidPos
evt.Skip()
self._mouseIn = False
self._selectRec = False
def setExistKey(self, list):
flag = False
for i in range(len(list)):
if list[i][AG.KEYFRAME][AG.SELECT] == 1:
inside = self.inside(self.pos, self.newPos, (list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0], list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]))
if inside == True:
list[i][AG.KEYFRAME][AG.SELECT] = 0
if inside == False:
find = False
for j in range(3,5):
inside = self.inside(self.pos, self.newPos, (list[i][j][AG.LOCAL_VALUE][0], list[i][j][AG.LOCAL_VALUE][1]))
if inside == False:
list[i][j][AG.SELECT] = 0
if inside == True:
list[i][j][AG.SELECT] = 1
find = True
flag = True
if find == False:
list[i][AG.KEYFRAME][AG.SELECT] == 0
return flag
def setNewKey(self, list):
for i in range(len(list)):
inside = self.inside(self.pos, self.newPos, (list[i][2][0][0], list[i][2][0][1]))
if inside == True:
list[i][AG.KEYFRAME][AG.SELECT] = 1
if inside == False:
list[i][AG.KEYFRAME][AG.SELECT] = 0
def setSelection(self):
if self.property == self._mainDialog.namestr:
self.setSelectionBase(self.X)
self.setSelectionBase(self.Y)
self.setSelectionBase(self.Z)
return
if self.property == property[AG.X]:
self.setSelectionBase(self.X)
return
if self.property == property[AG.Y]:
self.setSelectionBase(self.Y)
return
if self.property == property[AG.Z]:
self.setSelectionBase(self.Z)
return
def setSelectionBase(self, list):
self.setExistKey(list)
if self.setExistKey(list) == True:
return
else:
self.setNewKey(list)
def inside(self, point0, point1, point):
if point0[0]<=point1[0] and point0[1]<=point1[1]:
if point0[0]<point[0] and point[0]<point1[0] and point0[1]<point[1] and point[1]<point1[1]:
return True
else:
return False
elif point1[0]<=point0[0] and point0[1]<=point1[1]:
if point1[0]<point[0] and point[0]<point0[0] and point0[1]<point[1] and point[1]<point1[1]:
return True
else:
return False
elif point0[0]<=point1[0] and point1[1]<=point0[1]:
if point0[0]<point[0] and point[0]<point1[0] and point1[1]<point[1] and point[1]<point0[1]:
return True
else:
return False
elif point1[0]<=point0[0] and point1[1]<=point0[1]:
if point1[0]<point[0] and point[0]<point0[0] and point1[1]<point[1] and point[1]<point0[1]:
return True
else:
return False
else:
return False
def recalculateSlope(self):
if self.property == self._mainDialog.namestr:
self.recalculateSlopeBase(self.X)
self.recalculateSlopeBase(self.Y)
self.recalculateSlopeBase(self.Z)
return
if self.property == property[AG.X]:
self.recalculateSlopeBase(self.X)
return
if self.property == property[AG.Y]:
self.recalculateSlopeBase(self.Y)
return
if self.property == property[AG.Z]:
self.recalculateSlopeBase(self.Z)
return
def recalculateSlopeBase(self, list):
#recalculate the tangent slope
moveX = self.newMidPos[0]-self.midPos[0]
moveY = self.newMidPos[1]-self.midPos[1]
for i in range(len(list)):
if list[i][AG.KEYFRAME][AG.SELECT] == 1:
if list[i][AG.IN_TANGENT][AG.SELECT] == 1:
newPointX = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][0] + moveX
newPointY = list[i][AG.IN_TANGENT][AG.LOCAL_VALUE][1] + moveY
newSlope = [list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] - newPointX , newPointY - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1]]
temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0]
temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1]
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = newSlope[0]/self.unitWidth
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = newSlope[1]/self.unitHeight
handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
if handler[1][0][0]>= list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = temp0
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = temp1
return
if handler[1][0][0] < list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
if self._OneTangent == False:
list[i][AG.IN_TANGENT][0] = handler[1][0]
list[i][AG.IN_SLOPE][0] = handler[3][0]
list[i][AG.IN_SLOPE][1] = handler[3][1]
if self._OneTangent == True:
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = newSlope[0]/self.unitWidth
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = newSlope[1]/self.unitHeight
handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
list[i][AG.IN_TANGENT][0] = handler[1][0]
list[i][AG.OUT_TANGENT][0] = handler[2][0]
list[i][AG.IN_SLOPE][0] = handler[3][0]
list[i][AG.IN_SLOPE][1] = handler[3][1]
list[i][AG.OUT_SLOPE][0] = handler[4][0]
list[i][AG.OUT_SLOPE][1] = handler[4][1]
self.SetGraphEditorData(self.property, self.curFrame)
if list[i][AG.OUT_TANGENT][AG.SELECT] == 1:
newPointX = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][0] + moveX
newPointY = list[i][AG.OUT_TANGENT][AG.LOCAL_VALUE][1] + moveY
newSlope = [newPointX - list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0] , list[i][AG.KEYFRAME][AG.LOCAL_VALUE][1] - newPointY]
temp0 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0]
temp1 = self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1]
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = newSlope[0]/self.unitWidth
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = newSlope[1]/self.unitHeight
handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
if handler[2][0][0] <= list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][0] = temp0
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.OUTSLOPE][1] = temp1
return
if handler[2][0][0] > list[i][AG.KEYFRAME][AG.LOCAL_VALUE][0]:
if self._OneTangent == False:
list[i][AG.OUT_TANGENT][0] = handler[2][0]
list[i][AG.OUT_SLOPE][0] = handler[4][0]
list[i][AG.OUT_SLOPE][1] = handler[4][1]
if self._OneTangent == True:
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][0] = newSlope[0]/self.unitWidth
self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]][AG.INSLOPE][1] = newSlope[1]/self.unitHeight
handler = self.generateHandler(self._mainDialog.editor.animMgr.keyFramesInfo[list[i][AG.KEY]][list[i][AG.I]])
list[i][AG.IN_TANGENT][0] = handler[1][0]
list[i][AG.OUT_TANGENT][0] = handler[2][0]
list[i][AG.IN_SLOPE][0] = handler[3][0]
list[i][AG.IN_SLOPE][1] = handler[3][1]
list[i][AG.OUT_SLOPE][0] = handler[4][0]
list[i][AG.OUT_SLOPE][1] = handler[4][1]
self.SetGraphEditorData(self.property, self.curFrame)
def selectHandler(self):
self._selectHandler = False
def onAnimation(self):
if self._mainDialog.editor.mode == self._mainDialog.editor.ANIM_MODE:
self._mainDialog.editor.ui.animUI.OnAnimation(self._mainDialog.editor.ui.animUI.curFrame)
else:
pass
class GraphEditorUI(wx.Dialog):
"""
This is the graph editor main class implementation.
"""
def __init__(self, parent, editor, object):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Graph Editor",
pos=wx.DefaultPosition, size=(735, 535))
self.editor = editor
self.editor.GRAPH_EDITOR = True
self.object = object
self.xRange = 24+1
self.yRange = 50
if self.editor.mode == self.editor.ANIM_MODE:
self.curFrame = self.editor.ui.animUI.curFrame
self.curFrame = 1
self.mainPanel1 = wx.Panel(self, -1)
bmpZoomIn = ZoomIn.GetBitmap()
bmpZoomOut = ZoomOut.GetBitmap()
bmpOneTangent = OneTangent.GetBitmap()
bmpTwoTangents = TwoTangents.GetBitmap()
self.buttonZoomIn = wx.BitmapButton(self.mainPanel1, -1, bmpZoomIn, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonZoomOut = wx.BitmapButton(self.mainPanel1, -1, bmpZoomOut, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonOneTangent = wx.BitmapButton(self.mainPanel1, -1, bmpOneTangent, size = (30,30),style = wx.BU_AUTODRAW)
self.buttonTwoTangents = wx.BitmapButton(self.mainPanel1, -1, bmpTwoTangents, size = (30,30),style = wx.BU_AUTODRAW)
self.mainPanel2 = wx.Panel(self, -1)
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")
self.namestr = "%s"%(object[OG.OBJ_DEF].name)
self.root = self.tree.AddRoot(self.namestr)
self.AddTreeNodes(self.root, property)
self.tree.Expand(self.root)
self.tree.SelectItem(self.root,select=True)
self.str = self.tree.GetItemText(self.root)
self.graphEditorWindow =GraphEditorWindow(self.mainPanel2, wx.Size(500, 450), str(object[OG.OBJ_DEF].name), self.xRange, self.yRange, self.curFrame, self.object)
self.SetProperties()
self.DoLayout()
self.Bind(wx.EVT_BUTTON, self.OnZoomIn, self.buttonZoomIn)
self.Bind(wx.EVT_BUTTON, self.OnZoomOut, self.buttonZoomOut)
self.Bind(wx.EVT_BUTTON, self.OnOneTangent, self.buttonOneTangent)
self.Bind(wx.EVT_BUTTON, self.OnTwoTangents, self.buttonTwoTangents)
self.Bind(wx.EVT_CLOSE, self.OnExit)
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
def SetProperties(self):
pass
def DoLayout(self):
dialogSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer1 = wx.FlexGridSizer(1, 4, 0, 0)
mainSizer2 = wx.FlexGridSizer(1, 2, 0, 0)
mainSizer1.Add(self.buttonOneTangent, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 570)
mainSizer1.Add(self.buttonTwoTangents, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
mainSizer1.Add(self.buttonZoomIn, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
mainSizer1.Add(self.buttonZoomOut, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
mainSizer2.Add(self.tree, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 10)
mainSizer2.Add(self.graphEditorWindow, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
self.mainPanel1.SetSizerAndFit(mainSizer1)
self.mainPanel2.SetSizer(mainSizer2)
dialogSizer.Add(self.mainPanel2, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 10)
dialogSizer.Add(self.mainPanel1, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, 5)
self.SetSizer(dialogSizer)
self.Layout()
self.dialogSizer = dialogSizer
def AddTreeNodes(self, parentItem, items):
for item in items:
if type(item) == str:
self.tree.AppendItem(parentItem, item)
def OnSelChanged(self, evt):
item = evt.GetItem()
if item:
self.str = self.tree.GetItemText(item)
self.graphEditorWindow.refresh()
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
def OnZoomIn(self,evt):
self.graphEditorWindow.zoom = self.graphEditorWindow.zoom/float(1.2)
self.graphEditorWindow.unitWidth = self.graphEditorWindow.unitWidth*float(1.2)
self.graphEditorWindow.unitHeight = self.graphEditorWindow.unitHeight*float(1.2)
self.graphEditorWindow.generateInfo()
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
def OnZoomOut(self,evt):
self.graphEditorWindow.zoom = self.graphEditorWindow.zoom*float(1.2)
self.graphEditorWindow.unitWidth = self.graphEditorWindow.unitWidth/float(1.2)
self.graphEditorWindow.unitHeight = self.graphEditorWindow.unitHeight/float(1.2)
self.graphEditorWindow.generateInfo()
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
def OnOneTangent(self,evt):
self.graphEditorWindow._OneTangent = True
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
def OnTwoTangents(self,evt):
self.graphEditorWindow._OneTangent = False
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
def curFrameChange(self):
if self.editor.mode == self.editor.ANIM_MODE:
self.curFrame = self.editor.ui.animUI.curFrame
self.graphEditorWindow.SetGraphEditorData(self.str, self.curFrame)
else:
pass
def OnExit(self,evt):
self.Destroy()
self.editor.ui.graphEditorMenuItem.Check(False)
self.object = None
self.editor.GRAPH_EDITOR = False

View File

@ -8,6 +8,7 @@ to be game specific.
from LevelEditorUI import *
from LevelEditorBase import *
from ObjectMgr import *
from AnimMgr import *
from ObjectHandler import *
from ObjectPalette import *
from ProtoPalette import *
@ -23,6 +24,7 @@ class LevelEditor(LevelEditorBase):
# If you have your own ObjectPalette and ObjectHandler
# connect them in your own LevelEditor class
self.objectMgr = ObjectMgr(self)
self.animMgr = AnimMgr(self)
self.objectPalette = ObjectPalette()
self.objectHandler = ObjectHandler(self)
self.protoPalette = ProtoPalette()

View File

@ -37,6 +37,8 @@ class LevelEditorBase(DirectObject):
self.BASE_MODE = BitMask32.bit(0)
self.CREATE_CURVE_MODE = BitMask32.bit(2)
self.EDIT_CURVE_MODE = BitMask32.bit(3)
self.ANIM_MODE = BitMask32.bit(4)
self.GRAPH_EDITOR = False
self.mode = self.BASE_MODE
self.preMode = None
@ -245,8 +247,10 @@ class LevelEditorBase(DirectObject):
return
base.direct.deselectAll()
base.direct.selected.last = None
self.ui.reset()
self.objectMgr.reset()
self.animMgr.reset()
self.actionMgr.reset()
self.ui.perspView.camera.setPos(-19, -19, 19)
self.ui.perspView.camera.lookAt(Point3(0, 0, 0))

View File

@ -14,6 +14,9 @@ from LayerEditorUI import *
from HotKeyUI import *
from ProtoPaletteUI import *
from ActionMgr import *
from AnimControlUI import *
from CurveAnimUI import *
from GraphEditorUI import *
class PandaTextDropTarget(wx.TextDropTarget):
def __init__(self, editor, view):
@ -118,6 +121,10 @@ ID_PARENT_TO_SELECTED = 306
ID_CREATE_CURVE = 601
ID_EDIT_CURVE = 602
ID_CURVE_ANIM = 603
ID_ANIM = 701
ID_GRAPH = 702
class LevelEditorUIBase(WxPandaShell):
""" Class for Panda3D LevelEditor """
@ -140,7 +147,10 @@ class LevelEditorUIBase(WxPandaShell):
ID_HOT_KEYS : ("&Hot Keys", None),
ID_PARENT_TO_SELECTED : ("&Parent To Selected", None),
ID_CREATE_CURVE : ("&Create Curve", None),
ID_EDIT_CURVE : ("&Edit Curve", None)
ID_EDIT_CURVE : ("&Edit Curve", None),
ID_CURVE_ANIM : ("&Curve Animation", None),
ID_ANIM : ("&Edit Animation", None),
ID_GRAPH : ("&Graph Editor", None)
})
self.editor = editor
@ -217,8 +227,45 @@ class LevelEditorUIBase(WxPandaShell):
self.editCurveMenuItem = self.menuCurve.Append(ID_EDIT_CURVE, self.MENU_TEXTS[ID_EDIT_CURVE][0], kind = wx.ITEM_CHECK)
self.Bind(wx.EVT_MENU, self.onEditCurve, self.editCurveMenuItem)
self.curveAnimMenuItem = self.menuCurve.Append(ID_CURVE_ANIM, self.MENU_TEXTS[ID_CURVE_ANIM][0], kind = wx.ITEM_CHECK)
self.Bind(wx.EVT_MENU, self.onCurveAnim, self.curveAnimMenuItem)
self.menuAnim = wx.Menu()
self.menuBar.Insert(4, self.menuAnim, "&AnimationMode")
self.editAnimMenuItem = self.menuAnim.Append(ID_ANIM, self.MENU_TEXTS[ID_ANIM][0], kind = wx.ITEM_CHECK)
self.Bind(wx.EVT_MENU, self.onAnimation, self.editAnimMenuItem)
self.graphEditorMenuItem = self.menuAnim.Append(ID_GRAPH, self.MENU_TEXTS[ID_GRAPH][0], kind = wx.ITEM_CHECK)
self.Bind(wx.EVT_MENU, self.onGraphEditor, self.graphEditorMenuItem)
WxPandaShell.createMenu(self)
def onGraphEditor(self,e):
if base.direct.selected.last == None:
dlg = wx.MessageDialog(None, 'Please select a object first.', 'NOTICE', wx.OK )
dlg.ShowModal()
dlg.Destroy()
self.graphEditorMenuItem.Check(False)
else:
currentObj = self.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
self.graphEditorUI = GraphEditorUI(self, self.editor, currentObj)
self.graphEditorUI.Show()
self.graphEditorMenuItem.Check(True)
def onAnimation(self,e):
if self.editor.mode != self.editor.ANIM_MODE:
self.animUI = AnimControlUI(self, self.editor)
self.animUI.Show()
self.editor.mode = self.editor.ANIM_MODE
if self.editor.mode == self.editor.ANIM_MODE:
self.editAnimMenuItem.Check(True)
def onCurveAnim(self,e):
self.curveAnimUI = CurveAnimUI(self, self.editor)
self.curveAnimUI.Show()
self.curveAnimMenuItem.Check(True)
def onCreateCurve(self,e):
"""Function to invoke curve creating, need to check previous mode"""
@ -248,7 +295,7 @@ class LevelEditorUIBase(WxPandaShell):
self.editCurveMenuItem.Check(False)
def onEditCurve(self,e):
"""Function to invoke curve editing and transfer global information to local information. Need to check previous mode"""
"""Function to invoke curve editing and translate global information to local information. Need to check previous mode"""
if self.editor.mode == self.editor.EDIT_CURVE_MODE:
self.editCurveMenuItem.Check(False)
self.editor.curveEditor.onBaseMode()
@ -639,3 +686,4 @@ class CurveDegreeUI(wx.Dialog):
if(str(self.degree.GetSelection())=='2'):
self.parent.editor.curveEditor.degree = 4
self.Destroy()

View File

@ -31,8 +31,12 @@ class ObjectMgrBase:
self.lastUid = ''
self.lastUidMode = 0
self.currNodePath = None
self.currLiveNP = None
self.Actor = []
self.findActors(render)
self.Nodes = []
self.findNodes(render)
def reset(self):
base.direct.deselectAllCB()
@ -50,6 +54,8 @@ class ObjectMgrBase:
self.objects = {}
self.npIndex = {}
self.saveData = []
self.Actor = []
self.Nodes = []
def genUniqueId(self):
# [gjeon] to solve the problem of unproper $USERNAME
@ -265,6 +271,17 @@ class ObjectMgrBase:
def removeObjectById(self, uid):
obj = self.findObjectById(uid)
nodePath = obj[OG.OBJ_NP]
for i in range(0,len(self.Actor)):
if self.Actor[i] == obj:
del self.Actor[i]
break
for i in range(0,len(self.Nodes)):
if self.Nodes[i][OG.OBJ_UID] == uid:
del self.Nodes[i]
break
self.editor.animMgr.removeAnimInfo(obj[OG.OBJ_UID])
del self.objects[uid]
del self.npIndex[nodePath]
@ -279,6 +296,16 @@ class ObjectMgrBase:
def removeObjectByNodePath(self, nodePath):
uid = self.npIndex.get(nodePath)
if uid:
for i in range(0,len(self.Actor)):
if self.Actor[i][OG.OBJ_UID] == uid:
del self.Actor[i]
break
for i in range(0,len(self.Nodes)):
if self.Nodes[i][OG.OBJ_UID] == uid:
del self.Nodes[i]
break
self.editor.animMgr.removeAnimInfo(uid)
del self.objects[uid]
del self.npIndex[nodePath]
@ -880,5 +907,27 @@ class ObjectMgrBase:
def flatten(self, newobjModel, model, objDef, uid):
# override this to flatten models
pass
def findActors(self, parent):
for child in parent.getChildren():
if child.hasTag('OBJRoot') and not child.hasTag('Controller'):
obj = self.findObjectByNodePath(child)
if obj:
if isinstance(obj[OG.OBJ_NP],Actor):
self.Actor.append(obj)
self.findActors(child)
def findNodes(self, parent):
for child in parent.getChildren():
if child.hasTag('OBJRoot') and not child.hasTag('Controller'):
obj = self.findObjectByNodePath(child)
if obj:
self.Nodes.append(obj)
self.findActors(child)

View File

@ -5,11 +5,24 @@ import wx
import os
import math
from wx.lib.embeddedimage import PyEmbeddedImage
from wx.lib.scrolledpanel import ScrolledPanel
from wx.lib.agw.cubecolourdialog import *
from direct.wxwidgets.WxSlider import *
from pandac.PandaModules import *
import ObjectGlobals as OG
import AnimGlobals as AG
#----------------------------------------------------------------------
Key = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAA3NCSVQICAjb4U/gAAABIElE"
"QVQokZWSMW7CQBBFZ2Z3sQ02Ni4sOS6QiLgO5yBXIMcJ1KENje8QLESH7F3FVFQIIS3eTWGJ"
"VE7Iq6Z4+tL8GVRSwmPQg94fKiIOBoNer2et/U1FRER8X6+LonBdFwB4l+p53mq1qqRUUsZx"
"nKYpBwDOuRACEQGgaRoAYETn8/l4PL4uFkqp/X6fZRlnjO12u7KqENEa43keADDGvuo6Go0A"
"wPd9YkxrzY0x4/FYKlXX9eVymc1mjIiIgiD43G4BwFprmgYRubU2DMPnySTw/ev1+pSmRISI"
"SZJ8bDan06ksSyLiQmDXCfr9fp7nb8vldDp9mc9d1/1R27XaClscxzkcDlEUhcOhvt06U1uE"
"EMaYtpbOXlu01vf5Hz/wDRuDdIDl5WtQAAAAAElFTkSuQmCC")
#----------------------------------------------------------------------
class AnimFileDrop(wx.FileDropTarget):
def __init__(self, editor):
@ -55,13 +68,63 @@ class ObjectPropUI(wx.Panel):
self.label = wx.StaticText(self.labelPane, label=label)
self.labelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.labelSizer.Add(self.label)
bmpKey = Key.GetBitmap()
self.setKeyButton = wx.BitmapButton(self.labelPane, -1, bmpKey, size = (15,15),style = wx.BU_AUTODRAW)
self.labelSizer.Add(self.setKeyButton)
self.labelPane.SetSizer(self.labelSizer)
self.uiPane = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.labelPane)
sizer.Add(self.uiPane, 1, wx.EXPAND, 0)
self.SetSizer(sizer)
self.setKeyButton.Bind(wx.EVT_BUTTON, self.onKey)
def onKey(self,evt):
self.parent = wx.GetTopLevelParent(self)
if self.parent.editor.mode == self.parent.editor.ANIM_MODE:
obj= self.parent.editor.objectMgr.findObjectByNodePath(base.direct.selected.last)
objUID = obj[OG.OBJ_UID]
propertyName = self.label.GetLabelText()
value = self.getValue()
frame = self.parent.editor.ui.animUI.curFrame
if self.parent.editor.animMgr.keyFramesInfo.has_key((objUID,propertyName)):
for i in range(len(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])):
if self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i][AG.FRAME] == frame:
del self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)][i]
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)].append([frame, value, [], []])
#sort keyFrameInfo list by the order of frame number
sortKeyList = self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)]
for i in range(0, len(sortKeyList)-1):
for j in range(i+1, len(sortKeyList)):
if sortKeyList[i][AG.FRAME]>sortKeyList[j][AG.FRAME]:
temp = sortKeyList[i]
sortKeyList[i] = sortKeyList[j]
sortKeyList[j] = temp
self.parent.editor.animMgr.generateSlope(self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)])
else:
self.parent.editor.animMgr.keyFramesInfo[(objUID,propertyName)] = [[frame, value, [], []]]
exist = False
for keyFrame in self.parent.editor.animMgr.keyFrames:
if frame == keyFrame:
exist = True
break
if exist == False:
self.parent.editor.animMgr.keyFrames.append(frame)
self.parent.editor.ui.animUI.OnPropKey()
else:
self.parent.editor.ui.animUI.OnPropKey()
else:
evt.Skip()
def setValue(self, value):
self.ui.SetValue(value)