rendering.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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_PageUp:
  58. keyName = 'PAGE_UP'
  59. elif e.key() == Qt.Key_PageDown:
  60. keyName = 'PAGE_DOWN'
  61. elif e.key() == Qt.Key_Backspace:
  62. keyName = 'BACKSPACE'
  63. elif e.key() == Qt.Key_Escape:
  64. keyName = 'ESCAPE'
  65. if keyName == None:
  66. return
  67. self.keyDownCb(keyName)
  68. class Renderer:
  69. def __init__(self, width, height, ownWindow=False):
  70. self.width = width
  71. self.height = height
  72. self.img = QImage(width, height, QImage.Format_RGB888)
  73. self.painter = QPainter()
  74. self.window = None
  75. if ownWindow:
  76. self.app = QApplication([])
  77. self.window = Window()
  78. def close(self):
  79. """
  80. Deallocate resources used
  81. """
  82. pass
  83. def beginFrame(self):
  84. self.painter.begin(self.img)
  85. self.painter.setRenderHint(QPainter.Antialiasing, False)
  86. # Clear the background
  87. self.painter.setBrush(QColor(0, 0, 0))
  88. self.painter.drawRect(0, 0, self.width - 1, self.height - 1)
  89. def endFrame(self):
  90. self.painter.end()
  91. if self.window:
  92. if self.window.closed:
  93. self.window = None
  94. else:
  95. self.window.setPixmap(self.getPixmap())
  96. self.app.processEvents()
  97. def getPixmap(self):
  98. return QPixmap.fromImage(self.img)
  99. def getArray(self):
  100. """
  101. Get a numpy array of RGB pixel values.
  102. The size argument should be (3,w,h)
  103. """
  104. width = self.width
  105. height = self.height
  106. shape = (width, height, 3)
  107. numBytes = self.width * self.height * 3
  108. buf = self.img.bits().asstring(numBytes)
  109. output = np.frombuffer(buf, dtype='uint8')
  110. output = output.reshape(shape)
  111. return output
  112. def push(self):
  113. self.painter.save()
  114. def pop(self):
  115. self.painter.restore()
  116. def rotate(self, degrees):
  117. self.painter.rotate(degrees)
  118. def translate(self, x, y):
  119. self.painter.translate(x, y)
  120. def scale(self, x, y):
  121. self.painter.scale(x, y)
  122. def setLineColor(self, r, g, b, a=255):
  123. self.painter.setPen(QColor(r, g, b, a))
  124. def setColor(self, r, g, b, a=255):
  125. self.painter.setBrush(QColor(r, g, b, a))
  126. def setLineWidth(self, width):
  127. pen = self.painter.pen()
  128. pen.setWidthF(width)
  129. self.painter.setPen(pen)
  130. def drawLine(self, x0, y0, x1, y1):
  131. self.painter.drawLine(x0, y0, x1, y1)
  132. def drawCircle(self, x, y, r):
  133. center = QPoint(x, y)
  134. self.painter.drawEllipse(center, r, r)
  135. def drawPolygon(self, points):
  136. """Takes a list of points (tuples) as input"""
  137. points = map(lambda p: QPoint(p[0], p[1]), points)
  138. self.painter.drawPolygon(QPolygon(points))
  139. def drawPolyline(self, points):
  140. """Takes a list of points (tuples) as input"""
  141. points = map(lambda p: QPoint(p[0], p[1]), points)
  142. self.painter.drawPolyline(QPolygon(points))
  143. def fillRect(self, x, y, width, height, r, g, b, a=255):
  144. self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a))