Modes.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  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 Actions
  12. import regles
  13. from Pion import Pion
  14. from Combattant import Combattant
  15. from Decor import Decor
  16. class ModeBase(object):
  17. """mode de base: tous les modes heritent de cette classe"""
  18. def __init__(self, plateau):
  19. self.plateau = plateau
  20. #le mode est il active
  21. self._actif = False
  22. #le dragmode est il active sur la QGraphicsView
  23. self._activerDragMode = 0
  24. #curseur de la QGraphicsView
  25. self._sourceCurseur = ""
  26. #met le focus sur la QGraphicsView a l'activation
  27. self._focus = False
  28. def nom(self):
  29. return self.__class__.__name__
  30. def activer(self, param = None):
  31. """active le mode"""
  32. self.activerCurseur()
  33. if self._focus:
  34. self.plateau.fenetre.ui.cbt_vue.setFocus()
  35. self._actif = True
  36. def desactiver(self):
  37. """desactive le mode"""
  38. self.desactiverCurseur()
  39. self.plateau.fenetre.ui.cbt_vue.setDragMode(1)
  40. self._actif = False
  41. def reinit(self):
  42. """remet les variables a 0 et reactive le mode"""
  43. pass
  44. def activerCurseur(self):
  45. self.plateau.fenetre.ui.cbt_vue.setDragMode(self._activerDragMode)
  46. curseurPix = QPixmap(self._sourceCurseur)
  47. if not curseurPix.isNull():
  48. curseur = QCursor(curseurPix, 0, curseurPix.height())
  49. self.plateau.fenetre.ui.cbt_vue.setCursor(curseur)
  50. def desactiverCurseur(self):
  51. self.plateau.fenetre.ui.cbt_vue.setCursor(QCursor(Qt.ArrowCursor))
  52. ### gestion des evenements souris
  53. # clic gauche
  54. def clic_combattant(self, num):
  55. pass
  56. def clic_decor(self, num):
  57. pass
  58. def clic_case(self, coord):
  59. pass
  60. #double clic gauche
  61. def doubleClic_combattant(self, num):
  62. pass
  63. def doubleClic_decor(self, num):
  64. pass
  65. def doubleClic_case(self, coord):
  66. pass
  67. #survol de la souris (entree)
  68. def survol_combattant(self, num):
  69. pass
  70. def survol_decor(self, num):
  71. pass
  72. def survol_case(self, coord):
  73. pass
  74. #survol de la souris (sortie)
  75. def finSurvol_combattant(self, num):
  76. pass
  77. def finSurvol_decor(self, num):
  78. pass
  79. def finSurvol_case(self, coord):
  80. pass
  81. #survol de la souris avec clic gauche enfonce (entree)
  82. def survolClic_combattant(self, event):
  83. pass
  84. def survolClic_decor(self, event):
  85. pass
  86. def survolClic_case(self, coord):
  87. pass
  88. #autre
  89. def clicGauche(self, event):
  90. pass
  91. def finClicGauche(self, event):
  92. pass
  93. def mouvementSouris(self, event):
  94. pass
  95. def toucheClavier(self, event):
  96. pass
  97. def clicDroit(self, event):
  98. pass
  99. class ModeBaseCp(ModeBase):
  100. """mode servant de base a tous les modes lies a la creation de plateau"""
  101. def __init__(self, plateau):
  102. super(ModeBaseCp, self).__init__(plateau)
  103. self.type = "cp"
  104. def clicDroit(self, event):
  105. self.plateau.activerMode(StandardCp)
  106. class ModeBasePi(ModeBase):
  107. """mode servant de base a tous les modes lies aux actions des combattants"""
  108. def __init__(self, plateau):
  109. super(ModeBasePi, self).__init__(plateau)
  110. self.type = "pi"
  111. def clicDroit(self, event):
  112. self.plateau.activerMode(StandardPi)
  113. ### --------------------------------------- ####
  114. class StandardCp(ModeBaseCp):
  115. """mode standard en creation de plateau"""
  116. def __init__(self, plateau):
  117. super(StandardCp, self).__init__(plateau)
  118. self._sourceCurseur = ""
  119. self._focus = False
  120. self._activerDragMode = True
  121. def activer(self, param):
  122. """active le mode"""
  123. self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(1)
  124. for cache in self.plateau.caches:
  125. cache.modeChange(self.__class__)
  126. super(StandardCp, self).activer()
  127. def clic_combattant(self, num):
  128. self.plateau.activerMode(DeplacementPion, num)
  129. def clic_decor(self, num):
  130. self.plateau.activerMode(DeplacementPion, num)
  131. class MajCases(ModeBaseCp):
  132. """mode de mise a jour des cases (terrain, couleur, effet special)"""
  133. def __init__(self, plateau):
  134. super(MajCases, self).__init__(plateau)
  135. self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
  136. self._focus = True
  137. self._param = None #parametre avec lequel on mettra a jour la case
  138. def activer(self, param):
  139. """active le mode"""
  140. self.majParam(param)
  141. super(MajCases, self).activer()
  142. def desactiver(self):
  143. """desactive le mode"""
  144. self.plateau.pinceau.reinit()
  145. super(MajCases, self).desactiver()
  146. def majParam(self, param):
  147. self._param = param
  148. def param(self):
  149. return self._param
  150. def clic_case(self, coord):
  151. #demarre une operation de peinture des cases
  152. self.plateau.pinceau.demarrer(coord)
  153. def survolClic_case(self, coord):
  154. self.plateau.pinceau.maj(coord)
  155. def finClicGauche(self, event):
  156. if self.plateau.pinceau.estActif():
  157. for coord in self.plateau.pinceau.selection():
  158. self.plateau.cases[coord].majTerrain(self._param)
  159. self.plateau.pinceau.reinit()
  160. self.reinit()
  161. def toucheClavier(self, event):
  162. if event.key() == Qt.Key_Up:
  163. self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()+1)
  164. elif event.key() == Qt.Key_Down:
  165. self.plateau.fenetre.ui.epaisseurPinceau.setValue(self.plateau.fenetre.ui.epaisseurPinceau.value()-1)
  166. class MajCasesEffet(MajCases):
  167. """mode de mise a jour des cases (effets speciaux)"""
  168. def __init__(self, plateau):
  169. super(MajCasesEffet, self).__init__(plateau)
  170. self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
  171. def finClicGauche(self, event):
  172. if self.plateau.pinceau.estActif():
  173. for coord in self.plateau.pinceau.selection():
  174. self.plateau.cases[coord].majEffet(self._param)
  175. self.plateau.pinceau.reinit()
  176. self.reinit()
  177. class Pipette(ModeBaseCp):
  178. """mode pipette: on preleve la couleur ou le terrain d'une case"""
  179. def __init__(self, plateau):
  180. super(Pipette, self).__init__(plateau)
  181. self._sourceCurseur = ":/interface/16/ressource/seringue_16.png"
  182. def activerCurseur(self):
  183. super(Pipette, self).activerCurseur()
  184. def clic_case(self, coord):
  185. self.plateau.activerMode(MajCases, self.plateau.cases[coord].terrain)
  186. class ZonePlacement(ModeBaseCp):
  187. """mode de definition de la/les zones de placement des joueurs"""
  188. def __init__(self, plateau):
  189. super(ZonePlacement, self).__init__(plateau)
  190. self._sourceCurseur = ":/interface/16/ressource/pinceau.png"
  191. self._focus = True
  192. def activerCurseur(self):
  193. super(ZonePlacement, self).activerCurseur()
  194. def activer(self, param = None):
  195. self.plateau.pinceau.majForme("rectP")
  196. self.plateau.pinceau.verrouillerForme(True)
  197. super(ZonePlacement, self).activer()
  198. def desactiver(self):
  199. self.plateau.pinceau.reinit()
  200. super(ZonePlacement, self).desactiver()
  201. def clic_case(self, coord):
  202. #demarre une operation de peinture des cases
  203. self.plateau.pinceau.demarrer(coord)
  204. def survolClic_case(self, coord):
  205. self.plateau.pinceau.maj(coord)
  206. def finClicGauche(self, coord):
  207. if self.plateau.pinceau.estActif():
  208. if len(self.plateau.pinceau.selection()) > 0:
  209. self.plateau.majZonePlacement(self.plateau.pinceau.selection())
  210. class EditerCaches(ModeBaseCp):
  211. """mode de creation/ edition des caches"""
  212. def __init__(self, plateau):
  213. super(EditerCaches, self).__init__(plateau)
  214. self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
  215. self._focus = True
  216. self._numCache = None
  217. def activer(self, param = None):
  218. self._numCache = param
  219. self.plateau.pinceau.majForme("rectP")
  220. super(EditerCaches, self).activer()
  221. def desactiver(self):
  222. self.plateau.pinceau.reinit()
  223. super(EditerCaches, self).desactiver()
  224. def clic_case(self, coord):
  225. self.plateau.pinceau.demarrer(coord)
  226. def survolClic_case(self, coord):
  227. self.plateau.pinceau.maj(coord)
  228. def finClicGauche(self, coord):
  229. if self.plateau.pinceau.estActif():
  230. if len(self.plateau.pinceau.selection()) > 0:
  231. if self._numCache != None:
  232. self.plateau.editerFormeCache(self._numCache, self.plateau.pinceau.selection())
  233. else:
  234. self.plateau.nouveauCache(self.plateau.pinceau.selection())
  235. self.plateau.activerMode(StandardCp)
  236. class EntreesSorties(ModeBaseCp):
  237. """mode de definition deentrees et sorties du plateau"""
  238. def __init__(self, plateau):
  239. super(EntreesSorties, self).__init__(plateau)
  240. self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
  241. self._focus = True
  242. def activerCurseur(self):
  243. super(EntreesSorties, self).activerCurseur()
  244. def activer(self, param):
  245. self.es = param
  246. self.es.creerForme()
  247. super(EntreesSorties, self).activer()
  248. def desactiver(self):
  249. if not self.es.estPositionne:
  250. self.es.prepareGeometryChange()
  251. self.es.plateau = None
  252. self.plateau.removeItem(self.es)
  253. super(EntreesSorties, self).desactiver()
  254. def mouvementSouris(self, event):
  255. if event.buttons() != Qt.LeftButton:
  256. if not self.es.estPositionne:
  257. self.es.majProjection(event.scenePos())
  258. def clicGauche(self, event):
  259. if not event.isAccepted():
  260. self.es.positionner()
  261. self.plateau.entreesSorties.append(self.es)
  262. self.desactiver()
  263. def toucheClavier(self, event):
  264. if event.key() == Qt.Key_Delete:
  265. #supprimer l'es
  266. self.desactiver()
  267. elif event.key() == Qt.Key_Right:
  268. self.es.nbRotations += 1
  269. self.es.majProjection()
  270. elif event.key() == Qt.Key_Left:
  271. self.es.nbRotations -= 1
  272. self.es.majProjection()
  273. class CreationPion(ModeBaseCp):
  274. """mode de creation de pions (combattant ou decor)"""
  275. def __init__(self, plateau):
  276. super(CreationPion, self).__init__(plateau)
  277. self._focus = True
  278. self._pion = None
  279. def activer(self, pion):
  280. self._pion = pion
  281. self.plateau.proj.creer(self._pion)
  282. super(CreationPion, self).activer()
  283. def desactiver(self):
  284. self.plateau.proj.desactiver()
  285. self._pion = None
  286. super(CreationPion, self).desactiver()
  287. def survol_case(self, coord):
  288. if self._pion:
  289. self.plateau.proj.majCoord(coord)
  290. def clic_case(self, coord):
  291. if self._pion:
  292. if not self.plateau.cases[coord].pionOccupant():
  293. self.plateau.creerPion(self._pion)
  294. def toucheClavier(self, event):
  295. if self._pion:
  296. if event.key() == Qt.Key_Right:
  297. self.plateau.proj.majRotation(1)
  298. elif event.key() == Qt.Key_Left:
  299. self.plateau.proj.majRotation(-1)
  300. class SuppressionPion(ModeBaseCp):
  301. """mode de suppression de pions (combattant ou decor)"""
  302. def __init__(self, plateau):
  303. super(SuppressionPion, self).__init__(plateau)
  304. self._sourceCurseur = ":/interface/16/ressource/gomme_16.png"
  305. self._enSurbrillance = []
  306. self._focus = True
  307. self._cible = ""
  308. def activer(self, cible = Pion):
  309. #cible est le nom de la classe des objets a supprimer
  310. self._cible = cible
  311. super(SuppressionPion, self).activer()
  312. def desactiver(self):
  313. for num in self._enSurbrillance:
  314. if num >= 10000:
  315. if num in self.plateau.decors:
  316. self.plateau.decors[num].surbrillance(False)
  317. else:
  318. if num in self.plateau.combattants:
  319. self.plateau.combattants[num].surbrillance(False)
  320. super(SuppressionPion, self).desactiver()
  321. def clicGauche(self, event):
  322. """supprime le pion sous le clic. S'il y en a plusieurs,
  323. supprime le premier de la pile"""
  324. num = None
  325. item = self.plateau.itemAt(event.scenePos())
  326. if isinstance(item.parentItem(), self._cible):
  327. num = item.parentItem().numero
  328. elif isinstance(item.parentItem().parentItem(), self._cible):
  329. num = item.parentItem().parentItem().numero
  330. if num:
  331. self.plateau.pionSupprimer(num)
  332. def survol_combattant(self, num):
  333. if self._cible == Combattant:
  334. self.plateau.combattants[num].surbrillance(True, 0.4)
  335. self._enSurbrillance.append(num)
  336. def finSurvol_combattant(self, num):
  337. if self._cible == Combattant:
  338. self.plateau.combattants[num].surbrillance(False)
  339. def survol_decor(self, num):
  340. if self._cible == Decor:
  341. self.plateau.decors[num].surbrillance(True, 0.4)
  342. self._enSurbrillance.append(num)
  343. def finSurvol_decor(self, num):
  344. if self._cible == Decor:
  345. self.plateau.decors[num].surbrillance(False)
  346. class DeplacementPion(ModeBaseCp):
  347. """mode de deplacement de pions (combattant ou decor) en mode creation
  348. attention: different des actions de type deplacement qu'effectuent les pions en mode Combat"""
  349. def __init__(self, plateau):
  350. super(DeplacementPion, self).__init__(plateau)
  351. self._num = 0
  352. def activer(self, num):
  353. self._num = num
  354. if self._num < 10000:
  355. pion = self.plateau.combattants[self._num]
  356. else:
  357. pion = self.plateau.decors[self._num]
  358. self.plateau.proj.creer(pion)
  359. self.deplace = False
  360. super(DeplacementPion, self).activer()
  361. def desactiver(self):
  362. self.plateau.proj.desactiver()
  363. self._num = 0
  364. super(DeplacementPion, self).desactiver()
  365. def survol_case(self, coord):
  366. if self._num > 0:
  367. self.plateau.proj.majCoord(coord)
  368. self.deplace = True
  369. def clic_case(self, coord):
  370. if self._num > 0:
  371. if self.deplace:
  372. if self._num < 10000:
  373. pion = self.plateau.combattants[self._num]
  374. else:
  375. pion = self.plateau.decors[self._num]
  376. pion.majPosition(self.plateau.proj.coord(), self.plateau.proj.nbRotations())
  377. def toucheClavier(self, event):
  378. if self._num > 0:
  379. if event.key() == Qt.Key_Right:
  380. self.plateau.proj.majRotation(1)
  381. self.deplace = True
  382. elif event.key() == Qt.Key_Left:
  383. self.plateau.proj.majRotation(-1)
  384. self.deplace = True
  385. #-----------------------------------------------
  386. #-----------------------------------------------
  387. class StandardPi(ModeBasePi):
  388. """mode standard de la manipulation de pion en combat"""
  389. def __init__(self, plateau):
  390. super(StandardPi, self).__init__(plateau)
  391. self._focus = False
  392. self._activerDragMode = True
  393. def activer(self, num):
  394. self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(3)
  395. for cache in self.plateau.caches:
  396. cache.modeChange(self.__class__)
  397. super(StandardPi, self).activer()
  398. def clic_combattant(self, num):
  399. self.plateau.activerMode(PionSelectionne, num)
  400. def clic_decor(self, num):
  401. self.plateau.activerMode(PionSelectionne, num)
  402. def nouvelleAction(self, action):
  403. pass
  404. class PionSelectionne(ModeBasePi):
  405. """mode active a la selection d'un pion combattant"""
  406. def __init__(self, plateau):
  407. super(PionSelectionne, self).__init__(plateau)
  408. self._focus = True
  409. self._num = None
  410. self._action = None
  411. def pion(self):
  412. """retourne la ref du pion actuellement selectionne"""
  413. retour = None
  414. if self._num in self.plateau.combattants:
  415. retour = self.plateau.combattants[self._num]
  416. elif self._num in self.plateau.decors:
  417. retour = self.plateau.decors[self._num]
  418. return retour
  419. def activer(self, num):
  420. self._num = num
  421. self.plateau.fenetre.ui.cbt_panneauDroite.setCurrentIndex(2)
  422. self.pion().afficheOmbreSelection(True)
  423. self.plateau.majPanneauPi()
  424. super(PionSelectionne, self).activer()
  425. def desactiver(self):
  426. if self._action:
  427. self._action.desactiver()
  428. self._action = None
  429. self.pion().afficheOmbreSelection(False)
  430. self._num = None
  431. self.plateau.majPanneauPi()
  432. super(PionSelectionne, self).desactiver()
  433. def nouvelleAction(self, action):
  434. if self._action:
  435. self._action.desactiver()
  436. self._action = None
  437. self._action = action()
  438. self._action.activer(self.plateau, self._num)
  439. def survol_case(self, coord):
  440. if self._action:
  441. self._action.majCoordCible(coord)
  442. def clic_case(self, coord):
  443. if self._action:
  444. terminee = self._action.valider()
  445. if not self._action.enCours(): self._action = None
  446. def clicDroit(self, event):
  447. if self._action != None:
  448. self._action.desactiver()
  449. self._action = None
  450. else:
  451. super(PionSelectionne, self).clicDroit(event)
  452. def toucheClavier(self, event):
  453. if self._num > 0:
  454. if event.key() == Qt.Key_Right:
  455. self._action.pivoter(1)
  456. elif event.key() == Qt.Key_Left:
  457. self._action.pivoter(-1)