"""pinceau utilise pour la selection et la mise a jour des cases du plateau""" from PyQt4.QtCore import QLineF, QRectF, QPointF from PyQt4.QtGui import QPen, QColor, QGraphicsLineItem, QGraphicsRectItem from lib.dmF import mini, maxi class Pinceau(): def __init__(self, plateau): self.plateau = plateau self._forme = "simple" self._epaisseur = 1 self._formeVerrouillee = False self._coordOrigine = None self._origine = None self._point2 = None self._selection = [] self._objetGraphique = None self._actif = False def estActif(self): return self._actif def majForme(self, forme): if forme in ["simple", "ligne", "frontiere", "pot", "rectV", "rectP"] and \ not self._formeVerrouillee: self._forme = forme def verrouillerForme(self, actif = True): self._formeVerrouillee = actif def majEpaisseur(self, val): if val in range(1, 5): self._epaisseur = val def defOrigine(self, coord): if self.plateau.geo.coordonneesValides(coord): self._coordOrigine = coord self._origine = self.plateau.cases[coord].centreGraphique def defPoint2(self, coord): if self.plateau.geo.coordonneesValides(coord): self._point2 = self.plateau.cases[coord].centreGraphique def selection(self): return self._selection def demarrer(self, coord): """commence a peindre a partir de la case choisie comme origine""" self._formeVerrouillee = False if self.plateau.geo.coordonneesValides(coord): self._coordOrigine = coord self._origine = self.plateau.cases[coord].centreGraphique self._point2 = self.plateau.cases[coord].centreGraphique self._actif = True self.maj(coord) def maj(self, coord): """on met a jour la selection en fonction de la case qui vient d'etre ajoutee""" if self._actif: enPlus = [] #cases a ajouter a la selection enMoins = [] #cases a retirer de la selection if self._origine == None: self._origine = self.plateau.cases[coord].centreGraphique if self._forme == "simple": #pas de forme: on ajoute les cases survolees a la liste des cases zone = self.plateau.geo.zone(coord, self._epaisseur - 1) for coord in zone: if not coord in self._selection: enPlus.append(coord) elif self._forme == "pot": #pot de peinture: on ne met a jour que si aucune projection n'est affichee if not len(self._selection) > 0: enPlus = self.selectionPot(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) else: select.remove(coord) enPlus = select #toutes les coord qui restent dans select sont a ajouter elif self._forme == "rectV" or self._forme == "rectP": #rectangle if self._objetGraphique == None: pinceau = QPen() pinceau.setColor(QColor("black")) self._objetGraphique = QGraphicsRectItem() self._objetGraphique.prepareGeometryChange() self._objetGraphique.setPen(pinceau) self.plateau.addItem(self._objetGraphique) self._point2 = self.plateau.cases[coord].centreGraphique 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) select = self.selectionRectangle(self._coordOrigine, coord, (self._forme == "rectP")) #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) else: select.remove(coord) enPlus = select #toutes les coord qui restent dans select sont a ajouter elif 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) #on liste les cases intersectant la forme # if self._objetGraphique: # select = self.plateau.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1) # else: # select = [coord] select = self.selectionLigne(self._coordOrigine, coord) #on prend l'epaisseur en compte selectPlus = [] for coord in select: zone = self.plateau.geo.zone(coord, self._epaisseur - 1) for ajout in zone: if not ajout in select and not ajout in selectPlus: selectPlus.append(ajout) select += selectPlus for coord in self._selection: if not coord in select: enMoins.append(coord) else: 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 reinit(self): for coord in self._selection: self.afficherCase(coord, False) if self._objetGraphique: self.plateau.removeItem(self._objetGraphique) self._objetGraphique = None self._origine = None self._point2 = None self._selection = [] self._actif = False def afficherCase(self, coord, actif): self.plateau.cases[coord].majEstCibleCurseur(actif) def selectionLigne(self, coord0, coord1): retour = self.plateau.geo.ligne(coord0, coord1) return retour def selectionRectangle(self, coord0, coord1, plein = True): """retourne les cases selectionnees lors de l'utilisation de la forme 'rectP' ou 'rectV'""" retour = [] #a: point en haut a gauche xa = mini(coord0[0], coord1[0]); ya = mini(coord0[1], coord1[1]) #b: point en bas a droite xb = maxi(coord0[0], coord1[0]); yb = maxi(coord0[1], coord1[1]) for coord in self.plateau.cases: x, y = coord if xa <= x <= xb and ya <= y <= yb: if plein: retour.append((x,y)) else: if x == xa or x == xb or y == ya or y == yb: retour.append((x,y)) return retour 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.plateau.coordonneesAuPoint(self._origine) 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 selectionPot(self, coord0): retour = [coord0] aVerifier = [coord0] while len(aVerifier) > 0: coord = aVerifier[0] for voisine in self.plateau.cases[coord].voisins: if not voisine in retour: if self.ontTerrainsSimilaires(voisine, coord): retour.append(voisine) aVerifier.append(voisine) aVerifier.remove(coord) return retour def ontTerrainsSimilaires(self, coord1, coord2): if len(self.plateau.cases[coord1].terrain.idM()) > 0: if self.plateau.cases[coord1].terrain.idM() == \ self.plateau.cases[coord2].terrain.idM(): return True else: if self.plateau.cases[coord1].terrain.couleur.rgb() == \ self.plateau.cases[coord2].terrain.couleur.rgb(): return True return False