diff --git a/.gitignore b/.gitignore index d9005f2..da7e738 100644 --- a/.gitignore +++ b/.gitignore @@ -150,3 +150,4 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +.vscode/ \ No newline at end of file diff --git a/frc2024.png b/images/Field.png similarity index 100% rename from frc2024.png rename to images/Field.png diff --git a/images/XboxOne_A.png b/images/XboxOne_A.png new file mode 100644 index 0000000..28c3b60 Binary files /dev/null and b/images/XboxOne_A.png differ diff --git a/images/XboxOne_B.png b/images/XboxOne_B.png new file mode 100644 index 0000000..2a4d9b6 Binary files /dev/null and b/images/XboxOne_B.png differ diff --git a/images/XboxOne_Diagram.png b/images/XboxOne_Diagram.png new file mode 100644 index 0000000..9b79c5d Binary files /dev/null and b/images/XboxOne_Diagram.png differ diff --git a/images/XboxOne_Diagram_Simple.png b/images/XboxOne_Diagram_Simple.png new file mode 100644 index 0000000..7e3a1d9 Binary files /dev/null and b/images/XboxOne_Diagram_Simple.png differ diff --git a/images/XboxOne_Dpad.png b/images/XboxOne_Dpad.png new file mode 100644 index 0000000..9c04c85 Binary files /dev/null and b/images/XboxOne_Dpad.png differ diff --git a/images/XboxOne_Dpad_Down.png b/images/XboxOne_Dpad_Down.png new file mode 100644 index 0000000..8c1134c Binary files /dev/null and b/images/XboxOne_Dpad_Down.png differ diff --git a/images/XboxOne_Dpad_Left.png b/images/XboxOne_Dpad_Left.png new file mode 100644 index 0000000..45ddb16 Binary files /dev/null and b/images/XboxOne_Dpad_Left.png differ diff --git a/images/XboxOne_Dpad_Right.png b/images/XboxOne_Dpad_Right.png new file mode 100644 index 0000000..a1fbc2c Binary files /dev/null and b/images/XboxOne_Dpad_Right.png differ diff --git a/images/XboxOne_Dpad_Up.png b/images/XboxOne_Dpad_Up.png new file mode 100644 index 0000000..e8eab7d Binary files /dev/null and b/images/XboxOne_Dpad_Up.png differ diff --git a/images/XboxOne_LB.png b/images/XboxOne_LB.png new file mode 100644 index 0000000..f6c414b Binary files /dev/null and b/images/XboxOne_LB.png differ diff --git a/images/XboxOne_LT.png b/images/XboxOne_LT.png new file mode 100644 index 0000000..e9681c9 Binary files /dev/null and b/images/XboxOne_LT.png differ diff --git a/images/XboxOne_Left_Stick.png b/images/XboxOne_Left_Stick.png new file mode 100644 index 0000000..9c5ca5c Binary files /dev/null and b/images/XboxOne_Left_Stick.png differ diff --git a/images/XboxOne_Left_Stick_Click.png b/images/XboxOne_Left_Stick_Click.png new file mode 100644 index 0000000..ad0428f Binary files /dev/null and b/images/XboxOne_Left_Stick_Click.png differ diff --git a/images/XboxOne_Menu.png b/images/XboxOne_Menu.png new file mode 100644 index 0000000..2cbfb08 Binary files /dev/null and b/images/XboxOne_Menu.png differ diff --git a/images/XboxOne_RB.png b/images/XboxOne_RB.png new file mode 100644 index 0000000..5dcfc6d Binary files /dev/null and b/images/XboxOne_RB.png differ diff --git a/images/XboxOne_RT.png b/images/XboxOne_RT.png new file mode 100644 index 0000000..7bf27f4 Binary files /dev/null and b/images/XboxOne_RT.png differ diff --git a/images/XboxOne_Right_Stick.png b/images/XboxOne_Right_Stick.png new file mode 100644 index 0000000..3d83a22 Binary files /dev/null and b/images/XboxOne_Right_Stick.png differ diff --git a/images/XboxOne_Right_Stick_Click.png b/images/XboxOne_Right_Stick_Click.png new file mode 100644 index 0000000..de08508 Binary files /dev/null and b/images/XboxOne_Right_Stick_Click.png differ diff --git a/images/XboxOne_Windows.png b/images/XboxOne_Windows.png new file mode 100644 index 0000000..3756d29 Binary files /dev/null and b/images/XboxOne_Windows.png differ diff --git a/images/XboxOne_X.png b/images/XboxOne_X.png new file mode 100644 index 0000000..a0f0ac1 Binary files /dev/null and b/images/XboxOne_X.png differ diff --git a/images/XboxOne_Y.png b/images/XboxOne_Y.png new file mode 100644 index 0000000..4e31627 Binary files /dev/null and b/images/XboxOne_Y.png differ diff --git a/main.py b/main.py index b29e324..fd64fb3 100644 --- a/main.py +++ b/main.py @@ -47,6 +47,9 @@ def addTab(i): global tabIndex return tabIndex == i + def getIsVisible(): + return True + def onClick(pos): global tabIndex tabIndex = i @@ -54,7 +57,7 @@ def addTab(i): render.renderElements(pos) pg.display.update() - render.addButton(rect, tabs[i].name, getIsSelected, onClick) + render.addButton(rect, tabs[i].name, getIsSelected, getIsVisible, onClick) for i in range(len(tabs)): addTab(i) @@ -97,6 +100,10 @@ while running: elif event.type == pg.KEYDOWN: tabs[tabIndex].keyDown(event.key) + if event.key == pg.K_TAB: + tabIndex = (tabIndex + 1) % len(tabs) + tabs[tabIndex].load() + render.renderElements(pg.mouse.get_pos()) elif event.type == pg.QUIT: running = False diff --git a/src/buttonEditor.py b/src/buttonEditor.py index 8363077..41739ab 100644 --- a/src/buttonEditor.py +++ b/src/buttonEditor.py @@ -20,15 +20,31 @@ ogDragFramePos = -1 selFrame = -1 +buttonImages = {} +buttonMode = False +buttonPositions = { + 'A': ((1089,494),100), + 'B': ((1187,404),100), + 'X': ((996,411),100), + 'Y': ((1093,321),100), + + 'Dpad': ((549,619),220), + + 'Menu': ((832,411),100), + 'Windows': ((629,411),100), + + 'Left_Stick': ((375,422),150), + 'Right_Stick': ((914,622),150), + + 'LB': ((352,184),150), + 'RB': ((1100,184),150), + + 'LT': ((356,67),150), + 'RT': ((1096,67),150) +} -def getPosKeyframes(): - frames = [] - for keyFrame in keyFrames: - if keyFrame['type'] == 'position': - frames.append(keyFrame) - return frames - +controllerCount = 2 def getKeyframeAtPos(index): @@ -39,6 +55,13 @@ def getKeyframeAtPos(index): +def getFrameIndex(frame): + if frame == None: + return -1 + return keyFrames.index(frame) + + + def getPosKeyframeAtPos(index): for frame in keyFrames: if frame["timeIndex"] == index and frame['type'] == 'position': @@ -47,6 +70,15 @@ def getPosKeyframeAtPos(index): +def getPosKeyframes(): + frames = [] + for keyFrame in keyFrames: + if keyFrame['type'] == 'position': + frames.append(keyFrame) + return frames + + + def getBezierPointCounts(): counts = [] frames = getPosKeyframes() @@ -64,13 +96,6 @@ def getPosKeyframeByIndex(index): -def getFrameIndex(frame): - if frame == None: - return -1 - return keyFrames.index(frame) - - - def getSurroundingPosFrames(index): prevFrame = None for i in range(index,-1,-1): @@ -214,6 +239,82 @@ def clickBar(pos, doubleClick): }) return +# def getControllerRects(): +# rects = [] +# for i in range(controllerCount): +# rects.append() + +def renderXboxControllers(): + for rect in controllerRects: + + offsetSize = rect[2]/buttonImages['Controller'].get_width() + + def offsetControllerButton(index): + pos, size = buttonPositions[index] + rect2 = ((pos[0]-(size/2), pos[1]-(size/2), size, size)) + return (rect[0]+(rect2[0])*offsetSize,rect[1]+(rect2[1])*offsetSize,rect2[2]*offsetSize,rect2[2]*offsetSize) + + + render.image(buttonImages['Controller'], rect) + + render.image(buttonImages['A'], offsetControllerButton('A')) + render.image(buttonImages['B'], offsetControllerButton('B')) + render.image(buttonImages['X'], offsetControllerButton('X')) + render.image(buttonImages['Y'], offsetControllerButton('Y')) + + render.image(buttonImages['Dpad'], offsetControllerButton('Dpad')) + + render.image(buttonImages['Menu'], offsetControllerButton('Menu')) + render.image(buttonImages['Windows'], offsetControllerButton("Windows")) + + render.image(buttonImages['Left_Stick'], offsetControllerButton('Left_Stick')) + render.image(buttonImages['Right_Stick'], offsetControllerButton('Right_Stick')) + + + render.image(buttonImages['LB'], offsetControllerButton('LB')) + render.image(buttonImages['RB'], offsetControllerButton('RB')) + + render.image(buttonImages['LT'], offsetControllerButton("LT")) + render.image(buttonImages['RT'], offsetControllerButton('RT')) + +def controllerClick(pos): + for rect in controllerRects: + + offsetSize = rect[2]/buttonImages['Controller'].get_width() + + def offsetControllerButton(index): + pos, size = buttonPositions[index] + rect2 = ((pos[0]-(size/2), pos[1]-(size/2), size, size)) + return (rect[0]+(rect2[0])*offsetSize,rect[1]+(rect2[1])*offsetSize,rect2[2]*offsetSize,rect2[2]*offsetSize) + + + if render.isInRect(pos, offsetControllerButton('A')): + print('A!') + elif render.isInRect(pos, offsetControllerButton('B')): + pass + elif render.isInRect(pos, offsetControllerButton('X')): + pass + elif render.isInRect(pos, offsetControllerButton('Y')): + pass + elif render.isInRect(pos, offsetControllerButton('Dpad')): + pass + elif render.isInRect(pos, offsetControllerButton('Menu')): + pass + elif render.isInRect(pos, offsetControllerButton('Windows')): + pass + elif render.isInRect(pos, offsetControllerButton('Left_Stick')): + pass + elif render.isInRect(pos, offsetControllerButton('Right_Stick')): + pass + elif render.isInRect(pos, offsetControllerButton('LB')): + pass + elif render.isInRect(pos, offsetControllerButton('RB')): + pass + elif render.isInRect(pos, offsetControllerButton('LT')): + pass + elif render.isInRect(pos, offsetControllerButton('RT')): + pass + class buttonEditor: name = "Button Editor" @@ -229,31 +330,75 @@ class buttonEditor: global bottomBarRect bottomBarRect = (0, (render.screen.get_height()-render.bottomBarHeight), render.screen.get_width(), render.bottomBarHeight) + global buttonImages + buttonImages = { + "Controller": render.pg.image.load('images/XboxOne_Diagram_Simple.png').convert_alpha(), + + "A": render.pg.image.load('images/XboxOne_A.png').convert_alpha(), + "B": render.pg.image.load('images/XboxOne_B.png').convert_alpha(), + "X": render.pg.image.load('images/XboxOne_X.png').convert_alpha(), + "Y": render.pg.image.load('images/XboxOne_Y.png').convert_alpha(), + + "Dpad": render.pg.image.load('images/XboxOne_Dpad.png').convert_alpha(), + "Dpad_Up": render.pg.image.load('images/XboxOne_Dpad_Up.png').convert_alpha(), + "Dpad_Down": render.pg.image.load('images/XboxOne_Dpad_Down.png').convert_alpha(), + "Dpad_Left": render.pg.image.load('images/XboxOne_Dpad_Left.png').convert_alpha(), + "Dpad_Right": render.pg.image.load('images/XboxOne_Dpad_Right.png').convert_alpha(), + + "Menu": render.pg.image.load('images/XboxOne_Menu.png').convert_alpha(), + "Windows": render.pg.image.load('images/XboxOne_Windows.png').convert_alpha(), + + "Left_Stick": render.pg.image.load('images/XboxOne_Left_Stick.png').convert_alpha(), + "Left_Stick_Click": render.pg.image.load('images/XboxOne_Left_Stick_Click.png').convert_alpha(), + "Right_Stick": render.pg.image.load('images/XboxOne_Right_Stick.png').convert_alpha(), + "Right_Stick_Click": render.pg.image.load('images/XboxOne_Right_Stick_Click.png').convert_alpha(), + + + "LB": render.pg.image.load('images/XboxOne_LB.png').convert_alpha(), + "RB": render.pg.image.load('images/XboxOne_RB.png').convert_alpha(), + "LT": render.pg.image.load('images/XboxOne_LT.png').convert_alpha(), + "RT": render.pg.image.load('images/XboxOne_RT.png').convert_alpha() + + } + ControllerSize = (render.width/2, render.width*(buttonImages['Controller'].get_height()/buttonImages['Controller'].get_width())/2) + ControllerYOffset = (render.height-ControllerSize[1])/2 + global controllerRects + controllerRects = { + (0, render.topBarHeight+ControllerYOffset, ControllerSize[0], ControllerSize[1]), + (ControllerSize[0], render.topBarHeight+ControllerYOffset, ControllerSize[0], ControllerSize[1]) + } def refresh(self): - global ogNodes - global ogCtrlNodes - global ogRotNodes - render.clear() - render.drawField() - - pointCounts = getBezierPointCounts() - for i in range(0,len(ogCtrlNodes)): - render.bezier(ogNodes[i], ogCtrlNodes[i], ogNodes[i+1], pointCounts[i]) - - if selFrame != -1 and len(ogNodes) > 0: - pos, rot = getRobotAtIndex(selFrame) - render.robotSquare(pos, rot) - + if not buttonMode: + global ogNodes + global ogCtrlNodes + global ogRotNodes + + render.drawField() + + pointCounts = getBezierPointCounts() + for i in range(0,len(ogCtrlNodes)): + render.bezier(ogNodes[i], ogCtrlNodes[i], ogNodes[i+1], pointCounts[i]) + + if selFrame != -1 and len(ogNodes) > 0: + pos, rot = getRobotAtIndex(selFrame) + render.robotSquare(pos, rot) + else: + renderXboxControllers() + + reloadBar((0,0)) render.update() def mouseDown(self, pos): - if pos[1] > bottomBarRect[1]: + if buttonMode: + controllerClick(pos) + self.refresh() + elif pos[1] > bottomBarRect[1]: clickBar(pos, False) self.refresh() @@ -292,6 +437,10 @@ class buttonEditor: elif key == render.pg.K_RIGHT and selFrame < displayTicks-1: selFrame += 1 self.refresh() + elif key == render.pg.K_e: + global buttonMode + buttonMode = not buttonMode + self.refresh() diff --git a/src/pathEditor.py b/src/pathEditor.py index cb03f2f..813393b 100644 --- a/src/pathEditor.py +++ b/src/pathEditor.py @@ -26,6 +26,8 @@ clickIndex = -1 render = None + + def refresh(): render.clear() render.drawField() @@ -47,6 +49,8 @@ def refresh(): render.circle(nodeColor, pos, nodeRadius) render.update() + + def getElemAt(pos): for i in range(0,len(nodes)): if getDist(pos, nodes[i], nodeRadius): @@ -61,9 +65,13 @@ def getElemAt(pos): return 1, i return -1, -1 + + def getDist(pos1, pos2, dist): return math.sqrt(math.pow(pos1[0]-pos2[0], 2) + math.pow(pos1[1]-pos2[1], 2)) <= dist + + def addNode(pos): nodes.append(pos) if len(nodes) > 1: @@ -76,6 +84,8 @@ def addNode(pos): nodeRotations.append(math.pi/2) refresh() + + def nearestCirclePoint(center, pos, R): vX = pos[0] - center[0] vY = pos[1] - center[1] @@ -84,6 +94,8 @@ def nearestCirclePoint(center, pos, R): aY = center[1] + vY / magV * R return (aX, aY) + + def points2rad(center, pos): diffX = center[0] - pos[0] diffY = center[1] - pos[1] @@ -91,6 +103,8 @@ def points2rad(center, pos): class pathEditor: name = "Path Editor" + + def __init__(self, tmprender): # global screen # screen = tmpscreen @@ -99,30 +113,38 @@ class pathEditor: refresh() + + def mouseDown(self, pos): global clickType global clickIndex clickType, clickIndex = getElemAt(pos) if clickType == -1: addNode(pos) - + + + def mouseUp(self, pos): global clickType global clickIndex if clickType != -1: clickType = -1 clickIndex = -1 - + + + def mouseMove(self, pos): if clickType != -1: if clickType == 0: - nodes[clickIndex] = pos + nodes[clickIndex] = pos if clickType == 1: - curveEditPoints[clickIndex] = pos + curveEditPoints[clickIndex] = pos if clickType == 2: - nodeRotations[clickIndex] = points2rad(nodes[clickIndex], nearestCirclePoint(nodes[clickIndex], pos, rotNodeDist/render.offsetSize)) + nodeRotations[clickIndex] = points2rad(nodes[clickIndex], nearestCirclePoint(nodes[clickIndex], pos, rotNodeDist/render.offsetSize)) refresh() + + def doubleClick(self, pos): clickType, clickIndex = getElemAt(pos) if clickType == -1: @@ -139,8 +161,12 @@ class pathEditor: nodeRotations.pop(clickIndex) refresh() + + def keyDown(self, key): pass - + + + def load(self): refresh() \ No newline at end of file diff --git a/src/render.py b/src/render.py index d589f97..baa6534 100644 --- a/src/render.py +++ b/src/render.py @@ -15,6 +15,8 @@ nodeSquareWidth = 3 nodeTickLength = 5 class render(): + + def __init__(self, pg, screen, topBarHeight, bottomBarHeight): self.pg = pg self.screen = screen @@ -28,20 +30,32 @@ class render(): self.font = self.pg.font.Font(None, 25) - self.fieldImg = pg.image.load("frc2024.png").convert_alpha() + self.fieldImg = pg.image.load("images/Field.png").convert_alpha() self.offsetSize = self.fieldImg.get_width() / self.width self.fieldImg = pg.transform.scale(self.fieldImg, (self.width, self.height)) self.elements = [] + def invert(img): + inv = pygame.Surface(img.get_rect().size, pygame.SRCALPHA) + inv.fill((255,255,255,255)) + inv.blit(img, (0,0), None, BLEND_RGB_SUB) + return inv + def line(self, color, pos1, pos2, width): - self.pg.draw.line(self.screen, color, pos1, pos2, round(width/self.offsetSize)) + self.pg.draw.line(self.screen, color, pos1, pos2, round(width/self.offsetSize)) + + def circle(self, color, pos, radius): - self.pg.draw.circle(self.screen, color, pos, radius/self.offsetSize) + self.pg.draw.circle(self.screen, color, pos, radius/self.offsetSize) + + def drawrect(self, color, rect): - self.pg.draw.rect(self.screen, color, rect) + self.pg.draw.rect(self.screen, color, rect) + + def isInRect(self, pos, rect): return pos[0] >= rect[0] and \ @@ -49,6 +63,13 @@ class render(): pos[1] >= rect[1] and \ pos[1] <= rect[1]+rect[3] + + + def image(self, img, rect): + self.screen.blit(self.pg.transform.scale(img, (rect[2], rect[3])), rect) + + + def robotSquare(self, pos, rot): 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]) @@ -72,6 +93,8 @@ class render(): 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) @@ -82,35 +105,50 @@ class render(): 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) + + def drawField(self): self.screen.blit(self.fieldImg, self.rect) + + def renderElements(self, pos): for elem in self.elements: - if elem['type'] == 'button': + if elem['type'] == 'button' and elem['getIsVisible'](): # print(elem['getIsSelected']()) self.renderButton(elem['rect'], elem['text'], elem['getIsSelected'](), pos) + + def clickElement(self, pos): for elem in self.elements: if elem['type'] == 'button' and self.isInRect(pos, elem['rect']): elem['onClick'](pos) + + def update(self): self.pg.display.update() - def addButton(self, rect, text, getIsSelected, onClick): + + + def addButton(self, rect, text, getIsSelected, getIsVisible, onClick): self.elements.append({ "type": "button", "text": text, "getIsSelected": getIsSelected, + "getIsVisible": getIsVisible, "onClick": onClick, "rect": rect }) + + def renderButton(self, rect, text, selected, mousePos): # print(isInRect(mousePos, rect))