Good tabs

This commit is contained in:
Astatin3
2024-03-14 12:35:36 -06:00
parent 2dab7295ac
commit 5ee635352d
6 changed files with 334 additions and 72 deletions
+51 -42
View File
@@ -1,4 +1,6 @@
import math
from copy import copy
import pygame as pg
from pygame.locals import *
from sys import exit
@@ -7,6 +9,8 @@ import numpy as np
import src.render as render
import src.menu as menu
import src.pathEditor as pathEditor
import src.buttonEditor as buttonEditor
import src.export as export
doubleClickDuration = 200
@@ -14,50 +18,48 @@ pg.init()
pg.font.init()
topBarHeight = 40
bottomBarHeight = 40
bottomBarHeight = 60
screen_width = 1200
screen_height = (screen_width * (643/1286)) + topBarHeight + bottomBarHeight
screen = pg.display.set_mode((screen_width, screen_height))
screen = pg.display.set_mode((screen_width, screen_height))#, pg.RESIZABLE)
pg.display.set_caption("Auto Planner")
pathR = render.render(pg, screen, topBarHeight)
tabIndex = 1
render = render.render(pg, screen, topBarHeight, bottomBarHeight)
tabIndex = 0
tabs = [
menu.menu(pg, pathR),
pathEditor.pathEditor(pg, pathR)
menu.menu(pg, render),
pathEditor.pathEditor(render),
buttonEditor.buttonEditor(render, pathEditor),
export.export(pg, render)
]
def isInRect(pos, rect):
return pos[0] >= rect[0] and \
pos[0] <= rect[2] and \
pos[1] >= rect[1] and \
pos[1] <= rect[3]
tabs[tabIndex].load()
def refreshTabs(pos):
for i in range(len(tabs)):
# color = i * (255/(len(tabs)-1))
# color = (color, color, color)
x1 = i * (screen_width/(len(tabs)))
x2 = (i+1) * (screen_width/(len(tabs)))
rect = (x1, 0, x2, topBarHeight)
if i == tabIndex:
color = (255, 255, 255)
elif isInRect(pos, rect):
color = (127,127,127)
else:
color = (63,63,63)
pg.draw.rect(screen, color, rect)
pg.display.update()
refreshTabs((screen_width/2, screen_height/2))
def addTab(i):
x1 = i * (screen_width/(len(tabs)))
x2 = (screen_width/(len(tabs)))
rect = (x1, 0, x2, topBarHeight)
def getIsSelected():
global tabIndex
return tabIndex == i
def onClick(pos):
global tabIndex
tabIndex = i
tabs[tabIndex].load()
render.renderElements(pos)
pg.display.update()
render.addButton(rect, tabs[i].name, getIsSelected, onClick)
for i in range(len(tabs)):
addTab(i)
render.renderElements((screen_width/2, screen_height/2))
running = True
last_click = -1
@@ -68,8 +70,16 @@ def offsetPos(pos):
while running:
for event in pg.event.get():
if event.type == pg.MOUSEBUTTONDOWN:
if event.type == pg.MOUSEMOTION:
pos = pg.mouse.get_pos()
render.renderElements(pos)
if pos[1] > topBarHeight:
tabs[tabIndex].mouseMove(offsetPos(pos))
# refreshTabs(pos)
elif event.type == pg.MOUSEBUTTONDOWN:
pos = pg.mouse.get_pos()
render.clickElement(pos)
if pos[1] > topBarHeight:
now = pg.time.get_ticks()
if now - last_click <= doubleClickDuration:
@@ -77,19 +87,18 @@ while running:
else:
tabs[tabIndex].mouseDown(offsetPos(pos))
last_click = pg.time.get_ticks()
if event.type == pg.MOUSEMOTION:
pos = pg.mouse.get_pos()
if pos[1] > topBarHeight:
tabs[tabIndex].mouseMove(offsetPos(pos))
refreshTabs(pos)
# else:
# clickTab(pos)
if event.type == pg.MOUSEBUTTONUP:
elif event.type == pg.MOUSEBUTTONUP:
pos = pg.mouse.get_pos()
if pos[1] > topBarHeight:
tabs[tabIndex].mouseUp(offsetPos(pos))
if event.type == pg.QUIT:
elif event.type == pg.KEYDOWN:
tabs[tabIndex].keyDown(event.key)
elif event.type == pg.QUIT:
running = False
pg.quit()
+148
View File
@@ -0,0 +1,148 @@
render = None
pathEditor = None
bottomBarRect = None
ogNodes = []
ogCtrlNodes = []
events = []
matchLength = 15
matchTicks = 15 * 50
displayTickResolution = 5
displayTicks = round(matchTicks / displayTickResolution)
indicatorBarRect = None
selFrame = -1
# def addTab(i):
# x1 = i * (render.width/(displayTicks))
# x2 = (render.width/(displayTicks))
# rect = (x1, bottomBarRect[1], x2, bottomBarRect[3])
# def getIsSelected():
# return False
# def onClick(pos):
# pass
# render.addButton(rect, "", getIsSelected, onClick)
def getTimeBarColor(index):
for event in events:
if event["timeIndex"] == index:
if event['type'] == 'position':
return (127,127,0)
elif event['type'] == 'controller':
return (0,127,0)
return (16,16,32)
def renderSelectIndicator(i):
x1 = i * (render.width/(displayTicks))
x2 = (render.width/(displayTicks))
rect = (x1, indicatorBarRect[1], x2, indicatorBarRect[3])
if i == selFrame:
render.drawrect((255,0,0), rect)
def reloadBar(pos):
toggle = False
for i in range(displayTicks):
x1 = i * (render.width/(displayTicks))
x2 = (render.width/(displayTicks))
rect = (x1, bottomBarRect[1], x2, bottomBarRect[3])
color = getTimeBarColor(i)
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)
else:
color = (color[0]+16+(toggle*16),color[1]+16+(toggle*16),color[2]+32+(toggle*16))
toggle = not toggle
render.drawrect(color, rect)
renderSelectIndicator(i)
render.update()
def clickBar(pos):
for i in range(displayTicks):
x1 = i * (render.width/(displayTicks))
x2 = (render.width/(displayTicks))
rect = (x1, bottomBarRect[1], x2, bottomBarRect[3])
if render.isInRect(pos, rect):
global selFrame
selFrame = i
reloadBar(pos)
return
class buttonEditor:
name = "Button Editor"
def __init__(self, tmprender, tmppathEditor):
global render
render = tmprender
global pathEditor
pathEditor = tmppathEditor
global indicatorBarRect
indicatorBarHeight = round(render.screen.get_width()/displayTicks)
indicatorBarRect = (0, render.screen.get_height()-indicatorBarHeight, render.screen.get_width(), indicatorBarHeight)
global bottomBarRect
bottomBarRect = (0, (render.screen.get_height()-render.bottomBarHeight), render.screen.get_width(), render.screen.get_height())
def refresh(self):
render.clear()
render.drawField()
render.renderBezier(pathEditor.nodes, pathEditor.curveEditPoints)
reloadBar((0,0))
render.update()
def mouseDown(self, pos):
if pos[1] > bottomBarRect[1]:
clickBar(pos)
pass
def mouseUp(self, pos):
pass
def mouseMove(self, pos):
reloadBar(pos)
def doubleClick(self, pos):
pass
def keyDown(self, key):
pass
def load(self):
global ogNodes
global ogCtrlNodes
global selFrame
selFrame = -1
# for i in range(displayTicks):
# addTab(i)
if ogNodes != pathEditor.nodes or \
ogCtrlNodes != pathEditor.curveEditPoints:
ogNodes = pathEditor.nodes
ogCtrlNodes = pathEditor.curveEditPoints
# for i in range(len(ogNodes)):
# events
self.refresh()
+31
View File
@@ -0,0 +1,31 @@
pg = None
render = None
bottomBarHeight = 0
class export:
name = "Export"
def __init__(self, tmppg, tmprender):
global pg
pg = tmppg
global render
render = tmprender
def mouseDown(self, pos):
pass
def mouseUp(self, pos):
pass
def mouseMove(self, pos):
pass
def doubleClick(self, pos):
pass
def keyDown(self, key):
pass
def load(self):
render.clear()
pg.display.update()
+3
View File
@@ -22,6 +22,9 @@ class menu:
def doubleClick(self, pos):
pass
def keyDown(self, key):
pass
def load(self):
render.clear()
pg.display.update()
+24 -18
View File
@@ -2,11 +2,11 @@ import math
from pygame.locals import *
nodeColor = (255, 255, 255)
nodeRadius = 15
nodeRadius = 12
rotNodeDist = 35
rotNodeColor = (255, 0, 255)
rotNodeRadius = 10
rotNodeRadius = 8
nodeSquareRadius = 35
nodeSquareColor = (127, 127, 127, 0.5)
@@ -16,7 +16,7 @@ lineApproximationLineColor = (127, 127, 127, 0.5)
lineApproximationLineWidth = 3
curveEditPointColor = (0, 255, 255)
curveEditPointRadius = 5
curveEditPointRadius = 8
nodes = []
curveEditPoints = []
@@ -25,12 +25,13 @@ nodeRotations = []
clickType = -1
clickIndex = -1
pg = None
render = None
def refresh():
render.render(nodes, curveEditPoints)
render.clear()
render.drawField()
render.renderBezier(nodes, curveEditPoints)
for i in range(0,len(curveEditPoints)):
render.line(lineApproximationLineColor, nodes[i], curveEditPoints[i], lineApproximationLineWidth)
@@ -58,20 +59,20 @@ def refresh():
for pos in nodes:
render.circle(nodeColor, pos, nodeRadius)
pg.display.update()
render.update()
def getElemAt(pos):
for i in range(0,len(curveEditPoints)):
if getDist(pos, curveEditPoints[i], curveEditPointRadius):
return 1, i
for i in range(0,len(nodes)):
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]
if getDist(pos, (posX, posY), nodeRadius):
return 2, i
for i in range(0,len(nodes)):
if getDist(pos, nodes[i], nodeRadius):
return 0, i
for i in range(0,len(curveEditPoints)):
if getDist(pos, curveEditPoints[i], curveEditPointRadius):
return 1, i
return -1, -1
def getDist(pos1, pos2, dist):
@@ -79,12 +80,14 @@ def getDist(pos1, pos2, dist):
def addNode(pos):
nodes.append(pos)
nodeRotations.append(math.pi/2)
if len(nodes) > 1:
index = len(nodes)-1
# Middle point between current point and previous point
editPos = (nodes[index-1][0]+pos[0])/2,(nodes[index-1][1]+pos[1])/2
curveEditPoints.append(editPos)
nodeRotations.append(nodeRotations[index-1])
else:
nodeRotations.append(math.pi/2)
refresh()
def nearestCirclePoint(center, pos, R):
@@ -102,9 +105,7 @@ def points2rad(center, pos):
class pathEditor:
name = "Path Editor"
def __init__(self, tmppg, tmprender):
global pg
pg = tmppg
def __init__(self, tmprender):
# global screen
# screen = tmpscreen
global render
@@ -137,7 +138,7 @@ class pathEditor:
refresh()
def doubleClick(self, pos):
clickType, clickIndex = getElemAt(pg.mouse.get_pos())
clickType, clickIndex = getElemAt(pos)
if clickType == -1:
pass
if clickType == 0:
@@ -151,4 +152,9 @@ class pathEditor:
nodes.pop(clickIndex)
nodeRotations.pop(clickIndex)
refresh()
def keyDown(self, key):
pass
def load(self):
refresh()
+77 -12
View File
@@ -6,28 +6,45 @@ curvePointCount = 300
curvePointColor = (255, 255, 0)
curvePointRadius = 2
selTabBorderSize = 2
selTabBorderIndent = 3
class render():
def __init__(self, pg, screen, offsetY):
def __init__(self, pg, screen, topBarHeight, bottomBarHeight):
self.pg = pg
self.screen = screen
self.offsetY = offsetY
self.topBarHeight = topBarHeight
self.bottomBarHeight = bottomBarHeight
self.width = self.screen.get_width()
self.height = self.screen.get_width() * (643/1286)
self.rect = (0, self.offsetY, self.width, self.height)
self.rect = (0, self.topBarHeight, self.width, self.height+bottomBarHeight)
self.font = self.pg.font.Font(None, 25)
self.fieldImg = pg.image.load("frc2024.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 line(self, color, pos1, pos2, width):
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)
def drawrect(self, color, rect):
self.pg.draw.rect(self.screen, color, rect)
def isInRect(self, pos, rect):
return pos[0] >= rect[0] and \
pos[0] <= rect[0]+rect[2] and \
pos[1] >= rect[1] and \
pos[1] <= rect[1]+rect[3]
def bezier(self, p0, p1, p2):
#for p in [p0, p1, p2]:
# pg.draw.circle(self.screen, (255, 255, 255), p, 5)
@@ -39,13 +56,61 @@ class render():
def clear(self):
self.pg.draw.rect(self.screen, (0, 0, 0), self.rect)
def render(self, nodes, curveEditPoints):
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':
# 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 renderBezier(self, nodes, curveEditPoints):
for i in range(0,len(curveEditPoints)):
# self.pg.draw.line(self.screen, lineApproximationLineColor, nodes[i], curveEditPoints[i], lineApproximationLineWidth)
# self.pg.draw.line(self.screen, lineApproximationLineColor, curveEditPoints[i], nodes[i+1], lineApproximationLineWidth)
self.bezier(nodes[i], curveEditPoints[i], nodes[i+1])
# self.pg.draw.circle(self.screen, curveEditPointColor, curveEditPoints[i], curveEditPointRadius)
def update(self):
self.pg.display.update()
def addButton(self, rect, text, getIsSelected, onClick):
self.elements.append({
"type": "button",
"text": text,
"getIsSelected": getIsSelected,
"onClick": onClick,
"rect": rect
})
def renderButton(self, rect, text, selected, mousePos):
# print(isInRect(mousePos, rect))
if self.isInRect(mousePos, rect):
color = (16,64,32)
else:
color = (16,16,32)
if selected:
borderColor = (0,255,0)
else:
borderColor = (64,127,127)
text = self.font.render(text, True, (255,255,255))
text_rect = text.get_rect(center=(rect[0]+(rect[2]/2), rect[1]+(rect[3]/2)))
self.pg.draw.rect(self.screen, color, rect)
rect = (rect[0]+selTabBorderIndent,rect[1]+selTabBorderIndent,
rect[2]-selTabBorderIndent*2,rect[3]-selTabBorderIndent*2)
self.pg.draw.rect(self.screen, borderColor, rect)
rect = (rect[0]+selTabBorderSize,rect[1]+selTabBorderSize,
rect[2]-selTabBorderSize*2,rect[3]-selTabBorderSize*2)
self.pg.draw.rect(self.screen, color, rect)
self.screen.blit(text, text_rect)
self.update()