Pinceau.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. """pinceau utilise pour la selection et la mise a jour des cases du plateau"""
  2. from PyQt4.QtCore import *
  3. from PyQt4.QtGui import *
  4. from Terrain import Terrain
  5. class Pinceau():
  6. def __init__(self, plateau):
  7. self.plateau = plateau
  8. self._forme = "simple"
  9. self._epaisseur = 1
  10. self._formeVerrouillee = False
  11. self._origine = None
  12. self._point2 = None
  13. self._selection = []
  14. self._objetGraphique = None
  15. self._actif = False
  16. def estActif(self):
  17. return self._actif
  18. def majForme(self, forme):
  19. if forme in ["simple", "ligne", "frontiere", "pot", \
  20. "rectV", "rectP", "ellipseV", "ellipseP"] and not self._formeVerrouillee:
  21. self._forme = forme
  22. def verrouillerForme(self, actif = True):
  23. self._formeVerrouillee = actif
  24. def majEpaisseur(self, val):
  25. if val in range(1, 5):
  26. self._epaisseur = val
  27. def defOrigine(self, coord):
  28. if self.plateau.coordonneesValides(coord):
  29. self._origine = self.plateau.cases[coord].centreGraphique
  30. def defPoint2(self, coord):
  31. if self.plateau.coordonneesValides(coord):
  32. self._point2 = self.plateau.cases[coord].centreGraphique
  33. def selection(self):
  34. return self._selection
  35. def demarrer(self, coord):
  36. """commence a peindre a partir de la case choisie comme origine"""
  37. self._formeVerrouillee = False
  38. if self.plateau.coordonneesValides(coord):
  39. self._origine = self.plateau.cases[coord].centreGraphique
  40. self._point2 = self.plateau.cases[coord].centreGraphique
  41. self._actif = True
  42. self.maj(coord)
  43. def maj(self, coord):
  44. """on met a jour la selection en fonction de la case qui vient d'etre ajoutee"""
  45. if self._actif:
  46. enPlus = [] #cases a ajouter a la selection
  47. enMoins = [] #cases a retirer de la selection
  48. if self._origine == None: self._origine = self.plateau.cases[coord].centreGraphique
  49. if self._forme == "simple":
  50. #pas de forme: on ajoute les cases survolees a la liste des cases
  51. zone = self.plateau.zone(coord, self._epaisseur - 1)
  52. for coord in zone:
  53. if not coord in self._selection:
  54. enPlus.append(coord)
  55. elif self._forme == "pot":
  56. #pot de peinture: on ne met a jour que si aucune projection n'est affichee
  57. if not len(self._selection) > 0:
  58. enPlus = self.selectionPot(coord)
  59. elif self._forme == "frontiere":
  60. #droite qui selectionne toutes les cases situees au dessus d'elle
  61. if self._objetGraphique == None:
  62. pinceau = QPen()
  63. pinceau.setColor(QColor("black"))
  64. self._objetGraphique = QGraphicsLineItem()
  65. self._objetGraphique.setPen(pinceau)
  66. self.plateau.addItem(self._objetGraphique)
  67. self._point2 = self.plateau.cases[coord].centreGraphique
  68. ligne = QLineF(self._origine, self._point2)
  69. orientation = int((1+int(ligne.angle()/22.5))/2)
  70. ligne.setAngle(orientation*45)
  71. self._objetGraphique.setLine(ligne)
  72. select = self.selectionFrontiere()
  73. #on met compare avec l'ancienne selection pour minimiser le nombre de cases a maj
  74. for coord in self._selection:
  75. if not coord in select:
  76. enMoins.append(coord)
  77. else:
  78. select.remove(coord)
  79. enPlus = select #toutes les coord qui restent dans select sont a ajouter
  80. else:
  81. if self._forme == "ligne":
  82. #segment simple
  83. if self._objetGraphique == None:
  84. pinceau = QPen()
  85. pinceau.setColor(QColor("black"))
  86. self._objetGraphique = QGraphicsLineItem()
  87. self._objetGraphique.setPen(pinceau)
  88. self._objetGraphique.prepareGeometryChange()
  89. self.plateau.addItem(self._objetGraphique)
  90. self._point2 = self.plateau.cases[coord].centreGraphique
  91. ligne = QLineF(self._origine, self._point2)
  92. self._objetGraphique.setLine(ligne)
  93. elif self._forme == "rectV" or self._forme == "rectP":
  94. #rectangle
  95. if self._objetGraphique == None:
  96. pinceau = QPen()
  97. pinceau.setColor(QColor("black"))
  98. self._objetGraphique = QGraphicsRectItem()
  99. self._objetGraphique.prepareGeometryChange()
  100. self._objetGraphique.setPen(pinceau)
  101. self.plateau.addItem(self._objetGraphique)
  102. self._point2 = self.plateau.cases[coord].centreGraphique
  103. rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
  104. QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) )
  105. self._objetGraphique.setRect(rect)
  106. elif self._forme == "ellipseV" or self._forme == "ellipseP":
  107. #ellipse
  108. if self._objetGraphique == None:
  109. pinceau = QPen()
  110. pinceau.setColor(QColor("black"))
  111. self._objetGraphique = QGraphicsEllipseItem()
  112. self._objetGraphique.prepareGeometryChange()
  113. self._objetGraphique.setPen(pinceau)
  114. self.plateau.addItem(self._objetGraphique)
  115. self._point2 = self.plateau.cases[coord].centreGraphique
  116. rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
  117. QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) )
  118. self._objetGraphique.setRect(rect)
  119. #on liste les cases intersectant la forme
  120. if self._objetGraphique:
  121. select = self.plateau.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1)
  122. else:
  123. select = [coord]
  124. for coord in self._selection:
  125. if not coord in select:
  126. enMoins.append(coord)
  127. else:
  128. select.remove(coord)
  129. enPlus = select
  130. for coord in enPlus:
  131. self.afficherCase(coord, True)
  132. self._selection.append(coord)
  133. for coord in enMoins:
  134. self.afficherCase(coord, False)
  135. self._selection.remove(coord)
  136. def reinit(self):
  137. for coord in self._selection:
  138. self.afficherCase(coord, False)
  139. if self._objetGraphique:
  140. self.plateau.removeItem(self._objetGraphique)
  141. self._objetGraphique = None
  142. self._origine = None
  143. self._point2 = None
  144. self._selection = []
  145. self._actif = False
  146. def afficherCase(self, coord, actif):
  147. self.plateau.cases[coord].majEstCibleCurseur(actif)
  148. def selectionFrontiere(self):
  149. """retourne les cases selectionnees lors de l'utilisation de la forme 'frontiere'"""
  150. listeCases = []
  151. if self._objetGraphique != None:
  152. ligne = self._objetGraphique.line()
  153. normale = ligne.normalVector()
  154. normale = normale.unitVector()
  155. coordOrigine = self.plateau.coordonneesAuPoint(self._origine)
  156. dx = normale.p2().x() - normale.p1().x()
  157. dy = normale.p2().y() - normale.p1().y()
  158. for coord in self.plateau.cases:
  159. if dx < 0 and dy == 0: #normale pointe vers la gauche
  160. if (coord[0] - coordOrigine[0]) <= 0:
  161. listeCases.append(coord)
  162. if dx > 0 and dy == 0: #normale pointe vers la droite
  163. if (coord[0] - coordOrigine[0]) >= 0:
  164. listeCases.append(coord)
  165. if dx == 0 and dy < 0: #pointe vers le haut (rappel: axe y vers le bas)
  166. if (coord[1] - coordOrigine[1]) <= 0:
  167. listeCases.append(coord)
  168. elif dx == 0 and dy > 0: #pointe vers le bas
  169. if (coord[1] - coordOrigine[1]) >= 0:
  170. listeCases.append(coord)
  171. if dx > 0 and dy < 0: #pointe vers le haut droite
  172. if (coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) >= 0:
  173. listeCases.append(coord)
  174. elif dx > 0 and dy > 0: #pointe vers le bas droite
  175. if -1*(coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) <= 0:
  176. listeCases.append(coord)
  177. if dx < 0 and dy < 0: #pointe vers le haut gauche
  178. if (coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) <= 0:
  179. listeCases.append(coord)
  180. elif dx < 0 and dy > 0: #pointe vers le bas gauche
  181. if -1*(coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) >= 0:
  182. listeCases.append(coord)
  183. return listeCases
  184. def selectionPot(self, coord0):
  185. retour = [coord0]
  186. aVerifier = [coord0]
  187. while len(aVerifier) > 0:
  188. coord = aVerifier[0]
  189. for voisine in self.plateau.cases[coord].voisins:
  190. if not voisine in retour:
  191. if self.ontTerrainsSimilaires(voisine, coord):
  192. retour.append(voisine)
  193. aVerifier.append(voisine)
  194. aVerifier.remove(coord)
  195. return retour
  196. def ontTerrainsSimilaires(self, coord1, coord2):
  197. return (self.plateau.cases[coord1].terrain.nom == self.plateau.cases[coord2].terrain.nom and \
  198. self.plateau.cases[coord1].terrain.couleur.rgb() == self.plateau.cases[coord2].terrain.couleur.rgb() and \
  199. self.plateau.cases[coord1].terrain.imgTexture.definition() == self.plateau.cases[coord1].terrain.imgTexture.definition())