Add exporting

This commit is contained in:
Astatin3
2024-03-19 20:43:48 -06:00
parent a5467a244c
commit 0a3ded5a1b
7 changed files with 249 additions and 13 deletions
+4
View File
@@ -24,3 +24,7 @@ python3 ./main.py
##### "Export" Tab: ##### "Export" Tab:
- Click export, and save to a file - Click export, and save to a file
### Known Bugs:
- Because the variables don't get transferred over yet, you must click on the button editor tab before exporting.
- The driver controller's movement stick is rotated by 90 degrees (Maybe)
+3 -1
View File
@@ -32,7 +32,7 @@ tabIndex = 0
tabs = [ tabs = [
pathEditor.pathEditor(render), pathEditor.pathEditor(render),
buttonEditor.buttonEditor(render, pathEditor), buttonEditor.buttonEditor(render, pathEditor),
export.export(pg, render) export.export(pg, render, buttonEditor)
] ]
tabs[tabIndex].load() tabs[tabIndex].load()
@@ -51,6 +51,7 @@ def addTab(i):
def onClick(pos): def onClick(pos):
global tabIndex global tabIndex
tabs[tabIndex].unload()
tabIndex = i tabIndex = i
tabs[tabIndex].load() tabs[tabIndex].load()
render.renderElements(pos) render.renderElements(pos)
@@ -100,6 +101,7 @@ while running:
elif event.type == pg.KEYDOWN: elif event.type == pg.KEYDOWN:
tabs[tabIndex].keyDown(event.key) tabs[tabIndex].keyDown(event.key)
if event.key == pg.K_TAB: if event.key == pg.K_TAB:
tabs[tabIndex].unload()
tabIndex = (tabIndex + 1) % len(tabs) tabIndex = (tabIndex + 1) % len(tabs)
tabs[tabIndex].load() tabs[tabIndex].load()
render.renderElements(pg.mouse.get_pos()) render.renderElements(pg.mouse.get_pos())
+3
View File
@@ -0,0 +1,3 @@
numpy
pygame
crossfiledialog
+8
View File
@@ -17,6 +17,7 @@ keyFrames = []
matchLength = 15 matchLength = 15
TPS = 50 TPS = 50
tickTime = round(1/TPS*1000)
matchTicks = matchLength * TPS matchTicks = matchLength * TPS
displayTickResolution = 4 displayTickResolution = 4
displayTicks = round(matchTicks / displayTickResolution) displayTicks = round(matchTicks / displayTickResolution)
@@ -165,6 +166,9 @@ def getButtonFrameAtPos(index):
def getRobotAtIndex(index): def getRobotAtIndex(index):
prevFrame, nextFrame = getSurroundingPosFrames(index) prevFrame, nextFrame = getSurroundingPosFrames(index)
# print(prevFrame)
# print(nextFrame)
if prevFrame == None and nextFrame == None: if prevFrame == None and nextFrame == None:
return (0,0), 0 return (0,0), 0
if prevFrame == None: if prevFrame == None:
@@ -644,3 +648,7 @@ class buttonEditor:
self.updateNodes(True) self.updateNodes(True)
self.refresh() self.refresh()
def unload(self):
pass
+223 -3
View File
@@ -1,16 +1,224 @@
import crossfiledialog
import struct
import copy
pg = None pg = None
render = None buttonEditor = None
events = []
#Save according to https://github.com/Team4388/2024AcrossTheRidgebotiverse/blob/Prep-For-Denver/src/main/java/frc4388/robot/commands/Autos/neo%20AutoRecoding%20format.txt
moveMultiplier = 0.1
rotMultiplier = 1
def buttonsToBytes(buttons):
data = 0
for i in range(16):
data |= buttons[i] << i
return data.to_bytes(2, "little", signed=True)
def toByte(num):
if num > 255:
raise OverflowError
return num.to_bytes(1, 'big', signed=False)
def toShort(num):
if num > 65535:
raise OverflowError
return num.to_bytes(2, 'big', signed=True)
def toInt(num):
return struct.pack('>i', num)
def toDouble(num):
return struct.pack('>d', num)
class xboxController:
def __init__(self):
self.buttons = [False for i in range(16)]
self.leftStick = (0,0)
self.rightStick = (0,0)
self.LT = -1
self.RT = -1
self.POV = -1
def getPOVhat(up, down, left, right):
if up and right:
return 45
elif right and down:
return 135
elif down and left:
return 225
elif left and up:
return 315
elif up:
return 0
elif right:
return 90
elif down:
return 180
elif left:
return 270
else:
return -1
def getSticksAtFrame(index):
fractionIndex = round(index/buttonEditor.displayTickResolution)
newpos, newrot = buttonEditor.getRobotAtIndex(fractionIndex)
oldpos, oldrot = buttonEditor.getRobotAtIndex(fractionIndex-1)
# print(oldrot-newrot)
diffPos = ((oldpos[0]-newpos[0])*moveMultiplier, (oldpos[1]-newpos[1])*moveMultiplier)
diffRot = (oldrot-newrot)*rotMultiplier
if abs(diffPos[0]) > 1 or abs(diffPos[1]) > 1 or abs(diffRot) > 1:
print("Error! Robot moved too fast!, Try to edit 'Multiplier' values in export.py")
return (0, 0), 0
print(diffPos)
# print(diffRot)
return diffPos, diffRot
def getControllersAtFrame(index):
controllers = [xboxController(), xboxController()]
if index >= buttonEditor.matchTicks:
return controllers
pos, rot = getSticksAtFrame(index)
controllers[0].leftStick = pos
controllers[0].rightStick = (rot,0)
btns = buttonEditor.getLeftButtonFrame(index)
if btns == None:
btns = buttonEditor.createBlankController()
else:
btns = btns['controllers']
for i in range(len(controllers)):
ctrlr = btns[i]
controllers[i].buttons[0] = ctrlr['A']
controllers[i].buttons[1] = ctrlr['B']
controllers[i].buttons[2] = ctrlr['X']
controllers[i].buttons[3] = ctrlr['Y']
controllers[i].buttons[4] = ctrlr['LB']
controllers[i].buttons[5] = ctrlr['RB']
controllers[i].buttons[6] = ctrlr['Menu']
controllers[i].buttons[7] = ctrlr['Windows']
controllers[i].buttons[8] = ctrlr['Left_Stick']
controllers[i].buttons[9] = ctrlr['Right_Stick']
controllers[i].LT = (ctrlr['LT']*2)-1
controllers[i].RT = (ctrlr['RT']*2)-1
controllers[i].POV = getPOVhat(ctrlr['Dpad_Up'], ctrlr['Dpad_Down'],
ctrlr['Dpad_Left'], ctrlr['Dpad_Right'])
return controllers
def getFrameData(index):
controllers = getControllersAtFrame(index)
data = b''
for ctrlr in controllers:
# print(ctrlr.leftStick[0])
data += toDouble(ctrlr.leftStick[0])
data += toDouble(ctrlr.leftStick[1])
data += toDouble(ctrlr.LT)
data += toDouble(ctrlr.RT)
data += toDouble(ctrlr.rightStick[0])
data += toDouble(ctrlr.rightStick[1])
data += buttonsToBytes(ctrlr.buttons)
# for btn in ctrlr.buttons:
# data += toBit(data)
# print(toBit(data))
data += toShort(ctrlr.POV)
data += toInt(index * buttonEditor.tickTime)
return data
def getHeader():
header = toByte(6) # Num Axes per controller
header += toByte(1) # Num POVs
header += toByte(2) # Num Controllers
header += toShort(buttonEditor.matchTicks) # Num Frames
return header
def getData():
data = b''
for i in range(buttonEditor.matchTicks):
data += getFrameData(i)
return getHeader() + data
def save():
path = crossfiledialog.save_file('Save auto file', './')
# path = "./file.txt"
with open(path, "wb") as f:
f.write(getData())
class export: class export:
name = "Export" name = "Export"
def __init__(self, tmppg, tmprender): def __init__(self, tmppg, tmprender, tmpbuttonEditor):
global pg global pg
pg = tmppg pg = tmppg
global render global render
render = tmprender render = tmprender
global buttonEditor
buttonEditor = tmpbuttonEditor
# render.addButton() self.loaded = False
def getIsSelected():
return False
def getIsVisible():
return self.loaded
def onClick(pos):
save()
render.addButton((round(render.width/4),round(render.screen.get_height()/4),round(render.width/2),round(render.height/2)),
"Export", getIsSelected, getIsVisible, onClick)
def mouseDown(self, pos): def mouseDown(self, pos):
pass pass
@@ -28,5 +236,17 @@ class export:
pass pass
def load(self): def load(self):
self.loaded = True
# for keyFrame in buttonEditor.keyFrames:
# keyFrame['timeIndex'] = keyFrame['timeIndex'] * buttonEditor.displayTickResolution
render.clear() render.clear()
pg.display.update() pg.display.update()
def unload(self):
self.loaded = False
# for keyFrame in buttonEditor.keyFrames:
# keyFrame['timeIndex'] = round(keyFrame['timeIndex'] / buttonEditor.displayTickResolution)
+3 -4
View File
@@ -161,12 +161,11 @@ class pathEditor:
nodeRotations.pop(clickIndex) nodeRotations.pop(clickIndex)
refresh() refresh()
def keyDown(self, key): def keyDown(self, key):
pass pass
def load(self): def load(self):
refresh() refresh()
def unload(self):
pass
+1 -1
View File
@@ -159,7 +159,7 @@ class render():
def clickElement(self, pos): def clickElement(self, pos):
for elem in self.elements: for elem in self.elements:
if elem['type'] == 'button' and self.isInRect(pos, elem['rect']): if elem['type'] == 'button' and elem['getIsVisible']() and self.isInRect(pos, elem['rect']):
elem['onClick'](pos) elem['onClick'](pos)