Files
autoPlanner2025/buttonEditor.py
T

230 lines
9.4 KiB
Python
Raw Normal View History

2024-07-03 14:15:25 -06:00
import sys
import os
import numpy as np
2024-07-25 09:58:46 -04:00
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QHBoxLayout, QWidget
from PySide6.QtGui import QPixmap, QPainter, QPen, QColor
2024-07-03 14:15:25 -06:00
from PySide6.QtCore import Qt, QPoint, QRect
class ButtonEditor(QMainWindow):
2024-07-03 17:44:46 -06:00
def __init__(self, pathPlanner):
2024-07-03 14:15:25 -06:00
super().__init__()
self.setWindowTitle("Button Editor")
2024-07-03 17:44:46 -06:00
self.pathPlanner = pathPlanner
2024-07-03 14:15:25 -06:00
2024-07-03 17:44:46 -06:00
self.imageLabel = QLabel(self)
scriptDir = os.path.dirname(os.path.abspath(__file__))
imagePath = os.path.join(scriptDir, "images", "Field.png")
self.pixmap = QPixmap(imagePath)
2024-07-03 14:15:25 -06:00
if self.pixmap.isNull():
2024-07-03 17:44:46 -06:00
self.imageLabel.setText(f"Image not found at: {imagePath}")
2024-07-03 14:15:25 -06:00
else:
2024-07-03 17:44:46 -06:00
self.imageLabel.setPixmap(self.pixmap)
2024-07-03 14:15:25 -06:00
2024-07-03 17:44:46 -06:00
self.pathPlannerButton = QPushButton("Main Window")
self.pathPlannerButton.clicked.connect(self.showPathPlanner)
self.buttonEditorButton = QPushButton("Button Editor")
self.buttonEditorButton.clicked.connect(self.showButtonEditor)
2024-07-03 14:15:25 -06:00
2024-07-03 17:44:46 -06:00
buttonLayout = QHBoxLayout()
buttonLayout.addWidget(self.pathPlannerButton)
buttonLayout.addWidget(self.buttonEditorButton)
2024-07-03 14:15:25 -06:00
layout = QVBoxLayout()
2024-07-03 17:44:46 -06:00
layout.addLayout(buttonLayout)
layout.addWidget(self.imageLabel)
2024-07-03 14:15:25 -06:00
2024-07-25 09:58:46 -04:00
self.timeLabel = QLabel("(0:00 / 0:15 sec)", self)
layout.addWidget(self.timeLabel, alignment=Qt.AlignCenter)
2024-07-09 07:18:37 -06:00
self.rectanglesWidget = QWidget()
2024-07-25 09:58:46 -04:00
self.rectanglesLayout = QHBoxLayout()
self.rectanglesLayout.setSpacing(0)
self.rectanglesLayout.setContentsMargins(40, 0, 0, 0)
self.rectanglesWidget.setLayout(self.rectanglesLayout)
layout.addWidget(self.rectanglesWidget)
2024-07-09 07:18:37 -06:00
2024-07-03 14:15:25 -06:00
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
2024-07-25 09:58:46 -04:00
self.resize(self.pixmap.width(), self.pixmap.height() + 250)
2024-07-03 14:15:25 -06:00
2024-07-25 09:58:46 -04:00
# Variables
2024-07-03 17:44:46 -06:00
self.matchLength = 15
self.TPS = 50
self.matchTicks = self.matchLength * self.TPS
2024-07-25 09:58:46 -04:00
self.displayTickResolution = 6.25
2024-07-03 17:44:46 -06:00
self.displayTicks = round(self.matchTicks / self.displayTickResolution)
2024-07-25 09:58:46 -04:00
self.currentFrame = 1
self.keyFrameData = [{"isNode": False, "isButton": False} for _ in range(self.displayTicks)]
self.updateKeyFrameData()
self.displayFrames = list(range(1, self.displayTicks + 1))
self.currentTime = [i * self.matchLength / (self.displayTicks - 1) for i in range(self.displayTicks)]
num_nodes = 2
node_indices = np.linspace(0, self.displayTicks - 1, num_nodes, dtype=int)
for idx in node_indices:
self.keyFrameData[idx]["isNode"] = True
2024-07-03 17:44:46 -06:00
2024-07-09 07:18:37 -06:00
self.setupFrames()
2024-07-25 09:58:46 -04:00
self.updateRectangles()
self.updateTimeLabel()
def updateKeyFrameData(self):
num_nodes = len(self.pathPlanner.coordinates) if self.pathPlanner else 0
self.keyFrameData = [{"isNode": False, "isButton": False} for _ in range(self.displayTicks)]
if num_nodes > 0:
node_indices = np.linspace(0, self.displayTicks - 1, num_nodes, dtype=int)
for idx in node_indices:
self.keyFrameData[idx]["isNode"] = True
def resizeEvent(self, event):
super().resizeEvent(event)
self.updateRectangles()
self.updateTimeLabel()
2024-07-03 17:44:46 -06:00
2024-07-09 07:18:37 -06:00
def setupFrames(self):
self.displayFrames = list(range(1, self.displayTicks + 1))
2024-07-25 09:58:46 -04:00
print(len(self.keyFrameData))
2024-07-09 07:18:37 -06:00
print(len(self.displayFrames))
2024-07-03 17:44:46 -06:00
def showButtonEditor(self):
2024-07-03 14:15:25 -06:00
self.show()
2024-07-09 07:18:37 -06:00
if self.pathPlanner:
self.pathPlanner.hide()
2024-07-03 14:15:25 -06:00
2024-07-03 17:44:46 -06:00
def showPathPlanner(self):
2024-07-03 14:15:25 -06:00
self.hide()
2024-07-09 07:18:37 -06:00
if self.pathPlanner:
self.pathPlanner.show()
2024-07-03 15:12:25 -06:00
2024-07-03 17:44:46 -06:00
def updateScene(self):
2024-07-25 09:58:46 -04:00
self.updateKeyFrameData()
2024-07-03 15:12:25 -06:00
self.pixmap = QPixmap(os.path.join(os.path.dirname(os.path.abspath(__file__)), "images", "Field.png"))
painter = QPainter(self.pixmap)
2024-07-09 07:18:37 -06:00
painter.setPen(Qt.NoPen)
painter.setBrush(Qt.white)
2024-07-03 15:12:25 -06:00
2024-07-09 07:18:37 -06:00
if self.pathPlanner and hasattr(self.pathPlanner, 'coordinates'):
for i, (x, y) in enumerate(self.pathPlanner.coordinates):
nodeRect = QRect(x - self.pathPlanner.nodeSize // 6, y - self.pathPlanner.nodeSize // 6,
self.pathPlanner.nodeSize // 3, self.pathPlanner.nodeSize // 3)
painter.drawEllipse(nodeRect)
painter.drawText(nodeRect, Qt.AlignCenter, str(i + 1))
2024-07-03 15:12:25 -06:00
2024-07-09 07:18:37 -06:00
if len(self.pathPlanner.coordinates) > 1:
2024-07-25 09:58:46 -04:00
total_points = 60
points_per_curve = total_points // len(self.pathPlanner.controlPoints)
remaining_points = total_points % len(self.pathPlanner.controlPoints)
for i, controlPair in enumerate(self.pathPlanner.controlPoints):
if i < len(self.pathPlanner.coordinates) - 1:
start = QPoint(self.pathPlanner.coordinates[i][0], self.pathPlanner.coordinates[i][1])
end = QPoint(self.pathPlanner.coordinates[i + 1][0], self.pathPlanner.coordinates[i + 1][1])
pen = QPen(Qt.yellow if self.keyFrameData[i]["isNode"] else Qt.white) # Set color based on isNode
pen.setWidth(2)
painter.setPen(pen)
num_points = points_per_curve
if i < remaining_points:
num_points += 1
for t in np.linspace(0, 1, num_points):
point = self.pointOnBezierCurve(start, controlPair[0], controlPair[1], end, t)
painter.drawEllipse(point, 2, 2)
2024-07-03 15:12:25 -06:00
2024-07-25 09:58:46 -04:00
if i == self.currentFrame - 1:
t = (self.currentFrame - 1) / (num_points - 1)
2024-07-09 07:18:37 -06:00
point = self.pointOnBezierCurve(start, controlPair[0], controlPair[1], end, t)
2024-07-25 09:58:46 -04:00
start_angle = self.pathPlanner.nodeAngles[i] if i < len(self.pathPlanner.nodeAngles) else 0
end_angle = self.pathPlanner.nodeAngles[i + 1] if i + 1 < len(self.pathPlanner.nodeAngles) else 0
angle = self.interpolateAngle(start_angle, end_angle, t)
self.drawRobot(painter, point, angle)
2024-07-03 15:12:25 -06:00
painter.end()
2024-07-03 17:44:46 -06:00
self.imageLabel.setPixmap(self.pixmap)
2024-07-25 09:58:46 -04:00
self.updateRectangles()
2024-07-09 07:18:37 -06:00
def interpolateAngle(self, start_angle, end_angle, t):
diff = (end_angle - start_angle + 180) % 360 - 180
return start_angle + diff * t
def drawRobot(self, painter, position, angle):
side_length = self.pathPlanner.nodeSize
half_side = side_length / 2
painter.save()
painter.translate(position)
painter.rotate(angle - 90)
painter.setBrush(Qt.NoBrush)
painter.setPen(QPen(QColor(127, 127, 127), 2))
painter.drawRect(-half_side, -half_side, side_length, side_length)
painter.setPen(QPen(QColor(255, 0, 0), 2))
painter.drawLine(0, 0, half_side, 0)
painter.drawLine(half_side, 0, half_side - 5, -5)
painter.drawLine(half_side, 0, half_side - 5, 5)
painter.restore()
def pointOnBezierCurve(self, start, control1, control2, end, t):
x = (1-t)**3 * start.x() + 3*(1-t)**2*t * control1.x() + 3*(1-t)*t**2 * control2.x() + t**3 * end.x()
y = (1-t)**3 * start.y() + 3*(1-t)**2*t * control1.y() + 3*(1-t)*t**2 * control2.y() + t**3 * end.y()
return QPoint(int(x), int(y))
def updateRectangles(self):
2024-07-25 09:58:46 -04:00
for i in reversed(range(self.rectanglesLayout.count())):
widgetToRemove = self.rectanglesLayout.itemAt(i).widget()
self.rectanglesLayout.removeWidget(widgetToRemove)
widgetToRemove.setParent(None)
2024-07-09 07:18:37 -06:00
2024-07-25 09:58:46 -04:00
window_width = self.rectanglesWidget.width()
if self.keyFrameData:
rect_width = window_width / len(self.keyFrameData)
2024-07-09 07:18:37 -06:00
2024-07-25 09:58:46 -04:00
rect_height = 100
for index, frame in enumerate(self.keyFrameData):
2024-07-09 07:18:37 -06:00
rectWidget = QWidget()
rectWidget.setFixedSize(rect_width, rect_height)
2024-07-25 09:58:46 -04:00
if frame["isNode"]:
rectWidget.setStyleSheet("background-color: yellow;")
else:
if index % 2 == 0:
rectWidget.setStyleSheet("background-color: #ADD8E6;")
else:
rectWidget.setStyleSheet("background-color: #00008B;")
rectWidget.mousePressEvent = lambda event, idx=index: self.rectangleClicked(idx)
self.rectanglesLayout.addWidget(rectWidget)
def rectangleClicked(self, index):
self.currentFrame = index + 1
self.updateRectangles()
self.updateScene()
self.updateTimeLabel()
clicked_widget = self.rectanglesLayout.itemAt(index).widget()
clicked_widget.setStyleSheet("background-color: red;")
def updateTimeLabel(self):
current_time = self.currentTime[self.currentFrame - 1]
minutes = int(current_time // 60)
seconds = int(current_time % 60)
milliseconds = int((current_time % 1) * 1000)
self.timeLabel.setText(f"{minutes}:{seconds:02d}.{milliseconds:03d} / {self.matchLength:.3f} sec")
2024-07-09 07:18:37 -06:00
if __name__ == "__main__":
app = QApplication(sys.argv)
window = ButtonEditor(None)
window.updateScene()
2024-07-25 09:58:46 -04:00
window.updateRectangles()
2024-07-09 07:18:37 -06:00
window.show()
2024-07-25 09:58:46 -04:00
sys.exit(app.exec())