rendering.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import numpy as np
  2. from PyQt5.QtCore import Qt
  3. from PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, QPolygon
  4. from PyQt5.QtCore import QPoint, QSize, QRect
  5. from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
  6. from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QFrame
  7. class Window(QMainWindow):
  8. """
  9. Simple application window to render the environment into
  10. """
  11. def __init__(self):
  12. super().__init__()
  13. self.setWindowTitle('MiniGrid Gym Environment')
  14. self.imgLabel = QLabel()
  15. self.imgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken)
  16. # Arrange widgets horizontally
  17. hbox = QHBoxLayout()
  18. hbox.addStretch(1)
  19. hbox.addWidget(self.imgLabel)
  20. hbox.addStretch(1)
  21. # Create a main widget for the window
  22. mainWidget = QWidget(self)
  23. self.setCentralWidget(mainWidget)
  24. mainWidget.setLayout(hbox)
  25. # Show the application window
  26. self.show()
  27. self.setFocus()
  28. self.closed = False
  29. # Callback for keyboard events
  30. self.keyDownCb = None
  31. def closeEvent(self, event):
  32. self.closed = True
  33. def setPixmap(self, pixmap):
  34. self.imgLabel.setPixmap(pixmap)
  35. def setKeyDownCb(self, callback):
  36. self.keyDownCb = callback
  37. def keyPressEvent(self, e):
  38. if self.keyDownCb == None:
  39. return
  40. keyName = None
  41. if e.key() == Qt.Key_Left:
  42. keyName = 'LEFT'
  43. elif e.key() == Qt.Key_Right:
  44. keyName = 'RIGHT'
  45. elif e.key() == Qt.Key_Up:
  46. keyName = 'UP'
  47. elif e.key() == Qt.Key_Down:
  48. keyName = 'DOWN'
  49. elif e.key() == Qt.Key_Space:
  50. keyName = 'SPACE'
  51. elif e.key() == Qt.Key_Return:
  52. keyName = 'RETURN'
  53. elif e.key() == Qt.Key_Alt:
  54. keyName = 'ALT'
  55. elif e.key() == Qt.Key_Control:
  56. keyName = 'CTRL'
  57. elif e.key() == Qt.Key_Backspace:
  58. keyName = 'BACKSPACE'
  59. elif e.key() == Qt.Key_Escape:
  60. keyName = 'ESCAPE'
  61. if keyName == None:
  62. return
  63. self.keyDownCb(keyName)
  64. class Renderer:
  65. def __init__(self, width, height, ownWindow=False):
  66. self.width = width
  67. self.height = height
  68. self.img = QImage(width, height, QImage.Format_RGB888)
  69. self.painter = QPainter()
  70. self.window = None
  71. if ownWindow:
  72. self.app = QApplication([])
  73. self.window = Window()
  74. def close(self):
  75. """
  76. Deallocate resources used
  77. """
  78. pass
  79. def beginFrame(self):
  80. self.painter.begin(self.img)
  81. self.painter.setRenderHint(QPainter.Antialiasing, False)
  82. # Clear the background
  83. self.painter.setBrush(QColor(0, 0, 0))
  84. self.painter.drawRect(0, 0, self.width - 1, self.height - 1)
  85. def endFrame(self):
  86. self.painter.end()
  87. if self.window:
  88. if self.window.closed:
  89. self.window = None
  90. else:
  91. self.window.setPixmap(self.getPixmap())
  92. self.app.processEvents()
  93. def getPixmap(self):
  94. return QPixmap.fromImage(self.img)
  95. def getArray(self):
  96. """
  97. Get a numpy array of RGB pixel values.
  98. The size argument should be (3,w,h)
  99. """
  100. width = self.width
  101. height = self.height
  102. shape = (width, height, 3)
  103. numBytes = self.width * self.height * 3
  104. buf = self.img.bits().asstring(numBytes)
  105. output = np.frombuffer(buf, dtype='uint8')
  106. output = output.reshape(shape)
  107. return output
  108. def push(self):
  109. self.painter.save()
  110. def pop(self):
  111. self.painter.restore()
  112. def rotate(self, degrees):
  113. self.painter.rotate(degrees)
  114. def translate(self, x, y):
  115. self.painter.translate(x, y)
  116. def scale(self, x, y):
  117. self.painter.scale(x, y)
  118. def setLineColor(self, r, g, b, a=255):
  119. self.painter.setPen(QColor(r, g, b, a))
  120. def setColor(self, r, g, b, a=255):
  121. self.painter.setBrush(QColor(r, g, b, a))
  122. def setLineWidth(self, width):
  123. pen = self.painter.pen()
  124. pen.setWidthF(width)
  125. self.painter.setPen(pen)
  126. def drawLine(self, x0, y0, x1, y1):
  127. self.painter.drawLine(x0, y0, x1, y1)
  128. def drawCircle(self, x, y, r):
  129. center = QPoint(x, y)
  130. self.painter.drawEllipse(center, r, r)
  131. def drawPolygon(self, points):
  132. """Takes a list of points (tuples) as input"""
  133. points = map(lambda p: QPoint(p[0], p[1]), points)
  134. self.painter.drawPolygon(QPolygon(points))
  135. def fillRect(self, x, y, width, height, r, g, b, a=255):
  136. self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a))