|
|
@@ -0,0 +1,249 @@
|
|
|
+"""pinceau utilise pour la selection et la mise a jour des cases du plateau"""
|
|
|
+
|
|
|
+class Pinceau():
|
|
|
+ def __init__(self, plateau):
|
|
|
+ self.plateau = plateau
|
|
|
+
|
|
|
+ self._forme = "simple"
|
|
|
+ self._epaisseur = 1
|
|
|
+
|
|
|
+ self._origine = None
|
|
|
+ self._point2 = None
|
|
|
+ self._selection = []
|
|
|
+
|
|
|
+ self._objetGraphique = None
|
|
|
+
|
|
|
+ self._actif = False
|
|
|
+
|
|
|
+ def majForme(self, forme):
|
|
|
+ if forme in ["simple", "ligne", "frontiere", "pot", \
|
|
|
+ "rectV", "rectP", "ecclipseV", "ecclipseP"]:
|
|
|
+ self._forme = forme
|
|
|
+
|
|
|
+ def majEpaisseur(self, val):
|
|
|
+ if val in range(1, 5):
|
|
|
+ self._epaisseur = val
|
|
|
+
|
|
|
+ def defOrigine(self, coord):
|
|
|
+ if self.plateau.coordonneesValides(coord):
|
|
|
+ self._origine = self.cases[coord].centreGraphique
|
|
|
+
|
|
|
+ def defPoint2(self, coord):
|
|
|
+ if self.plateau.coordonneesValides(coord):
|
|
|
+ self._point2 = self.cases[coord].centreGraphique
|
|
|
+
|
|
|
+ def selection(self):
|
|
|
+ return self._selection
|
|
|
+
|
|
|
+ def demarrer(self, coord):
|
|
|
+ """commence a peindre a partir de la case choisie comme origine"""
|
|
|
+ if self.plateau.coordonneesValides(coord):
|
|
|
+ self._origine = self.cases[coord].centreGraphique
|
|
|
+ self._point2 = self.cases[coord].centreGraphique
|
|
|
+ self._actif = True
|
|
|
+
|
|
|
+ def maj(self, coord):
|
|
|
+ """on met a jour la selection en fonction de la case qui vient d'etre ajoutee"""
|
|
|
+ enPlus = [] #cases a ajouter a la selection
|
|
|
+ enMoins = [] #cases a retirer de la selection
|
|
|
+
|
|
|
+ if self._forme == "simple":
|
|
|
+ #pas de forme: on ajoute les cases survolees a la liste des cases
|
|
|
+ zone = self.plateau.zone(coord, self._epaisseur - 1)
|
|
|
+ for coord in zone:
|
|
|
+ if not coord in self._selection:
|
|
|
+ enPlus.append(coord)
|
|
|
+
|
|
|
+ elif self._forme == "frontiere":
|
|
|
+ #droite qui selectionne toutes les cases situees au dessus d'elle
|
|
|
+ if self._objetGraphique == None:
|
|
|
+ pinceau = QPen()
|
|
|
+ pinceau.setColor(QColor("black"))
|
|
|
+ self._objetGraphique = QGraphicsLineItem()
|
|
|
+ self._objetGraphique.setPen(pinceau)
|
|
|
+ self.plateau.addItem(self._objetGraphique)
|
|
|
+
|
|
|
+ self._point2 = self.plateau.cases[coord].centreGraphique
|
|
|
+ ligne = QLineF(self._origine, self._point2)
|
|
|
+ orientation = int((1+int(ligne.angle()/22.5))/2)
|
|
|
+ ligne.setAngle(orientation*45)
|
|
|
+ self._objetGraphique.setLine(ligne)
|
|
|
+ select = self.selectionFrontiere()
|
|
|
+ #on met compare avec l'ancienne selection pour minimiser le nombre de cases a maj
|
|
|
+ for coord in self._selection:
|
|
|
+ if not coord in select:
|
|
|
+ enMoins.append(coord)
|
|
|
+ select.remove(coord)
|
|
|
+ enPlus = select #toutes les coord qui restent dans select sont a ajouter
|
|
|
+
|
|
|
+ else:
|
|
|
+ if self._forme == "ligne":
|
|
|
+ #segment simple
|
|
|
+ if self._objetGraphique == None:
|
|
|
+ pinceau = QPen()
|
|
|
+ pinceau.setColor(QColor("black"))
|
|
|
+ self._objetGraphique = QGraphicsLineItem()
|
|
|
+ self._objetGraphique.setPen(pinceau)
|
|
|
+ self._objetGraphique.prepareGeometryChange()
|
|
|
+ self.plateau.addItem(self._objetGraphique)
|
|
|
+ self._point2 = self.plateau.cases[coord].centreGraphique
|
|
|
+ ligne = QLineF(self._origine, self._point2)
|
|
|
+ self._objetGraphique.setLine(ligne)
|
|
|
+
|
|
|
+ elif self._forme == "rectV" or self.modeParam["typeFormeDessin"] == "rectP":
|
|
|
+ #rectangle
|
|
|
+ if self.modeParam["formeDessin"] == None:
|
|
|
+ pinceau = QPen()
|
|
|
+ pinceau.setColor(QColor("black"))
|
|
|
+ self._objetGraphique = QGraphicsRectItem()
|
|
|
+ self._objetGraphique.prepareGeometryChange()
|
|
|
+ self._objetGraphique.setPen(pinceau)
|
|
|
+ self.plateau.addItem(self._objetGraphique)
|
|
|
+ rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
|
|
|
+ QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) )
|
|
|
+ self._objetGraphique.setRect(rect)
|
|
|
+
|
|
|
+ elif self._forme == "ellipseV" or self.modeParam["typeFormeDessin"] == "ellipseP":
|
|
|
+ #ellipse
|
|
|
+ if self._objetGraphique == None:
|
|
|
+ pinceau = QPen()
|
|
|
+ pinceau.setColor(QColor("black"))
|
|
|
+ self._objetGraphique = QGraphicsEllipseItem()
|
|
|
+ self._objetGraphique.prepareGeometryChange()
|
|
|
+ self._objetGraphique.setPen(pinceau)
|
|
|
+ self.plateau.addItem(self._objetGraphique)
|
|
|
+ rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \
|
|
|
+ QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) )
|
|
|
+ self._objetGraphique.setRect(rect)
|
|
|
+
|
|
|
+ #on liste les cases intersectant la forme
|
|
|
+ select = self.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1)
|
|
|
+
|
|
|
+ for coord in self._selection:
|
|
|
+ if not coord in select:
|
|
|
+ enMoins.append(coord)
|
|
|
+ select.remove(coord)
|
|
|
+ enPlus = select
|
|
|
+
|
|
|
+ for coord in enPlus:
|
|
|
+ self.afficherCase(coord, True)
|
|
|
+ self._selection.append(coord)
|
|
|
+ for coord in enMoins:
|
|
|
+ self.afficherCase(coord, False)
|
|
|
+ self._selection.remove(coord)
|
|
|
+
|
|
|
+ def annuler(self):
|
|
|
+ self.reinit()
|
|
|
+
|
|
|
+ def terminer(self):
|
|
|
+ return self._selection
|
|
|
+
|
|
|
+ def reinit(self):
|
|
|
+ for coord in self_selection:
|
|
|
+ self.afficherCase(coord, False)
|
|
|
+ self._origine = (-1, -1)
|
|
|
+ self._point2 = (-1, -1)
|
|
|
+ self._selection = []
|
|
|
+ self._actif = False
|
|
|
+
|
|
|
+ def afficherCase(self, coord, actif):
|
|
|
+ self.plateau.cases[coord].majEstCibleCurseur(actif)
|
|
|
+
|
|
|
+
|
|
|
+ def selectionFrontiere(self):
|
|
|
+ """retourne les cases selectionnees lors de l'utilisation de la forme 'frontiere'"""
|
|
|
+ listeCases = []
|
|
|
+ if self._objetGraphique != None:
|
|
|
+ ligne = self._objetGraphique.line()
|
|
|
+ normale = ligne.normalVector()
|
|
|
+ normale = normale.unitVector()
|
|
|
+ coordOrigine = self.coordonneesAuPoint(self.modeParam["origineFormeDessin"])
|
|
|
+ dx = normale.p2().x() - normale.p1().x()
|
|
|
+ dy = normale.p2().y() - normale.p1().y()
|
|
|
+ for coord in self.plateau.cases:
|
|
|
+ if dx < 0 and dy == 0: #normale pointe vers la gauche
|
|
|
+ if (coord[0] - coordOrigine[0]) <= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ if dx > 0 and dy == 0: #normale pointe vers la droite
|
|
|
+ if (coord[0] - coordOrigine[0]) >= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ if dx == 0 and dy < 0: #pointe vers le haut (rappel: axe y vers le bas)
|
|
|
+ if (coord[1] - coordOrigine[1]) <= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ elif dx == 0 and dy > 0: #pointe vers le bas
|
|
|
+ if (coord[1] - coordOrigine[1]) >= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ if dx > 0 and dy < 0: #pointe vers le haut droite
|
|
|
+ if (coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) >= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ elif dx > 0 and dy > 0: #pointe vers le bas droite
|
|
|
+ if -1*(coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) <= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ if dx < 0 and dy < 0: #pointe vers le haut gauche
|
|
|
+ if (coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) <= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ elif dx < 0 and dy > 0: #pointe vers le bas gauche
|
|
|
+ if -1*(coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) >= 0:
|
|
|
+ listeCases.append(coord)
|
|
|
+ return listeCases
|
|
|
+
|
|
|
+
|
|
|
+ def casesSousForme(self, forme, plein = True, epaisseur = 0):
|
|
|
+ """renvoie la liste des cases en collision avec un QGraphicsItem en parametre
|
|
|
+ plein = False: pas le contenu de la forme
|
|
|
+ epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee"""
|
|
|
+ tmp = []
|
|
|
+ listeCases = []
|
|
|
+ point1 = None
|
|
|
+ point2 = None
|
|
|
+ #point 1 et 2
|
|
|
+ if forme.__class__.__name__ == "QGraphicsLineItem":
|
|
|
+ point1 = forme.line().p1()
|
|
|
+ point2 = forme.line().p2()
|
|
|
+ elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem":
|
|
|
+ point1 = forme.rect().topLeft()
|
|
|
+ point2 = forme.rect().bottomRight()
|
|
|
+ else:
|
|
|
+ point1 = forme.boundingRect().topLeft()
|
|
|
+ point2 = forme.boundingRect().bottomRight()
|
|
|
+
|
|
|
+ #preselection des cases (meilleures perf)
|
|
|
+ if point1 != None and point2 != None and point1 != point2:
|
|
|
+ preSelection = self.preSelectionCollision(point1, point2)
|
|
|
+ else:
|
|
|
+ preSelection = []
|
|
|
+ for coord in self.cases:
|
|
|
+ preSelection.append(coord)
|
|
|
+
|
|
|
+ #on liste les cases en collision avec la forme
|
|
|
+ for coord in preSelection:
|
|
|
+ if self.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape):
|
|
|
+ if plein:
|
|
|
+ tmp.append(coord)
|
|
|
+ else:
|
|
|
+ contenu = True
|
|
|
+ for i in range(0,len(self.cases[coord].polygon())):
|
|
|
+ if not forme.contains(self.cases[coord].polygon().at(i)):
|
|
|
+ contenu = False
|
|
|
+ break
|
|
|
+ if contenu == False:
|
|
|
+ tmp.append(coord)
|
|
|
+ #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire
|
|
|
+ if not plein and epaisseur > 0:
|
|
|
+ for coord in tmp:
|
|
|
+ zone = self.zone(coord, epaisseur)
|
|
|
+ for coord2 in zone:
|
|
|
+ if not coord2 in listeCases:
|
|
|
+ listeCases.append(coord2)
|
|
|
+ else:
|
|
|
+ listeCases = tmp
|
|
|
+ #si la liste est vide, on ajoute l'origine de la forme
|
|
|
+ if len(listeCases) == 0:
|
|
|
+ listeCases = [self.coordonneesAuPoint(point1)]
|
|
|
+ return listeCases
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|