#from __future__ import unicode_literals # -*- coding: utf-8 -*- """les modes d'interaction permettent l'interaction entre l'interface (l'utilisateur) et le plateau de combat. Un seul mode ne peut etre actif a la fois Cette classe doit permettre de recevoir les commandes de l'utilisateur de maniere a produire un resultat unique (cases peintes, pion deplace...)""" from PyQt4.QtCore import Qt from PyQt4.QtGui import QPixmap, QCursor import Actions from Cache import Cache from EntreeSortie import EntreeSortie from dialogues import dmSaisie import dmK from lib.dialogues import dmAltitude, dmVol import regles class ModeBase(object): """mode de base: tous les modes heritent de cette classe""" def __init__(self, plateau): self.plateau = plateau #le mode est il active self._actif = False #le dragmode est il active sur la QGraphicsView self._activerDragMode = 0 #curseur de la QGraphicsView self._sourceCurseur = "" #met le focus sur la QGraphicsView a l'activation self._focus = False def nom(self): return self.__class__.__name__ def arborescence(self): """retourne l'arborescence actuelle des modes (sous forme de texte)""" txt = self.plateau.nom() if len(txt) > 30: txt = txt[0:30] + "..." return "Plateau: {}".format(txt) def activer(self, param = None): """active le mode""" self.activerCurseur() if self._focus: self.plateau.fenetre.ui.cbt_vue.setFocus() self._actif = True def desactiver(self): """desactive le mode""" self.desactiverCurseur() self.plateau.fenetre.ui.cbt_vue.setDragMode(1) self._actif = False def reinit(self): """remet les variables a 0 et reactive le mode""" pass def activerCurseur(self): self.plateau.fenetre.ui.cbt_vue.setDragMode(self._activerDragMode) curseurPix = QPixmap(self._sourceCurseur) if not curseurPix.isNull(): curseur = QCursor(curseurPix, 0, curseurPix.height()) self.plateau.fenetre.ui.cbt_vue.setCursor(curseur) def desactiverCurseur(self): self.plateau.fenetre.ui.cbt_vue.setCursor(QCursor(Qt.ArrowCursor)) ### gestion des evenements souris # clic gauche def clic_combattant(self, num): return False def clic_decor(self, num): return False def clic_case(self, coord): return False def clic_es(self, es): #clic sur une entree/sortie return False #double clic gauche def doubleClic_combattant(self, num): return False def doubleClic_decor(self, num): return False def doubleClic_case(self, coord): return False #survol de la souris (entree) def survol_combattant(self, num): return False def survol_decor(self, num): return False def survol_case(self, coord): return False #survol de la souris (sortie) def finSurvol_combattant(self, num): return False def finSurvol_decor(self, num): return False def finSurvol_case(self, coord): return False #survol de la souris avec clic gauche enfonce (entree) def survolClic_combattant(self, event): return False def survolClic_decor(self, event): return False def survolClic_case(self, coord): return False #autre def clicGauche(self, event): return False def finClicGauche(self, event): return False def mouvementSouris(self, event): return False def toucheClavier(self, event): return False def clicDroit(self, event): return False class ModeBaseCp(ModeBase): """mode servant de base a tous les modes lies a la creation de plateau""" def __init__(self, plateau): super(ModeBaseCp, self).__init__(plateau) self.type = "cp" def arborescence(self): txt = super(ModeBaseCp, self).arborescence() return txt + " > Mode Création" def activer(self, param = None): self.plateau.fenetre.ui.cbt_modeCreation.setChecked(True) super(ModeBaseCp, self).activer(param) def desactiver(self): self.plateau.fenetre.ui.cbt_modeCreation.setChecked(False) super(ModeBaseCp, self).desactiver() def clicDroit(self, event): self.plateau.activerMode(StandardCp) return True class ModeBasePi(ModeBase): """mode servant de base a tous les modes lies aux actions des combattants""" def __init__(self, plateau): super(ModeBasePi, self).__init__(plateau) self.type = "pi" def arborescence(self): txt = super(ModeBasePi, self).arborescence() return txt + " > Combat" def activer(self, param = None): self.plateau.fenetre.ui.cbt_modeCombat.setChecked(True) super(ModeBasePi, self).activer(param) def desactiver(self): self.plateau.fenetre.ui.cbt_modeCombat.setChecked(False) super(ModeBasePi, self).desactiver() def clicDroit(self, event): self.plateau.activerMode(StandardPi) return True ### --------------------------------------- #### class StandardCp(ModeBaseCp): """mode standard en creation de plateau""" def __init__(self, plateau): super(StandardCp, self).__init__(plateau) self._sourceCurseur = "" self._focus = False self._activerDragMode = True def activer(self, param): """active le mode""" self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(1) self.plateau.majCaches() super(StandardCp, self).activer() def clic_combattant(self, num): self.plateau.activerMode(DeplacementPion, num) return True def clic_decor(self, num): self.plateau.activerMode(DeplacementPion, num) return True def clic_es(self, es): self.plateau.activerMode(EditionEntreeSortie, es) return True class MajCases(ModeBaseCp): """mode de mise a jour des cases (terrain, couleur, effet special)""" def __init__(self, plateau): super(MajCases, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png" self._focus = True self._param = None #parametre avec lequel on mettra a jour la case self._caseSurvolee = None def arborescence(self): txt = super(MajCases, self).arborescence() return txt + " > Mise à jour des cases" def activer(self, param): """active le mode""" self.majParam(param) super(MajCases, self).activer() def desactiver(self): """desactive le mode""" if self.plateau.pinceau: self.plateau.pinceau.reinit() super(MajCases, self).desactiver() def majParam(self, param): self._param = param def param(self): return self._param def clic_case(self, coord): #demarre une operation de peinture des cases self.plateau.pinceau.demarrer(coord) return True def survolClic_case(self, coord): accepte = False if coord != self._caseSurvolee: self.plateau.pinceau.maj(coord) accepte = True return accepte def finClicGauche(self, event): accepte = False altitude = 0 if self.plateau.fenetre.ui.cp_gererAlt.isChecked() or dmK.touchesEnfoncees() == ["maj"]: altitude = self.saisieAltitude() if self.plateau.pinceau.estActif(): for coord in self.plateau.pinceau.selection(): self.plateau.cases[coord].majTerrain(self._param) self.plateau.cases[coord].majAltitude(altitude) self.plateau.pinceau.reinit() self.reinit() accepte = True return accepte def toucheClavier(self, event): accepte = False if event.key() == Qt.Key_Up: self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()+1) accepte = True elif event.key() == Qt.Key_Down: self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()-1) accepte = True return accepte def saisieAltitude(self): """affiche la fenetre de dialogue de saisie de l'altitude et renvoie la valeur saisie""" return dmAltitude(self.plateau.zP) class MajCasesEffet(MajCases): """mode de mise a jour des cases (effets speciaux)""" def __init__(self, plateau): super(MajCasesEffet, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png" def finClicGauche(self, event): accepte = False if self.plateau.pinceau.estActif(): for coord in self.plateau.pinceau.selection(): self.plateau.cases[coord].majEffet(self._param) self.plateau.pinceau.reinit() self.reinit() accepte = True return accepte class Pipette(ModeBaseCp): """mode pipette: on preleve la couleur ou le terrain d'une case""" def __init__(self, plateau): super(Pipette, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/seringue_16.png" def arborescence(self): txt = super(Pipette, self).arborescence() return txt + " > Pipette" def activerCurseur(self): super(Pipette, self).activerCurseur() def clic_case(self, coord): self.plateau.activerMode(MajCases, self.plateau.cases[coord].terrain) return True class ZonePlacement(ModeBaseCp): """mode de definition de la/les zones de placement des joueurs""" def __init__(self, plateau): super(ZonePlacement, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png" self._focus = True def arborescence(self): txt = super(ZonePlacement, self).arborescence() return txt + " > Création de la zone de placement" def activer(self, param = None): self.plateau.pinceau.majForme("rectP") self.plateau.pinceau.verrouillerForme(True) super(ZonePlacement, self).activer() def desactiver(self): self.plateau.pinceau.reinit() super(ZonePlacement, self).desactiver() def clic_case(self, coord): #demarre une operation de peinture des cases self.plateau.pinceau.demarrer(coord) return True def survolClic_case(self, coord): self.plateau.pinceau.maj(coord) return True def finClicGauche(self, coord): if self.plateau.pinceau.estActif(): lst = [] #on enleve d'eventuelles cases cachees for coord in self.plateau.pinceau.selection(): if not self.plateau.cases[coord].estCachee(): lst.append(coord) if len(lst) > 0: self.plateau.majZonePlacement(lst) self.plateau.activerMode(StandardCp) return True class PlacerCaches(ModeBaseCp): """mode de creation/ edition des caches""" def __init__(self, plateau): super(PlacerCaches, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png" self._focus = True self._numCache = None def arborescence(self): txt = super(PlacerCaches, self).arborescence() return txt + " > Création de caches" def activer(self, param = None): self._numCache = param self.plateau.pinceau.majForme("rectP") super(PlacerCaches, self).activer() def desactiver(self): self.plateau.pinceau.reinit() super(PlacerCaches, self).desactiver() def creerCache(self, listeCases, nom): """cree le cache avec le nom et la liste des cases en parametre""" #determination d'un nouvel id pour le cache idCache = 0 if len(self.plateau.caches) > 0: idCache = max(self.plateau.caches) + 1 #nom par defaut si besoin if not len(nom) > 0: nom = "Cache {}".format(idCache + 1) #creation du cache cache = Cache(idCache) cache.creer(self.plateau, listeCases, nom) def clic_case(self, coord): #on peint la liste des cases qui sera cachee self.plateau.pinceau.demarrer(coord) return True def survolClic_case(self, coord): self.plateau.pinceau.maj(coord) return True def finClicGauche(self, coord): #si la liste de cases peintes est valide, on demande le nom du cache et on le cree accepte = False if self.plateau.pinceau.estActif(): lst = [] #on enleve d'eventuelles cases sur la zone de placement for coord in self.plateau.pinceau.selection(): if not coord in self.plateau.listeCasesZonePlacement: lst.append(coord) if len(lst) > 0: nom = dmSaisie("Entrez le nom du cache à créer:") self.creerCache(lst, nom) self.plateau.activerMode(StandardCp) accepte = True return accepte class EntreeSortieBase(ModeBaseCp): """mode de base de la gestion des entrees et sorties du plateau""" def __init__(self, plateau): super(EntreeSortieBase, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png" self._focus = True def arborescence(self): txt = super(EntreeSortieBase, self).arborescence() return txt + " > Création des entrées/sorties" def activerCurseur(self): super(EntreeSortieBase, self).activerCurseur() def activer(self, param): self.es = param self.es.saisir() super(EntreeSortieBase, self).activer() def desactiver(self): if not self.es.estPositionne: self.es.prepareGeometryChange() self.es.plateau = None self.plateau.removeItem(self.es) if self.es in self.plateau.entreesSorties: self.plateau.entreesSorties.remove(self.es) super(EntreeSortieBase, self).desactiver() def mouvementSouris(self, event): accepte = False if event.buttons() != Qt.LeftButton: if not self.es.estPositionne: self.es.majProjection(event.scenePos()) accepte = True return accepte def toucheClavier(self, event): accepte = False if event.key() == Qt.Key_Delete: self.es.supprimer() if self.es in self.plateau.entreesSorties: self.plateau.entreesSorties.remove(self.es) self.plateau.activerMode(StandardCp) accepte = True elif event.key() == Qt.Key_Right: self.es.nbRotations += 1 self.es.majProjection() accepte = True elif event.key() == Qt.Key_Left: self.es.nbRotations -= 1 self.es.majProjection() accepte = True return accepte class CreationEntreeSortie(EntreeSortieBase): """mode de creation des entrees / sorties""" def __init__(self, plateau): super(CreationEntreeSortie, self).__init__(plateau) def activer(self, typeES): self.plateau.fenetre.ui.cbt_vue.fitInView(self.plateau.sceneRect(), Qt.KeepAspectRatio) param = EntreeSortie(self.plateau, typeES) param.creerForme() super(CreationEntreeSortie, self).activer(param) def clicGauche(self, event): self.es.positionner() self.plateau.entreesSorties.append(self.es) self.plateau.activerMode(StandardCp) return True class EditionEntreeSortie(EntreeSortieBase): """mode d'edition des entrees / sorties""" def __init__(self, plateau): super(EditionEntreeSortie, self).__init__(plateau) def arborescence(self): txt = super(EntreeSortieBase, self).arborescence() return txt + " > Edition des entrées/sorties" def clicGauche(self, event): accepte = False if not event.isAccepted(): self.es.positionner() self.plateau.activerMode(StandardCp) accepte = True return accepte class CreationPion(ModeBaseCp): """mode de creation de pions (combattant ou decor)""" def __init__(self, plateau): super(CreationPion, self).__init__(plateau) self._focus = True self._pion = None def arborescence(self): txt = super(CreationPion, self).arborescence() return txt + " > Création de pion" def activer(self, pion): self._pion = pion self.plateau.proj.creer(self._pion) super(CreationPion, self).activer() def desactiver(self): self.plateau.proj.desactiver() self._pion = None super(CreationPion, self).desactiver() def survol_case(self, coord): if self._pion: self.plateau.proj.majCoord(coord) return True return False def clic_case(self, coord): if self._pion: if self.plateau.proj.valide(): # if isinstance(self._pion, Combattant) and dmK.touchesEnfoncees() == ["maj"]: # nouveauZ = self.plateau.dialogueVol(self._pion.zR) # self._pion.majZ(nouveauZ) self.plateau.pions.nouveau(self._pion) return True return False def toucheClavier(self, event): if self._pion: if event.key() == Qt.Key_Right: self.plateau.proj.majRotation(1) return True elif event.key() == Qt.Key_Left: self.plateau.proj.majRotation(-1) return True return False class SuppressionPion(ModeBaseCp): """mode de suppression de pions (combattant ou decor)""" def __init__(self, plateau): super(SuppressionPion, self).__init__(plateau) self._sourceCurseur = ":/interface/16/ressource/gomme_16.png" self._enSurbrillance = [] self._focus = True def arborescence(self): txt = super(SuppressionPion, self).arborescence() return txt + " > Suppression de pion" def activer(self, param = None): #cible est le nom de la classe des objets a supprimer super(SuppressionPion, self).activer() def desactiver(self): for num in self.plateau.pions: self.plateau.pions[num].surbrillance(False) super(SuppressionPion, self).desactiver() def clicGauche(self, event): """supprime le pion sous le clic. S'il y en a plusieurs, supprime le premier de la pile""" num = self.plateau.pionAuPoint(event.scenePos()) if num: self.plateau.pions.supprimer(num) return True return False def survol_combattant(self, num): self.plateau.pions[num].surbrillance(True, 0.4) return True def finSurvol_combattant(self, num): self.plateau.pions[num].surbrillance(False) return True def survol_decor(self, num): self.plateau.pions[num].surbrillance(True, 0.4) return True def finSurvol_decor(self, num): self.plateau.pions[num].surbrillance(False) return True class DeplacementPion(ModeBaseCp): """mode de deplacement de pions (combattant ou decor) en mode creation attention: different des actions de type deplacement qu'effectuent les pions en mode Combat""" def __init__(self, plateau): super(DeplacementPion, self).__init__(plateau) self._num = 0 def arborescence(self): txt = super(DeplacementPion, self).arborescence() return txt + " > Deplacement de pion" def activer(self, num): self._num = num pion = self.plateau.pions[self._num] self.plateau.proj.creer(pion) self.deplace = False super(DeplacementPion, self).activer() def desactiver(self): self.plateau.proj.desactiver() self._num = 0 super(DeplacementPion, self).desactiver() def survol_case(self, coord): if self._num != 0: self.plateau.proj.majCoord(coord) self.deplace = True return True return False def clic_case(self, coord): if self._num !=0 and self.plateau.proj.valide(): if self.deplace: pion = self.plateau.pions[self._num] if self._num > 0 and dmK.touchesEnfoncees() == ["maj"]: maxi = ((self.plateau.zP - pion.h) if self.plateau.zP else None) nouveauZ = dmVol(pion.zR, maxi) pion.majZ(nouveauZ) pion.majPosition(self.plateau.proj.coord(), self.plateau.proj.nbRotations()) if self._num > 0: self.plateau.gC.reinitialiser() #-> au cas ou le pion serait deplace vers ou depuis un cache return True return False def toucheClavier(self, event): accepte = False if self._num > 0: if event.key() == Qt.Key_Right: self.plateau.proj.majRotation(1) self.deplace = True accepte = True elif event.key() == Qt.Key_Left: self.plateau.proj.majRotation(-1) self.deplace = True accepte = True return accepte #----------------------------------------------- #----------------------------------------------- class StandardPi(ModeBasePi): """mode standard de la manipulation de pion en combat""" def __init__(self, plateau): super(StandardPi, self).__init__(plateau) self._focus = False self._activerDragMode = True def activer(self, num): self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(3) self.plateau.fenetre.ui.cbt_panneauBas.setCurrentIndex(1) self.plateau.majCaches() super(StandardPi, self).activer() def clic_combattant(self, num): self.plateau.activerMode(PionSelectionne, num) return True def clic_decor(self, num): self.plateau.activerMode(PionSelectionne, num) return True def nouvelleAction(self, action): pass class PionSelectionne(ModeBasePi): """mode active a la selection d'un pion combattant""" def __init__(self, plateau): super(PionSelectionne, self).__init__(plateau) self._focus = True self._num = None self._action = None def arborescence(self): txt = super(PionSelectionne, self).arborescence() txt2 = self.pion().nom() if self.pion() else "" if len(txt2) > 15: txt2 = txt2[0:15] + "..." txt3 = " > {}".format(self._action.nom()) if self._action else "" return txt + " > {}".format(txt2) + txt3 def pion(self): """retourne la ref du pion actuellement selectionne""" return (self.plateau.pions[self._num]) if (self._num in self.plateau.pions) else None def activer(self, num): self._num = num self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(2) self.plateau.fenetre.ui.cbt_panneauBas.setCurrentIndex(0) self.plateau.fenetre.ui.act_img.chargerImage(self.plateau.pionSelectionne().img.rimage) self.pion().afficheOmbreSelection(True) self.plateau.majPanneauPi() super(PionSelectionne, self).activer() def desactiver(self): if self._action: self._action.desactiver() self._action = None if self.pion(): self.pion().afficheOmbreSelection(False) self._num = None self.plateau.fenetre.ui.act_img.clear() self.plateau.majPanneauPi() super(PionSelectionne, self).desactiver() def nouvelleAction(self, action): if self._action: self._action.desactiver() self._action = None self._action = action() self._action.activer(self.plateau, self._num) self.plateau.majArborescenceModes() def action(self): return self._action def survol_case(self, coord): if self._action: self._action.majCoordCible(coord) return True return False def clic_case(self, coord): accepte = False if self._action: self._action.valider() if not self._action.enCours(): self._action = None accepte = True return accepte def clicDroit(self, event): accepte = False if self._action != None: self._action.desactiver() self._action = None accepte = True self.plateau.majArborescenceModes() else: accepte = super(PionSelectionne, self).clicDroit(event) return accepte def toucheClavier(self, event): if self._num > 0: if event.key() == Qt.Key_Right: self._action.pivoter(1) return True elif event.key() == Qt.Key_Left: self._action.pivoter(-1) return True elif event.key() == Qt.Key_Up: self._action.modifierRayon(1) return True elif event.key() == Qt.Key_Down: self._action.modifierRayon(-1) return True return False