Add moving keyframes

This commit is contained in:
Astatin3
2024-03-15 15:08:37 -06:00
parent ddf82989b3
commit f17464f173
4 changed files with 148 additions and 62 deletions
+120 -35
View File
@@ -15,11 +15,13 @@ matchTicks = 15 * 50
displayTickResolution = 4
displayTicks = round(matchTicks / displayTickResolution)
indicatorBarHeight = None
dragFrameIndex = -1
ogDragFramePos = -1
selFrame = -1
def getPosKeyframes():
frames = []
for keyFrame in keyFrames:
@@ -27,18 +29,24 @@ def getPosKeyframes():
frames.append(keyFrame)
return frames
def getKeyframeAtPos(index):
for frame in keyFrames:
if frame["timeIndex"] == index:
return frame
return None
def getPosKeyframeAtPos(index):
for frame in keyFrames:
if frame["timeIndex"] == index and frame['type'] == 'position':
return frame
return None
def getBezierPointCounts():
counts = []
frames = getPosKeyframes()
@@ -46,42 +54,59 @@ def getBezierPointCounts():
counts.append(frames[i]['timeIndex'] - frames[i-1]['timeIndex'])
return counts
def getPosKeyframeByIndex(index):
for frame in keyFrames:
if frame["index"] == index and frame['type'] == 'position':
return frame
return None
def getFrameIndex(frame):
if frame == None:
return -1
return keyFrames.index(frame)
def getSurroundingPosFrames(index):
prevFrame = None
for i in range(index,-1,-1):
frame = getKeyframeAtPos(i)
if frame != None:
frame = getPosKeyframeAtPos(i)
if frame != None and (dragFrameIndex == -1 or not frame == keyFrames[dragFrameIndex]):
prevFrame = frame
break
nextFrame = None
for i in range(index,displayTicks,1):
frame = getKeyframeAtPos(i)
if frame != None:
frame = getPosKeyframeAtPos(i)
if frame != None and (dragFrameIndex == -1 or not frame == keyFrames[dragFrameIndex]):
nextFrame = frame
break
if nextFrame == None and prevFrame == None:
return prevFrame, nextFrame
elif nextFrame == None:
return prevFrame, prevFrame
elif prevFrame == None:
return nextFrame, nextFrame
# elif nextFrame == None:
# return prevFrame, prevFrame
# elif prevFrame == None:
# return nextFrame, nextFrame
return prevFrame, nextFrame
def getRobotAtIndex(index):
prevFrame, nextFrame = getSurroundingPosFrames(index)
if prevFrame['timeIndex'] - nextFrame['timeIndex'] == 0:
if prevFrame == None:
return nextFrame['position'], nextFrame['rotation']
elif nextFrame == None:
return prevFrame['position'], prevFrame['rotation']
elif nextFrame['timeIndex'] - prevFrame['timeIndex'] == 0:
return prevFrame['position'], prevFrame['rotation']
relPos = -((prevFrame['timeIndex'] - index)/(nextFrame['timeIndex'] - prevFrame['timeIndex']-1))
relPos = -((prevFrame['timeIndex'] - index)/(nextFrame['timeIndex'] - prevFrame['timeIndex']))
pos = calcBezierPoint(prevFrame['position'], ogCtrlNodes[prevFrame['index']], nextFrame['position'], relPos)
@@ -91,10 +116,20 @@ def getRobotAtIndex(index):
rot = ((nextFrame['rotation']-prevFrame['rotation']+math.pi*2)*relPos) + prevFrame['rotation']
else:
rot = ((nextFrame['rotation']-prevFrame['rotation'])*relPos) + prevFrame['rotation']
# diff = (nextFrame['rotation']-prevFrame['rotation'])
# if diff >= math.pi:
# rot = ((nextFrame['rotation']-prevFrame['rotation']-math.pi*2)*relPos) + prevFrame['rotation']
# elif diff <= math.pi:
# rot = ((nextFrame['rotation']-prevFrame['rotation']+math.pi*2)*relPos) + prevFrame['rotation']
# else:
# rot = ((nextFrame['rotation']-prevFrame['rotation'])*relPos) + prevFrame['rotation']
return pos, rot
def getTimeBarColor(index):
frame = getKeyframeAtPos(index)
if frame == None:
@@ -102,28 +137,20 @@ def getTimeBarColor(index):
if frame['type'] == 'position':
return (127,127,0)
elif frame['type'] == 'controller':
return (0,127,0)
return (127,0,127)
return (16,16,32)
# def renderSelectIndicator(i):
# if i == selFrame:
# x1 = i * (render.width/(displayTicks))
# x2 = (render.width/(displayTicks))
# # render.drawrect((255,0,0), (x1, bottomBarRect[1], x2, indicatorBarHeight))
# # render.drawrect((255,0,0), (x1, render.screen.get_height()-indicatorBarHeight, x2, indicatorBarHeight))
# render.drawrect((255,0,0), (x1, bottomBarRect[1]+((bottomBarRect[3]-indicatorBarHeight)/2), x2, indicatorBarHeight))
# # render.drawrect((255,0,0), rect)
def calcBezierPoint(p0, p1, p2, t):
px = p0[0]*(1-t)**2 + 2*(1-t)*t*p1[0] + p2[0]*t**2
py = p0[1]*(1-t)**2 + 2*(1-t)*t*p1[1] + p2[1]*t**2
return (px, py)
def reloadBar(pos):
toggle = False
for i in range(displayTicks):
@@ -135,9 +162,26 @@ def reloadBar(pos):
if i == selFrame:
color = (color[0]+64,color[1]+64,color[2]+64)
if render.isInRect(pos, rect):
color = (color[0]+64,color[1]+64,color[2]+64)
if dragFrameIndex != -1 and getKeyframeAtPos(i) == None:
if keyFrames[dragFrameIndex]['type'] == 'position':
prevFrame, nextFrame = getSurroundingPosFrames(ogDragFramePos)
# print(prevFrame['timeIndex'] == nextFrame['timeIndex'])
if prevFrame == nextFrame:
pass
elif prevFrame == None:
if i < nextFrame['timeIndex']:
keyFrames[dragFrameIndex]['timeIndex'] = i
elif nextFrame == None:
if i > prevFrame['timeIndex']:
keyFrames[dragFrameIndex]['timeIndex'] = i
elif i > prevFrame['timeIndex'] and i < nextFrame['timeIndex']:
keyFrames[dragFrameIndex]['timeIndex'] = i
else:
keyFrames[dragFrameIndex]['timeIndex'] = i
else:
color = (color[0]+16+(toggle*16),color[1]+16+(toggle*16),color[2]+32+(toggle*16))
@@ -147,7 +191,9 @@ def reloadBar(pos):
# renderSelectIndicator(i)
render.update()
def clickBar(pos):
def clickBar(pos, doubleClick):
for i in range(displayTicks):
x1 = i * (render.width/(displayTicks))
x2 = (render.width/(displayTicks))
@@ -155,7 +201,17 @@ def clickBar(pos):
if render.isInRect(pos, rect):
global selFrame
global dragFrameIndex
global ogDragFramePos
selFrame = i
if not doubleClick and dragFrameIndex == -1:
dragFrameIndex = getFrameIndex(getKeyframeAtPos(i))
ogDragFramePos = i
if doubleClick and getKeyframeAtPos(i) == None:
keyFrames.append({
'type': 'controller',
'timeIndex': i
})
return
class buttonEditor:
@@ -173,6 +229,8 @@ class buttonEditor:
global bottomBarRect
bottomBarRect = (0, (render.screen.get_height()-render.bottomBarHeight), render.screen.get_width(), render.bottomBarHeight)
def refresh(self):
global ogNodes
global ogCtrlNodes
@@ -191,21 +249,40 @@ class buttonEditor:
reloadBar((0,0))
render.update()
def mouseDown(self, pos):
if pos[1] > bottomBarRect[1]:
clickBar(pos)
clickBar(pos, False)
self.refresh()
pass
def mouseUp(self, pos):
pass
global dragFrameIndex
if dragFrameIndex != -1:
dragFrameIndex = -1
ogDragFramePos = -1
self.refresh()
reloadBar((0, 0))
def mouseMove(self, pos):
reloadBar(pos)
global dragFrameIndex
if dragFrameIndex != -1 or pos[1] > bottomBarRect[1]:
reloadBar(pos)
# if pos[1] > bottomBarRect[1]:
def doubleClick(self, pos):
pass
if pos[1] > bottomBarRect[1]:
clickBar(pos, True)
self.refresh()
def keyDown(self, key):
global selFrame
@@ -215,7 +292,9 @@ class buttonEditor:
elif key == render.pg.K_RIGHT and selFrame < displayTicks-1:
selFrame += 1
self.refresh()
def updateNodes(self, loadKeyframes):
global ogNodes
global ogCtrlNodes
@@ -232,6 +311,8 @@ class buttonEditor:
frame['position'] = ogNodes[i]
frame['rotation'] = ogRotNodes[i]
def load(self):
global selFrame
selFrame = -1
@@ -248,9 +329,13 @@ class buttonEditor:
self.updateNodes(False)
for i in range(len(ogNodes)):
if len(ogNodes) == 1:
timeIndex = 0
else:
timeIndex = round((i)/(len(ogNodes)-1) * (displayTicks-1))
keyFrames.append({
"type": "position",
"timeIndex": round((i)/(len(ogNodes)-1) * (displayTicks-1)),
"timeIndex": timeIndex,
"index": i,
"position": ogNodes[i],
"rotation": ogRotNodes[i]
-1
View File
@@ -1,6 +1,5 @@
pg = None
render = None
bottomBarHeight = 0
class export:
name = "Export"
+6 -6
View File
@@ -38,8 +38,8 @@ def refresh():
render.circle(curveEditPointColor, curveEditPoints[i], curveEditPointRadius)
for i in range(0,len(nodeRotations)):
posX = (math.sin(nodeRotations[i])*rotNodeDist) + nodes[i][0]
posY = (math.cos(nodeRotations[i])*rotNodeDist) + nodes[i][1]
posX = (math.sin(nodeRotations[i])*rotNodeDist/render.offsetSize) + nodes[i][0]
posY = (math.cos(nodeRotations[i])*rotNodeDist/render.offsetSize) + nodes[i][1]
render.circle(rotNodeColor, (posX, posY), rotNodeRadius)
render.robotSquare(nodes[i], nodeRotations[i])
for pos in nodes:
@@ -52,8 +52,8 @@ def getElemAt(pos):
if getDist(pos, nodes[i], nodeRadius):
return 0, i
for i in range(0,len(nodeRotations)):
posX = (math.sin(nodeRotations[i])*rotNodeDist) + nodes[i][0]
posY = (math.cos(nodeRotations[i])*rotNodeDist) + nodes[i][1]
posX = (math.sin(nodeRotations[i])*rotNodeDist/render.offsetSize) + nodes[i][0]
posY = (math.cos(nodeRotations[i])*rotNodeDist/render.offsetSize) + nodes[i][1]
if getDist(pos, (posX, posY), nodeRadius):
return 2, i
for i in range(0,len(curveEditPoints)):
@@ -120,14 +120,14 @@ class pathEditor:
if clickType == 1:
curveEditPoints[clickIndex] = pos
if clickType == 2:
nodeRotations[clickIndex] = points2rad(nodes[clickIndex], nearestCirclePoint(nodes[clickIndex], pos, rotNodeDist))
nodeRotations[clickIndex] = points2rad(nodes[clickIndex], nearestCirclePoint(nodes[clickIndex], pos, rotNodeDist/render.offsetSize))
refresh()
def doubleClick(self, pos):
clickType, clickIndex = getElemAt(pos)
if clickType == -1:
pass
if clickType == 0:
elif clickType == 0:
if clickIndex > 0:
if clickIndex < len(nodes)-1:
newPos = (nodes[clickIndex-1][0]+nodes[clickIndex][0])/2,(nodes[clickIndex-1][1]+nodes[clickIndex][1])/2
+22 -20
View File
@@ -50,35 +50,37 @@ class render():
pos[1] <= rect[1]+rect[3]
def robotSquare(self, pos, rot):
pos1 = ((math.sin(rot + math.pi*-0.25)*nodeSquareRadius) + pos[0],
(math.cos(rot + math.pi*-0.25)*nodeSquareRadius) + pos[1])
pos2 = ((math.sin(rot + math.pi*0.25)*nodeSquareRadius) + pos[0],
(math.cos(rot + math.pi*0.25)*nodeSquareRadius) + pos[1])
pos3 = ((math.sin(rot + math.pi*0.75)*nodeSquareRadius) + pos[0],
(math.cos(rot + math.pi*0.75)*nodeSquareRadius) + pos[1])
pos4 = ((math.sin(rot + math.pi*1.25)*nodeSquareRadius) + pos[0],
(math.cos(rot + math.pi*1.25)*nodeSquareRadius) + pos[1])
pos1 = ((math.sin(rot + math.pi*-0.25)*nodeSquareRadius/self.offsetSize) + pos[0],
(math.cos(rot + math.pi*-0.25)*nodeSquareRadius/self.offsetSize) + pos[1])
pos2 = ((math.sin(rot + math.pi*0.25)*nodeSquareRadius/self.offsetSize) + pos[0],
(math.cos(rot + math.pi*0.25)*nodeSquareRadius/self.offsetSize) + pos[1])
pos3 = ((math.sin(rot + math.pi*0.75)*nodeSquareRadius/self.offsetSize) + pos[0],
(math.cos(rot + math.pi*0.75)*nodeSquareRadius/self.offsetSize) + pos[1])
pos4 = ((math.sin(rot + math.pi*1.25)*nodeSquareRadius/self.offsetSize) + pos[0],
(math.cos(rot + math.pi*1.25)*nodeSquareRadius/self.offsetSize) + pos[1])
pos5 = ((math.sin(rot)*(nodeSquareRadius+nodeTickLength)) + pos[0],
(math.cos(rot)*(nodeSquareRadius+nodeTickLength)) + pos[1])
pos6 = ((math.sin(rot)*(nodeSquareRadius-nodeTickLength)) + pos[0],
(math.cos(rot)*(nodeSquareRadius-nodeTickLength)) + pos[1])
pos5 = ((math.sin(rot)*(nodeSquareRadius+nodeTickLength)/self.offsetSize) + pos[0],
(math.cos(rot)*(nodeSquareRadius+nodeTickLength)/self.offsetSize) + pos[1])
pos6 = ((math.sin(rot)*(nodeSquareRadius-nodeTickLength)/self.offsetSize) + pos[0],
(math.cos(rot)*(nodeSquareRadius-nodeTickLength)/self.offsetSize) + pos[1])
self.line(nodeSquareColor, pos1, pos2, nodeSquareWidth)
self.line(nodeSquareColor, pos2, pos3, nodeSquareWidth)
self.line(nodeSquareColor, pos3, pos4, nodeSquareWidth)
self.line(nodeSquareColor, pos4, pos1, nodeSquareWidth)
self.line(nodeSquareColor, pos1, pos2, nodeSquareWidth*self.offsetSize)
self.line(nodeSquareColor, pos2, pos3, nodeSquareWidth*self.offsetSize)
self.line(nodeSquareColor, pos3, pos4, nodeSquareWidth*self.offsetSize)
self.line(nodeSquareColor, pos4, pos1, nodeSquareWidth*self.offsetSize)
self.line(nodeSquareColor, pos5, pos6, nodeSquareWidth)
self.line(nodeSquareColor, pos5, pos6, nodeSquareWidth*self.offsetSize)
def bezier(self, p0, p1, p2, curvePointCount):
#for p in [p0, p1, p2]:
# pg.draw.circle(self.screen, (255, 255, 255), p, 5)
for t in np.arange(0, 1, 1/curvePointCount):
px = p0[0]*(1-t)**2 + 2*(1-t)*t*p1[0] + p2[0]*t**2
py = p0[1]*(1-t)**2 + 2*(1-t)*t*p1[1] + p2[1]*t**2
self.circle(curvePointColor, (px, py), curvePointRadius)
px = p0[0]*(1-t)**2 + 2*(1-t)*t*p1[0] + p2[0]*t**2
py = p0[1]*(1-t)**2 + 2*(1-t)*t*p1[1] + p2[1]*t**2
self.circle(curvePointColor, (px, py), curvePointRadius)
self.circle(curvePointColor, p2, curvePointRadius)
#self.drawrect(curvePointColor, (round(px+0.5), round(py+0.5), curvePointRadius, curvePointRadius))
def clear(self):
self.pg.draw.rect(self.screen, (0, 0, 0), self.rect)