Modes.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. #from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. """les modes d'interaction permettent l'interaction
  4. entre l'interface (l'utilisateur) et le plateau de combat.
  5. Un seul mode ne peut etre actif a la fois
  6. Cette classe doit permettre de recevoir les commandes de l'utilisateur
  7. de maniere a produire un resultat unique (cases peintes, pion deplace...)"""
  8. from PyQt4.QtCore import *
  9. from PyQt4.QtGui import *
  10. from EntreeSortie import EntreeSortie
  11. import regles
  12. class ModeBase(object):
  13. """mode de base: tous les modes heritent de cette classe"""
  14. def __init__(self, plateau):
  15. self.plateau = plateau
  16. #le mode est il active
  17. self._actif = False
  18. #le dragmode est il active sur la QGraphicsView
  19. self._activerDragMode = 0
  20. #curseur de la QGraphicsView
  21. self._sourceCurseur = ""
  22. #met le focus sur la QGraphicsView a l'activation
  23. self._focus = False
  24. def nom(self):
  25. return self.__class__.__name__
  26. def activer(self, param = None):
  27. """active le mode"""
  28. self.activerCurseur()
  29. if self._focus:
  30. self.plateau.fenetre.ui.cbt_vue.setFocus()
  31. self._actif = True
  32. def desactiver(self):
  33. """desactive le mode"""
  34. self.desactiverCurseur()
  35. self.plateau.fenetre.ui.cbt_vue.setDragMode(1)
  36. self._actif = False
  37. def reinit(self):
  38. """remet les variables a 0 et reactive le mode"""
  39. pass
  40. def activerCurseur(self):
  41. self.plateau.fenetre.ui.cbt_vue.setDragMode(self._activerDragMode)
  42. curseurPix = QPixmap(self._sourceCurseur)
  43. if not curseurPix.isNull():
  44. curseurPinceau = QCursor(curseurPix, 0, curseurPix.height())
  45. self.plateau.fenetre.ui.cbt_vue.setCursor(curseurPinceau)
  46. def desactiverCurseur(self):
  47. self.plateau.fenetre.ui.cbt_vue.setCursor(QCursor(Qt.ArrowCursor))
  48. ### gestion des evenements souris
  49. # clic gauche
  50. def clic_combattant(self, num):
  51. pass
  52. def clic_decor(self, num):
  53. pass
  54. def clic_case(self, coord):
  55. pass
  56. #double clic gauche
  57. def doubleClic_combattant(self, num):
  58. pass
  59. def doubleClic_decor(self, num):
  60. pass
  61. def doubleClic_case(self, coord):
  62. pass
  63. #survol de la souris (entree)
  64. def survol_combattant(self, num):
  65. pass
  66. def survol_decor(self, num):
  67. pass
  68. def survol_case(self, coord):
  69. pass
  70. #survol de la souris (sortie)
  71. def finSurvol_combattant(self, num):
  72. pass
  73. def finSurvol_decor(self, num):
  74. pass
  75. def finSurvol_case(self, coord):
  76. pass
  77. #survol de la souris avec clic gauche enfonce (entree)
  78. def survolClic_combattant(self, event):
  79. pass
  80. def survolClic_decor(self, event):
  81. pass
  82. def survolClic_case(self, coord):
  83. pass
  84. #autre
  85. def clicGauche(self, event):
  86. pass
  87. def finClicGauche(self, event):
  88. pass
  89. def mouvementSouris(self, event):
  90. pass
  91. def toucheClavier(self, event):
  92. pass
  93. def clicDroit(self, event):
  94. pass
  95. class ModeBaseCp(ModeBase):
  96. """mode servant de base a tous les modes lies a la creation de plateau"""
  97. def __init__(self, plateau):
  98. super(ModeBaseCp, self).__init__(plateau)
  99. self.type = "cp"
  100. def clicDroit(self, event):
  101. self.plateau.activerMode(Modes.StandardCp)
  102. class ModeBasePi(ModeBase):
  103. """mode servant de base a tous les modes lies aux actions des combattants"""
  104. def __init__(self, plateau):
  105. super(ModeBasePi, self).__init__(plateau)
  106. self.type = "pi"
  107. def clicDroit(self, event):
  108. self.plateau.activerMode(Modes.StandardPi)
  109. ### --------------------------------------- ####
  110. class StandardCp(ModeBaseCp):
  111. """mode standard en creation de plateau"""
  112. def __init__(self, plateau):
  113. super(StandardCp, self).__init__(plateau)
  114. self._sourceCurseur = ""
  115. self._focus = False
  116. self._activerDragMode = True
  117. def clic_pion(self, num):
  118. pass
  119. #doit selectionner le pion
  120. class MajCases(ModeBaseCp):
  121. """mode de mise a jour des cases (terrain, couleur, effet special)"""
  122. def __init__(self, plateau):
  123. super(MajCases, self).__init__(plateau)
  124. self._sourceCurseur = "img\\curseurPinceau.png"
  125. self._focus = True
  126. self._param = None #parametre avec lequel on mettra a jour la case
  127. def activer(self, param):
  128. """active le mode"""
  129. self.majParam(param)
  130. super(MajCases, self).activer()
  131. def desactiver(self):
  132. """desactive le mode"""
  133. self.plateau.pinceau.reinit()
  134. super(MajCases, self).desactiver()
  135. def majParam(self, param):
  136. self._param = param
  137. def param(self):
  138. return self._param
  139. def clic_case(self, coord):
  140. #demarre une operation de peinture des cases
  141. self.plateau.pinceau.demarrer(coord)
  142. def survolClic_case(self, coord):
  143. self.plateau.pinceau.maj(coord)
  144. def finClicGauche(self, event):
  145. if self.plateau.pinceau.estActif():
  146. for coord in self.plateau.pinceau.selection():
  147. if self._param.__class__.__name__ == "Terrain":
  148. self.plateau.cases[coord].majTerrain(self._param)
  149. elif self._param.__class__.__name__ == "QColor":
  150. if self._param.isValid():
  151. self.plateau.cases[coord].majTerrain(None)
  152. self.plateau.cases[coord].majCouleur(self._param)
  153. elif self._param.__class__.__name__ == "EffetCase":
  154. self.plateau.cases[coord].majEffet(self._param)
  155. self.plateau.pinceau.reinit()
  156. self.reinit()
  157. def toucheClavier(self, event):
  158. if event.key() == Qt.Key_Up:
  159. self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()+1)
  160. elif event.key() == Qt.Key_Down:
  161. self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()-1)
  162. class Pipette(ModeBaseCp):
  163. """mode pipette: on preleve la couleur ou le terrain d'une case"""
  164. def __init__(self, plateau):
  165. super(Pipette, self).__init__(plateau)
  166. self._sourceCurseur = "img\\curseurSeringue.png"
  167. def activerCurseur(self):
  168. super(Pipette, self).activerCurseur()
  169. def clic_case(self, coord):
  170. if len(self.plateau.cases[coord].terrain.nom) > 0:
  171. param = self.plateau.cases[coord].terrain
  172. else:
  173. param = self.plateau.cases[coord].couleur
  174. self.plateau.activerMode(MajCases, param)
  175. class ZonePlacement(ModeBaseCp):
  176. """mode de definition de la/les zones de placement des joueurs"""
  177. def __init__(self, plateau):
  178. super(ZonePlacement, self).__init__(plateau)
  179. self._sourceCurseur = "img\\curseurPinceau.png"
  180. self._focus = True
  181. def activerCurseur(self):
  182. super(ZonePlacement, self).activerCurseur()
  183. def activer(self, param = None):
  184. self.plateau.pinceau.majForme("rectP")
  185. self.plateau.pinceau.verrouillerForme(True)
  186. super(ZonePlacement, self).activer()
  187. def desactiver(self):
  188. self.plateau.pinceau.reinit()
  189. super(ZonePlacement, self).desactiver()
  190. def clic_case(self, coord):
  191. #demarre une operation de peinture des cases
  192. self.plateau.pinceau.demarrer(coord)
  193. def survolClic_case(self, coord):
  194. self.plateau.pinceau.maj(coord)
  195. def finClicGauche(self, coord):
  196. if self.plateau.pinceau.estActif():
  197. if len(self.plateau.pinceau.selection()) > 0:
  198. self.plateau.majZonePlacement(self.plateau.pinceau.selection())
  199. class EntreesSorties(ModeBaseCp):
  200. """mode de definition deentrees et sorties du plateau"""
  201. def __init__(self, plateau):
  202. super(EntreesSorties, self).__init__(plateau)
  203. self._sourceCurseur = "img\\curseurPinceau.png"
  204. self._focus = True
  205. def activerCurseur(self):
  206. super(EntreesSorties, self).activerCurseur()
  207. def activer(self, param):
  208. self.es = param
  209. self.es.creerForme()
  210. super(EntreesSorties, self).activer()
  211. def desactiver(self):
  212. if not self.es.estPositionne:
  213. self.es.prepareGeometryChange()
  214. self.es.plateau = None
  215. self.plateau.removeItem(self.es)
  216. super(EntreesSorties, self).desactiver()
  217. def mouvementSouris(self, event):
  218. if event.buttons() != Qt.LeftButton:
  219. if not self.es.estPositionne:
  220. self.es.majProjection(event.scenePos())
  221. def clicGauche(self, event):
  222. if not event.isAccepted():
  223. self.es.positionner()
  224. self.plateau.entreesSorties.append(self.es)
  225. self.desactiver()
  226. def toucheClavier(self, event):
  227. if event.key() == Qt.Key_Delete:
  228. #supprimer l'es
  229. self.desactiver()
  230. elif event.key() == Qt.Key_Right:
  231. self.es.nbRotations += 1
  232. self.es.majProjection()
  233. elif event.key() == Qt.Key_Left:
  234. self.es.nbRotations -= 1
  235. self.es.majProjection()
  236. class CreationPion(ModeBaseCp):
  237. """mode de creation de pions (combattant ou decor)"""
  238. def __init__(self, plateau):
  239. super(CreationPion, self).__init__(plateau)
  240. self._focus = True
  241. self._pion = None
  242. def activer(self, pion):
  243. self._pion = pion
  244. self.plateau.proj.creer(self._pion)
  245. super(CreationPion, self).activer()
  246. def desactiver(self):
  247. self.plateau.proj.desactiver()
  248. self._pion = None
  249. super(CreationPion, self).desactiver()
  250. def survol_case(self, coord):
  251. if self._pion:
  252. self.plateau.proj.majCoord(coord)
  253. def clic_case(self, coord):
  254. if self._pion:
  255. self.plateau.creerPion(self._pion)
  256. def toucheClavier(self, event):
  257. if self._pion:
  258. if event.key() == Qt.Key_Right:
  259. self.plateau.proj.majRotation(1)
  260. elif event.key() == Qt.Key_Left:
  261. self.plateau.proj.majRotation(-1)
  262. class SuppressionPion(ModeBaseCp):
  263. """mode de suppression de pions (combattant ou decor)"""
  264. def __init__(self, plateau):
  265. super(SuppressionPion, self).__init__(plateau)
  266. self._sourceCurseur = "img\\gomme.png"
  267. self._focus = True
  268. def clicGauche(self, event):
  269. """supprime le pion sous le clic. S'il y en a plusieurs,
  270. supprime le premier de la pile"""
  271. item = self.plateau.itemAt(event.scenePos())
  272. if item.parentItem().__class__.__name__ in ["Combattant", "Decor"]:
  273. self.plateau.pionSupprimer(item.parentItem().numero)
  274. class DeplacementPion(ModeBaseCp):
  275. """mode de deplacement de pions (combattant ou decor) en mode creation
  276. attention: different des actions de type deplacement qu'effectuent les pions en mode Combat"""
  277. def __init__(self, plateau):
  278. super(DeplacementPion, self).__init__(plateau)
  279. self._num = 0
  280. def activer(self, num):
  281. self._num = num
  282. if self._num < 10000:
  283. pion = self.plateau.combattants[self._num]
  284. else:
  285. pion = self.plateau.decors[self._num]
  286. self.plateau.proj.creer(pion)
  287. self.deplace = False
  288. super(DeplacementPion, self).activer()
  289. def desactiver(self):
  290. self.plateau.proj.desactiver()
  291. self._num = 0
  292. super(DeplacementPion, self).desactiver()
  293. def survol_case(self, coord):
  294. if self._num > 0:
  295. self.plateau.proj.majCoord(coord)
  296. self.deplace = True
  297. def clic_case(self, coord):
  298. if self._num > 0:
  299. if self.deplace:
  300. if self._num < 10000:
  301. pion = self.plateau.combattants[self._num]
  302. else:
  303. pion = self.plateau.decors[self._num]
  304. pion.majPosition(self.plateau.proj.coord(), self.plateau.proj.nbRotations())
  305. def toucheClavier(self, event):
  306. if self._num > 0:
  307. if event.key() == Qt.Key_Right:
  308. self.plateau.proj.majRotation(1)
  309. self.deplace = True
  310. elif event.key() == Qt.Key_Left:
  311. self.plateau.proj.majRotation(-1)
  312. self.deplace = True
  313. #-----------------------------------------------
  314. #-----------------------------------------------
  315. class StandardPi(ModeBasePi):
  316. """mode standard de la manipulation de pion en combat"""
  317. def __init__(self, plateau):
  318. super(StandardPi, self).__init__(plateau)
  319. self._focus = False
  320. self._activerDragMode = True
  321. def clic_combattant(self, num):
  322. self.plateau.activerMode(PionSelectionne, num)
  323. class PionSelectionne(ModeBasePi):
  324. """mode active a la selection d'un pion combattant"""
  325. def __init__(self, plateau):
  326. super(PionSelectionne, self).__init__(plateau)
  327. self._focus = True
  328. self._num = None
  329. def pion(self):
  330. """retourne la ref du pion actuellement selectionne"""
  331. return self.plateau.combattants[self._num]
  332. def activer(self, num):
  333. self._num = num
  334. #intensifie l'ombre du pion
  335. self.pion().afficheOmbreSelection(True)
  336. ### maj la selection dans la liste d'ordre de jeu
  337. for i in range(0, self.plateau.fenetre.ui.inf_listeOrdreJeu.rowCount()):
  338. if str(self.plateau.fenetre.ui.inf_listeOrdreJeu.item(i, 0).text().toUtf8()) == str(self._num):
  339. self.plateau.fenetre.ui.inf_listeOrdreJeu.setCurrentCell(i,0)
  340. ### maj des infos dans le panneau pi
  341. self.plateau.fenetre.ui.pi_nom.setText(QString.fromUtf8(self.pion().txtId()))
  342. if len(self.pion().img.nomFichier) > 0:
  343. pix = QPixmap(QString.fromUtf8("img\\"+self.pion().img.nomFichier))
  344. pix = pix.scaled(44, 44, Qt.KeepAspectRatio, Qt.SmoothTransformation)
  345. else:
  346. pix = QPixmap()
  347. self.plateau.fenetre.ui.pi_img.setPixmap(QPixmap())
  348. ### maj de la liste des attributs
  349. self.plateau.fenetre.ui.pi_listeAttributs.setColumnWidth(0, 50)
  350. self.plateau.disconnect(self.plateau.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.plateau.listeAttributCelluleModifiee)
  351. #on vide la liste
  352. while self.plateau.fenetre.ui.pi_listeAttributs.rowCount() > 0:
  353. self.plateau.fenetre.ui.pi_listeAttributs.removeRow(0)
  354. #creation des lignes de base
  355. lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans listeAttributCelluleModifiee
  356. for i in range(0, 10): #10 premieres colonnes reservees pour les infos de base
  357. self.plateau.fenetre.ui.pi_listeAttributs.insertRow(i)
  358. item = QTableWidgetItem()
  359. if i < len(lignesBase):
  360. item.setText(QString.fromUtf8(lignesBase[i]))
  361. item.setFlags(Qt.NoItemFlags)
  362. self.plateau.fenetre.ui.pi_listeAttributs.setItem(i, 0, item)
  363. self.plateau.fenetre.ui.pi_listeAttributs.setRowHidden(i, (i >= len(lignesBase)))
  364. #maj des donnees de base
  365. self.plateau.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Nom"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pion().nom))))
  366. self.plateau.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Etat"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pion().etat))))
  367. self.plateau.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Alt."), 1, QTableWidgetItem(QString.fromUtf8(str(self.pion().z))))
  368. #attributs issus des regles utilisees
  369. ordre = regles.ordreAttributs()
  370. for elt in ordre:
  371. ligne = 10 + ordre.index(elt)
  372. self.plateau.fenetre.ui.pi_listeAttributs.insertRow(ligne)
  373. item = QTableWidgetItem(QString.fromUtf8(elt))
  374. item.setFlags(Qt.NoItemFlags)
  375. self.plateau.fenetre.ui.pi_listeAttributs.setItem(ligne, 0, item)
  376. self.plateau.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pion().listeAttributs[elt]))))
  377. self.plateau.connect(self.plateau.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.plateau.listeAttributCelluleModifiee)
  378. ###affiche les notes du combattant
  379. self.plateau.fenetre.ui.pi_notes.setText(QString.fromUtf8(self.pion().notes))
  380. ###maj la liste des attaques du pion
  381. #on vide la liste
  382. while self.plateau.fenetre.ui.pi_listeAttaques.rowCount() > 0:
  383. self.plateau.fenetre.ui.pi_listeAttaques.removeRow(0)
  384. i = 0
  385. for attaque in self.pion().attaques:
  386. self.plateau.fenetre.ui.pi_listeAttaques.insertRow(i)
  387. self.plateau.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pion().attaques.index(attaque)))))
  388. icone = None
  389. if attaque.typ == "cac":
  390. icone = QIcon("img\\curseurEpee.png")
  391. if attaque.typ == "dist":
  392. icone = QIcon("img\\arc.png")
  393. if attaque.typ == "zone":
  394. icone = QIcon("img\\baguette.png")
  395. if icone != None:
  396. self.plateau.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
  397. self.plateau.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
  398. self.plateau.majInfosAttaqueEC()
  399. super(PionSelectionne, self).activer()
  400. def desactiver(self):
  401. self.pion().afficheOmbreSelection(False)
  402. #maj des infos dans le panneau pi
  403. self.plateau.fenetre.ui.pi_img.setPixmap(QPixmap())
  404. self.plateau.fenetre.ui.pi_nom.setText(QString.fromUtf8("Pas de pion\nselectionné"))
  405. #vide la liste des attributs
  406. self.plateau.disconnect(self.plateau.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
  407. while self.plateau.fenetre.ui.pi_listeAttributs.rowCount() > 0:
  408. self.plateau.fenetre.ui.pi_listeAttributs.removeRow(0)
  409. #vide la liste des attaques du pion
  410. while self.plateau.fenetre.ui.pi_listeAttaques.rowCount() > 0:
  411. self.plateau.fenetre.ui.pi_listeAttaques.removeRow(0)
  412. self.plateau.majInfosAttaqueEC()
  413. super(PionSelectionne, self).desactiver()