mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Kivy/Android
- switching of redeal images (redeal/stopped) corrected. - new wrapper class for options management. Refactorings. - redeal, pause and demo logo style selections updated.
This commit is contained in:
parent
611bd37024
commit
c5b22563a8
6 changed files with 162 additions and 56 deletions
|
@ -1779,6 +1779,8 @@ class Game(object):
|
|||
return
|
||||
if TOOLKIT == 'gtk':
|
||||
return
|
||||
if TOOLKIT == 'kivy':
|
||||
return
|
||||
if not Image:
|
||||
return
|
||||
self.canvas.hideAllItems()
|
||||
|
@ -1801,6 +1803,8 @@ class Game(object):
|
|||
return
|
||||
|
||||
def redealAnimation(self):
|
||||
if TOOLKIT == 'kivy':
|
||||
return
|
||||
if self.preview:
|
||||
return
|
||||
if not self.app.opt.animations or not self.app.opt.redeal_animation:
|
||||
|
@ -3428,6 +3432,11 @@ class Game(object):
|
|||
d = time.time() - self.stats.update_time + self.stats.elapsed_time
|
||||
self.updateStatus(time=format_time(d))
|
||||
|
||||
def displayPauseImage(self):
|
||||
n = self.random.initial_seed % len(self.app.gimages.pause)
|
||||
self.pause_logo = self.app.gimages.pause[int(n)]
|
||||
self.canvas.setTopImage(self.pause_logo)
|
||||
|
||||
def doPause(self):
|
||||
if self.finished:
|
||||
return
|
||||
|
@ -3439,9 +3448,7 @@ class Game(object):
|
|||
if self.pause:
|
||||
# self.updateTime()
|
||||
self.canvas.hideAllItems()
|
||||
n = self.random.initial_seed % len(self.app.gimages.pause)
|
||||
self.pause_logo = self.app.gimages.pause[int(n)]
|
||||
self.canvas.setTopImage(self.pause_logo)
|
||||
self.displayPauseImage()
|
||||
else:
|
||||
self.stats.update_time = time.time()
|
||||
self.updatePlayTime()
|
||||
|
|
|
@ -698,12 +698,17 @@ class LImageItem(BoxLayout, LBase):
|
|||
self.game = None
|
||||
self.card = None
|
||||
self.group = None
|
||||
self.image_type = "undefined"
|
||||
if 'game' in kw:
|
||||
self.game = kw['game']
|
||||
if 'card' in kw:
|
||||
self.card = kw['card']
|
||||
self.image_type = "card"
|
||||
if 'group' in kw:
|
||||
self.group = kw['group']
|
||||
if 'image_type' in kw:
|
||||
self.image_type = kw['image_type']
|
||||
|
||||
self.dragstart = None
|
||||
# ev. noch globales cache für stacks->game und cards->stack
|
||||
# einrichten. Aber: stacks hängt vom jeweiligen spiel ab.
|
||||
|
@ -711,6 +716,9 @@ class LImageItem(BoxLayout, LBase):
|
|||
def __str__(self):
|
||||
return f'<LImageItem @ {hex(id(self))}>'
|
||||
|
||||
def get_image_type(self):
|
||||
return self.image_type
|
||||
|
||||
def send_event_pressed_n(self, event, n):
|
||||
if self.group and n in self.group.bindings:
|
||||
self.group.bindings[n](event)
|
||||
|
|
69
pysollib/kivy/LObjWrap.py
Normal file
69
pysollib/kivy/LObjWrap.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/python
|
||||
# -*- mode: python; coding: utf-8; -*-
|
||||
# =============================================================================
|
||||
# Copyright (C) 2017-2023 LB
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# Flake8: noqa
|
||||
#
|
||||
# =============================================================================
|
||||
|
||||
import logging
|
||||
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.properties import BooleanProperty
|
||||
from kivy.properties import NumericProperty
|
||||
from kivy.properties import ListProperty
|
||||
from kivy.properties import StringProperty
|
||||
|
||||
# =============================================================================
|
||||
# Joins kivy properties to object members of referenced class.
|
||||
# Usage:
|
||||
# - use derived classes LBoolWrap etc. according to type.
|
||||
# - write: obj.value = <new value>
|
||||
# - read: <actual value> = obj.value
|
||||
# - If you need additional functionality on change add a callback function
|
||||
# as 'command'. It will be called whenever the value changes.
|
||||
|
||||
class LObjWrap(EventDispatcher):
|
||||
def __init__(self,obj,ref,command=None):
|
||||
self.obj = obj
|
||||
self.ref = ref
|
||||
self.value = getattr(self.obj,self.ref)
|
||||
# logging.info("LObjWrap: setup for %s" % (self.ref))
|
||||
self.bind(value=self.on_value)
|
||||
if command is not None:
|
||||
self.bind(value=command)
|
||||
|
||||
def on_value(self,inst,val):
|
||||
logging.info("LObjWrap: %s = %s" % (self.ref,val))
|
||||
setattr(self.obj,self.ref,val)
|
||||
|
||||
class LBoolWrap(LObjWrap):
|
||||
value = BooleanProperty(False)
|
||||
|
||||
def __init__(self,obj,ref,command=None):
|
||||
super(LBoolWrap,self).__init__(obj,ref,command)
|
||||
|
||||
class LNumWrap(LObjWrap):
|
||||
value = NumericProperty(0)
|
||||
|
||||
def __init__(self,obj,ref,command=None):
|
||||
super(LNumWrap,self).__init__(obj,ref,command)
|
||||
|
||||
class LStringWrap(LObjWrap):
|
||||
value = StringProperty('')
|
||||
|
||||
def __init__(self,obj,ref,command=None):
|
||||
super(LStringWrap,self).__init__(obj,ref,command)
|
||||
|
||||
class LListWrap(LObjWrap):
|
||||
value = ListProperty([])
|
||||
|
||||
def __init__(self,obj,ref,command=None):
|
||||
super(LListWrap,self).__init__(obj,ref,command)
|
||||
|
||||
# =============================================================================
|
|
@ -40,6 +40,9 @@ from pysollib.kivy.LApp import LScrollView
|
|||
from pysollib.kivy.LApp import LTopLevel
|
||||
from pysollib.kivy.LApp import LTreeNode
|
||||
from pysollib.kivy.LApp import LTreeRoot
|
||||
from pysollib.kivy.LObjWrap import LBoolWrap
|
||||
from pysollib.kivy.LObjWrap import LNumWrap
|
||||
from pysollib.kivy.LObjWrap import LStringWrap
|
||||
from pysollib.kivy.androidrot import AndroidScreenRotation
|
||||
from pysollib.kivy.findcarddialog import destroy_find_card_dialog
|
||||
from pysollib.kivy.fullpicturedialog import destroy_full_picture_dialog
|
||||
|
@ -119,16 +122,18 @@ class LMenuBase(object):
|
|||
self.closeWindow(0)
|
||||
return auto_close_command
|
||||
|
||||
def make_auto_command(self, variable, command):
|
||||
def make_toggle_command(self, variable, command):
|
||||
def auto_command():
|
||||
variable.set(not variable.get())
|
||||
command()
|
||||
variable.value = not variable.value
|
||||
if command is not None:
|
||||
command()
|
||||
return auto_command
|
||||
|
||||
def make_val_command(self, variable, value, command):
|
||||
def val_command():
|
||||
variable.value = value
|
||||
command()
|
||||
if command is not None:
|
||||
command()
|
||||
return val_command
|
||||
|
||||
def make_vars_command(self, command, key):
|
||||
|
@ -149,7 +154,7 @@ class LMenuBase(object):
|
|||
return _command
|
||||
|
||||
def addCheckNode(self, tv, rg, title, auto_var, auto_com):
|
||||
command = self.make_auto_command(auto_var, auto_com)
|
||||
command = self.make_toggle_command(auto_var, auto_com)
|
||||
rg1 = tv.add_node(
|
||||
LTreeNode(text=title, command=command, variable=auto_var), rg)
|
||||
return rg1
|
||||
|
@ -278,7 +283,7 @@ class MainMenuDialog(LMenuDialog):
|
|||
menubar, parent, title, app, **kw)
|
||||
|
||||
print('MainMenuDialog starting')
|
||||
AndroidScreenRotation.unlock()
|
||||
AndroidScreenRotation.unlock(toaster=False)
|
||||
|
||||
def buildTree(self, tv, node):
|
||||
rg = tv.add_node(
|
||||
|
@ -1134,17 +1139,23 @@ class LOptionsMenuGenerator(LTreeGenerator):
|
|||
self.menubar.tkopt.animations, 5,
|
||||
self.menubar.mOptAnimations)
|
||||
|
||||
# submenu.add_separator()
|
||||
|
||||
# NOTE: All the following animation features only work on the
|
||||
# desktop and only if pillow is installed. So its useless to
|
||||
# present them here.
|
||||
'''
|
||||
self.addCheckNode(tv, rg,
|
||||
_('Redeal animation'),
|
||||
self.menubar.tkopt.redeal_animation,
|
||||
self.menubar.mRedealAnimation)
|
||||
|
||||
self.addCheckNode(tv, rg,
|
||||
_('Winning animation'),
|
||||
self.menubar.tkopt.win_animation,
|
||||
self.menubar.mWinAnimation)
|
||||
self.addCheckNode(tv, rg,
|
||||
_('Flip animation'),
|
||||
self.menubar.tkopt.flip_animation,
|
||||
None)
|
||||
'''
|
||||
|
||||
yield
|
||||
# -------------------------------------------
|
||||
|
@ -1472,6 +1483,7 @@ class PysolMenubarTk:
|
|||
self.progress.update(step=1)
|
||||
|
||||
def _createTkOpt(self):
|
||||
opt = self.app.opt
|
||||
# structure to convert menu-options to Toolkit variables
|
||||
self.tkopt = Struct(
|
||||
gameid=IntVar(),
|
||||
|
@ -1501,9 +1513,10 @@ class PysolMenubarTk:
|
|||
sound_music_volume=IntVar(),
|
||||
cardback=IntVar(),
|
||||
tabletile=IntVar(),
|
||||
animations=IntVar(),
|
||||
redeal_animation=BooleanVar(),
|
||||
win_animation=BooleanVar(),
|
||||
animations=LNumWrap(opt, "animations"),
|
||||
redeal_animation=LBoolWrap(opt, "redeal_animation"),
|
||||
win_animation=LBoolWrap(opt, "win_animation"),
|
||||
flip_animation=LBoolWrap(opt, "flip_animation"),
|
||||
shadow=BooleanVar(),
|
||||
shade=BooleanVar(),
|
||||
shade_filled_stacks=BooleanVar(),
|
||||
|
@ -1518,10 +1531,10 @@ class PysolMenubarTk:
|
|||
helpbar=BooleanVar(),
|
||||
save_games_geometry=BooleanVar(),
|
||||
splashscreen=BooleanVar(),
|
||||
demo_logo=BooleanVar(),
|
||||
demo_logo_style=StringVar(),
|
||||
pause_text_style=StringVar(),
|
||||
redeal_icon_style=StringVar(),
|
||||
demo_logo=LBoolWrap(opt, "demo_logo"),
|
||||
demo_logo_style=LStringWrap(opt, "demo_logo_style"),
|
||||
pause_text_style=LStringWrap(opt, "pause_text_style"),
|
||||
redeal_icon_style=LStringWrap(opt, "redeal_icon_style"),
|
||||
mouse_type=StringVar(),
|
||||
mouse_undo=BooleanVar(),
|
||||
negative_bottom=BooleanVar(),
|
||||
|
@ -1570,9 +1583,6 @@ class PysolMenubarTk:
|
|||
tkopt.sound_music_volume.set(opt.sound_music_volume)
|
||||
tkopt.cardback.set(self.app.cardset.backindex)
|
||||
tkopt.tabletile.set(self.app.tabletile_index)
|
||||
tkopt.animations.set(opt.animations)
|
||||
tkopt.redeal_animation.set(opt.redeal_animation)
|
||||
tkopt.win_animation.set(opt.win_animation)
|
||||
tkopt.shadow.set(opt.shadow)
|
||||
tkopt.shade.set(opt.shade)
|
||||
tkopt.toolbar.set(opt.toolbar)
|
||||
|
@ -1583,10 +1593,6 @@ class PysolMenubarTk:
|
|||
tkopt.toolbar_relief.set(opt.toolbar_relief)
|
||||
tkopt.statusbar.set(opt.statusbar)
|
||||
tkopt.save_games_geometry.set(opt.save_games_geometry)
|
||||
tkopt.demo_logo.set(opt.demo_logo)
|
||||
tkopt.demo_logo_style.set(opt.demo_logo_style)
|
||||
tkopt.pause_text_style.set(opt.pause_text_style)
|
||||
tkopt.redeal_icon_style.set(opt.redeal_icon_style)
|
||||
tkopt.splashscreen.set(opt.splashscreen)
|
||||
tkopt.mouse_type.set(opt.mouse_type)
|
||||
tkopt.mouse_undo.set(opt.mouse_undo)
|
||||
|
@ -2334,17 +2340,14 @@ the next time you restart the %(app)s""") % {'app': TITLE})
|
|||
def mOptAnimations(self, *args):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.animations = self.tkopt.animations.value
|
||||
|
||||
def mRedealAnimation(self, *args):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.redeal_animation = self.tkopt.redeal_animation.value
|
||||
|
||||
def mWinAnimation(self, *args):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.win_animation = self.tkopt.win_animation.value
|
||||
|
||||
def mWinDialog(self, *args):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
|
@ -2499,13 +2502,13 @@ the next time you restart the %(app)s""") % {'app': TITLE})
|
|||
self.toolbarConfig(w, self.tkopt.toolbar_vars[w].get())
|
||||
|
||||
def mOptDemoLogoStyle(self, *event):
|
||||
self.setDemoLogoStyle(self.tkopt.demo_logo_style.get())
|
||||
self.setDemoLogoStyle()
|
||||
|
||||
def mOptPauseTextStyle(self, *event):
|
||||
self.setPauseTextStyle(self.tkopt.pause_text_style.get())
|
||||
self.setPauseTextStyle()
|
||||
|
||||
def mOptRedealIconStyle(self, *event):
|
||||
self.setRedealIconStyle(self.tkopt.redeal_icon_style.get())
|
||||
self.setRedealIconStyle()
|
||||
|
||||
def mOptStatusbar(self, *event):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
|
@ -2542,7 +2545,6 @@ the next time you restart the %(app)s""") % {'app': TITLE})
|
|||
def mOptDemoLogo(self, *event):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.demo_logo = self.tkopt.demo_logo.get()
|
||||
|
||||
def mOptSplashscreen(self, *event):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
|
@ -2630,20 +2632,15 @@ the next time you restart the %(app)s""") % {'app': TITLE})
|
|||
# other graphics
|
||||
#
|
||||
|
||||
def setDemoLogoStyle(self, style):
|
||||
def setDemoLogoStyle(self, style=None):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
if style == "none":
|
||||
self.app.opt.demo_logo = False
|
||||
if self.tkopt.demo_logo_style.value == "none":
|
||||
self.tkopt.demo_logo.value = False
|
||||
else:
|
||||
self.app.opt.demo_logo = True
|
||||
self.app.opt.demo_logo_style = style
|
||||
self.tkopt.demo_logo_style.set(style) # update radiobutton
|
||||
self.tkopt.demo_logo.value = True
|
||||
self.app.loadImages2()
|
||||
self.app.loadImages4()
|
||||
self.app.updateCardset()
|
||||
self.game.endGame(bookmark=1)
|
||||
self.game.quitGame(bookmark=1)
|
||||
|
||||
def setDialogIconStyle(self, style):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
|
@ -2653,27 +2650,25 @@ the next time you restart the %(app)s""") % {'app': TITLE})
|
|||
self.app.loadImages1()
|
||||
self.app.loadImages4()
|
||||
|
||||
def setPauseTextStyle(self, style):
|
||||
def setPauseTextStyle(self, style=None):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.pause_text_style = style
|
||||
self.tkopt.pause_text_style.set(style) # update radiobutton
|
||||
self.app.loadImages2()
|
||||
self.app.loadImages4()
|
||||
self.app.updateCardset()
|
||||
self.game.endGame(bookmark=1)
|
||||
self.game.quitGame(bookmark=1)
|
||||
if self.tkopt.pause.value:
|
||||
self.app.game.displayPauseImage()
|
||||
|
||||
def setRedealIconStyle(self, style):
|
||||
def setRedealIconStyle(self, style=None):
|
||||
if self._cancelDrag(break_pause=False):
|
||||
return
|
||||
self.app.opt.redeal_icon_style = style
|
||||
self.tkopt.redeal_icon_style.set(style) # update radiobutton
|
||||
self.app.loadImages2()
|
||||
self.app.loadImages4()
|
||||
self.app.updateCardset()
|
||||
self.game.endGame(bookmark=1)
|
||||
self.game.quitGame(bookmark=1)
|
||||
try:
|
||||
images = self.app.game.canvas.findImagesByType("redeal_image")
|
||||
for i in images:
|
||||
i.group.stack.updateRedealImage()
|
||||
except: # noqa
|
||||
pass
|
||||
|
||||
#
|
||||
# stacks descriptions
|
||||
|
|
|
@ -277,6 +277,7 @@ class MfxCanvasImage(object):
|
|||
|
||||
super(MfxCanvasImage, self).__init__()
|
||||
self.canvas = canvas
|
||||
self.redeal = False
|
||||
|
||||
# animation mode support:
|
||||
self.animation = 0
|
||||
|
@ -291,12 +292,15 @@ class MfxCanvasImage(object):
|
|||
else:
|
||||
image = LImage(texture=ed.texture)
|
||||
if self.hint == "redeal_image":
|
||||
cm = cardmagnif(canvas, size)/3.0
|
||||
cm = cardmagnif(canvas, size)/1.9
|
||||
image.size = [cm*ed.getWidth(), cm*ed.getHeight()]
|
||||
self.redeal = True
|
||||
aimage = LImageItem(
|
||||
size=ed.size, group=group, image_type=self.hint)
|
||||
else:
|
||||
image.size = [ed.getWidth(), ed.getHeight()]
|
||||
aimage = LImageItem(size=ed.size, group=group)
|
||||
|
||||
aimage = LImageItem(size=ed.size, group=group)
|
||||
aimage.add_widget(image)
|
||||
aimage.size = image.size
|
||||
size = image.size
|
||||
|
@ -322,6 +326,13 @@ class MfxCanvasImage(object):
|
|||
return f'<MfxCanvasImage @ {hex(id(self))}>'
|
||||
|
||||
def config(self, **kw):
|
||||
# print('MfxCanvasImage conifg:',kw)
|
||||
if "image" in kw:
|
||||
# print('is redeal image:',self.redeal)
|
||||
if self.redeal:
|
||||
image = self.image.children[0]
|
||||
image.texture = kw["image"].texture
|
||||
# print('redeal texture:',image.texture)
|
||||
pass
|
||||
|
||||
def makeDeferredRaise(self, pos):
|
||||
|
@ -819,6 +830,14 @@ class MfxCanvas(LImage):
|
|||
print('MfxCanvas: findCard no cardid')
|
||||
return -1
|
||||
|
||||
def findImagesByType(self, image_type):
|
||||
images = []
|
||||
for c in self.children:
|
||||
if type(c) is LImageItem:
|
||||
if c.get_image_type() == image_type:
|
||||
images.append(c)
|
||||
return images
|
||||
|
||||
def setTextColor(self, color):
|
||||
# print('MfxCanvas: setTextColor')
|
||||
# color is ignored: it sets a predefined (option settable)
|
||||
|
|
|
@ -1857,6 +1857,14 @@ class TalonStack(Stack,
|
|||
for stack in self.game.allstacks:
|
||||
stack.updateText()
|
||||
|
||||
def updateRedealImage(self):
|
||||
deal = self.canDealCards() != 0
|
||||
if self.images.redeal is not None:
|
||||
img = (self.getRedealImages())[deal]
|
||||
if img is not None and img is not self.images.redeal_img:
|
||||
self.images.redeal.config(image=img)
|
||||
self.images.redeal_img = img
|
||||
|
||||
def updateText(self, update_rounds=1, update_redeal=1):
|
||||
# assertView(self)
|
||||
Stack.updateText(self)
|
||||
|
|
Loading…
Add table
Reference in a new issue