rendering.py 4.6 KB

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