Added animation system
This commit is contained in:
parent
debb5223cc
commit
b18c13895c
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue