--- /dev/null
+from os.path import dirname, exists, basename
+from platform import system
+from glob import glob
+from pathlib import Path
+from random import choice
+from logging import info
+from panda3d.core import AudioSound, Filename
+
+
+class MusicMgr:
+
+ def __init__(self, volume):
+ files = self.curr_path + 'assets/audio/music/*.ogg'
+ self._start_music(glob(files))
+ base.musicManager.setVolume(.8 * volume)
+ base.sfxManagerList[0].setVolume(volume)
+ taskMgr.add(self._on_frame, 'on frame music')
+
+ @property
+ def is_appimage(self):
+ par_path = str(Path(__file__).parent.absolute())
+ is_appimage = par_path.startswith('/tmp/.mount_Pmachi')
+ return is_appimage and par_path.endswith('/usr/bin')
+
+ @property
+ def curr_path(self):
+ if system() == 'Windows':
+ return ''
+ if exists('main.py'):
+ return ''
+ else:
+ par_path = str(Path(__file__).parent.absolute())
+ if self.is_appimage:
+ par_path = str(Path(par_path).absolute())
+ par_path += '/'
+ return par_path
+
+ def _start_music(self, files):
+ self._music = loader.load_music(choice(files))
+ info('playing music ' + self._music.get_name())
+ self._music.play()
+
+ def set_volume(self, volume):
+ base.musicManager.setVolume(.8 * volume)
+ base.sfxManagerList[0].setVolume(volume)
+
+ def _on_frame(self, task):
+ if self._music.status() == AudioSound.READY:
+ oggs = Filename(self.curr_path + 'assets/audio/music/*.ogg').to_os_specific()
+ files = glob(oggs)
+ rm_music = Filename(self.curr_path + 'assets/audio/music/' + basename(self._music.get_name())).to_os_specific()
+ # basename is needed in windows
+ files.remove(rm_music)
+ self._start_music(files)
+ return task.cont
+++ /dev/null
-import argparse
-import simplepbr
-#import gltf
-from glob import glob
-from importlib import import_module
-from inspect import isclass
-from sys import platform, argv, exit
-from logging import info, debug
-from os.path import exists
-from os import makedirs
-from panda3d.core import Filename, load_prc_file_data, AntialiasAttrib, \
- Texture, WindowProperties, LVector2i, TextNode
-from panda3d.bullet import BulletWorld, BulletDebugNode
-from direct.showbase.ShowBase import ShowBase
-from direct.gui.OnscreenText import OnscreenText
-from direct.fsm.FSM import FSM
-from game.music import MusicMgr
-from game.items.background import Background
-from game.menu import Menu
-from game.scene import Scene
-from game.scenes.scene_basketball import SceneBasketBall
-from game.scenes.scene_box import SceneBox
-from game.scenes.scene_domino_box_basketball import SceneDominoBoxBasketball
-from game.scenes.scene_domino_box import SceneDominoBox
-from game.scenes.scene_domino import SceneDomino
-from game.scenes.scene_teeter_domino_box_basketball import SceneTeeterDominoBoxBasketball
-from game.scenes.scene_teeter_tooter import SceneTeeterTooter
-from ya2.dictfile import DctFile
-from ya2.lib.p3d.p3d import LibP3d
-from ya2.engine.lang import LangMgr
-from ya2.engine.log import LogMgr
-from ya2.engine.functional import FunctionalTest
-
-
-class MainFsm(FSM):
-
- def __init__(self, pmachines):
- super().__init__('Main FSM')
- self._pmachines = pmachines
-
- def enterMenu(self):
- self._pmachines.on_menu_enter()
-
- def exitMenu(self):
- self._pmachines.on_menu_exit()
-
- def enterScene(self, cls):
- self._pmachines.on_scene_enter(cls)
-
- def exitScene(self):
- self._pmachines.on_scene_exit()
-
-
-class PmachinesApp:
-
- scenes = [
- SceneDomino,
- SceneBox,
- SceneDominoBox,
- SceneBasketBall,
- SceneDominoBoxBasketball,
- SceneTeeterTooter,
- SceneTeeterDominoBoxBasketball]
-
- def __init__(self):
- info('platform: %s' % platform)
- info('exists main.py: %s' % exists('main.py'))
- self._args = args = self._parse_args()
- self._configure(args)
- self.base = ShowBase()
- self._pipeline = None
- self.updating = args.update
- self.version = args.version
- self.log_mgr = LogMgr.init_cls()(self)
- self._prepare_window(args)
- if args.update:
- return
- if args.functional_test:
- self._options['settings']['volume'] = 0
- self._music = MusicMgr(self._options['settings']['volume'])
- self.lang_mgr = LangMgr(self._options['settings']['language'],
- 'pmachines',
- 'assets/locale/')
- self._fsm = MainFsm(self)
- if args.screenshot:
- cls = [cls for cls in self.scenes if cls.__name__ == args.screenshot][0]
- scene = cls(BulletWorld(), None, True, False, lambda: None, self.scenes)
- scene.screenshot()
- scene.destroy()
- exit()
- elif self._options['development']['auto_start']:
- mod_name = 'game.scenes.scene_' + self._options['development']['auto_start']
- for member in import_module(mod_name).__dict__.values():
- if isclass(member) and issubclass(member, Scene) and \
- member != Scene:
- cls = member
- self._fsm.demand('Scene', cls)
- else:
- self._fsm.demand('Menu')
- if args.functional_test or args.functional_ref:
- FunctionalTest(args.functional_ref)
-
- def on_menu_enter(self):
- self._menu_bg = Background()
- self._menu = Menu(
- self._fsm, self.lang_mgr, self._options, self._music,
- self._pipeline, self.scenes, self._args.functional_test or self._args.functional_ref)
-
- def on_home(self):
- self._fsm.demand('Menu')
-
- def on_menu_exit(self):
- self._menu_bg.destroy()
- self._menu.destroy()
-
- def on_scene_enter(self, cls):
- self._set_physics()
- self._scene = cls(
- self.world, self.on_home,
- self._options['development']['auto_close_instructions'],
- self._options['development']['debug_items'],
- self.reload,
- self.scenes)
-
- def on_scene_exit(self):
- self._unset_physics()
- self._scene.destroy()
-
- def reload(self, cls):
- self._fsm.demand('Scene', cls)
-
- def _configure(self, args):
- load_prc_file_data('', 'window-title pmachines')
- load_prc_file_data('', 'framebuffer-srgb true')
- load_prc_file_data('', 'sync-video true')
- if args.functional_test or args.functional_ref:
- load_prc_file_data('', 'win-size 1360 768')
- # otherwise it is not centered in exwm
- # load_prc_file_data('', 'threading-model Cull/Draw')
- # it freezes when you go to the next scene
- if args.screenshot:
- load_prc_file_data('', 'window-type offscreen')
- load_prc_file_data('', 'audio-library-name null')
-
- def _parse_args(self):
- parser = argparse.ArgumentParser()
- parser.add_argument('--update', action='store_true')
- parser.add_argument('--version', action='store_true')
- parser.add_argument('--optfile')
- parser.add_argument('--screenshot')
- parser.add_argument('--functional-test', action='store_true')
- parser.add_argument('--functional-ref', action='store_true')
- cmd_line = [arg for arg in iter(argv[1:]) if not arg.startswith('-psn_')]
- args = parser.parse_args(cmd_line)
- return args
-
- def _prepare_window(self, args):
- data_path = ''
- if (platform.startswith('win') or platform.startswith('linux')) and (
- not exists('main.py') or __file__.startswith('/app/bin/')):
- # it is the deployed version for windows
- data_path = str(Filename.get_user_appdata_directory()) + '/pmachines'
- home = '/home/flavio' # we must force this for wine
- if data_path.startswith('/c/users/') and exists(home + '/.wine/'):
- data_path = home + '/.wine/drive_' + data_path[1:]
- info('creating dirs: %s' % data_path)
- makedirs(data_path, exist_ok=True)
- optfile = args.optfile if args.optfile else 'options.ini'
- info('data path: %s' % data_path)
- info('option file: %s' % optfile)
- info('fixed path: %s' % LibP3d.fixpath(data_path + '/' + optfile))
- default_opt = {
- 'settings': {
- 'volume': 1,
- 'language': 'en',
- 'fullscreen': 1,
- 'resolution': '',
- 'antialiasing': 1,
- 'shadows': 1},
- 'development': {
- 'simplepbr': 1,
- 'verbose_log': 0,
- 'physics_debug': 0,
- 'auto_start': 0,
- 'auto_close_instructions': 0,
- 'show_buffers': 0,
- 'debug_items': 0,
- 'mouse_coords': 0,
- 'fps': 0}}
- opt_path = LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile
- opt_exists = exists(opt_path)
- self._options = DctFile(
- LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile,
- default_opt)
- if not opt_exists:
- self._options.store()
- res = self._options['settings']['resolution']
- if res:
- res = LVector2i(*[int(_res) for _res in res.split('x')])
- else:
- resolutions = []
- if not self.version:
- d_i = base.pipe.get_display_information()
- def _res(idx):
- return d_i.get_display_mode_width(idx), \
- d_i.get_display_mode_height(idx)
- resolutions = [
- _res(idx) for idx in range(d_i.get_total_display_modes())]
- res = sorted(resolutions)[-1]
- fullscreen = self._options['settings']['fullscreen']
- props = WindowProperties()
- if args.functional_test or args.functional_ref:
- fullscreen = False
- else:
- props.set_size(res)
- props.set_fullscreen(fullscreen)
- props.set_icon_filename('assets/images/icon/pmachines.ico')
- if not args.screenshot and not self.version:
- base.win.request_properties(props)
- #gltf.patch_loader(base.loader)
- if self._options['development']['simplepbr'] and not self.version:
- self._pipeline = simplepbr.init(
- use_normal_maps=True,
- use_emission_maps=False,
- use_occlusion_maps=True,
- msaa_samples=4 if self._options['settings']['antialiasing'] else 1,
- enable_shadows=int(self._options['settings']['shadows']))
- debug(f'msaa: {self._pipeline.msaa_samples}')
- debug(f'shadows: {self._pipeline.enable_shadows}')
- render.setAntialias(AntialiasAttrib.MAuto)
- self.base.set_background_color(0, 0, 0, 1)
- self.base.disable_mouse()
- if self._options['development']['show_buffers']:
- base.bufferViewer.toggleEnable()
- if self._options['development']['fps']:
- base.set_frame_rate_meter(True)
- #self.base.accept('window-event', self._on_win_evt)
- self.base.accept('aspectRatioChanged', self._on_aspect_ratio_changed)
- if self._options['development']['mouse_coords']:
- coords_txt = OnscreenText(
- '', parent=base.a2dTopRight, scale=0.04,
- pos=(-.03, -.06), fg=(.9, .9, .9, 1), align=TextNode.A_right)
- def update_coords(task):
- txt = '%s %s' % (int(base.win.get_pointer(0).x),
- int(base.win.get_pointer(0).y))
- coords_txt['text'] = txt
- return task.cont
- taskMgr.add(update_coords, 'update_coords')
-
- def _set_physics(self):
- if self._options['development']['physics_debug']:
- debug_node = BulletDebugNode('Debug')
- debug_node.show_wireframe(True)
- debug_node.show_constraints(True)
- debug_node.show_bounding_boxes(True)
- debug_node.show_normals(True)
- self._debug_np = render.attach_new_node(debug_node)
- self._debug_np.show()
- self.world = BulletWorld()
- self.world.set_gravity((0, 0, -9.81))
- if self._options['development']['physics_debug']:
- self.world.set_debug_node(self._debug_np.node())
- def update(task):
- dt = globalClock.get_dt()
- self.world.do_physics(dt, 10, 1/180)
- return task.cont
- self._phys_tsk = taskMgr.add(update, 'update')
-
- def _unset_physics(self):
- if self._options['development']['physics_debug']:
- self._debug_np.remove_node()
- self.world = None
- taskMgr.remove(self._phys_tsk)
-
- def _on_aspect_ratio_changed(self):
- if self._fsm.state == 'Scene':
- self._scene.on_aspect_ratio_changed()
+++ /dev/null
-from itertools import product
-from panda3d.core import NodePath
-from ya2.lib.p3d.gfx import set_srgb
-
-
-class Background:
-
- def __init__(self):
- self._root = NodePath('background_root')
- self._root.reparent_to(render)
- ncols, nrows = 16, 8
- start_size, end_size = 5, 2.5
- offset = 5
- for col, row in product(range(ncols), range(nrows)):
- model = loader.load_model('assets/models/bam/background/background.bam')
- model.set_scale(end_size / start_size)
- model.reparent_to(self._root)
- total_width, total_height = end_size * ncols, end_size * nrows
- left, bottom = -total_width/2, -total_height/2
- model.set_pos(left + end_size * col, offset, bottom + end_size * row)
- self._root.clear_model_nodes()
- self._root.flatten_strong()
- set_srgb(self._root)
-
- def destroy(self):
- self._root.remove_node()
+++ /dev/null
-from panda3d.bullet import BulletSphereShape, BulletRigidBodyNode, BulletGhostNode
-from game.items.item import Item
-
-
-class Basketball(Item):
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.92, friction=.6):
- super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/basketball/basketball.bam', .4, mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
-
- def _set_shape(self, apply_scale=True):
- self.node.add_shape(BulletSphereShape(1))
+++ /dev/null
-from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
-from game.items.item import Item
-
-
-class Box(Item):
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.8, model_scale=1):
- super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/box/box.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction, model_scale=model_scale)
-
- def _set_shape(self, apply_scale=True):
- self.node.add_shape(BulletBoxShape((.5, .5, .5)))
-
-
-class HitStrategy:
-
- def __init__(self, hit_by, node, world):
- self._hit_by = hit_by
- self._node = node
- self._world = world
-
- def win_condition(self):
- for contact in self._world.contact_test(self._node).get_contacts():
- other = contact.get_node1() if contact.get_node0() == self._node else contact.get_node0()
- if other == self._hit_by.node:
- return True
+++ /dev/null
-from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
-from game.items.item import Item, StillStrategy
-
-
-class Domino(Item):
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.6):
- super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/domino/domino.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
-
- def _set_shape(self, apply_scale=True):
- self.node.add_shape(BulletBoxShape((.1, .25, .5)))
-
-
-class UpStrategy(StillStrategy):
-
- def __init__(self, np, tgt_degrees):
- super().__init__(np)
- self._tgt_degrees = tgt_degrees
- self._np = np
-
- def win_condition(self):
- return super().win_condition() and abs(self._np.get_r()) <= self._tgt_degrees
-
-
-class DownStrategy(StillStrategy):
-
- def __init__(self, np, tgt_degrees):
- super().__init__(np)
- self._tgt_degrees = tgt_degrees
- self._np = np
-
- def win_condition(self):
- return self._np.get_z() < -6 or super().win_condition() and abs(self._np.get_r()) >= self._tgt_degrees
+++ /dev/null
-from panda3d.core import CullFaceAttrib, Point3, NodePath, Point2, Texture, \
- Plane, Vec3, BitMask32
-from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
-from direct.gui.OnscreenText import OnscreenText
-from ya2.lib.p3d.gfx import P3dGfxMgr, set_srgb
-
-
-class Command:
-
- def __init__(self, pos, rot):
- self.pos = pos
- self.rot = rot
-
-
-class FixedStrategy:
-
- def win_condition(self):
- return True
-
-
-class StillStrategy:
-
- def __init__(self, np):
- self._np = np
- self._positions = []
- self._rotations = []
-
- def win_condition(self):
- self._positions += [self._np.get_pos()]
- self._rotations += [self._np.get_hpr()]
- if len(self._positions) > 30:
- self._positions.pop(0)
- if len(self._rotations) > 30:
- self._rotations.pop(0)
- if len(self._positions) < 28:
- return
- avg_x = sum(pos.x for pos in self._positions) / len(self._positions)
- avg_y = sum(pos.y for pos in self._positions) / len(self._positions)
- avg_z = sum(pos.z for pos in self._positions) / len(self._positions)
- avg_h = sum(rot.x for rot in self._rotations) / len(self._rotations)
- avg_p = sum(rot.y for rot in self._rotations) / len(self._rotations)
- avg_r = sum(rot.z for rot in self._rotations) / len(self._rotations)
- avg_pos = Point3(avg_x, avg_y, avg_z)
- avg_rot = Point3(avg_h, avg_p, avg_r)
- return all((pos - avg_pos).length() < .1 for pos in self._positions) and \
- all((rot - avg_rot).length() < 1 for rot in self._rotations)
-
-
-class Item:
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, scene_repos, model_path, model_scale=1, exp_num_contacts=1, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.5):
- self._world = world
- self._plane_node = plane_node
- self._count = count
- self._cb_inst = cb_inst
- self._paused = False
- self._overlapping = False
- self._first_command = True
- self.repos_done = False
- self._mass = mass
- self._pos = pos
- self._r = r
- self.strategy = FixedStrategy()
- self._exp_num_contacts = exp_num_contacts
- self._curr_bottom = curr_bottom
- self._scene_repos = scene_repos
- self._model_scale = model_scale
- self._model_path = model_path
- self._commands = []
- self._command_idx = -1
- self._restitution = restitution
- self._friction = friction
- self._positions = []
- self._rotations = []
- if count:
- self.node = BulletGhostNode(self.__class__.__name__)
- else:
- self.node = BulletRigidBodyNode(self.__class__.__name__)
- self._set_shape(count)
- self._np = render.attach_new_node(self.node)
- if count:
- world.attach_ghost(self.node)
- else:
- world.attach_rigid_body(self.node)
- self._model = loader.load_model(model_path)
- set_srgb(self._model)
- self._model.flatten_light()
- self._model.reparent_to(self._np)
- self._np.set_scale(model_scale)
- self._np.flatten_strong()
- if count:
- self._set_outline_model()
- set_srgb(self._outline_model)
- self._model.hide(BitMask32(0x01))
- self._outline_model.hide(BitMask32(0x01))
- self._start_drag_pos = None
- self._prev_rot_info = None
- self._last_nonoverlapping_pos = None
- self._last_nonoverlapping_rot = None
- self._instantiated = not count
- self.interactable = count
- self._box_tsk = taskMgr.add(self.on_frame, 'on_frame')
- if count:
- self._repos()
- else:
- self._np.set_pos(pos)
- self._np.set_r(r)
-
- def _set_shape(self, apply_scale=True):
- pass
-
- def set_strategy(self, strategy):
- self.strategy = strategy
-
- def _repos(self):
- p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
- for hit in self._world.ray_test_all(p_from, p_to).get_hits():
- if hit.get_node() == self._plane_node:
- pos = hit.get_hit_pos()
- corner = P3dGfxMgr.screen_coord(pos)
- bounds = self._np.get_tight_bounds()
- bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
- self._np.set_pos(pos)
- plane = Plane(Vec3(0, 1, 0), bounds[0][1])
- pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
- margin, ar = .04, base.get_aspect_ratio()
- margin_x = margin / ar if ar >= 1 else margin
- margin_z = margin * ar if ar < 1 else margin
- top = self._curr_bottom()
- base.camLens.extrude((-1 + margin_x, top - margin_z), near_pt, far_pt)
- plane.intersects_line(
- pos3d, render.get_relative_point(base.camera, near_pt),
- render.get_relative_point(base.camera, far_pt))
- delta = Vec3(bounds[1][0], bounds[1][1], bounds[0][2])
- self._np.set_pos(pos3d + delta)
- if not hasattr(self, '_txt'):
- font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
- font.clear()
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- font.set_outline((0, 0, 0, 1), .8, .2)
- self._txt = OnscreenText(
- str(self._count), font=font, scale=0.06, fg=(.9, .9, .9, 1))
- pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
- self._txt['pos'] = p2d
- self.repos_done = True
-
- def repos_x(self, x):
- self._np.set_x(x)
- bounds = self._np.get_tight_bounds()
- bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
- pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
- self._txt['pos'] = p2d
-
- def get_bottom(self):
- bounds = self._np.get_tight_bounds()
- bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
- pos = self._np.get_pos() + (bounds[1][0], bounds[1][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
- ar = base.get_aspect_ratio()
- return p2d[1] if ar >= 1 else (p2d[1] * ar)
-
- def get_corner(self):
- bounds = self._np.get_tight_bounds()
- return bounds[1][0], bounds[1][1], bounds[0][2]
-
- def _set_outline_model(self):
- self._outline_model = loader.load_model(self._model_path)
- #clockw = CullFaceAttrib.MCullClockwise
- #self._outline_model.set_attrib(CullFaceAttrib.make(clockw))
- self._outline_model.set_attrib(CullFaceAttrib.make_reverse())
- self._outline_model.reparent_to(self._np)
- self._outline_model.set_scale(1.08)
- self._outline_model.set_light_off()
- self._outline_model.set_color(.4, .4, .4, 1)
- self._outline_model.set_color_scale(.4, .4, .4, 1)
- self._outline_model.hide()
-
- def on_frame(self, task):
- self._np.set_y(0)
- return task.cont
-
- def undo(self):
- self._command_idx -= 1
- self._np.set_pos(self._commands[self._command_idx].pos)
- self._np.set_hpr(self._commands[self._command_idx].rot)
-
- def redo(self):
- self._command_idx += 1
- self._np.set_pos(self._commands[self._command_idx].pos)
- self._np.set_hpr(self._commands[self._command_idx].rot)
-
- def play(self):
- if not self._instantiated:
- return
- self._world.remove_rigid_body(self.node)
- self.node.set_mass(self._mass)
- self._world.attach_rigid_body(self.node)
- self.node.set_restitution(self._restitution)
- self.node.set_friction(self._friction)
-
- def on_click_l(self, pos):
- if self._paused: return
- self._start_drag_pos = pos, self._np.get_pos()
- loader.load_sfx('assets/audio/sfx/grab.ogg').play()
- if not self._instantiated:
- self._world.remove_ghost(self.node)
- pos = self._np.get_pos()
- self._np.remove_node()
- self.node = BulletRigidBodyNode('box')
- self._set_shape()
- self._np = render.attach_new_node(self.node)
- self._world.attach_rigid_body(self.node)
- self._model.reparent_to(self._np)
- self._np.set_pos(pos)
- self._set_outline_model()
- self._np.set_scale(self._model_scale)
- self._model.show(BitMask32(0x01))
- self._outline_model.hide(BitMask32(0x01))
- self._instantiated = True
- self._txt.destroy()
- self._count -= 1
- if self._count:
- item = self.__class__(self._world, self._plane_node, self._cb_inst, self._curr_bottom, self._scene_repos, count=self._count, mass=self._mass, pos=self._pos, r=self._r) # pylint: disable=no-value-for-parameter
- self._cb_inst(item)
- self._scene_repos()
-
- def on_click_r(self, pos):
- if self._paused or not self._instantiated: return
- self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
- loader.load_sfx('assets/audio/sfx/grab.ogg').play()
-
- def on_release(self):
- if self._start_drag_pos or self._prev_rot_info:
- loader.load_sfx('assets/audio/sfx/release.ogg').play()
- self._command_idx += 1
- self._commands = self._commands[:self._command_idx]
- self._commands += [Command(self._np.get_pos(), self._np.get_hpr())]
- self._first_command = False
- self._start_drag_pos = self._prev_rot_info = None
- if self._overlapping:
- self._np.set_pos(self._last_nonoverlapping_pos)
- self._np.set_hpr(self._last_nonoverlapping_rot)
- self._outline_model.set_color(.4, .4, .4, 1)
- self._outline_model.set_color_scale(.4, .4, .4, 1)
- self._overlapping = False
-
- def on_mouse_on(self):
- if not self._paused and self.interactable:
- self._outline_model.show()
-
- def on_mouse_off(self):
- if self._start_drag_pos or self._prev_rot_info: return
- if self.interactable:
- self._outline_model.hide()
-
- def on_mouse_move(self, pos):
- if self._start_drag_pos:
- d_pos = pos - self._start_drag_pos[0]
- self._np.set_pos(self._start_drag_pos[1] + d_pos)
- if self._prev_rot_info:
- start_vec = self._prev_rot_info[0] - self._prev_rot_info[1]
- curr_vec = pos - self._prev_rot_info[1]
- d_angle = curr_vec.signed_angle_deg(start_vec, (0, -1, 0))
- self._np.set_r(self._prev_rot_info[2] + d_angle)
- self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
- if self._start_drag_pos or self._prev_rot_info:
- res = self._world.contact_test(self.node)
- nres = res.get_num_contacts()
- if nres <= self._exp_num_contacts:
- self._overlapping = False
- self._outline_model.set_color(.4, .4, .4, 1)
- self._outline_model.set_color_scale(.4, .4, .4, 1)
- if nres > self._exp_num_contacts and not self._overlapping:
- actual_nres = 0
- for contact in res.get_contacts():
- for node in [contact.get_node0(), contact.get_node1()]:
- if isinstance(node, BulletRigidBodyNode) and \
- node != self.node:
- actual_nres += 1
- if actual_nres >= 1:
- self._overlapping = True
- loader.load_sfx('assets/audio/sfx/overlap.ogg').play()
- self._outline_model.set_color(.9, .1, .1, 1)
- self._outline_model.set_color_scale(.9, .1, .1, 1)
- if not self._overlapping:
- self._last_nonoverlapping_pos = self._np.get_pos()
- self._last_nonoverlapping_rot = self._np.get_hpr()
-
- def on_aspect_ratio_changed(self):
- if not self._instantiated:
- self._repos()
-
- def store_state(self):
- self._paused = True
- self._model.set_transparency(True)
- self._model.set_alpha_scale(.3)
- if hasattr(self, '_txt') and not self._txt.is_empty():
- self._txt.set_alpha_scale(.3)
-
- def restore_state(self):
- self._paused = False
- self._model.set_alpha_scale(1)
- if hasattr(self, '_txt') and not self._txt.is_empty():
- self._txt.set_alpha_scale(1)
-
- def fail_condition(self):
- if self._np.get_z() < -6:
- return True
- self._positions += [self._np.get_pos()]
- self._rotations += [self._np.get_hpr()]
- if len(self._positions) > 30:
- self._positions.pop(0)
- if len(self._rotations) > 30:
- self._rotations.pop(0)
- if len(self._positions) < 28:
- return
- avg_x = sum(pos.x for pos in self._positions) / len(self._positions)
- avg_y = sum(pos.y for pos in self._positions) / len(self._positions)
- avg_z = sum(pos.z for pos in self._positions) / len(self._positions)
- avg_h = sum(rot.x for rot in self._rotations) / len(self._rotations)
- avg_p = sum(rot.y for rot in self._rotations) / len(self._rotations)
- avg_r = sum(rot.z for rot in self._rotations) / len(self._rotations)
- avg_pos = Point3(avg_x, avg_y, avg_z)
- avg_rot = Point3(avg_h, avg_p, avg_r)
- return all((pos - avg_pos).length() < .1 for pos in self._positions) and \
- all((rot - avg_rot).length() < 1 for rot in self._rotations)
-
- def destroy(self):
- self._np.remove_node()
- taskMgr.remove(self._box_tsk)
- if hasattr(self, '_txt'):
- self._txt.destroy()
- if not self._instantiated:
- self._world.remove_ghost(self.node)
- else:
- self._world.remove_rigid_body(self.node)
+++ /dev/null
-from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
-from game.items.item import Item
-
-
-class Shelf(Item):
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.6):
- super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/shelf/shelf.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
-
- def _set_shape(self, apply_scale=True):
- self.node.add_shape(BulletBoxShape((1, .5, .05)))
+++ /dev/null
-from panda3d.core import TransformState
-from panda3d.bullet import BulletCylinderShape, BulletRigidBodyNode, BulletGhostNode, YUp, ZUp
-from game.items.item import Item
-
-
-class TeeterTooter(Item):
-
- def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.5):
- super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/teeter_tooter/teeter_tooter.bam', exp_num_contacts=2, mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction, model_scale=.5)
-
- def _set_shape(self, apply_scale=True):
- scale = self._model_scale if apply_scale else 1
- self.node.add_shape(
- BulletCylinderShape(.1, 1.6, YUp),
- TransformState.makePos((0, 0, scale * .36)))
- self.node.add_shape(
- BulletCylinderShape(.1, .7, ZUp),
- TransformState.makePos((0, scale * .8, scale * -.1)))
- self.node.add_shape(
- BulletCylinderShape(.1, .7, ZUp),
- TransformState.makePos((0, scale * -.8, scale * -.1)))
+++ /dev/null
-from logging import info, debug
-from sys import platform, exit
-from os import environ, system
-from glob import glob
-from importlib import import_module
-from inspect import isclass
-from webbrowser import open_new_tab
-from panda3d.core import Texture, TextNode, WindowProperties, LVector2i, \
- TextProperties, TextPropertiesManager
-from direct.gui.DirectGui import DirectButton, DirectCheckButton, \
- DirectOptionMenu, DirectSlider, DirectCheckButton
-from direct.gui.DirectGuiGlobals import FLAT
-from direct.gui.OnscreenText import OnscreenText
-from direct.showbase.DirectObject import DirectObject
-from ya2.engine.gui.cursor import MouseCursor
-from game.scene import Scene
-from panda3d.bullet import BulletWorld
-
-
-class Menu(DirectObject):
-
- def __init__(self, fsm, lang_mgr, opt_file, music, pipeline, scenes, fun_test):
- super().__init__()
- self._fsm = fsm
- self._lang_mgr = lang_mgr
- self._opt_file = opt_file
- self._music = music
- self._pipeline = pipeline
- self._scenes = scenes
- self._fun_test = fun_test
- self._enforced_res = ''
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
- self._font.clear()
- self._font.set_pixels_per_unit(60)
- self._font.set_minfilter(Texture.FTLinearMipmapLinear)
- self._font.set_outline((0, 0, 0, 1), .8, .2)
- self._widgets = []
- self._common = {
- 'scale': .12,
- 'text_font': self._font,
- 'text_fg': (.9, .9, .9, 1),
- 'relief': FLAT,
- 'frameColor': (.4, .4, .4, .14),
- 'rolloverSound': loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- 'clickSound': loader.load_sfx('assets/audio/sfx/click.ogg')}
- self._common_btn = {'frameSize': (-4.8, 4.8, -.6, 1.2)} | self._common
- hlc = self._common_btn['frameColor']
- hlc = (hlc[0] + .2, hlc[1] + .2, hlc[2] + .2, hlc[3] + .2)
- self._common_opt = {
- 'item_frameColor': self._common_btn['frameColor'],
- 'popupMarker_frameColor': self._common_btn['frameColor'],
- 'item_relief': self._common_btn['relief'],
- 'item_text_font': self._common_btn['text_font'],
- 'item_text_fg': self._common_btn['text_fg'],
- 'textMayChange': 1,
- 'highlightColor': hlc,
- 'text_align': TextNode.A_center,
- } | self._common_btn
- f_s = self._common_opt['frameSize']
- self._common_opt['frameSize'] = f_s[0], f_s[1] - .56, f_s[2], f_s[3]
- self._common_slider = self._common | {
- 'range': (0, 1),
- 'thumb_frameColor': (.4, .4, .4, .4),
- 'thumb_scale': 1.6,
- 'scale': .4}
- del self._common_slider['rolloverSound']
- del self._common_slider['clickSound']
- self._set_main()
-
- def enforce_res(self, val):
- self._enforced_res = val
- info('enforced resolution: ' + val)
-
- def _set_main(self):
- self._widgets = []
- self._widgets += [DirectButton(
- text=_('Play'), pos=(0, 1, .6), command=self.on_play,
- **self._common_btn)]
- self._widgets += [DirectButton(
- text=_('Options'), pos=(0, 1, .2), command=self.on_options,
- **self._common_btn)]
- self._widgets += [DirectButton(
- text=_('Credits'), pos=(0, 1, -.2), command=self.on_credits,
- **self._common_btn)]
- self._widgets += [DirectButton(
- text=_('Exit'), pos=(0, 1, -.6), command=lambda: exit(),
- **self._common_btn)]
- self._rearrange_width()
- self.accept('enforce_resolution', self.enforce_res)
-
- def _set_options(self):
- self._widgets = []
- self._lang_funcs = [lambda: _('English'), lambda: _('Italian')]
- items = [fnc() for fnc in self._lang_funcs]
- inititem = {
- 'en': _('English'),
- 'it': _('Italian')
- }[self._opt_file['settings']['language']]
- btn = DirectOptionMenu(
- text=_('Language'), items=items, initialitem=inititem,
- pos=(0, 1, .8), command=self.on_language, **self._common_opt)
- btn.popupMenu['frameColor'] = self._common_btn['frameColor']
- btn.popupMenu['relief'] = self._common_btn['relief']
- self._widgets += [btn]
- self._widgets += [OnscreenText(
- _('Volume'), pos=(-.1, .55), font=self._common['text_font'],
- scale=self._common['scale'], fg=self._common['text_fg'],
- align=TextNode.A_right)]
- self._widgets += [DirectSlider(
- pos=(.5, 1, .57),
- value=self._opt_file['settings']['volume'],
- command=self.on_volume,
- **self._common_slider)]
- self._slider = self._widgets[-1]
- self._widgets += [DirectCheckButton(
- text=_('Fullscreen'), pos=(0, 1, .3), command=self.on_fullscreen,
- indicator_frameColor=self._common_opt['highlightColor'],
- indicator_relief=self._common_btn['relief'],
- indicatorValue=self._opt_file['settings']['fullscreen'],
- **self._common_btn)]
- res = self._opt_file['settings']['resolution']
- d_i = base.pipe.get_display_information()
- def _res(idx):
- return d_i.get_display_mode_width(idx), \
- d_i.get_display_mode_height(idx)
- resolutions = [
- _res(idx) for idx in range(d_i.get_total_display_modes())]
- resolutions = list(set(resolutions))
- resolutions = sorted(resolutions)
- resolutions = [(str(_res[0]), str(_res[1])) for _res in resolutions]
- resolutions = ['x'.join(_res) for _res in resolutions]
- if not res:
- res = resolutions[-1]
- btn = DirectOptionMenu(
- text=_('Resolution'), items=resolutions, initialitem=res,
- pos=(0, 1, .05), command=self.on_resolution, **self._common_opt)
- btn.popupMenu['frameColor'] = self._common_btn['frameColor']
- btn.popupMenu['relief'] = self._common_btn['relief']
- self._widgets += [btn]
- self._widgets += [DirectCheckButton(
- text=_('Antialiasing'), pos=(0, 1, -.2), command=self.on_aa,
- indicator_frameColor=self._common_opt['highlightColor'],
- indicator_relief=self._common_btn['relief'],
- indicatorValue=self._opt_file['settings']['antialiasing'],
- **self._common_btn)]
- self._widgets += [DirectCheckButton(
- text=_('Shadows'), pos=(0, 1, -.45), command=self.on_shadows,
- indicator_frameColor=self._common_opt['highlightColor'],
- indicator_relief=self._common_btn['relief'],
- indicatorValue=self._opt_file['settings']['shadows'],
- **self._common_btn)]
- self._widgets += [DirectButton(
- text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
- **self._common_btn)]
- self.accept('enforce_resolution', self.enforce_res)
-
- def _set_credits(self):
- self._widgets = []
- tp_scale = TextProperties()
- tp_scale.set_text_scale(.64)
- TextPropertiesManager.getGlobalPtr().setProperties('scale', tp_scale)
- self._widgets += [OnscreenText(
- _('Code and gfx\n \1scale\1Flavio Calva\2\n\n\nMusic\n \1scale\1Stefan Grossmann\2'),
- pos=(-.9, .55), font=self._common['text_font'],
- scale=self._common['scale'], fg=self._common['text_fg'],
- align=TextNode.A_left)]
- self._widgets += [DirectButton(
- text=_('Website'), pos=(-.6, 1, .29), command=self.on_website,
- **self._common_btn | {'scale': .08})]
- self._widgets += [OnscreenText(
- _('Special thanks to:\n \1scale\1rdb\2\n \1scale\1Luisa Tenuta\2\n \1scale\1Damiana Ercolani\2'),
- pos=(.1, .55), font=self._common['text_font'],
- scale=self._common['scale'], fg=self._common['text_fg'],
- align=TextNode.A_left)]
- self._widgets += [DirectButton(
- text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
- **self._common_btn)]
- self.accept('enforce_resolution', self.enforce_res)
-
- def on_play(self):
- self.destroy()
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._widgets = []
- cmn = self._common_btn.copy() | {
- 'frameSize': (-2.4, 2.4, -2.4, 2.4),
- 'frameColor': (1, 1, 1, .8),
- 'text_scale': .64}
- left = - (dx := .8) * (min(4, len(self._scenes)) - 1) / 2
- for i, cls in enumerate(self._scenes):
- top = .1 if len(self._scenes) < 5 else .6
- row = 0 if i < 4 else 1
- self._widgets += [DirectButton(
- text=cls.name(), pos=(left + dx * (i % 4), 1, top - dx * row),
- command=self.start, extraArgs=[cls], text_wordwrap=6,
- frameTexture='assets/images/scenes/%s.dds' % cls.__name__,
- **cmn)]
- for j in range(4):
- tnode = self._widgets[-1].component('text%s' % j).textNode
- height = - tnode.getLineHeight() / 2
- height += (tnode.get_height() - tnode.get_line_height()) / 2
- self._widgets[-1].component('text%s' % j).set_pos(0, 0, height)
- self._widgets += [DirectButton(
- text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
- **self._common_btn)]
-
- def start(self, cls):
- self._fsm.demand('Scene', cls)
-
- def on_options(self):
- self.destroy()
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._set_options()
-
- def on_credits(self):
- self.destroy()
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._set_credits()
-
- def _rearrange_width(self):
- max_width = 0
- for wdg in self._widgets:
- t_n = wdg.component('text0')
- u_l = t_n.textNode.get_upper_left_3d()
- l_r = t_n.textNode.get_lower_right_3d()
- max_width = max(l_r[0] - u_l[0], max_width)
- for wdg in self._widgets:
- m_w = max_width / 2 + .8
- wdg['frameSize'] = -m_w, m_w, wdg['frameSize'][2], wdg['frameSize'][3]
-
- def on_language(self, arg):
- lang_code = {
- _('English'): 'en_EN',
- _('Italian'): 'it_IT'}[arg]
- self._lang_mgr.set_lang(lang_code)
- self._opt_file['settings']['language'] = lang_code[:2]
- self._opt_file.store()
- self.on_options()
-
- def on_volume(self):
- self._opt_file['settings']['volume'] = self._slider['value']
- self._music.set_volume(self._slider['value'])
-
- def on_fullscreen(self, arg):
- props = WindowProperties()
- props.set_fullscreen(arg)
- if not self._fun_test:
- base.win.request_properties(props)
- # if we actually switch to fullscreen during the tests then
- # exwm inside qemu can't restore the correct resolution
- # i may re-enable this if/when i run the tests onto a
- # physical machine
- self._opt_file['settings']['fullscreen'] = int(arg)
- self._opt_file.store()
-
- def on_resolution(self, arg):
- info('on resolution: %s (%s)' % (arg, self._enforced_res))
- arg = self._enforced_res or arg
- info('set resolution: %s' % arg)
- props = WindowProperties()
- props.set_size(LVector2i(*[int(_res) for _res in arg.split('x')]))
- base.win.request_properties(props)
- self._opt_file['settings']['resolution'] = arg
- self._opt_file.store()
-
- def on_aa(self, arg):
- self._pipeline.msaa_samples = 4 if arg else 1
- debug(f'msaa: {self._pipeline.msaa_samples}')
- self._opt_file['settings']['antialiasing'] = int(arg)
- self._opt_file.store()
-
- def on_shadows(self, arg):
- self._pipeline.enable_shadows = int(arg)
- debug(f'shadows: {self._pipeline.enable_shadows}')
- self._opt_file['settings']['shadows'] = int(arg)
- self._opt_file.store()
-
- def on_website(self):
- if platform.startswith('linux'):
- environ['LD_LIBRARY_PATH'] = ''
- system('xdg-open https://www.ya2.it')
- else:
- open_new_tab('https://www.ya2.it')
-
- def on_back(self):
- self._opt_file.store()
- self.destroy()
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._set_main()
-
- def destroy(self):
- [wdg.destroy() for wdg in self._widgets]
- self._cursor.destroy()
- self.ignore('enforce_resolution')
+++ /dev/null
-from os.path import dirname, exists, basename
-from platform import system
-from glob import glob
-from pathlib import Path
-from random import choice
-from logging import info
-from panda3d.core import AudioSound, Filename
-
-
-class MusicMgr:
-
- def __init__(self, volume):
- files = self.curr_path + 'assets/audio/music/*.ogg'
- self._start_music(glob(files))
- base.musicManager.setVolume(.8 * volume)
- base.sfxManagerList[0].setVolume(volume)
- taskMgr.add(self._on_frame, 'on frame music')
-
- @property
- def is_appimage(self):
- par_path = str(Path(__file__).parent.absolute())
- is_appimage = par_path.startswith('/tmp/.mount_Pmachi')
- return is_appimage and par_path.endswith('/usr/bin')
-
- @property
- def curr_path(self):
- if system() == 'Windows':
- return ''
- if exists('main.py'):
- return ''
- else:
- par_path = str(Path(__file__).parent.absolute())
- if self.is_appimage:
- par_path = str(Path(par_path).absolute())
- par_path += '/'
- return par_path
-
- def _start_music(self, files):
- self._music = loader.load_music(choice(files))
- info('playing music ' + self._music.get_name())
- self._music.play()
-
- def set_volume(self, volume):
- base.musicManager.setVolume(.8 * volume)
- base.sfxManagerList[0].setVolume(volume)
-
- def _on_frame(self, task):
- if self._music.status() == AudioSound.READY:
- oggs = Filename(self.curr_path + 'assets/audio/music/*.ogg').to_os_specific()
- files = glob(oggs)
- rm_music = Filename(self.curr_path + 'assets/audio/music/' + basename(self._music.get_name())).to_os_specific()
- # basename is needed in windows
- files.remove(rm_music)
- self._start_music(files)
- return task.cont
+++ /dev/null
-from os.path import exists
-from os import makedirs
-from glob import glob
-from logging import debug, info
-from importlib import import_module
-from inspect import isclass
-from panda3d.core import AmbientLight, DirectionalLight, Point3, Texture, \
- TextPropertiesManager, TextNode, Spotlight, PerspectiveLens, BitMask32
-from panda3d.bullet import BulletPlaneShape, BulletGhostNode
-from direct.gui.OnscreenImage import OnscreenImage
-from direct.gui.OnscreenText import OnscreenText
-from direct.gui.DirectGui import DirectButton, DirectFrame
-from direct.gui.DirectGuiGlobals import FLAT, DISABLED, NORMAL
-from direct.showbase.DirectObject import DirectObject
-from game.items.background import Background
-from game.sidepanel import SidePanel
-from ya2.engine.gui.cursor import MouseCursor
-from ya2.lib.p3d.gfx import P3dGfxMgr
-
-
-class Scene(DirectObject):
-
- def __init__(self, world, exit_cb, auto_close_instr, dbg_items, reload_cb, scenes):
- super().__init__()
- self._world = world
- self._exit_cb = exit_cb
- self._dbg_items = dbg_items
- self._reload_cb = reload_cb
- self._scenes = scenes
- self._enforce_res = ''
- self.accept('enforce_res', self.enforce_res)
- self._set_camera()
- self._cursor = MouseCursor(
- 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
- (.01, .01))
- self._set_gui()
- self._set_lights()
- self._set_input()
- self._set_mouse_plane()
- self.items = []
- self.reset()
- self._state = 'init'
- self._paused = False
- self._item_active = None
- if auto_close_instr:
- self.__store_state()
- self.__restore_state()
- else:
- self._set_instructions()
- self._bg = Background()
- self._side_panel = SidePanel(world, self._mouse_plane_node, (-5, 4), (-3, 1), 1, self.items)
- self._scene_tsk = taskMgr.add(self.on_frame, 'on_frame')
-
- @staticmethod
- def name():
- return ''
-
- def _instr_txt(self):
- return ''
-
- def _set_items(self):
- self.items = []
-
- def screenshot(self, task=None):
- tex = Texture('screenshot')
- buffer = base.win.make_texture_buffer('screenshot', 512, 512, tex, True )
- cam = base.make_camera(buffer)
- cam.reparent_to(render)
- cam.node().get_lens().set_fov(base.camLens.get_fov())
- cam.set_pos(0, -20, 0)
- cam.look_at(0, 0, 0)
- import simplepbr
- simplepbr.init(
- window=buffer,
- camera_node=cam,
- use_normal_maps=True,
- use_emission_maps=False,
- use_occlusion_maps=True,
- msaa_samples=4,
- enable_shadows=True)
- base.graphicsEngine.renderFrame()
- base.graphicsEngine.renderFrame()
- fname = self.__class__.__name__
- if not exists('assets/images/scenes'):
- makedirs('assets/images/scenes')
- buffer.save_screenshot('assets/images/scenes/%s.png' % fname)
- # img = DirectButton(
- # frameTexture=buffer.get_texture(), relief=FLAT,
- # frameSize=(-.2, .2, -.2, .2))
- return buffer.get_texture()
-
- def current_bottom(self):
- curr_bottom = 1
- for item in self.items:
- if item.repos_done:
- curr_bottom = min(curr_bottom, item.get_bottom())
- return curr_bottom
-
- def reset(self):
- [itm.destroy() for itm in self.items]
- self._set_items()
- self._state = 'init'
- self._commands = []
- self._command_idx = 0
- if hasattr(self, '_success_txt'):
- self._success_txt.destroy()
- del self._success_txt
- self.__right_btn['state'] = NORMAL
-
- def enforce_res(self, val):
- self._enforce_res = val
- info('enforce res: ' + val)
-
- def destroy(self):
- self.ignore('enforce_res')
- self._unset_gui()
- self._unset_lights()
- self._unset_input()
- self._unset_mouse_plane()
- [itm.destroy() for itm in self.items]
- self._bg.destroy()
- self._side_panel.destroy()
- self._cursor.destroy()
- taskMgr.remove(self._scene_tsk)
- if hasattr(self, '_success_txt'):
- self._success_txt.destroy()
-
- def _set_camera(self):
- base.camera.set_pos(0, -20, 0)
- base.camera.look_at(0, 0, 0)
-
- def __load_img_btn(self, path, col):
- img = OnscreenImage('assets/images/buttons/%s.dds' % path)
- img.set_transparency(True)
- img.set_color(col)
- img.detach_node()
- return img
-
- def _set_gui(self):
- def load_images_btn(path, col):
- colors = {
- 'gray': [
- (.6, .6, .6, 1), # ready
- (1, 1, 1, 1), # press
- (.8, .8, .8, 1), # rollover
- (.4, .4, .4, .4)],
- 'green': [
- (.1, .68, .1, 1),
- (.1, 1, .1, 1),
- (.1, .84, .1, 1),
- (.4, .1, .1, .4)]}[col]
- return [self.__load_img_btn(path, col) for col in colors]
- abl, abr = base.a2dBottomLeft, base.a2dBottomRight
- btn_info = [
- ('home', self.on_home, NORMAL, abl, 'gray'),
- ('information', self._set_instructions, NORMAL, abl, 'gray'),
- ('right', self.on_play, NORMAL, abr, 'green'),
- #('next', self.on_next, DISABLED, abr, 'gray'),
- #('previous', self.on_prev, DISABLED, abr, 'gray'),
- #('rewind', self.reset, NORMAL, abr, 'gray')
- ]
- num_l = num_r = 0
- btns = []
- for binfo in btn_info:
- imgs = load_images_btn(binfo[0], binfo[4])
- if binfo[3] == base.a2dBottomLeft:
- sign, num = 1, num_l
- num_l += 1
- else:
- sign, num = -1, num_r
- num_r += 1
- fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
- btn = DirectButton(
- image=imgs, scale=.05, pos=(sign * (.06 + .11 * num), 1, .06),
- parent=binfo[3], command=binfo[1], state=binfo[2], relief=FLAT,
- frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1],
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
- btns += [btn]
- self.__home_btn, self.__info_btn, self.__right_btn = btns
- # , self.__next_btn, self.__prev_btn, self.__rewind_btn
- if self._dbg_items:
- self._info_txt = OnscreenText(
- '', parent=base.a2dTopRight, scale=0.04,
- pos=(-.03, -.06), fg=(.9, .9, .9, 1), align=TextNode.A_right)
-
- def _unset_gui(self):
- btns = [
- self.__home_btn, self.__info_btn, self.__right_btn,
- #self.__next_btn, self.__prev_btn, self.__rewind_btn
- ]
- [btn.destroy() for btn in btns]
- if self._dbg_items:
- self._info_txt.destroy()
-
- def _set_spotlight(self, name, pos, look_at, color, shadows=False):
- light = Spotlight(name)
- if shadows:
- light.setLens(PerspectiveLens())
- light_np = render.attach_new_node(light)
- light_np.set_pos(pos)
- light_np.look_at(look_at)
- light.set_color(color)
- render.set_light(light_np)
- return light_np
-
- def _set_lights(self):
- alight = AmbientLight('alight') # for ao
- alight.set_color((.15, .15, .15, 1))
- self._alnp = render.attach_new_node(alight)
- render.set_light(self._alnp)
- self._key_light = self._set_spotlight(
- 'key light', (-5, -80, 5), (0, 0, 0), (2.8, 2.8, 2.8, 1))
- self._shadow_light = self._set_spotlight(
- 'key light', (-5, -80, 5), (0, 0, 0), (.58, .58, .58, 1), True)
- self._shadow_light.node().set_shadow_caster(True, 2048, 2048)
- self._shadow_light.node().get_lens().set_film_size(2048, 2048)
- self._shadow_light.node().get_lens().set_near_far(1, 256)
- self._shadow_light.node().set_camera_mask(BitMask32(0x01))
-
- def _unset_lights(self):
- for light in [self._alnp, self._key_light, self._shadow_light]:
- render.clear_light(light)
- light.remove_node()
-
- def _set_input(self):
- self.accept('mouse1', self.on_click_l)
- self.accept('mouse1-up', self.on_release)
- self.accept('mouse3', self.on_click_r)
- self.accept('mouse3-up', self.on_release)
-
- def _unset_input(self):
- for evt in ['mouse1', 'mouse1-up', 'mouse3', 'mouse3-up']:
- self.ignore(evt)
-
- def _set_mouse_plane(self):
- shape = BulletPlaneShape((0, -1, 0), 0)
- #self._mouse_plane_node = BulletRigidBodyNode('mouse plane')
- self._mouse_plane_node = BulletGhostNode('mouse plane')
- self._mouse_plane_node.addShape(shape)
- #np = render.attachNewNode(self._mouse_plane_node)
- #self._world.attachRigidBody(self._mouse_plane_node)
- self._world.attach_ghost(self._mouse_plane_node)
-
- def _unset_mouse_plane(self):
- self._world.remove_ghost(self._mouse_plane_node)
-
- def _get_hits(self):
- if not base.mouseWatcherNode.has_mouse(): return []
- p_from, p_to = P3dGfxMgr.world_from_to(base.mouseWatcherNode.get_mouse())
- return self._world.ray_test_all(p_from, p_to).get_hits()
-
- def _update_info(self, item):
- txt = ''
- if item:
- txt = '%.3f %.3f\n%.3f°' % (
- item._np.get_x(), item._np.get_z(), item._np.get_r())
- self._info_txt['text'] = txt
-
- def _on_click(self, method):
- if self._paused:
- return
- for hit in self._get_hits():
- if hit.get_node() == self._mouse_plane_node:
- pos = hit.get_hit_pos()
- for hit in self._get_hits():
- for item in [i for i in self.items if hit.get_node() == i.node and i.interactable]:
- if not self._item_active:
- self._item_active = item
- getattr(item, method)(pos)
- img = 'move' if method == 'on_click_l' else 'rotate'
- if not (img == 'rotate' and not item._instantiated):
- self._cursor.set_image('assets/images/buttons/%s.dds' % img)
-
- def on_click_l(self):
- self._on_click('on_click_l')
-
- def on_click_r(self):
- self._on_click('on_click_r')
-
- def on_release(self):
- if self._item_active and not self._item_active._first_command:
- self._commands = self._commands[:self._command_idx]
- self._commands += [self._item_active]
- self._command_idx += 1
- #self.__prev_btn['state'] = NORMAL
- #fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
- #self.__prev_btn['frameColor'] = fcols[0]
- #if self._item_active._command_idx == len(self._item_active._commands) - 1:
- # self.__next_btn['state'] = DISABLED
- # self.__next_btn['frameColor'] = fcols[1]
- self._item_active = None
- [item.on_release() for item in self.items]
- self._cursor.set_image('assets/images/buttons/arrowUpLeft.dds')
-
- def repos(self):
- for item in self.items:
- item.repos_done = False
- self.items = sorted(self.items, key=lambda itm: itm.__class__.__name__)
- [item.on_aspect_ratio_changed() for item in self.items]
- self._side_panel.update(self.items)
- max_x = -float('inf')
- for item in self.items:
- if not item._instantiated:
- max_x = max(item._np.get_x(), max_x)
- for item in self.items:
- if not item._instantiated:
- item.repos_x(max_x)
-
- def on_aspect_ratio_changed(self):
- self.repos()
-
- def _win_condition(self):
- pass
-
- def _fail_condition(self):
- return all(itm.fail_condition() for itm in self.items) and not self._paused and self._state == 'playing'
-
- def on_frame(self, task):
- hits = self._get_hits()
- pos = None
- for hit in self._get_hits():
- if hit.get_node() == self._mouse_plane_node:
- pos = hit.get_hit_pos()
- hit_nodes = [hit.get_node() for hit in hits]
- if self._item_active:
- items_hit = [self._item_active]
- else:
- items_hit = [itm for itm in self.items if itm.node in hit_nodes]
- items_no_hit = [itm for itm in self.items if itm not in items_hit]
- [itm.on_mouse_on() for itm in items_hit]
- [itm.on_mouse_off() for itm in items_no_hit]
- if pos and self._item_active:
- self._item_active.on_mouse_move(pos)
- if self._dbg_items:
- self._update_info(items_hit[0] if items_hit else None)
- if self._win_condition():
- self._set_fail() if self._enforce_res == 'fail' else self._set_win()
- elif self._state == 'playing' and self._fail_condition():
- self._set_win() if self._enforce_res == 'win' else self._set_fail()
- if any(itm._overlapping for itm in self.items):
- self._cursor.cursor_img.img.set_color(.9, .1, .1, 1)
- else:
- self._cursor.cursor_img.img.set_color(.9, .9, .9, 1)
- return task.cont
-
- def cb_inst(self, item):
- self.items += [item]
-
- def on_play(self):
- self._state = 'playing'
- #self.__prev_btn['state'] = DISABLED
- #self.__next_btn['state'] = DISABLED
- self.__right_btn['state'] = DISABLED
- [itm.play() for itm in self.items]
-
- def on_next(self):
- self._commands[self._command_idx].redo()
- self._command_idx += 1
- fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
- #self.__prev_btn['state'] = NORMAL
- #self.__prev_btn['frameColor'] = fcols[0]
- more_commands = self._command_idx < len(self._commands)
- #self.__next_btn['state'] = NORMAL if more_commands else DISABLED
- #self.__next_btn['frameColor'] = fcols[0] if more_commands else fcols[1]
-
- def on_prev(self):
- self._command_idx -= 1
- self._commands[self._command_idx].undo()
- fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
- #self.__next_btn['state'] = NORMAL
- #self.__next_btn['frameColor'] = fcols[0]
- #self.__prev_btn['state'] = NORMAL if self._command_idx else DISABLED
- #self.__prev_btn['frameColor'] = fcols[0] if self._command_idx else fcols[1]
-
- def on_home(self):
- self._exit_cb()
-
- def _set_instructions(self):
- self._paused = True
- self.__store_state()
- mgr = TextPropertiesManager.get_global_ptr()
- for name in ['mouse_l', 'mouse_r']:
- graphic = OnscreenImage('assets/images/buttons/%s.dds' % name)
- graphic.set_scale(.5)
- graphic.get_texture().set_minfilter(Texture.FTLinearMipmapLinear)
- graphic.get_texture().set_anisotropic_degree(2)
- mgr.set_graphic(name, graphic)
- graphic.set_z(-.2)
- graphic.set_transparency(True)
- graphic.detach_node()
- frm = DirectFrame(frameColor=(.4, .4, .4, .06),
- frameSize=(-.6, .6, -.3, .3))
- font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
- font.clear()
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- font.set_outline((0, 0, 0, 1), .8, .2)
- self._txt = OnscreenText(
- self._instr_txt(), parent=frm, font=font, scale=0.06,
- fg=(.9, .9, .9, 1), align=TextNode.A_left)
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
- btn_scale = .05
- mar = .06 # margin
- z = h / 2 - font.get_line_height() * self._txt['scale'][1]
- z += (btn_scale + 2 * mar) / 2
- self._txt['pos'] = -w / 2, z
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
- fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
- frm['frameSize'] = fsz
- colors = [
- (.6, .6, .6, 1), # ready
- (1, 1, 1, 1), # press
- (.8, .8, .8, 1), # rollover
- (.4, .4, .4, .4)]
- imgs = [self.__load_img_btn('exitRight', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(l_r[0] - btn_scale, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self.__on_close_instructions, extraArgs=[frm],
- relief=FLAT, frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
-
- def _set_win(self):
- loader.load_sfx('assets/audio/sfx/success.ogg').play()
- self._paused = True
- self.__store_state()
- frm = DirectFrame(frameColor=(.4, .4, .4, .06),
- frameSize=(-.6, .6, -.3, .3))
- font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
- font.clear()
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- font.set_outline((0, 0, 0, 1), .8, .2)
- self._txt = OnscreenText(
- _('You win!'),
- parent=frm,
- font=font, scale=0.2,
- fg=(.9, .9, .9, 1))
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
- btn_scale = .05
- mar = .06 # margin
- z = h / 2 - font.get_line_height() * self._txt['scale'][1]
- z += (btn_scale + 2 * mar) / 2
- self._txt['pos'] = 0, z
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
- fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
- frm['frameSize'] = fsz
- colors = [
- (.6, .6, .6, 1), # ready
- (1, 1, 1, 1), # press
- (.8, .8, .8, 1), # rollover
- (.4, .4, .4, .4)]
- imgs = [self.__load_img_btn('home', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self._on_end_home, extraArgs=[frm],
- relief=FLAT, frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
- imgs = [self.__load_img_btn('rewind', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(0, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self._on_restart, extraArgs=[frm],
- relief=FLAT, frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
- enabled = self._scenes.index(self.__class__) < len(self._scenes) - 1
- if enabled:
- next_scene = self._scenes[self._scenes.index(self.__class__) + 1]
- else:
- next_scene = None
- imgs = [self.__load_img_btn('right', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self._on_next_scene,
- extraArgs=[frm, next_scene], relief=FLAT,
- frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn['state'] = NORMAL if enabled else DISABLED
- btn.set_transparency(True)
-
- def _set_fail(self):
- loader.load_sfx('assets/audio/sfx/success.ogg').play()
- self._paused = True
- self.__store_state()
- frm = DirectFrame(frameColor=(.4, .4, .4, .06),
- frameSize=(-.6, .6, -.3, .3))
- font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
- font.clear()
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- font.set_outline((0, 0, 0, 1), .8, .2)
- self._txt = OnscreenText(
- _('You have failed!'),
- parent=frm,
- font=font, scale=0.2,
- fg=(.9, .9, .9, 1))
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
- btn_scale = .05
- mar = .06 # margin
- z = h / 2 - font.get_line_height() * self._txt['scale'][1]
- z += (btn_scale + 2 * mar) / 2
- self._txt['pos'] = 0, z
- u_l = self._txt.textNode.get_upper_left_3d()
- l_r = self._txt.textNode.get_lower_right_3d()
- c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
- fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
- frm['frameSize'] = fsz
- colors = [
- (.6, .6, .6, 1), # ready
- (1, 1, 1, 1), # press
- (.8, .8, .8, 1), # rollover
- (.4, .4, .4, .4)]
- imgs = [self.__load_img_btn('home', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self._on_end_home, extraArgs=[frm],
- relief=FLAT, frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
- imgs = [self.__load_img_btn('rewind', col) for col in colors]
- btn = DirectButton(
- image=imgs, scale=btn_scale,
- pos=(0, 1, l_r[2] - mar - btn_scale),
- parent=frm, command=self._on_restart, extraArgs=[frm],
- relief=FLAT, frameColor=(.6, .6, .6, .08),
- rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
- clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- btn.set_transparency(True)
-
- def _on_restart(self, frm):
- self.__on_close_instructions(frm)
- self.reset()
-
- def _on_end_home(self, frm):
- self.__on_close_instructions(frm)
- self.on_home()
-
- def _on_next_scene(self, frm, scene):
- self.__on_close_instructions(frm)
- self._reload_cb(scene)
-
- def __store_state(self):
- btns = [
- self.__home_btn, self.__info_btn, self.__right_btn,
- #self.__next_btn, self.__prev_btn, self.__rewind_btn
- ]
- self.__btn_state = [btn['state'] for btn in btns]
- for btn in btns:
- btn['state'] = DISABLED
- [itm.store_state() for itm in self.items]
-
- def __restore_state(self):
- btns = [
- self.__home_btn, self.__info_btn, self.__right_btn,
- #self.__next_btn, self.__prev_btn, self.__rewind_btn
- ]
- for btn, state in zip(btns, self.__btn_state):
- btn['state'] = state
- [itm.restore_state() for itm in self.items]
- self._paused = False
-
- def __on_close_instructions(self, frm):
- frm.remove_node()
- self.__restore_state()
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, UpStrategy, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneBasketBall(Scene):
-
- @staticmethod
- def name():
- return _('Basket ball')
-
- def _set_items(self):
- self.items = []
- #self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
- self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, .21))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, .21))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-4.45, 0, -3.18), r=27, restitution=1)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-5.45, 0, -3.18), restitution=1)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 30))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37)]
- #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78))]
- #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78))]
- #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78))]
- #self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78))]
- #self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: you must hit every domino piece\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box, HitStrategy
-from game.items.shelf import Shelf
-from game.items.domino import Domino
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneBox(Scene):
-
- @staticmethod
- def name():
- return _('Box')
-
- def _set_items(self):
- self.items = []
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.46, 0, -3.95))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.43, 0, -3.95))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.29, 0, .26), r=28.45)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.15, 0, -1.49), r=28.45)]
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.55, 0, 1.23), friction=.4)]
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.38, 0, -3.35))]
- self.items[-1].set_strategy(HitStrategy(self.items[-2], self.items[-1].node, self.items[-1]._world))
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
- #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04), tgt_degrees=60)]
- #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04), tgt_degrees=60)]
- #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04), tgt_degrees=60)]
- #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04), tgt_degrees=60)]
- #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04), tgt_degrees=88)]
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: the left box must hit the right box\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneDomino(Scene):
-
- @staticmethod
- def name():
- return _('Domino')
-
- def _set_items(self):
- self.items = []
- #self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.2, 0, -.6))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.2, 0, -.6))]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 88))
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: every domino piece must fall\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, UpStrategy, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneDominoBox(Scene):
-
- @staticmethod
- def name():
- return _('Domino and box')
-
- def _set_items(self):
- self.items = []
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
- #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, .21))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, .21))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.94), r=37)]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
- self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37)]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78))]
- self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78))]
- self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: only the last piece of each row must be up\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, UpStrategy, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneDominoBoxBasketball(Scene):
-
- @staticmethod
- def name():
- return _('Domino, box and basket ball')
-
- def _set_items(self):
- self.items = []
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1, mass=5)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1)]
- self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.3, 1, 2.5))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
- #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.68, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.35, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.08, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.78, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.53, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: every domino piece must be hit\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, UpStrategy, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneTeeterDominoBoxBasketball(Scene):
-
- @staticmethod
- def name():
- return _('Teeter tooter, domino, box and basket ball')
-
- def _set_items(self):
- self.items = []
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=3, count=2, friction=1)]
- self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(.98, 1, 1.02))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-6.24, 0, -1.45))]
- self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-6.24, 0, -1.20))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, r=24.60, friction=1, pos=(-6.15, 0, -.93))]
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.3, friction=1, model_scale=.5, pos=(-5.38, 0, -.93), r=24.60)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(5.37, 0, -.78))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(7.48, 0, -.78))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.74, 0, -1.95))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(6.88, 0, -1.95))]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(4.83, 0, -1.39))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(5.67, 0, -1.39))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(6.59, 0, -1.39))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.53, 0, -1.95), restitution=.95)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.63, 0, -1.95), restitution=.95)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-3.65, 0, 1.05), r=28, friction=0)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.27, 0, 1.72), restitution=.95)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.88, 0, 1.72), restitution=.95)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.67, 0, .55), restitution=.95)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.52, 0, .55), restitution=.95)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-1.73, 0, 1.11))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-.97, 0, 1.11))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-.1, 0, 1.11))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: every domino piece must be hit\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from game.scene import Scene
-from game.items.box import Box
-from game.items.shelf import Shelf
-from game.items.domino import Domino, UpStrategy, DownStrategy
-from game.items.basketball import Basketball
-from game.items.teetertooter import TeeterTooter
-
-
-class SceneTeeterTooter(Scene):
-
- @staticmethod
- def name():
- return _('Teeter tooter')
-
- def _set_items(self):
- self.items = []
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=3, count=1, friction=1)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-2.76, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.27, 0, -.28))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.38, 0, -.28))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
- self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-2.74, 0, -1.20))]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, r=-25.30, friction=1, pos=(-2.78, 0, -.93))]
- self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.2, friction=1, model_scale=.5, pos=(-3.61, 0, -.99), r=-25.30)]
- self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.25, 0, -.57), r=52)]
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.50, 0, -.89))]
- self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
- #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
- #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
-
- def _instr_txt(self):
- txt = _('Scene: ') + self.name() + '\n\n'
- txt += _('Goal: you must hit every domino piece\n\n')
- txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
- 'keep \5mouse_r\5 pressed to rotate an item')
- return txt
-
- def _win_condition(self):
- return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
+++ /dev/null
-from textwrap import dedent
-from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, \
- GeomVertexWriter, GeomTriangles, GeomNode, Shader, Point3, Plane, Vec3
-from ya2.lib.p3d.gfx import P3dGfxMgr
-
-
-class SidePanel:
-
- def __init__(self, world, plane_node, top_l, bottom_r, y, items):
- self._world = world
- self._plane_node = plane_node
- self._set((-1, 1), y)
- self.update(items)
-
- def update(self, items):
- p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
- for hit in self._world.ray_test_all(p_from, p_to).get_hits():
- if hit.get_node() == self._plane_node:
- pos = hit.get_hit_pos()
- y = 0
- corner = -20, 20
- for item in items:
- if not item._instantiated:
- bounds = item._np.get_tight_bounds()
- if bounds[1][1] > y:
- y = bounds[1][1]
- icorner = item.get_corner()
- icorner = P3dGfxMgr.screen_coord(icorner)
- if icorner[0] > corner[0]:
- corner = icorner[0], corner[1]
- if icorner[1] < corner[1]:
- corner = corner[0], icorner[1]
- self._set((pos[0], pos[2]), y)
- bounds = self._np.get_tight_bounds()
- corner3d = bounds[1][0], bounds[1][1], bounds[0][2]
- corner2d = P3dGfxMgr.screen_coord(corner3d)
- plane = Plane(Vec3(0, 1, 0), y)
- pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
- ar, margin = base.get_aspect_ratio(), .04
- x = corner[0] / ar if ar >= 1 else corner[0]
- z = corner[1] * ar if ar < 1 else corner[1]
- x += margin / ar if ar >= 1 else margin
- z -= margin * ar if ar < 1 else margin
- base.camLens.extrude((x, z), near_pt, far_pt)
- plane.intersects_line(
- pos3d, render.get_relative_point(base.camera, near_pt),
- render.get_relative_point(base.camera, far_pt))
- corner_pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
- base.camLens.extrude((-1, 1), near_pt, far_pt)
- plane.intersects_line(
- corner_pos3d, render.get_relative_point(base.camera, near_pt),
- render.get_relative_point(base.camera, far_pt))
- self._np.set_pos((pos3d + corner_pos3d) / 2)
- scale = Vec3(pos3d[0] - corner_pos3d[0], 1, corner_pos3d[2] - pos3d[2])
- self._np.set_scale(scale)
-
- def _set(self, pos, y):
- if hasattr(self, '_np'):
- self._np.remove_node()
- vdata = GeomVertexData('quad', GeomVertexFormat.get_v3(), Geom.UHStatic)
- vdata.setNumRows(2)
- vertex = GeomVertexWriter(vdata, 'vertex')
- vertex.add_data3(.5, 0, -.5)
- vertex.add_data3(.5, 0, .5)
- vertex.add_data3(-.5, 0, .5)
- vertex.add_data3(-.5, 0, -.5)
- prim = GeomTriangles(Geom.UHStatic)
- prim.add_vertices(0, 1, 2)
- prim.add_vertices(0, 2, 3)
- prim.close_primitive()
- geom = Geom(vdata)
- geom.add_primitive(prim)
- node = GeomNode('gnode')
- node.add_geom(geom)
- self._np = render.attach_new_node(node)
- self._np.setTransparency(True)
- self._np.set_pos(pos[0], y, pos[1])
- vert = '''\
- #version 130
- uniform mat4 p3d_ModelViewProjectionMatrix;
- in vec4 p3d_Vertex;
- void main() {
- gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; }'''
- frag = '''\
- #version 130
- out vec4 p3d_FragColor;
- void main() {
- p3d_FragColor = vec4(.04, .04, .04, .08); }'''
- self._np.set_shader(Shader.make(Shader.SL_GLSL, dedent(vert), dedent(frag)))
- # mat = Material()
- # mat.set_base_color((1, 1, 1, 1))
- # mat.set_emission((1, 1, 1, 1))
- # mat.set_metallic(.5)
- # mat.set_roughness(.5)
- # np.set_material(mat)
- # texture_sz = 64
- # base_color_pnm = PNMImage(texture_sz, texture_sz)
- # base_color_pnm.fill(.1, .1, .1)
- # base_color_pnm.add_alpha()
- # base_color_pnm.alpha_fill(.04)
- # base_color_tex = Texture('base color')
- # base_color_tex.load(base_color_pnm)
- # ts = TextureStage('base color')
- # ts.set_mode(TextureStage.M_modulate)
- # np.set_texture(ts, base_color_tex)
- # emission_pnm = PNMImage(texture_sz, texture_sz)
- # emission_pnm.fill(0, 0, 0)
- # emission_tex = Texture('emission')
- # emission_tex.load(emission_pnm)
- # ts = TextureStage('emission')
- # ts.set_mode(TextureStage.M_emission)
- # np.set_texture(ts, emission_tex)
- # metal_rough_pnm = PNMImage(texture_sz, texture_sz)
- # ambient_occlusion = 1
- # roughness = .5
- # metallicity = .5
- # metal_rough_pnm.fill(ambient_occlusion, roughness, metallicity)
- # metal_rough_tex = Texture('ao metal roughness')
- # metal_rough_tex.load(metal_rough_pnm)
- # ts = TextureStage('ao metal roughness')
- # ts.set_mode(TextureStage.M_selector)
- # np.set_texture(ts, metal_rough_tex)
- # normal_pnm = PNMImage(texture_sz, texture_sz)
- # normal_pnm.fill(.5, .5, .1)
- # normal_tex = Texture('normals')
- # normal_tex.load(normal_pnm)
- # ts = TextureStage('normals')
- # ts.set_mode(TextureStage.M_normal)
- # np.set_texture(ts, normal_tex)
-
- def destroy(self):
- self._np.remove_node()
--- /dev/null
+from logging import info, debug
+from sys import platform, exit
+from os import environ, system
+from glob import glob
+from importlib import import_module
+from inspect import isclass
+from webbrowser import open_new_tab
+from panda3d.core import Texture, TextNode, WindowProperties, LVector2i, \
+ TextProperties, TextPropertiesManager
+from direct.gui.DirectGui import DirectButton, DirectCheckButton, \
+ DirectOptionMenu, DirectSlider, DirectCheckButton
+from direct.gui.DirectGuiGlobals import FLAT
+from direct.gui.OnscreenText import OnscreenText
+from direct.showbase.DirectObject import DirectObject
+from ya2.utils.cursor import MouseCursor
+from logics.scene import Scene
+from panda3d.bullet import BulletWorld
+
+
+class Menu(DirectObject):
+
+ def __init__(self, fsm, lang_mgr, opt_file, music, pipeline, scenes, fun_test):
+ super().__init__()
+ self._fsm = fsm
+ self._lang_mgr = lang_mgr
+ self._opt_file = opt_file
+ self._music = music
+ self._pipeline = pipeline
+ self._scenes = scenes
+ self._fun_test = fun_test
+ self._enforced_res = ''
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ self._font.clear()
+ self._font.set_pixels_per_unit(60)
+ self._font.set_minfilter(Texture.FTLinearMipmapLinear)
+ self._font.set_outline((0, 0, 0, 1), .8, .2)
+ self._widgets = []
+ self._common = {
+ 'scale': .12,
+ 'text_font': self._font,
+ 'text_fg': (.9, .9, .9, 1),
+ 'relief': FLAT,
+ 'frameColor': (.4, .4, .4, .14),
+ 'rolloverSound': loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ 'clickSound': loader.load_sfx('assets/audio/sfx/click.ogg')}
+ self._common_btn = {'frameSize': (-4.8, 4.8, -.6, 1.2)} | self._common
+ hlc = self._common_btn['frameColor']
+ hlc = (hlc[0] + .2, hlc[1] + .2, hlc[2] + .2, hlc[3] + .2)
+ self._common_opt = {
+ 'item_frameColor': self._common_btn['frameColor'],
+ 'popupMarker_frameColor': self._common_btn['frameColor'],
+ 'item_relief': self._common_btn['relief'],
+ 'item_text_font': self._common_btn['text_font'],
+ 'item_text_fg': self._common_btn['text_fg'],
+ 'textMayChange': 1,
+ 'highlightColor': hlc,
+ 'text_align': TextNode.A_center,
+ } | self._common_btn
+ f_s = self._common_opt['frameSize']
+ self._common_opt['frameSize'] = f_s[0], f_s[1] - .56, f_s[2], f_s[3]
+ self._common_slider = self._common | {
+ 'range': (0, 1),
+ 'thumb_frameColor': (.4, .4, .4, .4),
+ 'thumb_scale': 1.6,
+ 'scale': .4}
+ del self._common_slider['rolloverSound']
+ del self._common_slider['clickSound']
+ self._set_main()
+
+ def enforce_res(self, val):
+ self._enforced_res = val
+ info('enforced resolution: ' + val)
+
+ def _set_main(self):
+ self._widgets = []
+ self._widgets += [DirectButton(
+ text=_('Play'), pos=(0, 1, .6), command=self.on_play,
+ **self._common_btn)]
+ self._widgets += [DirectButton(
+ text=_('Options'), pos=(0, 1, .2), command=self.on_options,
+ **self._common_btn)]
+ self._widgets += [DirectButton(
+ text=_('Credits'), pos=(0, 1, -.2), command=self.on_credits,
+ **self._common_btn)]
+ self._widgets += [DirectButton(
+ text=_('Exit'), pos=(0, 1, -.6), command=lambda: exit(),
+ **self._common_btn)]
+ self._rearrange_width()
+ self.accept('enforce_resolution', self.enforce_res)
+
+ def _set_options(self):
+ self._widgets = []
+ self._lang_funcs = [lambda: _('English'), lambda: _('Italian')]
+ items = [fnc() for fnc in self._lang_funcs]
+ inititem = {
+ 'en': _('English'),
+ 'it': _('Italian')
+ }[self._opt_file['settings']['language']]
+ btn = DirectOptionMenu(
+ text=_('Language'), items=items, initialitem=inititem,
+ pos=(0, 1, .8), command=self.on_language, **self._common_opt)
+ btn.popupMenu['frameColor'] = self._common_btn['frameColor']
+ btn.popupMenu['relief'] = self._common_btn['relief']
+ self._widgets += [btn]
+ self._widgets += [OnscreenText(
+ _('Volume'), pos=(-.1, .55), font=self._common['text_font'],
+ scale=self._common['scale'], fg=self._common['text_fg'],
+ align=TextNode.A_right)]
+ self._widgets += [DirectSlider(
+ pos=(.5, 1, .57),
+ value=self._opt_file['settings']['volume'],
+ command=self.on_volume,
+ **self._common_slider)]
+ self._slider = self._widgets[-1]
+ self._widgets += [DirectCheckButton(
+ text=_('Fullscreen'), pos=(0, 1, .3), command=self.on_fullscreen,
+ indicator_frameColor=self._common_opt['highlightColor'],
+ indicator_relief=self._common_btn['relief'],
+ indicatorValue=self._opt_file['settings']['fullscreen'],
+ **self._common_btn)]
+ res = self._opt_file['settings']['resolution']
+ d_i = base.pipe.get_display_information()
+ def _res(idx):
+ return d_i.get_display_mode_width(idx), \
+ d_i.get_display_mode_height(idx)
+ resolutions = [
+ _res(idx) for idx in range(d_i.get_total_display_modes())]
+ resolutions = list(set(resolutions))
+ resolutions = sorted(resolutions)
+ resolutions = [(str(_res[0]), str(_res[1])) for _res in resolutions]
+ resolutions = ['x'.join(_res) for _res in resolutions]
+ if not res:
+ res = resolutions[-1]
+ btn = DirectOptionMenu(
+ text=_('Resolution'), items=resolutions, initialitem=res,
+ pos=(0, 1, .05), command=self.on_resolution, **self._common_opt)
+ btn.popupMenu['frameColor'] = self._common_btn['frameColor']
+ btn.popupMenu['relief'] = self._common_btn['relief']
+ self._widgets += [btn]
+ self._widgets += [DirectCheckButton(
+ text=_('Antialiasing'), pos=(0, 1, -.2), command=self.on_aa,
+ indicator_frameColor=self._common_opt['highlightColor'],
+ indicator_relief=self._common_btn['relief'],
+ indicatorValue=self._opt_file['settings']['antialiasing'],
+ **self._common_btn)]
+ self._widgets += [DirectCheckButton(
+ text=_('Shadows'), pos=(0, 1, -.45), command=self.on_shadows,
+ indicator_frameColor=self._common_opt['highlightColor'],
+ indicator_relief=self._common_btn['relief'],
+ indicatorValue=self._opt_file['settings']['shadows'],
+ **self._common_btn)]
+ self._widgets += [DirectButton(
+ text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
+ **self._common_btn)]
+ self.accept('enforce_resolution', self.enforce_res)
+
+ def _set_credits(self):
+ self._widgets = []
+ tp_scale = TextProperties()
+ tp_scale.set_text_scale(.64)
+ TextPropertiesManager.getGlobalPtr().setProperties('scale', tp_scale)
+ self._widgets += [OnscreenText(
+ _('Code and gfx\n \1scale\1Flavio Calva\2\n\n\nMusic\n \1scale\1Stefan Grossmann\2'),
+ pos=(-.9, .55), font=self._common['text_font'],
+ scale=self._common['scale'], fg=self._common['text_fg'],
+ align=TextNode.A_left)]
+ self._widgets += [DirectButton(
+ text=_('Website'), pos=(-.6, 1, .29), command=self.on_website,
+ **self._common_btn | {'scale': .08})]
+ self._widgets += [OnscreenText(
+ _('Special thanks to:\n \1scale\1rdb\2\n \1scale\1Luisa Tenuta\2\n \1scale\1Damiana Ercolani\2'),
+ pos=(.1, .55), font=self._common['text_font'],
+ scale=self._common['scale'], fg=self._common['text_fg'],
+ align=TextNode.A_left)]
+ self._widgets += [DirectButton(
+ text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
+ **self._common_btn)]
+ self.accept('enforce_resolution', self.enforce_res)
+
+ def on_play(self):
+ self.destroy()
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._widgets = []
+ cmn = self._common_btn.copy() | {
+ 'frameSize': (-2.4, 2.4, -2.4, 2.4),
+ 'frameColor': (1, 1, 1, .8),
+ 'text_scale': .64}
+ left = - (dx := .8) * (min(4, len(self._scenes)) - 1) / 2
+ for i, cls in enumerate(self._scenes):
+ top = .1 if len(self._scenes) < 5 else .6
+ row = 0 if i < 4 else 1
+ self._widgets += [DirectButton(
+ text=cls.name(), pos=(left + dx * (i % 4), 1, top - dx * row),
+ command=self.start, extraArgs=[cls], text_wordwrap=6,
+ frameTexture='assets/images/scenes/%s.dds' % cls.__name__,
+ **cmn)]
+ for j in range(4):
+ tnode = self._widgets[-1].component('text%s' % j).textNode
+ height = - tnode.getLineHeight() / 2
+ height += (tnode.get_height() - tnode.get_line_height()) / 2
+ self._widgets[-1].component('text%s' % j).set_pos(0, 0, height)
+ self._widgets += [DirectButton(
+ text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
+ **self._common_btn)]
+
+ def start(self, cls):
+ self._fsm.demand('Scene', cls)
+
+ def on_options(self):
+ self.destroy()
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._set_options()
+
+ def on_credits(self):
+ self.destroy()
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._set_credits()
+
+ def _rearrange_width(self):
+ max_width = 0
+ for wdg in self._widgets:
+ t_n = wdg.component('text0')
+ u_l = t_n.textNode.get_upper_left_3d()
+ l_r = t_n.textNode.get_lower_right_3d()
+ max_width = max(l_r[0] - u_l[0], max_width)
+ for wdg in self._widgets:
+ m_w = max_width / 2 + .8
+ wdg['frameSize'] = -m_w, m_w, wdg['frameSize'][2], wdg['frameSize'][3]
+
+ def on_language(self, arg):
+ lang_code = {
+ _('English'): 'en_EN',
+ _('Italian'): 'it_IT'}[arg]
+ self._lang_mgr.set_lang(lang_code)
+ self._opt_file['settings']['language'] = lang_code[:2]
+ self._opt_file.store()
+ self.on_options()
+
+ def on_volume(self):
+ self._opt_file['settings']['volume'] = self._slider['value']
+ self._music.set_volume(self._slider['value'])
+
+ def on_fullscreen(self, arg):
+ props = WindowProperties()
+ props.set_fullscreen(arg)
+ if not self._fun_test:
+ base.win.request_properties(props)
+ # if we actually switch to fullscreen during the tests then
+ # exwm inside qemu can't restore the correct resolution
+ # i may re-enable this if/when i run the tests onto a
+ # physical machine
+ self._opt_file['settings']['fullscreen'] = int(arg)
+ self._opt_file.store()
+
+ def on_resolution(self, arg):
+ info('on resolution: %s (%s)' % (arg, self._enforced_res))
+ arg = self._enforced_res or arg
+ info('set resolution: %s' % arg)
+ props = WindowProperties()
+ props.set_size(LVector2i(*[int(_res) for _res in arg.split('x')]))
+ base.win.request_properties(props)
+ self._opt_file['settings']['resolution'] = arg
+ self._opt_file.store()
+
+ def on_aa(self, arg):
+ self._pipeline.msaa_samples = 4 if arg else 1
+ debug(f'msaa: {self._pipeline.msaa_samples}')
+ self._opt_file['settings']['antialiasing'] = int(arg)
+ self._opt_file.store()
+
+ def on_shadows(self, arg):
+ self._pipeline.enable_shadows = int(arg)
+ debug(f'shadows: {self._pipeline.enable_shadows}')
+ self._opt_file['settings']['shadows'] = int(arg)
+ self._opt_file.store()
+
+ def on_website(self):
+ if platform.startswith('linux'):
+ environ['LD_LIBRARY_PATH'] = ''
+ system('xdg-open https://www.ya2.it')
+ else:
+ open_new_tab('https://www.ya2.it')
+
+ def on_back(self):
+ self._opt_file.store()
+ self.destroy()
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._set_main()
+
+ def destroy(self):
+ [wdg.destroy() for wdg in self._widgets]
+ self._cursor.destroy()
+ self.ignore('enforce_resolution')
--- /dev/null
+from textwrap import dedent
+from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, \
+ GeomVertexWriter, GeomTriangles, GeomNode, Shader, Point3, Plane, Vec3
+from ya2.p3d.gfx import P3dGfxMgr
+
+
+class SidePanel:
+
+ def __init__(self, world, plane_node, top_l, bottom_r, y, items):
+ self._world = world
+ self._plane_node = plane_node
+ self._set((-1, 1), y)
+ self.update(items)
+
+ def update(self, items):
+ p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+ for hit in self._world.ray_test_all(p_from, p_to).get_hits():
+ if hit.get_node() == self._plane_node:
+ pos = hit.get_hit_pos()
+ y = 0
+ corner = -20, 20
+ for item in items:
+ if not item._instantiated:
+ bounds = item._np.get_tight_bounds()
+ if bounds[1][1] > y:
+ y = bounds[1][1]
+ icorner = item.get_corner()
+ icorner = P3dGfxMgr.screen_coord(icorner)
+ if icorner[0] > corner[0]:
+ corner = icorner[0], corner[1]
+ if icorner[1] < corner[1]:
+ corner = corner[0], icorner[1]
+ self._set((pos[0], pos[2]), y)
+ bounds = self._np.get_tight_bounds()
+ corner3d = bounds[1][0], bounds[1][1], bounds[0][2]
+ corner2d = P3dGfxMgr.screen_coord(corner3d)
+ plane = Plane(Vec3(0, 1, 0), y)
+ pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
+ ar, margin = base.get_aspect_ratio(), .04
+ x = corner[0] / ar if ar >= 1 else corner[0]
+ z = corner[1] * ar if ar < 1 else corner[1]
+ x += margin / ar if ar >= 1 else margin
+ z -= margin * ar if ar < 1 else margin
+ base.camLens.extrude((x, z), near_pt, far_pt)
+ plane.intersects_line(
+ pos3d, render.get_relative_point(base.camera, near_pt),
+ render.get_relative_point(base.camera, far_pt))
+ corner_pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
+ base.camLens.extrude((-1, 1), near_pt, far_pt)
+ plane.intersects_line(
+ corner_pos3d, render.get_relative_point(base.camera, near_pt),
+ render.get_relative_point(base.camera, far_pt))
+ self._np.set_pos((pos3d + corner_pos3d) / 2)
+ scale = Vec3(pos3d[0] - corner_pos3d[0], 1, corner_pos3d[2] - pos3d[2])
+ self._np.set_scale(scale)
+
+ def _set(self, pos, y):
+ if hasattr(self, '_np'):
+ self._np.remove_node()
+ vdata = GeomVertexData('quad', GeomVertexFormat.get_v3(), Geom.UHStatic)
+ vdata.setNumRows(2)
+ vertex = GeomVertexWriter(vdata, 'vertex')
+ vertex.add_data3(.5, 0, -.5)
+ vertex.add_data3(.5, 0, .5)
+ vertex.add_data3(-.5, 0, .5)
+ vertex.add_data3(-.5, 0, -.5)
+ prim = GeomTriangles(Geom.UHStatic)
+ prim.add_vertices(0, 1, 2)
+ prim.add_vertices(0, 2, 3)
+ prim.close_primitive()
+ geom = Geom(vdata)
+ geom.add_primitive(prim)
+ node = GeomNode('gnode')
+ node.add_geom(geom)
+ self._np = render.attach_new_node(node)
+ self._np.setTransparency(True)
+ self._np.set_pos(pos[0], y, pos[1])
+ vert = '''\
+ #version 130
+ uniform mat4 p3d_ModelViewProjectionMatrix;
+ in vec4 p3d_Vertex;
+ void main() {
+ gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; }'''
+ frag = '''\
+ #version 130
+ out vec4 p3d_FragColor;
+ void main() {
+ p3d_FragColor = vec4(.04, .04, .04, .08); }'''
+ self._np.set_shader(Shader.make(Shader.SL_GLSL, dedent(vert), dedent(frag)))
+ # mat = Material()
+ # mat.set_base_color((1, 1, 1, 1))
+ # mat.set_emission((1, 1, 1, 1))
+ # mat.set_metallic(.5)
+ # mat.set_roughness(.5)
+ # np.set_material(mat)
+ # texture_sz = 64
+ # base_color_pnm = PNMImage(texture_sz, texture_sz)
+ # base_color_pnm.fill(.1, .1, .1)
+ # base_color_pnm.add_alpha()
+ # base_color_pnm.alpha_fill(.04)
+ # base_color_tex = Texture('base color')
+ # base_color_tex.load(base_color_pnm)
+ # ts = TextureStage('base color')
+ # ts.set_mode(TextureStage.M_modulate)
+ # np.set_texture(ts, base_color_tex)
+ # emission_pnm = PNMImage(texture_sz, texture_sz)
+ # emission_pnm.fill(0, 0, 0)
+ # emission_tex = Texture('emission')
+ # emission_tex.load(emission_pnm)
+ # ts = TextureStage('emission')
+ # ts.set_mode(TextureStage.M_emission)
+ # np.set_texture(ts, emission_tex)
+ # metal_rough_pnm = PNMImage(texture_sz, texture_sz)
+ # ambient_occlusion = 1
+ # roughness = .5
+ # metallicity = .5
+ # metal_rough_pnm.fill(ambient_occlusion, roughness, metallicity)
+ # metal_rough_tex = Texture('ao metal roughness')
+ # metal_rough_tex.load(metal_rough_pnm)
+ # ts = TextureStage('ao metal roughness')
+ # ts.set_mode(TextureStage.M_selector)
+ # np.set_texture(ts, metal_rough_tex)
+ # normal_pnm = PNMImage(texture_sz, texture_sz)
+ # normal_pnm.fill(.5, .5, .1)
+ # normal_tex = Texture('normals')
+ # normal_tex.load(normal_pnm)
+ # ts = TextureStage('normals')
+ # ts.set_mode(TextureStage.M_normal)
+ # np.set_texture(ts, normal_tex)
+
+ def destroy(self):
+ self._np.remove_node()
--- /dev/null
+import argparse
+import simplepbr
+#import gltf
+from glob import glob
+from importlib import import_module
+from inspect import isclass
+from sys import platform, argv, exit
+from logging import info, debug
+from os.path import exists
+from os import makedirs
+from panda3d.core import Filename, load_prc_file_data, AntialiasAttrib, \
+ Texture, WindowProperties, LVector2i, TextNode
+from panda3d.bullet import BulletWorld, BulletDebugNode
+from direct.showbase.ShowBase import ShowBase
+from direct.gui.OnscreenText import OnscreenText
+from direct.fsm.FSM import FSM
+from audio.music import MusicMgr
+from logics.items.background import Background
+from gui.menu import Menu
+from logics.scene import Scene
+from logics.scenes.scene_basketball import SceneBasketBall
+from logics.scenes.scene_box import SceneBox
+from logics.scenes.scene_domino_box_basketball import SceneDominoBoxBasketball
+from logics.scenes.scene_domino_box import SceneDominoBox
+from logics.scenes.scene_domino import SceneDomino
+from logics.scenes.scene_teeter_domino_box_basketball import SceneTeeterDominoBoxBasketball
+from logics.scenes.scene_teeter_tooter import SceneTeeterTooter
+from ya2.utils.dictfile import DctFile
+from ya2.p3d.p3d import LibP3d
+from ya2.utils.lang import LangMgr
+from ya2.utils.log import LogMgr
+from ya2.utils.functional import FunctionalTest
+
+
+class MainFsm(FSM):
+
+ def __init__(self, pmachines):
+ super().__init__('Main FSM')
+ self._pmachines = pmachines
+
+ def enterMenu(self):
+ self._pmachines.on_menu_enter()
+
+ def exitMenu(self):
+ self._pmachines.on_menu_exit()
+
+ def enterScene(self, cls):
+ self._pmachines.on_scene_enter(cls)
+
+ def exitScene(self):
+ self._pmachines.on_scene_exit()
+
+
+class PmachinesApp:
+
+ scenes = [
+ SceneDomino,
+ SceneBox,
+ SceneDominoBox,
+ SceneBasketBall,
+ SceneDominoBoxBasketball,
+ SceneTeeterTooter,
+ SceneTeeterDominoBoxBasketball]
+
+ def __init__(self):
+ info('platform: %s' % platform)
+ info('exists main.py: %s' % exists('main.py'))
+ self._args = args = self._parse_args()
+ self._configure(args)
+ self.base = ShowBase()
+ self._pipeline = None
+ self.updating = args.update
+ self.version = args.version
+ self.log_mgr = LogMgr.init_cls()(self)
+ self._prepare_window(args)
+ if args.update:
+ return
+ if args.functional_test:
+ self._options['settings']['volume'] = 0
+ self._music = MusicMgr(self._options['settings']['volume'])
+ self.lang_mgr = LangMgr(self._options['settings']['language'],
+ 'pmachines',
+ 'assets/locale/')
+ self._fsm = MainFsm(self)
+ if args.screenshot:
+ cls = [cls for cls in self.scenes if cls.__name__ == args.screenshot][0]
+ scene = cls(BulletWorld(), None, True, False, lambda: None, self.scenes)
+ scene.screenshot()
+ scene.destroy()
+ exit()
+ elif self._options['development']['auto_start']:
+ mod_name = 'logics.scenes.scene_' + self._options['development']['auto_start']
+ for member in import_module(mod_name).__dict__.values():
+ if isclass(member) and issubclass(member, Scene) and \
+ member != Scene:
+ cls = member
+ self._fsm.demand('Scene', cls)
+ else:
+ self._fsm.demand('Menu')
+ if args.functional_test or args.functional_ref:
+ FunctionalTest(args.functional_ref)
+
+ def on_menu_enter(self):
+ self._menu_bg = Background()
+ self._menu = Menu(
+ self._fsm, self.lang_mgr, self._options, self._music,
+ self._pipeline, self.scenes, self._args.functional_test or self._args.functional_ref)
+
+ def on_home(self):
+ self._fsm.demand('Menu')
+
+ def on_menu_exit(self):
+ self._menu_bg.destroy()
+ self._menu.destroy()
+
+ def on_scene_enter(self, cls):
+ self._set_physics()
+ self._scene = cls(
+ self.world, self.on_home,
+ self._options['development']['auto_close_instructions'],
+ self._options['development']['debug_items'],
+ self.reload,
+ self.scenes)
+
+ def on_scene_exit(self):
+ self._unset_physics()
+ self._scene.destroy()
+
+ def reload(self, cls):
+ self._fsm.demand('Scene', cls)
+
+ def _configure(self, args):
+ load_prc_file_data('', 'window-title pmachines')
+ load_prc_file_data('', 'framebuffer-srgb true')
+ load_prc_file_data('', 'sync-video true')
+ if args.functional_test or args.functional_ref:
+ load_prc_file_data('', 'win-size 1360 768')
+ # otherwise it is not centered in exwm
+ # load_prc_file_data('', 'threading-model Cull/Draw')
+ # it freezes when you go to the next scene
+ if args.screenshot:
+ load_prc_file_data('', 'window-type offscreen')
+ load_prc_file_data('', 'audio-library-name null')
+
+ def _parse_args(self):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--update', action='store_true')
+ parser.add_argument('--version', action='store_true')
+ parser.add_argument('--optfile')
+ parser.add_argument('--screenshot')
+ parser.add_argument('--functional-test', action='store_true')
+ parser.add_argument('--functional-ref', action='store_true')
+ cmd_line = [arg for arg in iter(argv[1:]) if not arg.startswith('-psn_')]
+ args = parser.parse_args(cmd_line)
+ return args
+
+ def _prepare_window(self, args):
+ data_path = ''
+ if (platform.startswith('win') or platform.startswith('linux')) and (
+ not exists('main.py') or __file__.startswith('/app/bin/')):
+ # it is the deployed version for windows
+ data_path = str(Filename.get_user_appdata_directory()) + '/pmachines'
+ home = '/home/flavio' # we must force this for wine
+ if data_path.startswith('/c/users/') and exists(home + '/.wine/'):
+ data_path = home + '/.wine/drive_' + data_path[1:]
+ info('creating dirs: %s' % data_path)
+ makedirs(data_path, exist_ok=True)
+ optfile = args.optfile if args.optfile else 'options.ini'
+ info('data path: %s' % data_path)
+ info('option file: %s' % optfile)
+ info('fixed path: %s' % LibP3d.fixpath(data_path + '/' + optfile))
+ default_opt = {
+ 'settings': {
+ 'volume': 1,
+ 'language': 'en',
+ 'fullscreen': 1,
+ 'resolution': '',
+ 'antialiasing': 1,
+ 'shadows': 1},
+ 'development': {
+ 'simplepbr': 1,
+ 'verbose_log': 0,
+ 'physics_debug': 0,
+ 'auto_start': 0,
+ 'auto_close_instructions': 0,
+ 'show_buffers': 0,
+ 'debug_items': 0,
+ 'mouse_coords': 0,
+ 'fps': 0}}
+ opt_path = LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile
+ opt_exists = exists(opt_path)
+ self._options = DctFile(
+ LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile,
+ default_opt)
+ if not opt_exists:
+ self._options.store()
+ res = self._options['settings']['resolution']
+ if res:
+ res = LVector2i(*[int(_res) for _res in res.split('x')])
+ else:
+ resolutions = []
+ if not self.version:
+ d_i = base.pipe.get_display_information()
+ def _res(idx):
+ return d_i.get_display_mode_width(idx), \
+ d_i.get_display_mode_height(idx)
+ resolutions = [
+ _res(idx) for idx in range(d_i.get_total_display_modes())]
+ res = sorted(resolutions)[-1]
+ fullscreen = self._options['settings']['fullscreen']
+ props = WindowProperties()
+ if args.functional_test or args.functional_ref:
+ fullscreen = False
+ else:
+ props.set_size(res)
+ props.set_fullscreen(fullscreen)
+ props.set_icon_filename('assets/images/icon/pmachines.ico')
+ if not args.screenshot and not self.version:
+ base.win.request_properties(props)
+ #gltf.patch_loader(base.loader)
+ if self._options['development']['simplepbr'] and not self.version:
+ self._pipeline = simplepbr.init(
+ use_normal_maps=True,
+ use_emission_maps=False,
+ use_occlusion_maps=True,
+ msaa_samples=4 if self._options['settings']['antialiasing'] else 1,
+ enable_shadows=int(self._options['settings']['shadows']))
+ debug(f'msaa: {self._pipeline.msaa_samples}')
+ debug(f'shadows: {self._pipeline.enable_shadows}')
+ render.setAntialias(AntialiasAttrib.MAuto)
+ self.base.set_background_color(0, 0, 0, 1)
+ self.base.disable_mouse()
+ if self._options['development']['show_buffers']:
+ base.bufferViewer.toggleEnable()
+ if self._options['development']['fps']:
+ base.set_frame_rate_meter(True)
+ #self.base.accept('window-event', self._on_win_evt)
+ self.base.accept('aspectRatioChanged', self._on_aspect_ratio_changed)
+ if self._options['development']['mouse_coords']:
+ coords_txt = OnscreenText(
+ '', parent=base.a2dTopRight, scale=0.04,
+ pos=(-.03, -.06), fg=(.9, .9, .9, 1), align=TextNode.A_right)
+ def update_coords(task):
+ txt = '%s %s' % (int(base.win.get_pointer(0).x),
+ int(base.win.get_pointer(0).y))
+ coords_txt['text'] = txt
+ return task.cont
+ taskMgr.add(update_coords, 'update_coords')
+
+ def _set_physics(self):
+ if self._options['development']['physics_debug']:
+ debug_node = BulletDebugNode('Debug')
+ debug_node.show_wireframe(True)
+ debug_node.show_constraints(True)
+ debug_node.show_bounding_boxes(True)
+ debug_node.show_normals(True)
+ self._debug_np = render.attach_new_node(debug_node)
+ self._debug_np.show()
+ self.world = BulletWorld()
+ self.world.set_gravity((0, 0, -9.81))
+ if self._options['development']['physics_debug']:
+ self.world.set_debug_node(self._debug_np.node())
+ def update(task):
+ dt = globalClock.get_dt()
+ self.world.do_physics(dt, 10, 1/180)
+ return task.cont
+ self._phys_tsk = taskMgr.add(update, 'update')
+
+ def _unset_physics(self):
+ if self._options['development']['physics_debug']:
+ self._debug_np.remove_node()
+ self.world = None
+ taskMgr.remove(self._phys_tsk)
+
+ def _on_aspect_ratio_changed(self):
+ if self._fsm.state == 'Scene':
+ self._scene.on_aspect_ratio_changed()
--- /dev/null
+from itertools import product
+from panda3d.core import NodePath
+from ya2.p3d.gfx import set_srgb
+
+
+class Background:
+
+ def __init__(self):
+ self._root = NodePath('background_root')
+ self._root.reparent_to(render)
+ ncols, nrows = 16, 8
+ start_size, end_size = 5, 2.5
+ offset = 5
+ for col, row in product(range(ncols), range(nrows)):
+ model = loader.load_model('assets/models/bam/background/background.bam')
+ model.set_scale(end_size / start_size)
+ model.reparent_to(self._root)
+ total_width, total_height = end_size * ncols, end_size * nrows
+ left, bottom = -total_width/2, -total_height/2
+ model.set_pos(left + end_size * col, offset, bottom + end_size * row)
+ self._root.clear_model_nodes()
+ self._root.flatten_strong()
+ set_srgb(self._root)
+
+ def destroy(self):
+ self._root.remove_node()
--- /dev/null
+from panda3d.bullet import BulletSphereShape, BulletRigidBodyNode, BulletGhostNode
+from logics.items.item import Item
+
+
+class Basketball(Item):
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.92, friction=.6):
+ super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/basketball/basketball.bam', .4, mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
+
+ def _set_shape(self, apply_scale=True):
+ self.node.add_shape(BulletSphereShape(1))
--- /dev/null
+from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
+from logics.items.item import Item
+
+
+class Box(Item):
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.8, model_scale=1):
+ super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/box/box.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction, model_scale=model_scale)
+
+ def _set_shape(self, apply_scale=True):
+ self.node.add_shape(BulletBoxShape((.5, .5, .5)))
+
+
+class HitStrategy:
+
+ def __init__(self, hit_by, node, world):
+ self._hit_by = hit_by
+ self._node = node
+ self._world = world
+
+ def win_condition(self):
+ for contact in self._world.contact_test(self._node).get_contacts():
+ other = contact.get_node1() if contact.get_node0() == self._node else contact.get_node0()
+ if other == self._hit_by.node:
+ return True
--- /dev/null
+from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
+from logics.items.item import Item, StillStrategy
+
+
+class Domino(Item):
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.6):
+ super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/domino/domino.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
+
+ def _set_shape(self, apply_scale=True):
+ self.node.add_shape(BulletBoxShape((.1, .25, .5)))
+
+
+class UpStrategy(StillStrategy):
+
+ def __init__(self, np, tgt_degrees):
+ super().__init__(np)
+ self._tgt_degrees = tgt_degrees
+ self._np = np
+
+ def win_condition(self):
+ return super().win_condition() and abs(self._np.get_r()) <= self._tgt_degrees
+
+
+class DownStrategy(StillStrategy):
+
+ def __init__(self, np, tgt_degrees):
+ super().__init__(np)
+ self._tgt_degrees = tgt_degrees
+ self._np = np
+
+ def win_condition(self):
+ return self._np.get_z() < -6 or super().win_condition() and abs(self._np.get_r()) >= self._tgt_degrees
--- /dev/null
+from panda3d.core import CullFaceAttrib, Point3, NodePath, Point2, Texture, \
+ Plane, Vec3, BitMask32
+from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
+from direct.gui.OnscreenText import OnscreenText
+from ya2.p3d.gfx import P3dGfxMgr, set_srgb
+
+
+class Command:
+
+ def __init__(self, pos, rot):
+ self.pos = pos
+ self.rot = rot
+
+
+class FixedStrategy:
+
+ def win_condition(self):
+ return True
+
+
+class StillStrategy:
+
+ def __init__(self, np):
+ self._np = np
+ self._positions = []
+ self._rotations = []
+
+ def win_condition(self):
+ self._positions += [self._np.get_pos()]
+ self._rotations += [self._np.get_hpr()]
+ if len(self._positions) > 30:
+ self._positions.pop(0)
+ if len(self._rotations) > 30:
+ self._rotations.pop(0)
+ if len(self._positions) < 28:
+ return
+ avg_x = sum(pos.x for pos in self._positions) / len(self._positions)
+ avg_y = sum(pos.y for pos in self._positions) / len(self._positions)
+ avg_z = sum(pos.z for pos in self._positions) / len(self._positions)
+ avg_h = sum(rot.x for rot in self._rotations) / len(self._rotations)
+ avg_p = sum(rot.y for rot in self._rotations) / len(self._rotations)
+ avg_r = sum(rot.z for rot in self._rotations) / len(self._rotations)
+ avg_pos = Point3(avg_x, avg_y, avg_z)
+ avg_rot = Point3(avg_h, avg_p, avg_r)
+ return all((pos - avg_pos).length() < .1 for pos in self._positions) and \
+ all((rot - avg_rot).length() < 1 for rot in self._rotations)
+
+
+class Item:
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, scene_repos, model_path, model_scale=1, exp_num_contacts=1, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.5):
+ self._world = world
+ self._plane_node = plane_node
+ self._count = count
+ self._cb_inst = cb_inst
+ self._paused = False
+ self._overlapping = False
+ self._first_command = True
+ self.repos_done = False
+ self._mass = mass
+ self._pos = pos
+ self._r = r
+ self.strategy = FixedStrategy()
+ self._exp_num_contacts = exp_num_contacts
+ self._curr_bottom = curr_bottom
+ self._scene_repos = scene_repos
+ self._model_scale = model_scale
+ self._model_path = model_path
+ self._commands = []
+ self._command_idx = -1
+ self._restitution = restitution
+ self._friction = friction
+ self._positions = []
+ self._rotations = []
+ if count:
+ self.node = BulletGhostNode(self.__class__.__name__)
+ else:
+ self.node = BulletRigidBodyNode(self.__class__.__name__)
+ self._set_shape(count)
+ self._np = render.attach_new_node(self.node)
+ if count:
+ world.attach_ghost(self.node)
+ else:
+ world.attach_rigid_body(self.node)
+ self._model = loader.load_model(model_path)
+ set_srgb(self._model)
+ self._model.flatten_light()
+ self._model.reparent_to(self._np)
+ self._np.set_scale(model_scale)
+ self._np.flatten_strong()
+ if count:
+ self._set_outline_model()
+ set_srgb(self._outline_model)
+ self._model.hide(BitMask32(0x01))
+ self._outline_model.hide(BitMask32(0x01))
+ self._start_drag_pos = None
+ self._prev_rot_info = None
+ self._last_nonoverlapping_pos = None
+ self._last_nonoverlapping_rot = None
+ self._instantiated = not count
+ self.interactable = count
+ self._box_tsk = taskMgr.add(self.on_frame, 'on_frame')
+ if count:
+ self._repos()
+ else:
+ self._np.set_pos(pos)
+ self._np.set_r(r)
+
+ def _set_shape(self, apply_scale=True):
+ pass
+
+ def set_strategy(self, strategy):
+ self.strategy = strategy
+
+ def _repos(self):
+ p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+ for hit in self._world.ray_test_all(p_from, p_to).get_hits():
+ if hit.get_node() == self._plane_node:
+ pos = hit.get_hit_pos()
+ corner = P3dGfxMgr.screen_coord(pos)
+ bounds = self._np.get_tight_bounds()
+ bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
+ self._np.set_pos(pos)
+ plane = Plane(Vec3(0, 1, 0), bounds[0][1])
+ pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
+ margin, ar = .04, base.get_aspect_ratio()
+ margin_x = margin / ar if ar >= 1 else margin
+ margin_z = margin * ar if ar < 1 else margin
+ top = self._curr_bottom()
+ base.camLens.extrude((-1 + margin_x, top - margin_z), near_pt, far_pt)
+ plane.intersects_line(
+ pos3d, render.get_relative_point(base.camera, near_pt),
+ render.get_relative_point(base.camera, far_pt))
+ delta = Vec3(bounds[1][0], bounds[1][1], bounds[0][2])
+ self._np.set_pos(pos3d + delta)
+ if not hasattr(self, '_txt'):
+ font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ font.clear()
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ font.set_outline((0, 0, 0, 1), .8, .2)
+ self._txt = OnscreenText(
+ str(self._count), font=font, scale=0.06, fg=(.9, .9, .9, 1))
+ pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
+ p2d = P3dGfxMgr.screen_coord(pos)
+ self._txt['pos'] = p2d
+ self.repos_done = True
+
+ def repos_x(self, x):
+ self._np.set_x(x)
+ bounds = self._np.get_tight_bounds()
+ bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
+ pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
+ p2d = P3dGfxMgr.screen_coord(pos)
+ self._txt['pos'] = p2d
+
+ def get_bottom(self):
+ bounds = self._np.get_tight_bounds()
+ bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
+ pos = self._np.get_pos() + (bounds[1][0], bounds[1][1], bounds[0][2])
+ p2d = P3dGfxMgr.screen_coord(pos)
+ ar = base.get_aspect_ratio()
+ return p2d[1] if ar >= 1 else (p2d[1] * ar)
+
+ def get_corner(self):
+ bounds = self._np.get_tight_bounds()
+ return bounds[1][0], bounds[1][1], bounds[0][2]
+
+ def _set_outline_model(self):
+ self._outline_model = loader.load_model(self._model_path)
+ #clockw = CullFaceAttrib.MCullClockwise
+ #self._outline_model.set_attrib(CullFaceAttrib.make(clockw))
+ self._outline_model.set_attrib(CullFaceAttrib.make_reverse())
+ self._outline_model.reparent_to(self._np)
+ self._outline_model.set_scale(1.08)
+ self._outline_model.set_light_off()
+ self._outline_model.set_color(.4, .4, .4, 1)
+ self._outline_model.set_color_scale(.4, .4, .4, 1)
+ self._outline_model.hide()
+
+ def on_frame(self, task):
+ self._np.set_y(0)
+ return task.cont
+
+ def undo(self):
+ self._command_idx -= 1
+ self._np.set_pos(self._commands[self._command_idx].pos)
+ self._np.set_hpr(self._commands[self._command_idx].rot)
+
+ def redo(self):
+ self._command_idx += 1
+ self._np.set_pos(self._commands[self._command_idx].pos)
+ self._np.set_hpr(self._commands[self._command_idx].rot)
+
+ def play(self):
+ if not self._instantiated:
+ return
+ self._world.remove_rigid_body(self.node)
+ self.node.set_mass(self._mass)
+ self._world.attach_rigid_body(self.node)
+ self.node.set_restitution(self._restitution)
+ self.node.set_friction(self._friction)
+
+ def on_click_l(self, pos):
+ if self._paused: return
+ self._start_drag_pos = pos, self._np.get_pos()
+ loader.load_sfx('assets/audio/sfx/grab.ogg').play()
+ if not self._instantiated:
+ self._world.remove_ghost(self.node)
+ pos = self._np.get_pos()
+ self._np.remove_node()
+ self.node = BulletRigidBodyNode('box')
+ self._set_shape()
+ self._np = render.attach_new_node(self.node)
+ self._world.attach_rigid_body(self.node)
+ self._model.reparent_to(self._np)
+ self._np.set_pos(pos)
+ self._set_outline_model()
+ self._np.set_scale(self._model_scale)
+ self._model.show(BitMask32(0x01))
+ self._outline_model.hide(BitMask32(0x01))
+ self._instantiated = True
+ self._txt.destroy()
+ self._count -= 1
+ if self._count:
+ item = self.__class__(self._world, self._plane_node, self._cb_inst, self._curr_bottom, self._scene_repos, count=self._count, mass=self._mass, pos=self._pos, r=self._r) # pylint: disable=no-value-for-parameter
+ self._cb_inst(item)
+ self._scene_repos()
+
+ def on_click_r(self, pos):
+ if self._paused or not self._instantiated: return
+ self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
+ loader.load_sfx('assets/audio/sfx/grab.ogg').play()
+
+ def on_release(self):
+ if self._start_drag_pos or self._prev_rot_info:
+ loader.load_sfx('assets/audio/sfx/release.ogg').play()
+ self._command_idx += 1
+ self._commands = self._commands[:self._command_idx]
+ self._commands += [Command(self._np.get_pos(), self._np.get_hpr())]
+ self._first_command = False
+ self._start_drag_pos = self._prev_rot_info = None
+ if self._overlapping:
+ self._np.set_pos(self._last_nonoverlapping_pos)
+ self._np.set_hpr(self._last_nonoverlapping_rot)
+ self._outline_model.set_color(.4, .4, .4, 1)
+ self._outline_model.set_color_scale(.4, .4, .4, 1)
+ self._overlapping = False
+
+ def on_mouse_on(self):
+ if not self._paused and self.interactable:
+ self._outline_model.show()
+
+ def on_mouse_off(self):
+ if self._start_drag_pos or self._prev_rot_info: return
+ if self.interactable:
+ self._outline_model.hide()
+
+ def on_mouse_move(self, pos):
+ if self._start_drag_pos:
+ d_pos = pos - self._start_drag_pos[0]
+ self._np.set_pos(self._start_drag_pos[1] + d_pos)
+ if self._prev_rot_info:
+ start_vec = self._prev_rot_info[0] - self._prev_rot_info[1]
+ curr_vec = pos - self._prev_rot_info[1]
+ d_angle = curr_vec.signed_angle_deg(start_vec, (0, -1, 0))
+ self._np.set_r(self._prev_rot_info[2] + d_angle)
+ self._prev_rot_info = pos, self._np.get_pos(), self._np.get_r()
+ if self._start_drag_pos or self._prev_rot_info:
+ res = self._world.contact_test(self.node)
+ nres = res.get_num_contacts()
+ if nres <= self._exp_num_contacts:
+ self._overlapping = False
+ self._outline_model.set_color(.4, .4, .4, 1)
+ self._outline_model.set_color_scale(.4, .4, .4, 1)
+ if nres > self._exp_num_contacts and not self._overlapping:
+ actual_nres = 0
+ for contact in res.get_contacts():
+ for node in [contact.get_node0(), contact.get_node1()]:
+ if isinstance(node, BulletRigidBodyNode) and \
+ node != self.node:
+ actual_nres += 1
+ if actual_nres >= 1:
+ self._overlapping = True
+ loader.load_sfx('assets/audio/sfx/overlap.ogg').play()
+ self._outline_model.set_color(.9, .1, .1, 1)
+ self._outline_model.set_color_scale(.9, .1, .1, 1)
+ if not self._overlapping:
+ self._last_nonoverlapping_pos = self._np.get_pos()
+ self._last_nonoverlapping_rot = self._np.get_hpr()
+
+ def on_aspect_ratio_changed(self):
+ if not self._instantiated:
+ self._repos()
+
+ def store_state(self):
+ self._paused = True
+ self._model.set_transparency(True)
+ self._model.set_alpha_scale(.3)
+ if hasattr(self, '_txt') and not self._txt.is_empty():
+ self._txt.set_alpha_scale(.3)
+
+ def restore_state(self):
+ self._paused = False
+ self._model.set_alpha_scale(1)
+ if hasattr(self, '_txt') and not self._txt.is_empty():
+ self._txt.set_alpha_scale(1)
+
+ def fail_condition(self):
+ if self._np.get_z() < -6:
+ return True
+ self._positions += [self._np.get_pos()]
+ self._rotations += [self._np.get_hpr()]
+ if len(self._positions) > 30:
+ self._positions.pop(0)
+ if len(self._rotations) > 30:
+ self._rotations.pop(0)
+ if len(self._positions) < 28:
+ return
+ avg_x = sum(pos.x for pos in self._positions) / len(self._positions)
+ avg_y = sum(pos.y for pos in self._positions) / len(self._positions)
+ avg_z = sum(pos.z for pos in self._positions) / len(self._positions)
+ avg_h = sum(rot.x for rot in self._rotations) / len(self._rotations)
+ avg_p = sum(rot.y for rot in self._rotations) / len(self._rotations)
+ avg_r = sum(rot.z for rot in self._rotations) / len(self._rotations)
+ avg_pos = Point3(avg_x, avg_y, avg_z)
+ avg_rot = Point3(avg_h, avg_p, avg_r)
+ return all((pos - avg_pos).length() < .1 for pos in self._positions) and \
+ all((rot - avg_rot).length() < 1 for rot in self._rotations)
+
+ def destroy(self):
+ self._np.remove_node()
+ taskMgr.remove(self._box_tsk)
+ if hasattr(self, '_txt'):
+ self._txt.destroy()
+ if not self._instantiated:
+ self._world.remove_ghost(self.node)
+ else:
+ self._world.remove_rigid_body(self.node)
--- /dev/null
+from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
+from logics.items.item import Item
+
+
+class Shelf(Item):
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.6):
+ super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/shelf/shelf.bam', mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction)
+
+ def _set_shape(self, apply_scale=True):
+ self.node.add_shape(BulletBoxShape((1, .5, .05)))
--- /dev/null
+from panda3d.core import TransformState
+from panda3d.bullet import BulletCylinderShape, BulletRigidBodyNode, BulletGhostNode, YUp, ZUp
+from logics.items.item import Item
+
+
+class TeeterTooter(Item):
+
+ def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, restitution=.5, friction=.5):
+ super().__init__(world, plane_node, cb_inst, curr_bottom, repos, 'assets/models/bam/teeter_tooter/teeter_tooter.bam', exp_num_contacts=2, mass=mass, pos=pos, r=r, count=count, restitution=restitution, friction=friction, model_scale=.5)
+
+ def _set_shape(self, apply_scale=True):
+ scale = self._model_scale if apply_scale else 1
+ self.node.add_shape(
+ BulletCylinderShape(.1, 1.6, YUp),
+ TransformState.makePos((0, 0, scale * .36)))
+ self.node.add_shape(
+ BulletCylinderShape(.1, .7, ZUp),
+ TransformState.makePos((0, scale * .8, scale * -.1)))
+ self.node.add_shape(
+ BulletCylinderShape(.1, .7, ZUp),
+ TransformState.makePos((0, scale * -.8, scale * -.1)))
--- /dev/null
+from os.path import exists
+from os import makedirs
+from glob import glob
+from logging import debug, info
+from importlib import import_module
+from inspect import isclass
+from panda3d.core import AmbientLight, DirectionalLight, Point3, Texture, \
+ TextPropertiesManager, TextNode, Spotlight, PerspectiveLens, BitMask32
+from panda3d.bullet import BulletPlaneShape, BulletGhostNode
+from direct.gui.OnscreenImage import OnscreenImage
+from direct.gui.OnscreenText import OnscreenText
+from direct.gui.DirectGui import DirectButton, DirectFrame
+from direct.gui.DirectGuiGlobals import FLAT, DISABLED, NORMAL
+from direct.showbase.DirectObject import DirectObject
+from logics.items.background import Background
+from gui.sidepanel import SidePanel
+from ya2.utils.cursor import MouseCursor
+from ya2.p3d.gfx import P3dGfxMgr
+
+
+class Scene(DirectObject):
+
+ def __init__(self, world, exit_cb, auto_close_instr, dbg_items, reload_cb, scenes):
+ super().__init__()
+ self._world = world
+ self._exit_cb = exit_cb
+ self._dbg_items = dbg_items
+ self._reload_cb = reload_cb
+ self._scenes = scenes
+ self._enforce_res = ''
+ self.accept('enforce_res', self.enforce_res)
+ self._set_camera()
+ self._cursor = MouseCursor(
+ 'assets/images/buttons/arrowUpLeft.dds', (.04, 1, .04), (.5, .5, .5, 1),
+ (.01, .01))
+ self._set_gui()
+ self._set_lights()
+ self._set_input()
+ self._set_mouse_plane()
+ self.items = []
+ self.reset()
+ self._state = 'init'
+ self._paused = False
+ self._item_active = None
+ if auto_close_instr:
+ self.__store_state()
+ self.__restore_state()
+ else:
+ self._set_instructions()
+ self._bg = Background()
+ self._side_panel = SidePanel(world, self._mouse_plane_node, (-5, 4), (-3, 1), 1, self.items)
+ self._scene_tsk = taskMgr.add(self.on_frame, 'on_frame')
+
+ @staticmethod
+ def name():
+ return ''
+
+ def _instr_txt(self):
+ return ''
+
+ def _set_items(self):
+ self.items = []
+
+ def screenshot(self, task=None):
+ tex = Texture('screenshot')
+ buffer = base.win.make_texture_buffer('screenshot', 512, 512, tex, True )
+ cam = base.make_camera(buffer)
+ cam.reparent_to(render)
+ cam.node().get_lens().set_fov(base.camLens.get_fov())
+ cam.set_pos(0, -20, 0)
+ cam.look_at(0, 0, 0)
+ import simplepbr
+ simplepbr.init(
+ window=buffer,
+ camera_node=cam,
+ use_normal_maps=True,
+ use_emission_maps=False,
+ use_occlusion_maps=True,
+ msaa_samples=4,
+ enable_shadows=True)
+ base.graphicsEngine.renderFrame()
+ base.graphicsEngine.renderFrame()
+ fname = self.__class__.__name__
+ if not exists('assets/images/scenes'):
+ makedirs('assets/images/scenes')
+ buffer.save_screenshot('assets/images/scenes/%s.png' % fname)
+ # img = DirectButton(
+ # frameTexture=buffer.get_texture(), relief=FLAT,
+ # frameSize=(-.2, .2, -.2, .2))
+ return buffer.get_texture()
+
+ def current_bottom(self):
+ curr_bottom = 1
+ for item in self.items:
+ if item.repos_done:
+ curr_bottom = min(curr_bottom, item.get_bottom())
+ return curr_bottom
+
+ def reset(self):
+ [itm.destroy() for itm in self.items]
+ self._set_items()
+ self._state = 'init'
+ self._commands = []
+ self._command_idx = 0
+ if hasattr(self, '_success_txt'):
+ self._success_txt.destroy()
+ del self._success_txt
+ self.__right_btn['state'] = NORMAL
+
+ def enforce_res(self, val):
+ self._enforce_res = val
+ info('enforce res: ' + val)
+
+ def destroy(self):
+ self.ignore('enforce_res')
+ self._unset_gui()
+ self._unset_lights()
+ self._unset_input()
+ self._unset_mouse_plane()
+ [itm.destroy() for itm in self.items]
+ self._bg.destroy()
+ self._side_panel.destroy()
+ self._cursor.destroy()
+ taskMgr.remove(self._scene_tsk)
+ if hasattr(self, '_success_txt'):
+ self._success_txt.destroy()
+
+ def _set_camera(self):
+ base.camera.set_pos(0, -20, 0)
+ base.camera.look_at(0, 0, 0)
+
+ def __load_img_btn(self, path, col):
+ img = OnscreenImage('assets/images/buttons/%s.dds' % path)
+ img.set_transparency(True)
+ img.set_color(col)
+ img.detach_node()
+ return img
+
+ def _set_gui(self):
+ def load_images_btn(path, col):
+ colors = {
+ 'gray': [
+ (.6, .6, .6, 1), # ready
+ (1, 1, 1, 1), # press
+ (.8, .8, .8, 1), # rollover
+ (.4, .4, .4, .4)],
+ 'green': [
+ (.1, .68, .1, 1),
+ (.1, 1, .1, 1),
+ (.1, .84, .1, 1),
+ (.4, .1, .1, .4)]}[col]
+ return [self.__load_img_btn(path, col) for col in colors]
+ abl, abr = base.a2dBottomLeft, base.a2dBottomRight
+ btn_info = [
+ ('home', self.on_home, NORMAL, abl, 'gray'),
+ ('information', self._set_instructions, NORMAL, abl, 'gray'),
+ ('right', self.on_play, NORMAL, abr, 'green'),
+ #('next', self.on_next, DISABLED, abr, 'gray'),
+ #('previous', self.on_prev, DISABLED, abr, 'gray'),
+ #('rewind', self.reset, NORMAL, abr, 'gray')
+ ]
+ num_l = num_r = 0
+ btns = []
+ for binfo in btn_info:
+ imgs = load_images_btn(binfo[0], binfo[4])
+ if binfo[3] == base.a2dBottomLeft:
+ sign, num = 1, num_l
+ num_l += 1
+ else:
+ sign, num = -1, num_r
+ num_r += 1
+ fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+ btn = DirectButton(
+ image=imgs, scale=.05, pos=(sign * (.06 + .11 * num), 1, .06),
+ parent=binfo[3], command=binfo[1], state=binfo[2], relief=FLAT,
+ frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+ btns += [btn]
+ self.__home_btn, self.__info_btn, self.__right_btn = btns
+ # , self.__next_btn, self.__prev_btn, self.__rewind_btn
+ if self._dbg_items:
+ self._info_txt = OnscreenText(
+ '', parent=base.a2dTopRight, scale=0.04,
+ pos=(-.03, -.06), fg=(.9, .9, .9, 1), align=TextNode.A_right)
+
+ def _unset_gui(self):
+ btns = [
+ self.__home_btn, self.__info_btn, self.__right_btn,
+ #self.__next_btn, self.__prev_btn, self.__rewind_btn
+ ]
+ [btn.destroy() for btn in btns]
+ if self._dbg_items:
+ self._info_txt.destroy()
+
+ def _set_spotlight(self, name, pos, look_at, color, shadows=False):
+ light = Spotlight(name)
+ if shadows:
+ light.setLens(PerspectiveLens())
+ light_np = render.attach_new_node(light)
+ light_np.set_pos(pos)
+ light_np.look_at(look_at)
+ light.set_color(color)
+ render.set_light(light_np)
+ return light_np
+
+ def _set_lights(self):
+ alight = AmbientLight('alight') # for ao
+ alight.set_color((.15, .15, .15, 1))
+ self._alnp = render.attach_new_node(alight)
+ render.set_light(self._alnp)
+ self._key_light = self._set_spotlight(
+ 'key light', (-5, -80, 5), (0, 0, 0), (2.8, 2.8, 2.8, 1))
+ self._shadow_light = self._set_spotlight(
+ 'key light', (-5, -80, 5), (0, 0, 0), (.58, .58, .58, 1), True)
+ self._shadow_light.node().set_shadow_caster(True, 2048, 2048)
+ self._shadow_light.node().get_lens().set_film_size(2048, 2048)
+ self._shadow_light.node().get_lens().set_near_far(1, 256)
+ self._shadow_light.node().set_camera_mask(BitMask32(0x01))
+
+ def _unset_lights(self):
+ for light in [self._alnp, self._key_light, self._shadow_light]:
+ render.clear_light(light)
+ light.remove_node()
+
+ def _set_input(self):
+ self.accept('mouse1', self.on_click_l)
+ self.accept('mouse1-up', self.on_release)
+ self.accept('mouse3', self.on_click_r)
+ self.accept('mouse3-up', self.on_release)
+
+ def _unset_input(self):
+ for evt in ['mouse1', 'mouse1-up', 'mouse3', 'mouse3-up']:
+ self.ignore(evt)
+
+ def _set_mouse_plane(self):
+ shape = BulletPlaneShape((0, -1, 0), 0)
+ #self._mouse_plane_node = BulletRigidBodyNode('mouse plane')
+ self._mouse_plane_node = BulletGhostNode('mouse plane')
+ self._mouse_plane_node.addShape(shape)
+ #np = render.attachNewNode(self._mouse_plane_node)
+ #self._world.attachRigidBody(self._mouse_plane_node)
+ self._world.attach_ghost(self._mouse_plane_node)
+
+ def _unset_mouse_plane(self):
+ self._world.remove_ghost(self._mouse_plane_node)
+
+ def _get_hits(self):
+ if not base.mouseWatcherNode.has_mouse(): return []
+ p_from, p_to = P3dGfxMgr.world_from_to(base.mouseWatcherNode.get_mouse())
+ return self._world.ray_test_all(p_from, p_to).get_hits()
+
+ def _update_info(self, item):
+ txt = ''
+ if item:
+ txt = '%.3f %.3f\n%.3f°' % (
+ item._np.get_x(), item._np.get_z(), item._np.get_r())
+ self._info_txt['text'] = txt
+
+ def _on_click(self, method):
+ if self._paused:
+ return
+ for hit in self._get_hits():
+ if hit.get_node() == self._mouse_plane_node:
+ pos = hit.get_hit_pos()
+ for hit in self._get_hits():
+ for item in [i for i in self.items if hit.get_node() == i.node and i.interactable]:
+ if not self._item_active:
+ self._item_active = item
+ getattr(item, method)(pos)
+ img = 'move' if method == 'on_click_l' else 'rotate'
+ if not (img == 'rotate' and not item._instantiated):
+ self._cursor.set_image('assets/images/buttons/%s.dds' % img)
+
+ def on_click_l(self):
+ self._on_click('on_click_l')
+
+ def on_click_r(self):
+ self._on_click('on_click_r')
+
+ def on_release(self):
+ if self._item_active and not self._item_active._first_command:
+ self._commands = self._commands[:self._command_idx]
+ self._commands += [self._item_active]
+ self._command_idx += 1
+ #self.__prev_btn['state'] = NORMAL
+ #fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+ #self.__prev_btn['frameColor'] = fcols[0]
+ #if self._item_active._command_idx == len(self._item_active._commands) - 1:
+ # self.__next_btn['state'] = DISABLED
+ # self.__next_btn['frameColor'] = fcols[1]
+ self._item_active = None
+ [item.on_release() for item in self.items]
+ self._cursor.set_image('assets/images/buttons/arrowUpLeft.dds')
+
+ def repos(self):
+ for item in self.items:
+ item.repos_done = False
+ self.items = sorted(self.items, key=lambda itm: itm.__class__.__name__)
+ [item.on_aspect_ratio_changed() for item in self.items]
+ self._side_panel.update(self.items)
+ max_x = -float('inf')
+ for item in self.items:
+ if not item._instantiated:
+ max_x = max(item._np.get_x(), max_x)
+ for item in self.items:
+ if not item._instantiated:
+ item.repos_x(max_x)
+
+ def on_aspect_ratio_changed(self):
+ self.repos()
+
+ def _win_condition(self):
+ pass
+
+ def _fail_condition(self):
+ return all(itm.fail_condition() for itm in self.items) and not self._paused and self._state == 'playing'
+
+ def on_frame(self, task):
+ hits = self._get_hits()
+ pos = None
+ for hit in self._get_hits():
+ if hit.get_node() == self._mouse_plane_node:
+ pos = hit.get_hit_pos()
+ hit_nodes = [hit.get_node() for hit in hits]
+ if self._item_active:
+ items_hit = [self._item_active]
+ else:
+ items_hit = [itm for itm in self.items if itm.node in hit_nodes]
+ items_no_hit = [itm for itm in self.items if itm not in items_hit]
+ [itm.on_mouse_on() for itm in items_hit]
+ [itm.on_mouse_off() for itm in items_no_hit]
+ if pos and self._item_active:
+ self._item_active.on_mouse_move(pos)
+ if self._dbg_items:
+ self._update_info(items_hit[0] if items_hit else None)
+ if self._win_condition():
+ self._set_fail() if self._enforce_res == 'fail' else self._set_win()
+ elif self._state == 'playing' and self._fail_condition():
+ self._set_win() if self._enforce_res == 'win' else self._set_fail()
+ if any(itm._overlapping for itm in self.items):
+ self._cursor.cursor_img.img.set_color(.9, .1, .1, 1)
+ else:
+ self._cursor.cursor_img.img.set_color(.9, .9, .9, 1)
+ return task.cont
+
+ def cb_inst(self, item):
+ self.items += [item]
+
+ def on_play(self):
+ self._state = 'playing'
+ #self.__prev_btn['state'] = DISABLED
+ #self.__next_btn['state'] = DISABLED
+ self.__right_btn['state'] = DISABLED
+ [itm.play() for itm in self.items]
+
+ def on_next(self):
+ self._commands[self._command_idx].redo()
+ self._command_idx += 1
+ fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+ #self.__prev_btn['state'] = NORMAL
+ #self.__prev_btn['frameColor'] = fcols[0]
+ more_commands = self._command_idx < len(self._commands)
+ #self.__next_btn['state'] = NORMAL if more_commands else DISABLED
+ #self.__next_btn['frameColor'] = fcols[0] if more_commands else fcols[1]
+
+ def on_prev(self):
+ self._command_idx -= 1
+ self._commands[self._command_idx].undo()
+ fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+ #self.__next_btn['state'] = NORMAL
+ #self.__next_btn['frameColor'] = fcols[0]
+ #self.__prev_btn['state'] = NORMAL if self._command_idx else DISABLED
+ #self.__prev_btn['frameColor'] = fcols[0] if self._command_idx else fcols[1]
+
+ def on_home(self):
+ self._exit_cb()
+
+ def _set_instructions(self):
+ self._paused = True
+ self.__store_state()
+ mgr = TextPropertiesManager.get_global_ptr()
+ for name in ['mouse_l', 'mouse_r']:
+ graphic = OnscreenImage('assets/images/buttons/%s.dds' % name)
+ graphic.set_scale(.5)
+ graphic.get_texture().set_minfilter(Texture.FTLinearMipmapLinear)
+ graphic.get_texture().set_anisotropic_degree(2)
+ mgr.set_graphic(name, graphic)
+ graphic.set_z(-.2)
+ graphic.set_transparency(True)
+ graphic.detach_node()
+ frm = DirectFrame(frameColor=(.4, .4, .4, .06),
+ frameSize=(-.6, .6, -.3, .3))
+ font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ font.clear()
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ font.set_outline((0, 0, 0, 1), .8, .2)
+ self._txt = OnscreenText(
+ self._instr_txt(), parent=frm, font=font, scale=0.06,
+ fg=(.9, .9, .9, 1), align=TextNode.A_left)
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
+ btn_scale = .05
+ mar = .06 # margin
+ z = h / 2 - font.get_line_height() * self._txt['scale'][1]
+ z += (btn_scale + 2 * mar) / 2
+ self._txt['pos'] = -w / 2, z
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
+ fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
+ frm['frameSize'] = fsz
+ colors = [
+ (.6, .6, .6, 1), # ready
+ (1, 1, 1, 1), # press
+ (.8, .8, .8, 1), # rollover
+ (.4, .4, .4, .4)]
+ imgs = [self.__load_img_btn('exitRight', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(l_r[0] - btn_scale, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self.__on_close_instructions, extraArgs=[frm],
+ relief=FLAT, frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+
+ def _set_win(self):
+ loader.load_sfx('assets/audio/sfx/success.ogg').play()
+ self._paused = True
+ self.__store_state()
+ frm = DirectFrame(frameColor=(.4, .4, .4, .06),
+ frameSize=(-.6, .6, -.3, .3))
+ font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ font.clear()
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ font.set_outline((0, 0, 0, 1), .8, .2)
+ self._txt = OnscreenText(
+ _('You win!'),
+ parent=frm,
+ font=font, scale=0.2,
+ fg=(.9, .9, .9, 1))
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
+ btn_scale = .05
+ mar = .06 # margin
+ z = h / 2 - font.get_line_height() * self._txt['scale'][1]
+ z += (btn_scale + 2 * mar) / 2
+ self._txt['pos'] = 0, z
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
+ fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
+ frm['frameSize'] = fsz
+ colors = [
+ (.6, .6, .6, 1), # ready
+ (1, 1, 1, 1), # press
+ (.8, .8, .8, 1), # rollover
+ (.4, .4, .4, .4)]
+ imgs = [self.__load_img_btn('home', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self._on_end_home, extraArgs=[frm],
+ relief=FLAT, frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+ imgs = [self.__load_img_btn('rewind', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(0, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self._on_restart, extraArgs=[frm],
+ relief=FLAT, frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+ enabled = self._scenes.index(self.__class__) < len(self._scenes) - 1
+ if enabled:
+ next_scene = self._scenes[self._scenes.index(self.__class__) + 1]
+ else:
+ next_scene = None
+ imgs = [self.__load_img_btn('right', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self._on_next_scene,
+ extraArgs=[frm, next_scene], relief=FLAT,
+ frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn['state'] = NORMAL if enabled else DISABLED
+ btn.set_transparency(True)
+
+ def _set_fail(self):
+ loader.load_sfx('assets/audio/sfx/success.ogg').play()
+ self._paused = True
+ self.__store_state()
+ frm = DirectFrame(frameColor=(.4, .4, .4, .06),
+ frameSize=(-.6, .6, -.3, .3))
+ font = base.loader.load_font('assets/fonts/Hanken-Book.ttf')
+ font.clear()
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ font.set_outline((0, 0, 0, 1), .8, .2)
+ self._txt = OnscreenText(
+ _('You have failed!'),
+ parent=frm,
+ font=font, scale=0.2,
+ fg=(.9, .9, .9, 1))
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ w, h = l_r[0] - u_l[0], u_l[2] - l_r[2]
+ btn_scale = .05
+ mar = .06 # margin
+ z = h / 2 - font.get_line_height() * self._txt['scale'][1]
+ z += (btn_scale + 2 * mar) / 2
+ self._txt['pos'] = 0, z
+ u_l = self._txt.textNode.get_upper_left_3d()
+ l_r = self._txt.textNode.get_lower_right_3d()
+ c_l_r = l_r[0], l_r[1], l_r[2] - 2 * mar - btn_scale
+ fsz = u_l[0] - mar, l_r[0] + mar, c_l_r[2] - mar, u_l[2] + mar
+ frm['frameSize'] = fsz
+ colors = [
+ (.6, .6, .6, 1), # ready
+ (1, 1, 1, 1), # press
+ (.8, .8, .8, 1), # rollover
+ (.4, .4, .4, .4)]
+ imgs = [self.__load_img_btn('home', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(-2.8 * btn_scale, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self._on_end_home, extraArgs=[frm],
+ relief=FLAT, frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+ imgs = [self.__load_img_btn('rewind', col) for col in colors]
+ btn = DirectButton(
+ image=imgs, scale=btn_scale,
+ pos=(0, 1, l_r[2] - mar - btn_scale),
+ parent=frm, command=self._on_restart, extraArgs=[frm],
+ relief=FLAT, frameColor=(.6, .6, .6, .08),
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.set_transparency(True)
+
+ def _on_restart(self, frm):
+ self.__on_close_instructions(frm)
+ self.reset()
+
+ def _on_end_home(self, frm):
+ self.__on_close_instructions(frm)
+ self.on_home()
+
+ def _on_next_scene(self, frm, scene):
+ self.__on_close_instructions(frm)
+ self._reload_cb(scene)
+
+ def __store_state(self):
+ btns = [
+ self.__home_btn, self.__info_btn, self.__right_btn,
+ #self.__next_btn, self.__prev_btn, self.__rewind_btn
+ ]
+ self.__btn_state = [btn['state'] for btn in btns]
+ for btn in btns:
+ btn['state'] = DISABLED
+ [itm.store_state() for itm in self.items]
+
+ def __restore_state(self):
+ btns = [
+ self.__home_btn, self.__info_btn, self.__right_btn,
+ #self.__next_btn, self.__prev_btn, self.__rewind_btn
+ ]
+ for btn, state in zip(btns, self.__btn_state):
+ btn['state'] = state
+ [itm.restore_state() for itm in self.items]
+ self._paused = False
+
+ def __on_close_instructions(self, frm):
+ frm.remove_node()
+ self.__restore_state()
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, UpStrategy, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneBasketBall(Scene):
+
+ @staticmethod
+ def name():
+ return _('Basket ball')
+
+ def _set_items(self):
+ self.items = []
+ #self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
+ self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, .21))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, .21))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-4.45, 0, -3.18), r=27, restitution=1)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-5.45, 0, -3.18), restitution=1)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 30))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37)]
+ #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78))]
+ #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78))]
+ #self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78))]
+ #self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78))]
+ #self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: you must hit every domino piece\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box, HitStrategy
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneBox(Scene):
+
+ @staticmethod
+ def name():
+ return _('Box')
+
+ def _set_items(self):
+ self.items = []
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.46, 0, -3.95))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.43, 0, -3.95))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.29, 0, .26), r=28.45)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.15, 0, -1.49), r=28.45)]
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.55, 0, 1.23), friction=.4)]
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.38, 0, -3.35))]
+ self.items[-1].set_strategy(HitStrategy(self.items[-2], self.items[-1].node, self.items[-1]._world))
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
+ #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04), tgt_degrees=60)]
+ #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04), tgt_degrees=60)]
+ #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04), tgt_degrees=60)]
+ #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04), tgt_degrees=60)]
+ #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04), tgt_degrees=88)]
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: the left box must hit the right box\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneDomino(Scene):
+
+ @staticmethod
+ def name():
+ return _('Domino')
+
+ def _set_items(self):
+ self.items = []
+ #self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.2, 0, -.6))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.2, 0, -.6))]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 88))
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: every domino piece must fall\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, UpStrategy, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneDominoBox(Scene):
+
+ @staticmethod
+ def name():
+ return _('Domino and box')
+
+ def _set_items(self):
+ self.items = []
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
+ #self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, .21))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, .21))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.94), r=37)]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
+ self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37)]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78))]
+ self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78))]
+ self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: only the last piece of each row must be up\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, UpStrategy, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneDominoBoxBasketball(Scene):
+
+ @staticmethod
+ def name():
+ return _('Domino, box and basket ball')
+
+ def _set_items(self):
+ self.items = []
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1, mass=5)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=1)]
+ self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.3, 1, 2.5))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
+ #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.68, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.35, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.08, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.78, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.53, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: every domino piece must be hit\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, UpStrategy, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneTeeterDominoBoxBasketball(Scene):
+
+ @staticmethod
+ def name():
+ return _('Teeter tooter, domino, box and basket ball')
+
+ def _set_items(self):
+ self.items = []
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=3, count=2, friction=1)]
+ self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(.98, 1, 1.02))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-6.24, 0, -1.45))]
+ self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-6.24, 0, -1.20))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, r=24.60, friction=1, pos=(-6.15, 0, -.93))]
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.3, friction=1, model_scale=.5, pos=(-5.38, 0, -.93), r=24.60)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(5.37, 0, -.78))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(7.48, 0, -.78))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.74, 0, -1.95))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(6.88, 0, -1.95))]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(4.83, 0, -1.39))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(5.67, 0, -1.39))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, pos=(6.59, 0, -1.39))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.53, 0, -1.95), restitution=.95)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.63, 0, -1.95), restitution=.95)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-3.65, 0, 1.05), r=28, friction=0)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.27, 0, 1.72), restitution=.95)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.88, 0, 1.72), restitution=.95)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.67, 0, .55), restitution=.95)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(.52, 0, .55), restitution=.95)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-1.73, 0, 1.11))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-.97, 0, 1.11))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.5, pos=(-.1, 0, 1.11))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: every domino piece must be hit\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
--- /dev/null
+from logics.scene import Scene
+from logics.items.box import Box
+from logics.items.shelf import Shelf
+from logics.items.domino import Domino, UpStrategy, DownStrategy
+from logics.items.basketball import Basketball
+from logics.items.teetertooter import TeeterTooter
+
+
+class SceneTeeterTooter(Scene):
+
+ @staticmethod
+ def name():
+ return _('Teeter tooter')
+
+ def _set_items(self):
+ self.items = []
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=3, count=1, friction=1)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=5, count=2)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-2.76, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.56, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.27, 0, -.28))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(4.38, 0, -.28))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
+ self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-2.74, 0, -1.20))]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=1, r=-25.30, friction=1, pos=(-2.78, 0, -.93))]
+ self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=.2, friction=1, model_scale=.5, pos=(-3.61, 0, -.99), r=-25.30)]
+ self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-.25, 0, -.57), r=52)]
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(3.50, 0, -.89))]
+ self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+ #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+ #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
+
+ def _instr_txt(self):
+ txt = _('Scene: ') + self.name() + '\n\n'
+ txt += _('Goal: you must hit every domino piece\n\n')
+ txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
+ 'keep \5mouse_r\5 pressed to rotate an item')
+ return txt
+
+ def _win_condition(self):
+ return all(itm.strategy.win_condition() for itm in self.items) and not self._paused
'''This is the main file. This launches the application.'''
-import ya2.engine.log # so logging's info/debug are logged
+import ya2.utils.log # so logging's info/debug are logged
from sys import argv
from panda3d.core import load_prc_file_data
if '--version' in argv:
load_prc_file_data('', 'window-type none')
from os.path import exists
from traceback import print_exc
-from game.app import PmachinesApp
+from logics.app import PmachinesApp
from p3d_appimage import AppImageBuilder
if __name__ == '__main__' or exists('main.pyo'):
from ya2.build.lang import LanguageBuilder
from p3d_appimage import AppImageBuilder
from p3d_flatpak import FlatpakBuilder
-import ya2.engine.log # so logging's info/debug are logged
-from game.app import PmachinesApp
+import ya2.utils.log # so logging's info/debug are logged
+from logics.app import PmachinesApp
appname = longname = 'pmachines'
from panda3d.core import Filename
from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText
-from ya2.gameobject import GameObject
+from ya2.patterns.gameobject import GameObject
from ya2.build.build import _branch
+++ /dev/null
-'''Unit tests for lib.build.'''
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent.parent))
-from os import getcwd, makedirs, walk
-from os.path import basename
-from shutil import rmtree
-from unittest import TestCase
-from re import compile
-from ya2.build.build import InsideDir, files, exec_cmd, _branch, _version, \
- to_be_built
-
-
-class BuildTests(TestCase):
-
- def setUp(self):
- makedirs('test_get_files/a')
- makedirs('test_get_files/b')
- makedirs('test_get_files/c')
- with open('test_get_files/a/c.ext1', 'w') as ftest:
- ftest.write('0123456789')
- with open('test_get_files/a/d.ext2', 'w'): pass
- with open('test_get_files/b/e.ext2', 'w') as ftest:
- ftest.write('0123456789')
- with open('test_get_files/b/f.ext3', 'w'): pass
- with open('test_get_files/c/g.ext2', 'w'): pass
-
- def tearDown(self):
- rmtree('test_get_files')
-
- def test_exec_cmd(self):
- self.assertEqual(exec_cmd('echo abc'), 'abc')
-
- def test_branch(self):
- self.assertIn(_branch(), ['master', 'rc', 'stable'])
-
- def test_version(self):
- patterns = [
- "^0a[0-9]+$",
- "^0rc[0-9]+$",
- "^0\.[0-9]+$"]
- compiled = [compile(pattern) for pattern in patterns]
- matches = [pattern.match(_version()) for pattern in compiled]
- self.assertTrue(any(matches))
-
- def test_get_files(self):
- _files = files(['ext2'], 'c')
- self.assertSetEqual(set(_files),
- set(['./test_get_files/a/d.ext2',
- './test_get_files/b/e.ext2']))
-
- def test_inside_dir(self):
- dirs = [basename(x[0]) for x in walk('.')]
- dirs = [dir_ for dir_ in dirs if dir_ not in ['.', '..']]
- dirname = dirs[0]
- self.assertNotEqual(basename(getcwd()), dirname)
- with InsideDir(dirname):
- self.assertEqual(basename(getcwd()), dirname)
- self.assertNotEqual(basename(getcwd()), dirname)
-
- def test_to_be_built(self):
- tgt = 'test_get_files/tgt.txt'
- with open('test_get_files/src.txt', 'w') as fsrc:
- fsrc.write('src')
- with open(tgt, 'w') as ftgt:
- ftgt.write('tgt')
- self.assertTrue(to_be_built(tgt, ['test_get_files/src.txt']))
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from os import remove, makedirs
-from os.path import exists
-from shutil import rmtree, copy
-from unittest import TestCase
-from ya2.build.lang import LanguageBuilder
-
-
-class LangTests(TestCase):
-
- def setUp(self):
- for dirname in ['locale', 'po']:
- rmtree('./tests/' + dirname, ignore_errors=True)
- makedirs('./tests/' + dirname, exist_ok=True)
- copy('assets/locale/po/it_IT.po', './tests/po/')
-
- def tearDown(self):
- for dirname in ['locale', 'po']:
- rmtree('./tests/' + dirname, ignore_errors=True)
-
- def test_lang(self):
- LanguageBuilder.pot('test_pmachines', './tests/po/')
- self.assertTrue(exists('./tests/po/test_pmachines.pot'))
- LanguageBuilder.merge('it_IT', './tests/po/', './tests/locale/', 'test_pmachines')
- LanguageBuilder.mo('./tests/locale/it_IT/LC_MESSAGES/test_pmachines.mo',
- './tests/locale/', 'test_pmachines')
- self.assertTrue(exists('./tests/locale/it_IT/LC_MESSAGES/test_pmachines.mo'))
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from os import remove, makedirs, environ
-from os.path import exists
-from shutil import rmtree, copy
-from unittest import TestCase
-from itertools import product
-from time import time
-from ya2.build.models import ModelsBuilder
-
-
-class ModelsBuilderTests(TestCase):
-
- def setUp(self):
- self.dirs = ['box', 'domino']
- for fmt_dir in product(['bam', 'gltf'], self.dirs):
- rmtree('assets/models/%s/%s' % fmt_dir, ignore_errors=True)
-
- def test_models(self):
- if environ.get('FAST') == '1':
- self.skipTest('skipped slow tests')
- for fmt_dir in product(['bam', 'gltf'], self.dirs):
- self.assertFalse(exists('assets/%s/%s' % fmt_dir))
- start = time()
- ModelsBuilder().build('assets/models', 1)
- self.assertTrue(time() - start > 1.5)
- files = [
- 'assets/models/bam/box/box.bam',
- 'assets/models/bam/box/base.dds',
- 'assets/models/bam/box/ao_metal_roughness.dds',
- 'assets/models/bam/box/normal.dds',
- 'assets/models/bam/domino/domino.bam',
- 'assets/models/bam/domino/base.dds',
- 'assets/models/bam/domino/ao_roughness_metal.dds',
- 'assets/models/bam/domino/normal.dds',
- 'assets/models/gltf/box/box.gltf',
- 'assets/models/gltf/box/base.png',
- 'assets/models/gltf/box/ao_metal_roughness.png',
- 'assets/models/gltf/box/normal.png',
- 'assets/models/gltf/domino/domino.gltf',
- 'assets/models/gltf/domino/base.png',
- 'assets/models/gltf/domino/ao_roughness_metal.png',
- 'assets/models/gltf/domino/normal.png']
- [self.assertTrue(exists(fname)) for fname in files]
- #start = time()
- #ModelsBuilder().build('assets/models', 1)
- #self.assertTrue(time() - start < 1.5) # test caching
- #[self.assertTrue(exists(fname)) for fname in files]
+++ /dev/null
-'''lib.build.mtprocesser's unit tests.'''
-from pathlib import Path
-import sys
-sys.path = [path for path in sys.path if path != '']
-
-# we're in yocto/tests/lib/build/
-sys.path.append(str(Path(__file__).parent.parent.parent.parent))
-from pathlib import Path
-from os.path import exists
-from unittest import TestCase
-from ya2.build.mtprocesser import ProcesserMgr
-
-
-class ProcesserMgrTests(TestCase):
- '''ProcesserMgr's unit tests '''
-
- def setUp(self):
- '''unit tests' set up'''
- for idx in [1, 2]:
- Path('./tests/%s.txt' % idx).unlink(missing_ok=True)
-
- def tearDown(self):
- '''unit tests' tear down'''
- self.setUp()
-
- def test_threaded(self):
- '''test of the threaded case'''
- pmgr = ProcesserMgr(2)
- pmgr.add('echo 1 > ./tests/1.txt')
- pmgr.add('echo 2 > ./tests/2.txt')
- pmgr.run()
- self.assertTrue(exists('./tests/1.txt'))
- self.assertTrue(exists('./tests/2.txt'))
-
- def test_nothreaded(self):
- '''test when we don't use threads'''
- pmgr = ProcesserMgr(1)
- pmgr.add('echo 1 > ./tests/1.txt')
- pmgr.run()
- self.assertTrue(exists('./tests/1.txt'))
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from panda3d.core import loadPrcFileData
-from ya2.engine.engine import Engine
-from ya2.engine.audio import EngineAudio
-
-
-class EngineAudioTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- # loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
- EngineAudio(self.eng, .4)
-
- def tearDown(self): self.eng.destroy()
-
- def test_init(self): self.assertIsInstance(self.eng.audio, EngineAudio)
-
- def test_volume(self):
- self.assertAlmostEqual(self.eng.lib.volume, .4)
- self.eng.audio.set_volume(.2)
- self.assertAlmostEqual(self.eng.lib.volume, .2)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import MagicMock
-from panda3d.core import loadPrcFileData
-from ya2.engine.engine import Engine
-
-
-class EngineCBMuxTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self):
- self.eng.destroy()
-
- def _callback(self, arg): pass
-
- def test_cbmux(self):
- self._callback = MagicMock(side_effect=self._callback)
- self.eng.cb_mux.add_cb(self._callback, [42])
- taskMgr.step()
- self._callback.assert_called_with(42)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import MagicMock
-from panda3d.core import loadPrcFileData
-from ya2.engine.engine import Engine
-from ya2.engine.audio import EngineAudio
-
-
-class EngineClockTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self):
- self.eng.destroy()
-
- def test_clock(self):
- # this test shows that even if you process frames, the engine's clock
- # is storing the unpaused time
- start_time = self.eng.clock.time
- self.eng.pause.logic.pause()
- taskMgr.step()
- self.eng.pause.logic.resume()
- self.assertEqual(start_time, self.eng.clock.time)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import MagicMock
-from panda3d.core import loadPrcFileData, ConfigVariableInt, ConfigVariableString
-from ya2.engine.engine import Engine
-from ya2.engine.configuration import Cfg
-
-
-class EngineConfigurationTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self):
- self.eng.destroy()
-
- def test_cfg(self):
- # let's check some fields
- self.assertEqual(self.eng.cfg.gui_cfg.fps, False)
- self.assertEqual(self.eng.cfg.profiling_cfg.profiling, False)
- self.assertEqual(self.eng.cfg.lang_cfg.lang, 'en')
- self.assertEqual(self.eng.cfg.cursor_cfg.cursor_hidden, False)
- self.assertEqual(self.eng.cfg.dev_cfg.multithreaded_render, False)
-
- def test_cfg_configure(self):
- # let's check that __configure has been executed
- self.assertEqual(ConfigVariableInt('texture-anosotropic-degree').getValue(), 2)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest.mock import create_autospec
-from unittest import TestCase
-from panda3d.core import loadPrcFileData, NodePath, ConfigVariableBool
-from ya2.engine.engine import Engine
-from ya2.engine.configuration import Cfg, CursorCfg
-
-
-class ConfigurationTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
-
- def tearDown(self):
- self.engine.destroy()
-
- def test_init(self):
- self.engine = Engine(Cfg(cursor_cfg=CursorCfg(cursor_hidden=True)))
- self.assertTrue(ConfigVariableBool('cursor-hidden'))
- self.assertFalse(ConfigVariableBool('fullscreen'))
-
-
-class EngineTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
-
- def tearDown(self):
- self.engine.destroy()
-
- def test_init(self):
- self.engine = Engine()
- self.engine.camera = create_autospec(NodePath)
- self.assertIsInstance(self.engine, Engine)
-
-
-# class Accepter(DirectObject):
-#
-# def __init__(self):
-# self = evt_dec(self)
-#
-# def evt_MouseClick(self, arg):
-# self.button = arg.button, 0
-#
-# def evt_MouseClickUp(self, arg):
-# self.button = arg.button, 1
-#
-#
-# class EventsTests(TestCase):
-#
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# self.engine = Engine()
-# self.engine.mouseWatcherNode = create_autospec(MouseWatcher)
-# self.engine.camLens = create_autospec(Lens)
-# self.engine.camera = create_autospec(NodePath)
-# self.engine.cam = NodePath()
-#
-# def tearDown(self):
-# self.engine.destroy()
-#
-# def test_init(self):
-# self.assertIsInstance(self.engine, Engine)
-# mouse_move = MouseMove(0, 0)
-# self.assertIsInstance(mouse_move, MouseMove)
-# mouse_enter = MouseEnter(0, 0)
-# self.assertIsInstance(mouse_enter, MouseEnter)
-# mouse_exit = MouseExit(0, 0, 0)
-# self.assertIsInstance(mouse_exit, MouseExit)
-# mouse_click = MouseClick(0, 0, 0)
-# self.assertIsInstance(mouse_click, MouseClick)
-# mouse_clickup = MouseClickUp(0, 0, 0)
-# self.assertIsInstance(mouse_clickup, MouseClickUp)
-# mouse_mgr = MouseMgr(self.engine)
-# self.assertIsInstance(mouse_mgr, MouseMgr)
-# self.assertEqual(mouse_mgr.pt_from_to, (0, 0))
-# self.assertEqual(mouse_mgr.pt_from, (0, 0, 0))
-# self.assertEqual(mouse_mgr.pt_to, (0, 0, 0))
-# acc = Accepter()
-# self.engine.messenger.send('mouse1')
-# self.assertEqual(acc.button, (0, 0))
-# self.engine.messenger.send('mouse1-up')
-# self.assertEqual(acc.button, (0, 1))
-# self.engine.messenger.send('mouse3')
-# self.assertEqual(acc.button, (1, 0))
-# self.engine.messenger.send('mouse3-up')
-# self.assertEqual(acc.button, (1, 1))
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import patch, create_autospec
-from panda3d.core import loadPrcFileData, GraphicsWindow
-from ya2.engine.engine import Engine
-from ya2.engine.event import EngineEvent
-
-
-class EngineEventTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
- EngineEvent(self.eng, True)
-
- def tearDown(self): self.eng.destroy()
-
- def test_init(self): self.assertIsInstance(self.eng.event, EngineEvent)
-
- def test_key2desc(self):
- with patch('builtins.base') as patched_base:
- # we need to patch it to run without base.win
- self.assertEqual(str(self.eng.event.key2desc('x')), 'x')
- base.win.get_keyboard_map().get_mapped_button_label = create_autospec(GraphicsWindow)
- base.win.get_keyboard_map().get_mapped_button_label.return_value = 'x'
- self.assertEqual(self.eng.event.key2desc('raw-x'), 'x')
-
- def test_desc2key(self):
- with patch('builtins.base') as patched_base:
- self.assertEqual(self.eng.event.desc2key('x'), 'x')
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from panda3d.core import loadPrcFileData, DynamicTextFont
-from ya2.engine.engine import Engine
-
-
-class EngineFontTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self): self.eng.destroy()
-
- def test_font(self):
- font = self.eng.font_mgr.load_font('../assets/fonts/Hanken-Book.ttf')
- print(font)
- self.assertIsInstance(font, DynamicTextFont)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from panda3d.core import loadPrcFileData
-from ya2.engine.engine import Engine
-from ya2.lib.p3d.gfx import P3dNode
-
-
-class EngineGfxTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self): self.eng.destroy()
-
- def test_init_clean(self):
- self.eng.gfx.init()
- self.assertIsInstance(self.eng.gfx.root, P3dNode)
- self.eng.gfx.clean()
- self.assertTrue(self.eng.gfx.root.is_empty)
-
- def test_frame_rate(self):
- self.eng.gfx.set_frame_rate(60)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from panda3d.core import loadPrcFileData
-from ya2.engine.engine import Engine
-from ya2.engine.joystick import JoystickMgr, JoystickState
-from ya2.engine.gui.menu import NavInfoPerPlayer
-
-
-class EngineJoystickTests(TestCase):
-
- def setUp(self):
- loadPrcFileData('', 'window-type none')
- loadPrcFileData('', 'audio-library-name null')
- self.eng = Engine()
-
- def tearDown(self): self.eng.destroy()
-
- def test_init(self):
- self.assertIsInstance(self.eng.joystick_mgr, JoystickMgr)
-
- def test_get_joystick(self):
- j_state = self.eng.joystick_mgr.get_joystick(0)
- self.assertIsInstance(j_state, JoystickState)
- self.assertEqual(j_state.x, 0)
- self.assertEqual(j_state.y, 0)
- self.assertEqual(j_state.b0, 0)
- self.assertEqual(j_state.b1, 0)
- self.assertEqual(j_state.b2, 0)
- self.assertEqual(j_state.b3, 0)
- self.assertEqual(j_state.dpad_l, 0)
- self.assertEqual(j_state.dpad_r, 0)
- self.assertEqual(j_state.dpad_u, 0)
- self.assertEqual(j_state.dpad_d, 0)
- self.assertEqual(j_state.trigger_l, 0)
- self.assertEqual(j_state.trigger_r, 0)
- self.assertEqual(j_state.shoulder_l, 0)
- self.assertEqual(j_state.shoulder_r, 0)
- self.assertEqual(j_state.stick_l, 0)
- self.assertEqual(j_state.stick_r, 0)
-
- def test_get_joystick_val(self):
- jmgr = self.eng.joystick_mgr
- self.assertEqual(jmgr.get_joystick_val(0, 'face_x'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'face_y'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'face_a'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'face_b'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'dpad_l'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'dpad_r'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'dpad_u'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'dpad_d'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'trigger_l'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'trigger_r'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'shoulder_l'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'shoulder_r'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'stick_l'), 0)
- self.assertEqual(jmgr.get_joystick_val(0, 'stick_r'), 0)
-
- def test_bind_keyboard(self):
- nav_info = [NavInfoPerPlayer(
- 'raw-arrow_left', 'raw-arrow_right', 'raw-arrow_up',
- 'raw-arrow_down', 'raw-rcontrol')]
- self.eng.joystick_mgr.bind_keyboard(nav_info)
- self.assertEqual(self.eng.joystick_mgr.nav[0].fire, 'raw-rcontrol')
- self.eng.joystick_mgr.unbind_keyboard(0)
- self.assertIsNone(self.eng.joystick_mgr.nav[0], None)
+++ /dev/null
-# from pathlib import Path
-# import sys
-# if '' in sys.path: sys.path.remove('')
-# sys.path.append(str(Path(__file__).parent.parent.parent))
-# from unittest import TestCase
-# from panda3d.core import loadPrcFileData
-# from ya2.gameobject import GameObject
-# from ya2.engine.engine import Engine
-# from ya2.computer_proxy import ComputerProxy, compute_once, once_a_frame
-
-
-# class ExampleProxy(GameObject, ComputerProxy):
-
-# def __init__(self):
-# GameObject.__init__(self)
-# ComputerProxy.__init__(self)
-# self.reset()
-
-# def reset(self): self.cnt = 0
-
-# @compute_once
-# def inc_cnt(self): self.cnt += 1
-
-# @once_a_frame
-# def inc_cnt_frame(self): self.cnt += 1
-
-
-# class ComputerProxyTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-# self.engine = Engine()
-# self.example_proxy = ExampleProxy()
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.assertIsInstance(self.example_proxy, ExampleProxy)
-
-# def test_compute_once(self):
-# self.example_proxy.reset()
-# self.example_proxy.inc_cnt()
-# self.example_proxy.inc_cnt()
-# self.assertEqual(self.example_proxy.cnt, 1)
-
-# def test_compute_once_a_frame(self):
-# self.example_proxy.reset()
-# self.example_proxy.on_start_frame()
-# self.example_proxy.inc_cnt_frame()
-# self.example_proxy.inc_cnt_frame()
-# self.assertEqual(self.example_proxy.cnt, 1)
-# self.example_proxy.on_start_frame()
-# self.example_proxy.inc_cnt_frame()
-# self.example_proxy.inc_cnt_frame()
-# self.assertEqual(self.example_proxy.cnt, 2)
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from os import remove
-from os.path import exists
-from unittest import TestCase
-from ya2.dictfile import DctFile
-
-
-class DictFileTests(TestCase):
-
- def setUp(self):
- if exists('./tests/test.ini'): remove('./tests/test.ini')
- self.dctfile = DctFile(
- './tests/test.ini',
- {'test': {'a': 0, 'b': 1, 'c': 2}})
- self.dctfile.store()
-
- def tearDown(self):
- remove('./tests/test.ini')
-
- def test_init(self):
- self.assertIsNotNone(self.dctfile)
-
- def test_deepupdate(self):
- self.dctfile['a'] = {'b': {'c': 4}}
- self.assertEqual(self.dctfile['a']['b']['c'], 4)
- self.dctfile['a'] = \
- DctFile.deepupdate(self.dctfile['a'], {'b': {'c': 5}})
- self.assertEqual(self.dctfile['a']['b']['c'], 5)
-
- def test_store(self):
- self.assertEqual(self.dctfile['test']['c'], 2)
- other = DctFile('./tests/test.ini')
- self.dctfile['test']['c'] = 3
- self.assertEqual(self.dctfile['test']['c'], 3)
- self.assertEqual(other['test']['c'], 2)
- self.dctfile.store()
- other = DctFile('./tests/test.ini')
- self.assertEqual(other['test']['c'], 3)
-
- def test_operations(self):
- self.assertEqual(self.dctfile['test']['c'], 2)
- self.dctfile['d'] = 3
- self.assertEqual(self.dctfile['d'], 3)
- self.assertIn('d', self.dctfile.dct)
- del self.dctfile['d']
- self.assertNotIn('d', self.dctfile.dct)
+++ /dev/null
-# from pathlib import Path
-# import sys
-# if '' in sys.path: sys.path.remove('')
-# sys.path.append(str(Path(__file__).parent.parent.parent))
-# from unittest import TestCase
-# from panda3d.core import loadPrcFileData
-# from ya2.engine.engine import Engine
-# from ya2.engine.configuration import Cfg
-# from ya2.game import GameLogic, Game
-# from ya2.gameobject import GameObject, FsmColleague, AudioColleague, \
-# EventColleague, LogicColleague
-
-
-# class LogicTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.eng.destroy()
-
-# def test_init(self):
-# self.eng = Engine()
-# game_obj = GameObject()
-# logic = GameLogic(game_obj)
-# self.assertIsInstance(logic, GameLogic)
-
-
-# class GameInstance(Game):
-
-# def __init__(self):
-# conf = Cfg()
-# Game.__init__(self, conf)
-# self.fsm = FsmColleague(self)
-# self.logic = LogicColleague(self)
-# self.audio = AudioColleague(self)
-# self.event = EventColleague(self)
-
-# def destroy(self):
-# self.fsm.destroy()
-# self.logic.destroy()
-# self.audio.destroy()
-# self.event.destroy()
-
-
-# class GameTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def test_init(self):
-# self.game = GameInstance()
-# self.assertIsInstance(self.game, Game)
-# self.game.destroy()
-
-# def tearDown(self):
-# self.game.eng.destroy()
+++ /dev/null
-# from pathlib import Path
-# import sys
-# if '' in sys.path: sys.path.remove('')
-# sys.path.append(str(Path(__file__).parent.parent.parent))
-# from unittest.mock import patch
-# from unittest import TestCase
-# from panda3d.core import loadPrcFileData
-# from ya2.engine.engine import Engine
-# from ya2.gameobject import AiColleague, AudioColleague, EventColleague, \
-# FsmColleague, GameObject, GfxColleague, GuiColleague, LogicColleague, \
-# PhysColleague, Colleague
-
-
-# class AiTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# ai = AiColleague(game_obj)
-# self.assertIsInstance(ai, AiColleague)
-
-
-# class AudioTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# audio = AudioColleague(game_obj)
-# self.assertIsInstance(audio, AudioColleague)
-
-
-# class ColleagueTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# colleague = Colleague(game_obj)
-# self.assertIsInstance(colleague, Colleague)
-
-
-# class EventTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# event = EventColleague(game_obj)
-# self.assertIsInstance(event, EventColleague)
-
-
-# class FsmTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# fsm = FsmColleague(game_obj)
-# self.assertIsInstance(fsm, FsmColleague)
-
-
-# class GfxTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# gfx = GfxColleague(game_obj)
-# self.assertIsInstance(gfx, GfxColleague)
-
-
-# class GuiTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# gui = GuiColleague(game_obj)
-# self.assertIsInstance(gui, GuiColleague)
-
-
-# class LogicTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# logic = LogicColleague(game_obj)
-# self.assertIsInstance(logic, LogicColleague)
-
-
-# class PhysicsTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# def test_init(self):
-# self.engine = Engine()
-# game_obj = GameObject()
-# phys = PhysColleague(game_obj)
-# self.assertIsInstance(phys, PhysColleague)
-
-
-# class GameObjectInstance(GameObject):
-
-# def __init__(self):
-# GameObject.__init__(self)
-# self.fsm = FsmColleague(self)
-# self.event = EventColleague(self)
-# self.ai = AiColleague(self)
-# self.phys = PhysColleague(self)
-# self.audio = AudioColleague(self)
-# self.logic = LogicColleague(self)
-# self.gui = GuiColleague(self)
-# self.gfx = GfxColleague(self)
-
-# def destroy(self):
-# self.fsm.destroy()
-# self.event.destroy()
-# self.ai.destroy()
-# self.phys.destroy()
-# self.audio.destroy()
-# self.logic.destroy()
-# self.gui.destroy()
-# self.gfx.destroy()
-
-
-# class GameObjectTests(TestCase):
-
-# def setUp(self):
-# loadPrcFileData('', 'window-type none')
-# loadPrcFileData('', 'audio-library-name null')
-
-# def tearDown(self):
-# self.engine.destroy()
-
-# @patch.object(GfxColleague, 'destroy')
-# @patch.object(GuiColleague, 'destroy')
-# @patch.object(LogicColleague, 'destroy')
-# @patch.object(AudioColleague, 'destroy')
-# @patch.object(PhysColleague, 'destroy')
-# @patch.object(AiColleague, 'destroy')
-# @patch.object(EventColleague, 'destroy')
-# @patch.object(FsmColleague, 'destroy')
-# def test_init(
-# self, mock_fsm_destroy, mock_event_destroy, mock_ai_destroy,
-# mock_phys_destroy, mock_audio_destroy, mock_logic_destroy,
-# mock_gui_destroy, mock_gfx_destroy):
-# self.engine = Engine()
-# mock_event_destroy.__name__ = 'destroy'
-# game_obj = GameObjectInstance()
-# self.assertIsInstance(game_obj, GameObject)
-# game_obj.destroy()
-# assert mock_fsm_destroy.called
-# assert mock_event_destroy.called
-# assert mock_ai_destroy.called
-# assert mock_phys_destroy.called
-# assert mock_audio_destroy.called
-# assert mock_logic_destroy.called
-# assert mock_gui_destroy.called
-# assert mock_gfx_destroy.called
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import MagicMock
-from ya2.observer import Subject
-
-
-class Observed(Subject): pass
-
-
-class Observer:
-
- def __init__(self, observed): self.__observed = observed
-
- def callback(self): pass
-
-
-class ObserverTests(TestCase):
-
- def test_all(self):
- observed = Observed()
- observer = Observer(observed)
- observer.callback = MagicMock(side_effect=observer.callback)
- observer.callback.__name__ = 'callback'
- self.assertFalse(observed.observing(observer.callback))
- observed.attach(observer.callback)
- self.assertTrue(observed.observing(observer.callback))
- observer.callback.assert_not_called()
- observed.notify('callback')
- observer.callback.assert_called()
- observed.detach(observer.callback)
- self.assertFalse(observed.observing(observer.callback))
--- /dev/null
+'''Unit tests for lib.build.'''
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent.parent))
+from os import getcwd, makedirs, walk
+from os.path import basename
+from shutil import rmtree
+from unittest import TestCase
+from re import compile
+from ya2.build.build import InsideDir, files, exec_cmd, _branch, _version, \
+ to_be_built
+
+
+class BuildTests(TestCase):
+
+ def setUp(self):
+ makedirs('test_get_files/a')
+ makedirs('test_get_files/b')
+ makedirs('test_get_files/c')
+ with open('test_get_files/a/c.ext1', 'w') as ftest:
+ ftest.write('0123456789')
+ with open('test_get_files/a/d.ext2', 'w'): pass
+ with open('test_get_files/b/e.ext2', 'w') as ftest:
+ ftest.write('0123456789')
+ with open('test_get_files/b/f.ext3', 'w'): pass
+ with open('test_get_files/c/g.ext2', 'w'): pass
+
+ def tearDown(self):
+ rmtree('test_get_files')
+
+ def test_exec_cmd(self):
+ self.assertEqual(exec_cmd('echo abc'), 'abc')
+
+ def test_branch(self):
+ self.assertIn(_branch(), ['master', 'rc', 'stable'])
+
+ def test_version(self):
+ patterns = [
+ "^0a[0-9]+$",
+ "^0rc[0-9]+$",
+ "^0\.[0-9]+$"]
+ compiled = [compile(pattern) for pattern in patterns]
+ matches = [pattern.match(_version()) for pattern in compiled]
+ self.assertTrue(any(matches))
+
+ def test_get_files(self):
+ _files = files(['ext2'], 'c')
+ self.assertSetEqual(set(_files),
+ set(['./test_get_files/a/d.ext2',
+ './test_get_files/b/e.ext2']))
+
+ def test_inside_dir(self):
+ dirs = [basename(x[0]) for x in walk('.')]
+ dirs = [dir_ for dir_ in dirs if dir_ not in ['.', '..']]
+ dirname = dirs[0]
+ self.assertNotEqual(basename(getcwd()), dirname)
+ with InsideDir(dirname):
+ self.assertEqual(basename(getcwd()), dirname)
+ self.assertNotEqual(basename(getcwd()), dirname)
+
+ def test_to_be_built(self):
+ tgt = 'test_get_files/tgt.txt'
+ with open('test_get_files/src.txt', 'w') as fsrc:
+ fsrc.write('src')
+ with open(tgt, 'w') as ftgt:
+ ftgt.write('tgt')
+ self.assertTrue(to_be_built(tgt, ['test_get_files/src.txt']))
--- /dev/null
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from os import remove, makedirs
+from os.path import exists
+from shutil import rmtree, copy
+from unittest import TestCase
+from ya2.build.lang import LanguageBuilder
+
+
+class LangTests(TestCase):
+
+ def setUp(self):
+ for dirname in ['locale', 'po']:
+ rmtree('./tests/' + dirname, ignore_errors=True)
+ makedirs('./tests/' + dirname, exist_ok=True)
+ copy('assets/locale/po/it_IT.po', './tests/po/')
+
+ def tearDown(self):
+ for dirname in ['locale', 'po']:
+ rmtree('./tests/' + dirname, ignore_errors=True)
+
+ def test_lang(self):
+ LanguageBuilder.pot('test_pmachines', './tests/po/')
+ self.assertTrue(exists('./tests/po/test_pmachines.pot'))
+ LanguageBuilder.merge('it_IT', './tests/po/', './tests/locale/', 'test_pmachines')
+ LanguageBuilder.mo('./tests/locale/it_IT/LC_MESSAGES/test_pmachines.mo',
+ './tests/locale/', 'test_pmachines')
+ self.assertTrue(exists('./tests/locale/it_IT/LC_MESSAGES/test_pmachines.mo'))
--- /dev/null
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from os import remove, makedirs, environ
+from os.path import exists
+from shutil import rmtree, copy
+from unittest import TestCase
+from itertools import product
+from time import time
+from ya2.build.models import ModelsBuilder
+
+
+class ModelsBuilderTests(TestCase):
+
+ def setUp(self):
+ self.dirs = ['box', 'domino']
+ for fmt_dir in product(['bam', 'gltf'], self.dirs):
+ rmtree('assets/models/%s/%s' % fmt_dir, ignore_errors=True)
+
+ def test_models(self):
+ if environ.get('FAST') == '1':
+ self.skipTest('skipped slow tests')
+ for fmt_dir in product(['bam', 'gltf'], self.dirs):
+ self.assertFalse(exists('assets/%s/%s' % fmt_dir))
+ start = time()
+ ModelsBuilder().build('assets/models', 1)
+ self.assertTrue(time() - start > 1.5)
+ files = [
+ 'assets/models/bam/box/box.bam',
+ 'assets/models/bam/box/base.dds',
+ 'assets/models/bam/box/ao_metal_roughness.dds',
+ 'assets/models/bam/box/normal.dds',
+ 'assets/models/bam/domino/domino.bam',
+ 'assets/models/bam/domino/base.dds',
+ 'assets/models/bam/domino/ao_roughness_metal.dds',
+ 'assets/models/bam/domino/normal.dds',
+ 'assets/models/gltf/box/box.gltf',
+ 'assets/models/gltf/box/base.png',
+ 'assets/models/gltf/box/ao_metal_roughness.png',
+ 'assets/models/gltf/box/normal.png',
+ 'assets/models/gltf/domino/domino.gltf',
+ 'assets/models/gltf/domino/base.png',
+ 'assets/models/gltf/domino/ao_roughness_metal.png',
+ 'assets/models/gltf/domino/normal.png']
+ [self.assertTrue(exists(fname)) for fname in files]
+ #start = time()
+ #ModelsBuilder().build('assets/models', 1)
+ #self.assertTrue(time() - start < 1.5) # test caching
+ #[self.assertTrue(exists(fname)) for fname in files]
--- /dev/null
+'''lib.build.mtprocesser's unit tests.'''
+from pathlib import Path
+import sys
+sys.path = [path for path in sys.path if path != '']
+
+# we're in yocto/tests/lib/build/
+sys.path.append(str(Path(__file__).parent.parent.parent.parent))
+from pathlib import Path
+from os.path import exists
+from unittest import TestCase
+from ya2.build.mtprocesser import ProcesserMgr
+
+
+class ProcesserMgrTests(TestCase):
+ '''ProcesserMgr's unit tests '''
+
+ def setUp(self):
+ '''unit tests' set up'''
+ for idx in [1, 2]:
+ Path('./tests/%s.txt' % idx).unlink(missing_ok=True)
+
+ def tearDown(self):
+ '''unit tests' tear down'''
+ self.setUp()
+
+ def test_threaded(self):
+ '''test of the threaded case'''
+ pmgr = ProcesserMgr(2)
+ pmgr.add('echo 1 > ./tests/1.txt')
+ pmgr.add('echo 2 > ./tests/2.txt')
+ pmgr.run()
+ self.assertTrue(exists('./tests/1.txt'))
+ self.assertTrue(exists('./tests/2.txt'))
+
+ def test_nothreaded(self):
+ '''test when we don't use threads'''
+ pmgr = ProcesserMgr(1)
+ pmgr.add('echo 1 > ./tests/1.txt')
+ pmgr.run()
+ self.assertTrue(exists('./tests/1.txt'))
--- /dev/null
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from os import remove
+from os.path import exists
+from unittest import TestCase
+from ya2.utils.dictfile import DctFile
+
+
+class DictFileTests(TestCase):
+
+ def setUp(self):
+ if exists('./tests/test.ini'): remove('./tests/test.ini')
+ self.dctfile = DctFile(
+ './tests/test.ini',
+ {'test': {'a': 0, 'b': 1, 'c': 2}})
+ self.dctfile.store()
+
+ def tearDown(self):
+ remove('./tests/test.ini')
+
+ def test_init(self):
+ self.assertIsNotNone(self.dctfile)
+
+ def test_deepupdate(self):
+ self.dctfile['a'] = {'b': {'c': 4}}
+ self.assertEqual(self.dctfile['a']['b']['c'], 4)
+ self.dctfile['a'] = \
+ DctFile.deepupdate(self.dctfile['a'], {'b': {'c': 5}})
+ self.assertEqual(self.dctfile['a']['b']['c'], 5)
+
+ def test_store(self):
+ self.assertEqual(self.dctfile['test']['c'], 2)
+ other = DctFile('./tests/test.ini')
+ self.dctfile['test']['c'] = 3
+ self.assertEqual(self.dctfile['test']['c'], 3)
+ self.assertEqual(other['test']['c'], 2)
+ self.dctfile.store()
+ other = DctFile('./tests/test.ini')
+ self.assertEqual(other['test']['c'], 3)
+
+ def test_operations(self):
+ self.assertEqual(self.dctfile['test']['c'], 2)
+ self.dctfile['d'] = 3
+ self.assertEqual(self.dctfile['d'], 3)
+ self.assertIn('d', self.dctfile.dct)
+ del self.dctfile['d']
+ self.assertNotIn('d', self.dctfile.dct)
--- /dev/null
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from unittest.mock import patch
+from unittest import TestCase
+from panda3d.core import loadPrcFileData
+#from ya2.engine.engine import Engine
+from ya2.patterns.gameobject import AiColleague, AudioColleague, EventColleague, \
+ FsmColleague, GameObject, GfxColleague, GuiColleague, LogicColleague, \
+ PhysColleague, Colleague
+
+
+class AiTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ ai = AiColleague(game_obj)
+ self.assertIsInstance(ai, AiColleague)
+
+
+class AudioTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ audio = AudioColleague(game_obj)
+ self.assertIsInstance(audio, AudioColleague)
+
+
+class ColleagueTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ colleague = Colleague(game_obj)
+ self.assertIsInstance(colleague, Colleague)
+
+
+class EventTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ event = EventColleague(game_obj)
+ self.assertIsInstance(event, EventColleague)
+
+
+class FsmTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ fsm = FsmColleague(game_obj)
+ self.assertIsInstance(fsm, FsmColleague)
+
+
+class GfxTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ #self.engine = Engine()
+ game_obj = GameObject()
+ gfx = GfxColleague(game_obj)
+ self.assertIsInstance(gfx, GfxColleague)
+
+
+class GuiTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ pass
+ #self.engine = Engine()
+ game_obj = GameObject()
+ gui = GuiColleague(game_obj)
+ self.assertIsInstance(gui, GuiColleague)
+
+
+class LogicTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ pass
+ #self.engine = Engine()
+ game_obj = GameObject()
+ logic = LogicColleague(game_obj)
+ self.assertIsInstance(logic, LogicColleague)
+
+
+class PhysicsTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ def test_init(self):
+ pass
+ #self.engine = Engine()
+ game_obj = GameObject()
+ phys = PhysColleague(game_obj)
+ self.assertIsInstance(phys, PhysColleague)
+
+
+class GameObjectInstance(GameObject):
+
+ def __init__(self):
+ GameObject.__init__(self)
+ self.fsm = FsmColleague(self)
+ self.event = EventColleague(self)
+ self.ai = AiColleague(self)
+ self.phys = PhysColleague(self)
+ self.audio = AudioColleague(self)
+ self.logic = LogicColleague(self)
+ self.gui = GuiColleague(self)
+ self.gfx = GfxColleague(self)
+
+ def destroy(self):
+ self.fsm.destroy()
+ self.event.destroy()
+ self.ai.destroy()
+ self.phys.destroy()
+ self.audio.destroy()
+ self.logic.destroy()
+ self.gui.destroy()
+ self.gfx.destroy()
+
+
+class GameObjectTests(TestCase):
+
+ def setUp(self):
+ loadPrcFileData('', 'window-type none')
+ loadPrcFileData('', 'audio-library-name null')
+
+ def tearDown(self):
+ pass
+ #self.engine.destroy()
+
+ @patch.object(GfxColleague, 'destroy')
+ @patch.object(GuiColleague, 'destroy')
+ @patch.object(LogicColleague, 'destroy')
+ @patch.object(AudioColleague, 'destroy')
+ @patch.object(PhysColleague, 'destroy')
+ @patch.object(AiColleague, 'destroy')
+ @patch.object(EventColleague, 'destroy')
+ @patch.object(FsmColleague, 'destroy')
+ def test_init(
+ self, mock_fsm_destroy, mock_event_destroy, mock_ai_destroy,
+ mock_phys_destroy, mock_audio_destroy, mock_logic_destroy,
+ mock_gui_destroy, mock_gfx_destroy):
+ #self.engine = Engine()
+ mock_event_destroy.__name__ = 'destroy'
+ game_obj = GameObjectInstance()
+ self.assertIsInstance(game_obj, GameObject)
+ game_obj.destroy()
+ assert mock_fsm_destroy.called
+ assert mock_event_destroy.called
+ assert mock_ai_destroy.called
+ assert mock_phys_destroy.called
+ assert mock_audio_destroy.called
+ assert mock_logic_destroy.called
+ assert mock_gui_destroy.called
+ assert mock_gfx_destroy.called
--- /dev/null
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from unittest import TestCase
+from unittest.mock import MagicMock
+from ya2.patterns.observer import Subject
+
+
+class Observed(Subject): pass
+
+
+class Observer:
+
+ def __init__(self, observed): self.__observed = observed
+
+ def callback(self): pass
+
+
+class ObserverTests(TestCase):
+
+ def test_all(self):
+ observed = Observed()
+ observer = Observer(observed)
+ observer.callback = MagicMock(side_effect=observer.callback)
+ observer.callback.__name__ = 'callback'
+ self.assertFalse(observed.observing(observer.callback))
+ observed.attach(observer.callback)
+ self.assertTrue(observed.observing(observer.callback))
+ observer.callback.assert_not_called()
+ observed.notify('callback')
+ observer.callback.assert_called()
+ observed.detach(observer.callback)
+ self.assertFalse(observed.observing(observer.callback))
from importlib import import_module
from inspect import isclass
from multiprocessing import Pool
-from game.scene import Scene
+from logics.scene import Scene
def do_screenshot(cls):
+++ /dev/null
-from functools import wraps
-
-
-def compute_once(fun):
- @wraps(fun)
- def wrapper(*args, **kwargs):
- self = args[0]
- key = fun.__name__, args # add support for kwargs
- if key not in self.buffered_vals:
- self.buffered_vals[key] = fun(*args, **kwargs)
- return self.buffered_vals[key]
- return wrapper
-
-
-def once_a_frame(fun):
- @wraps(fun)
- def wrapper(*args, **kwargs):
- self = args[0]
- key = fun.__name__, args # add support for kwargs
- if key not in self.buffered_vals_frm:
- self.buffered_vals_frm[key] = fun(*args, **kwargs)
- return self.buffered_vals_frm[key]
- return wrapper
-
-
-class ComputerProxy:
-
- def __init__(self):
- self.eng.attach_obs(self.on_start_frame)
- # there are issues if the object has another on_start_frame
- self.buffered_vals, self.buffered_vals_frm = {}, {}
-
- def on_start_frame(self):
- self.buffered_vals_frm = {}
-
- def destroy(self):
- self.eng.detach_obs(self.on_start_frame)
- self.buffered_vals = self.buffered_vals_frm = None
+++ /dev/null
-# class Decorator:\r
-\r
-# def __init__(self, decorated):\r
-# self.__dict__['_decorated'] = decorated\r
-\r
-# def __getattr__(self, attr): return getattr(self._decorated, attr)\r
-\r
-# def __setattr__(self, attr, value):\r
-# return setattr(self._decorated, attr, value)\r
+++ /dev/null
-import sys
-from logging import info
-from os import makedirs
-from os.path import dirname
-from collections.abc import Mapping
-from configparser import ConfigParser
-from json import load, dumps
-from ya2.gameobject import GameObject
-from ya2.lib.p3d.p3d import LibP3d
-
-
-class DctFile(GameObject):
-
- def __init__(self, fpath, default_dct=None, persistent=True):
- GameObject.__init__(self)
- default_dct = default_dct or {}
- if sys.platform == 'darwin' and LibP3d.runtime():
- fpath = dirname(__file__) + '/' + fpath
- self.fpath = fpath
- self.persistent = persistent
- try:
- #with open(fpath) as json: fdct = load(json)
- config = ConfigParser()
- config.read(fpath)
- fdct = {section: dict(config.items(section)) for section in config.sections()}
- fdct = self.__typed_dct(fdct)
- self.dct = self.__add_default(default_dct, fdct)
- except IOError: self.dct = default_dct
-
- @staticmethod
- def __typed_dct(dct):
- def convert_single_val(val):
- try: return int(val)
- except ValueError:
- try: return float(val)
- except ValueError:
- if not val or val[0] != '[':
- return val
- else:
- raise ValueError
- def converted(val):
- try: return convert_single_val(val)
- except ValueError:
- return [elm.strip() for elm in val[1:-1].split(',')]
- new_dct = {}
- for section, sec_dct in dct.items():
- for key, val in sec_dct.items():
- if section not in new_dct:
- new_dct[section] = {}
- new_dct[section][key] = converted(val)
- return new_dct
-
- @staticmethod
- def __add_default(dct, upd):
- for key, val in upd.items():
- if isinstance(val, Mapping):
- dct[key] = DctFile.__add_default(dct.get(key, {}), val)
- else: dct[key] = upd[key]
- return dct
-
- @staticmethod
- def deepupdate(dct, new_dct):
- for key, val in new_dct.items():
- if isinstance(val, Mapping):
- dct[key] = DctFile.deepupdate(dct.get(key, {}), val)
- else: dct[key] = val
- return dct
-
- def store(self):
- info('storing %s' % self.fpath)
- if not self.persistent: return
- #json_str = dumps(self.dct, sort_keys=True, indent=4,
- # separators=(',', ': '))
- #with open(self.fpath, 'w') as json: json.write(json_str)
- fdct = {}
- for section, sec_dct in self.dct.items():
- if section not in fdct:
- fdct[section] = {}
- for key, val in sec_dct.items():
- if type(val) == list:
- fdct[section][key] = '[%s]' % ', '.join(val)
- else:
- fdct[section][key] = val
- config = ConfigParser()
- for key in self.dct:
- config[key] = fdct[key]
- if dirname(self.fpath):
- makedirs(dirname(self.fpath), exist_ok=True)
- with open(self.fpath, 'w') as ini_file:
- config.write(ini_file)
-
- def __getitem__(self, arg): return self.dct[arg]
-
- def __setitem__(self, arg, val): self.dct[arg] = val
-
- def __delitem__(self, arg): del self.dct[arg]
+++ /dev/null
-import datetime
-from os import getcwd, system
-from logging import debug, info
-from pathlib import Path
-from shutil import rmtree
-from os import makedirs
-from os.path import join, exists
-from glob import glob
-from sys import exit
-from multiprocessing.connection import Listener
-from threading import Thread
-from panda3d.core import Filename
-from direct.gui.OnscreenText import OnscreenText
-from ya2.gameobject import GameObject
-from ya2.build.build import _branch
-
-
-class ListenerThread(Thread):
-
- def __init__(self, callbacks):
- Thread.__init__(self)
- address = ('localhost', 6000)
- self._listener = Listener(address)
- self._listener._listener._socket.settimeout(15)
- try:
- self._conn = self._listener.accept()
- except TimeoutError:
- info('listener timeout')
- self._callbacks = callbacks
-
- def run(self):
- running = hasattr(self, '_conn')
- while running:
- try:
- msg = self._conn.recv()
- if msg[0] == 'screenshot':
- taskMgr.doMethodLater(.01, self._callbacks[0], 'cb0', [msg[1]])
- elif msg[0] == 'enforce_res':
- taskMgr.doMethodLater(.01, self._callbacks[1], 'cb1', [msg[1]])
- elif msg[0] == 'verify':
- taskMgr.doMethodLater(.01, self._callbacks[2], 'cb2')
- elif msg[0] == 'set_idx':
- taskMgr.doMethodLater(.01, self._callbacks[3], 'cb3', [msg[1]])
- elif msg[0] == 'enforce_resolution':
- taskMgr.doMethodLater(.01, self._callbacks[4], 'cb4', [msg[1]])
- except EOFError:
- running = False
-
-
-class FunctionalTest(GameObject):
-
- def __init__(self, ref):
- super().__init__()
- self._listener = ListenerThread([self._do_screenshot, self._do_enforce_res, self.__verify, self._set_idx, self._do_enforce_resolution])
- self._listener.start()
- self.txt = OnscreenText('', fg=(1, 0, 0, 1), scale=.16)
- #self._path = ''
- #if self.eng.is_appimage:
- self._path = str(Filename().get_user_appdata_directory())
- self._path += '/pmachines/'
- self._path += 'tests/functional%s/' % ('_ref' if ref else '')
- home = '/home/flavio' # we must force this for wine
- # if self._path.startswith('/c/users/') and exists(str(Path.home()) + '/.local/share/flatpak-wine601/default/'):
- # self._path = str(Path.home()) + '/.local/share/flatpak-wine601/default/drive_' + self._path[1:]
- if self._path.startswith('/c/users/') and exists(home + '/.wine/'):
- self._path = home + '/.wine/drive_' + self._path[1:]
- if ref:
- self._path = join(
- Filename().get_user_appdata_directory(),
- 'pmachines/tests/functional_ref_%s/' % _branch())
- self._fnames = []
- #taskMgr.add(self.on_frame_unpausable, 'on-frame-unpausable')
- #self._do_screenshots(idx)
-
- def _set_idx(self, idx):
- if int(idx) == 1:
- rmtree(self._path, ignore_errors=True)
- info('creating dir: %s' % self._path)
- makedirs(self._path, exist_ok=True)
-
- def _do_screenshot(self, name):
- self._fnames += [self._path + name]
- #time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
- #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
- #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
- res = base.screenshot(self._path + name, False)
- info('screenshot %s (%s; %s)' % (self._path + name, res, getcwd()))
-
- def _do_enforce_res(self, res):
- info('enforce_res %s' % res)
- messenger.send('enforce_res', [res])
-
- def _do_enforce_resolution(self, res):
- info('enforce resolution %s (callback)' % res)
- messenger.send('enforce_resolution', [res])
-
- #def _screenshot(self, time, name):
- #self._fnames += [self._path + name + '.png']
- #self._tasks += [(
- # self._curr_time + time,
- # lambda: self._do_screenshot(self._path + name + '.png'),
- # 'screenshot: %s' % name)]
- #def txt(show_hide):
- # self.txt['text'] = name
- # (self.txt.show if show_hide else self.txt.hide)()
- #self._tasks += [(
- # self._curr_time + time + .1,
- # lambda: txt(True),
- # 'screenshot: %s (show)' % name)]
- #self._tasks += [(
- # self._curr_time + time + FunctionalTest.evt_time - .1,
- # lambda: txt(False),
- # 'screenshot: %s (hide)' % name)]
- #self._curr_time += time
-
- #def __keypress(self, key):
- #'''Emulates a keypress'''
- #dev = base.win.getInputDevice(0)
- #dev.buttonDown(key)
- #dev.buttonUp(key)
-
- #def __char_entered(self, char):
- #'''Emulates a character being entered.'''
- #dev = base.win.getInputDevice(0)
- #dev.keystroke(ord(char))
-
- # def _event(self, time, evt, messenger_evt=False, append_up=True, mouse_args=None):
- # def _append_up(evt_name):
- # return evt + ('' if evt.endswith('-up') or not append_up else '-up')
- # def cback_char(_evt):
- # self.__char_entered(_evt)
- # def cback_keyp(_evt):
- # self.__keypress(_evt)
- # self.__keypress('raw-' + _evt)
- # cback = lambda: (cback_char(evt) if len(evt) == 1 else cback_keyp(evt))
- # if evt in ['mousemove', 'mouseclick', 'mousedrag']:
- # if evt == 'mousemove':
- # cback = lambda: self.__mouse_move(*mouse_args)
- # elif evt == 'mouseclick':
- # cback = lambda: self.__mouse_click(*mouse_args)
- # elif evt == 'mousedrag':
- # cback = lambda: self.__mouse_drag(*mouse_args)
- # if messenger_evt:
- # cback = lambda: messenger.send(_append_up(evt))
- # self._tasks += [(
- # self._curr_time + time,
- # cback,
- # 'event: %s' % evt)]
- # def txt(show_hide):
- # self.txt['text'] = evt
- # (self.txt.show if show_hide else self.txt.hide)()
- # self._tasks += [(
- # self._curr_time + time + .2,
- # lambda: txt(True),
- # 'event: %s (show)' % evt)]
- # self._tasks += [(
- # self._curr_time + time + .8,
- # lambda: txt(False),
- # 'event: %s (hide)' % evt)]
- # self._curr_time += time
-
- # def _enforce_res(self, time, res):
- # cback = lambda: messenger.send('enforce_res', [res])
- # self._tasks += [(
- # self._curr_time + time,
- # cback,
- # 'enforce res: %s' % res)]
- # self._curr_time += time
-
- def __verify(self, task):
- files = glob(self._path + '*')
- for fname in self._fnames:
- info('verifying %s' % fname)
- assert exists(fname)
-
- #def on_frame_unpausable(self, task):
- #self._process_conn()
- #for tsk in self._tasks:
- # #if self._prev_time <= tsk[0] < self.eng.event.unpaused_time:
- # if self._prev_time <= tsk[0] < globalClock.getFrameTime():
- # debug('%s %s' % (tsk[0], tsk[2]))
- # tsk[1]()
- #self._prev_time = globalClock.getFrameTime() # self.eng.event.unpaused_time
- #return task.cont
-
- # def _do_screenshots_1(self):
- # info('_do_screenshots_1')
- # self._screenshot(FunctionalTest.start_time, 'main_menu')
- # self._do_screenshots_credits()
- # self._do_screenshots_options()
- # self._do_screenshots_exit()
-
- # def _do_screenshots_credits(self):
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'credits_menu')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'main_menu_back_from_credits')
- # # # go to credits
- # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._screenshot(FunctionalTest.screenshot_time, 'main_menu_highlight')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'credits_menu')
- # # # go to supporters
- # # self._event(FunctionalTest.evt_time, 'joypad0-face_a', True)
- # # self._screenshot(FunctionalTest.screenshot_time, 'supporters_menu')
- # # # back to main
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'joypad0-face_b', True)
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
-
- # def _do_screenshots_options(self):
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 300), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu')
- # # languages
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 60), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'open_languages')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(980, 120), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_italian')
- # # volume
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(740, 163), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_1')
- # # antialiasing
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 440), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_no')
- # # shadows
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 540), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'shadows_no')
- # # test aa and shadows
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(900, 490), 'left']) # close instructions
- # self._screenshot(FunctionalTest.screenshot_time, 'aa_no_shadows_no')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(25, 740), 'left']) # home
-
- # def _do_screenshots_restore_options(self):
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 300), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_restored')
- # # languages
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 60), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'open_languages_restored')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(980, 20), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_english')
- # # volume
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(719, 163), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_2')
- # # fullscreen
- # # the first one is because of the windowed mode in test
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
- # # self._event(8 + FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
- # # self._screenshot(8 + FunctionalTest.screenshot_time, 'back_from_fullscreen')
- # # resolution
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 340), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, 'resolutions')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1020, 160), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, '1440x900')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(740, 400), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, 'resolutions_2')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1110, 80), 'left'])
- # # self._screenshot(FunctionalTest.screenshot_time, '1360x768')
- # # antialiasing
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 440), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_yes')
- # # shadows
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 540), 'left'])
- # self._screenshot(FunctionalTest.screenshot_time, 'shadows_yes')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
-
- # # # go to options
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'options_menu')
- # # # language
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'language_open')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._screenshot(FunctionalTest.screenshot_time, 'language_highlight')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'language_it')
- # # # volume
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_right')
- # # self._event(FunctionalTest.evt_time, 'arrow_right')
- # # self._screenshot(FunctionalTest.screenshot_time, 'volume')
- # # # car's number
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'cars_open')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'cars_changed')
- # # # back
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
-
- # def _do_screenshots_play(self):
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
- # self._screenshot(FunctionalTest.screenshot_time, 'play_menu')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
- # self._screenshot(FunctionalTest.screenshot_time, 'back_from_play')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino scene
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_instructions')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(25, 740), 'left']) # home
- # self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_scene')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(70, 740), 'left']) # info
- # self._screenshot(FunctionalTest.screenshot_time, 'info')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (430, 280), 'left']) # drag a piece
- # self._screenshot(FunctionalTest.screenshot_time, 'domino_dragged')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1220, 740), 'left']) # rewind
- # self._screenshot(FunctionalTest.screenshot_time, 'rewind')
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (550, 380), 'left']) # drag a piece
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(630, 450), 'left']) # home
- # self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_fail')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (550, 380), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_2')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (570, 380), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(570, 355), (605, 355), 'right']) # rotate the piece
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
- # self._enforce_res(FunctionalTest.evt_time, 'win')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino')
- # self._enforce_res(FunctionalTest.evt_time, '')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_box')
- # # scene 2
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(880, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 620), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 540), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 620), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 540), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (705, 460), 'left']) # drag a box
- # self._enforce_res(FunctionalTest.evt_time, 'win')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box')
- # self._enforce_res(FunctionalTest.evt_time, '')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_box_domino')
- # # scene 3
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(930, 485), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 440), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 360), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box_domino')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 440), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (835, 250), 'left']) # drag a box
- # self._enforce_res(FunctionalTest.evt_time, 'win')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box_domino')
- # self._enforce_res(FunctionalTest.evt_time, '')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_basketball')
- # # scene 4
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(870, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(55, 50), (650, 310), 'left']) # drag a ball
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_basketball')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(55, 50), (380, 50), 'left']) # drag a ball
- # self._enforce_res(FunctionalTest.evt_time, 'win')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_basketball')
- # self._enforce_res(FunctionalTest.evt_time, '')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
- # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_box_basketball')
- # # scene 5
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(865, 490), 'left']) # close instructions
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (580, 440), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(30, 60), (590, 370), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_box_basketball')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (580, 440), 'left']) # drag a box
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(30, 60), (660, 440), 'left']) # drag a piece
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(660, 425), (625, 425), 'right']) # rotate a piece
- # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(660, 435), (650, 445), 'left']) # drag a piece
- # self._enforce_res(FunctionalTest.evt_time, 'win')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
- # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino_box_basketball')
- # self._enforce_res(FunctionalTest.evt_time, '')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
- # # self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_tooter')
- # # # scene 6
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(820, 455), 'left']) # close instructions
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (490, 300), 'left']) # drag a box
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
- # # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_tooter')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(640, 420), 'left']) # replay
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (490, 150), 'left']) # drag a box
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(515, 115), (515, 122), 'right']) # rotate a box
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
- # # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_tooter')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(690, 420), 'left']) # next
- # # self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_domino_box_basketball')
- # # # scene 7
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(880, 455), 'left']) # close instructions
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (155, 180), 'left']) # drag a box
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
- # # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_domino_box_basketball')
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(640, 420), 'left']) # replay
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (170, 80), 'left']) # drag a box
- # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(195, 50), (195, 80), 'right']) # rotate a box
- # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
- # # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_domino_box_basketball')
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(630, 450), 'left']) # home
- # self._screenshot(FunctionalTest.screenshot_time, 'home_from_play')
-
- # def _do_screenshots_exit(self):
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # self._verify()
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._exit()
- # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 600), 'left'])
-
-
- # def _do_screenshots_2(self):
- # info('_do_screenshots_2')
- # self._screenshot(FunctionalTest.start_time, 'main_menu_2')
- # self._do_screenshots_restore_options()
- # self._do_screenshots_play()
- # self._do_screenshots_exit()
- # # self._do_screenshots_game()
- # # self._do_screenshots_end()
-
- # # def _do_screenshots_restore_options(self):
- # # # go to options
- # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_restored')
- # # # # language
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'language_en_restored')
- # # # # volume
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_left')
- # # self._event(FunctionalTest.evt_time, 'arrow_left')
- # # self._screenshot(FunctionalTest.screenshot_time, 'volume_restored')
- # # # car's number
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'cars_restored')
- # # # graphics settings
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'graphics_settings')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'shadows')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'fog')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'normal_mapping')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'occlusion')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # # input
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'input')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_rec')
- # # self._event(FunctionalTest.evt_time, '8', True, False)
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_changed')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up', True, False)
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_restored')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'w', True, False)
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_already')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_already_closed')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p2')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p3')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p4')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
-
- # # def _do_screenshots_game(self):
- # # # single player
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'single_player_menu')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'track_page')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'car_page_start')
- # # self._event(FunctionalTest.evt_time, 'arrow_left')
- # # self._screenshot(FunctionalTest.screenshot_time, 'car_page_sel')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_start')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_left')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_left')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(FunctionalTest.evt_time, 'arrow_up')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._event(FunctionalTest.evt_time, 'backspace')
- # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry_empty')
- # # self._event(FunctionalTest.evt_time, 'f')
- # # self._event(FunctionalTest.evt_time, 'l')
- # # self._event(FunctionalTest.evt_time, 'a')
- # # self._event(FunctionalTest.evt_time, 'v')
- # # self._event(FunctionalTest.evt_time, 'i')
- # # self._event(FunctionalTest.evt_time, 'o')
- # # self._event(FunctionalTest.evt_time, 'enter')
- # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry_full')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_right')
- # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_sel')
- # # # some ai tests
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._event(40, 'escape-up')
- # # self._screenshot(FunctionalTest.screenshot_time, 'ingame_menu')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'race_back')
- # # self._event(FunctionalTest.evt_time, 'escape-up')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._screenshot(FunctionalTest.screenshot_time, 'ingame_sel')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'main_page_back_race')
-
- # # def _do_screenshots_end(self):
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._screenshot(FunctionalTest.screenshot_time, 'exit_page')
- # # self._event(FunctionalTest.evt_time, 'arrow_down')
- # # self._screenshot(FunctionalTest.screenshot_time, 'exit_page_sel')
- # # self._verify()
- # # self._event(FunctionalTest.evt_time, 'rcontrol')
- # # self._exit()
-
- # def _do_screenshots(self, idx):
- # [self._do_screenshots_1, self._do_screenshots_2][int(idx) - 1]()
+++ /dev/null
-from panda3d.core import GraphicsWindow, WindowProperties
-from ya2.lib.p3d.gui import P3dImg as Img
-from ya2.gameobject import GameObject
-
-
-class MouseCursorFacade:
-
- def show(self):
- if not self.eng.cfg.dev_cfg.functional_test:
- return self.cursor_img.show()
- def hide(self): return self.cursor_img.hide()
-
-
-class MouseCursor(GameObject, MouseCursorFacade):
-
- def __init__(self, filepath, scale, color, hotspot):
- GameObject.__init__(self)
- MouseCursorFacade.__init__(self)
- if not filepath: return
- self.__set_std_cursor(False)
- self.cursor_img = Img(filepath, scale=scale, foreground=True)
- self.cursor_img.img.set_color(color)
- #if self.eng.cfg.dev_cfg.functional_test:
- # self.cursor_img.hide()
- self.hotspot_dx = scale[0] * (1 - 2 * hotspot[0])
- self.hotspot_dy = scale[2] * (1 - 2 * hotspot[1])
- #self.eng.attach_obs(self.on_frame)
- #self.eng.attach_obs(self.on_frame_unpausable)
- self._tsk = taskMgr.add(self.__on_frame, 'on frame cursor')
-
- @staticmethod
- def __set_std_cursor(show):
- props = WindowProperties()
- props.set_cursor_hidden(not show)
- if isinstance(base.win, GraphicsWindow):
- base.win.requestProperties(props)
-
- #def show_standard(self): self.eng.lib.show_std_cursor()
-
- #def hide_standard(self): self.eng.lib.hide_std_cursor()
-
- #def cursor_top(self):
- # self.cursor_img.reparent_to(self.cursor_img.parent)
-
- def __on_frame(self, task):
- mwn = base.mouseWatcherNode
- if not mwn or not mwn.hasMouse():
- return task.again
- mouse = mwn.get_mouse_x(), mwn.get_mouse_y()
- h_x = mouse[0] * base.getAspectRatio() + self.hotspot_dx
- self.cursor_img.set_pos((h_x, mouse[1] - self.hotspot_dy))
- return task.again
-
- #def on_frame(self):
- # if not self.eng.pause.paused: self.__on_frame()
-
- #def on_frame_unpausable(self):
- # if self.eng.pause.paused: self.__on_frame()
-
- def set_image(self, img):
- self.cursor_img.img.set_texture(loader.load_texture(img), 1)
-
- def destroy(self):
- taskMgr.remove(self._tsk)
- self.cursor_img.destroy()
+++ /dev/null
-from logging import info
-from os.path import join, exists, dirname
-from gettext import translation
-from pathlib import Path
-from ya2.gameobject import GameObject
-import sys
-
-
-def is_runtime(): return not exists('main.py')
-
-
-def is_appimage():
- par_path = str(Path(__file__).parent.absolute())
- is_appimage = par_path.startswith('/tmp/.mount_Pmachines')
- return is_appimage and par_path.endswith('/usr/bin')
-
-
-def curr_path():
- if not is_runtime(): return ''
- if sys.platform == 'darwin':
- return dirname(__file__) + '/../Resources/'
- # return dirname(__file__)
- par_path = str(Path(__file__).parent.absolute())
- if is_appimage():
- return str(Path(par_path).absolute())
- is_snap = par_path.startswith('/snap/')
- is_snap = is_snap and par_path.endswith('/x1')
- if is_snap:
- return str(Path(par_path).absolute())
- #return getcwd()
- curr_path = dirname(__file__)
- info('current path: %s' % curr_path)
- return curr_path + '/'
-
-
-class LangMgr(GameObject):
-
- def __init__(self, lang, domain, dpath):
- GameObject.__init__(self)
- self.lang = lang
- self.domain = domain
- self.dpath = join(curr_path(), dpath)
- info('language: %s, %s' % (self.domain, self.dpath))
- self.set_lang(lang)
-
- @property
- def lang_codes(self):
- return [lang[1] for lang in self.eng.cfg.lang_cfg.languages]
-
- def set_lang(self, lang):
- self.lang = lang
- args = lang, self.domain, self.dpath
- info('setting language %s, %s, %s' % args)
- tra = translation(self.domain, self.dpath, [lang], fallback=True)
- tra.install()
+++ /dev/null
-from logging import basicConfig, info, INFO, DEBUG, getLogger
-from configparser import ConfigParser
-from sys import platform, argv
-from platform import system
-from pathlib import Path
-from glob import glob
-from json import load, dumps
-#from datetime import datetime
-from pprint import pprint
-from os import getcwd, environ
-from os.path import exists, dirname
-from traceback import print_stack
-from sys import version_info
-# from platform import system, release, architecture, platform, processor, \
-# version, machine
-# from multiprocessing import cpu_count
-from panda3d.core import Filename, GraphicsWindow, PandaSystem
-from panda3d.bullet import get_bullet_version
-from ya2.gameobject import Colleague
-from ya2.lib.p3d.p3d import LibP3d
-import sys
-
-
-lev = INFO
-opt_path = ''
-if platform in ['win32', 'linux'] and not exists('main.py'):
- # it is the deployed version for windows
- opt_path = str(Filename.get_user_appdata_directory()) + '/pmachines'
-opath = LibP3d.fixpath(opt_path + '/options.ini') if opt_path else \
- 'options.ini'
-if exists(opath):
- with open(opath) as json_file:
- #optfile = load(json_file)
- optfile = ConfigParser()
- optfile.read(opath)
- # optfile['development']['verbose'] and int(optfile['development']['verbose']) or \
- if optfile['development']['verbose_log'] and int(optfile['development']['verbose_log']):
- lev = DEBUG
-
-basicConfig(level=lev, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
-getLogger().setLevel(lev) # it doesn't work otherwise
-
-
-class LogMgrBase(Colleague): # headless log manager
-
- @staticmethod
- def init_cls():
- return LogMgr if base.win else LogMgrBase
-
- def __init__(self, mediator):
- Colleague.__init__(self, mediator)
- self.log_cfg()
-
- def log(self, msg, verbose=False):
- if verbose and not self.eng.cfg.dev_cfg.verbose_log: return
- info(msg)
-
- @property
- def is_appimage(self):
- par_path = str(Path(__file__).parent.absolute())
- is_appimage = par_path.startswith('/tmp/.mount_Pmachi')
- return is_appimage and par_path.endswith('/usr/bin')
-
- # @property
- # def curr_path(self):
- # # this is different from the music's one since it does not work
- # # with the version in windows
- # if sys.platform == 'darwin':
- # return dirname(__file__) + '/../Resources/'
- # # return dirname(__file__)
- # par_path = str(Path(__file__).parent.absolute())
- # if self.is_appimage:
- # return str(Path(par_path).absolute())
- # is_snap = par_path.startswith('/snap/')
- # is_snap = is_snap and par_path.endswith('/x1')
- # if is_snap:
- # return str(Path(par_path).absolute())
- # #return getcwd()
- # #curr_path = dirname(__file__)
- # curr_path = str(Path(__file__).parent.parent.parent.absolute())
- # info('current path: %s' % curr_path)
- # return curr_path
-
- @property
- def curr_path(self):
- if system() == 'Windows':
- return ''
- if exists('main.py'):
- return ''
- else:
- par_path = str(Path(__file__).parent.absolute())
- if self.is_appimage:
- par_path = str(Path(par_path).absolute())
- par_path += '/'
- return par_path
-
- @property
- def build_version(self):
- appimg_mnt = glob('/tmp/.mount_Pmachi*')
- if appimg_mnt:
- #with open(appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
- with open(self.curr_path + 'assets/bld_version.txt') as fver:
- return fver.read().strip()
- try:
- with open(self.curr_path + 'assets/bld_version.txt') as fver:
- return fver.read().strip()
- except FileNotFoundError:
- info('not found ' + self.curr_path + 'assets/bld_version.txt')
- return 'notfound'
-
- def log_cfg(self):
- if '--version' in argv:
- path = str(Filename.get_user_appdata_directory())
- home = '/home/flavio' # we must force this for wine
- if path.startswith('/c/users/') and exists(home + '/.wine/'):
- path = home + '/.wine/drive_' + path[1:]
- info('writing %s' % path + '/pmachines/obs_version.txt')
- with open(path + '/pmachines/obs_version.txt', 'w') as f:
- #f.write(self.eng.logic.version)
- f.write(self.build_version)
- if not platform.startswith('win'):
- from os import ttyname # here because it doesn't work on windows
- import sys
- try:
- with open(ttyname(0), 'w') as fout:
- sys.stdout = fout
- print('version: ' + self.build_version) # self.eng.logic.version)
- except OSError: # it doesn't work with crontab
- print('version: ' + self.build_version)
- messages = ['version: ' + self.build_version] # self.eng.logic.version]
- messages += ['argv[0]: %s' % argv[0]]
- messages += ['getcwd: %s' % getcwd()]
- messages += ['__file__: %s' % __file__]
- for elm in environ.items():
- messages += ['env::%s: %s' % elm]
- # os_info = (system(), release(), version())
- # messages += ['operative system: %s %s %s' % os_info]
- # messages += ['architecture: ' + str(architecture())]
- # messages += ['machine: ' + machine()]
- # messages += ['platform: ' + platform()]
- # messages += ['processor: ' + processor()]
- # try:
- # messages += ['cores: ' + str(cpu_count())]
- # except NotImplementedError: # on Windows
- # messages += ['cores: not implemented']
- lib_ver = PandaSystem.get_version_string()
- try:
- import psutil
- mem = psutil.virtual_memory().total / 1000000000.0
- messages += ['memory: %s GB' % round(mem, 2)]
- except ImportError: info("can't import psutil") # windows
- lib_commit = PandaSystem.get_git_commit()
- py_ver = [str(elm) for elm in version_info[:3]]
- messages += ['python version: %s' % '.'.join(py_ver)]
- messages += ['panda version: %s %s' % (lib_ver, lib_commit)]
- messages += ['bullet version: ' + str(get_bullet_version())]
- messages += ['appdata: ' + str(Filename.get_user_appdata_directory())]
- if base.win and isinstance(base.win, GraphicsWindow): # not headless
- print(base.win.get_keyboard_map())
- list(map(self.log, messages))
-
- @staticmethod
- def log_tasks():
- info('tasks: %s' % taskMgr.getAllTasks())
- info('do-laters: %s' % taskMgr.getDoLaters())
-
- @staticmethod
- def plog(obj):
- print('\n\n')
- print_stack()
- pprint(obj)
- print('\n\n')
-
-
-class LogMgr(LogMgrBase):
-
- def log_cfg(self):
- LogMgrBase.log_cfg(self)
- messages = [base.win.get_gsg().get_driver_vendor()]
- messages += [base.win.get_gsg().get_driver_renderer()]
- shad_maj = base.win.get_gsg().get_driver_shader_version_major()
- shad_min = base.win.get_gsg().get_driver_shader_version_minor()
- messages += ['shader: {maj}.{min}'.format(maj=shad_maj, min=shad_min)]
- messages += [base.win.get_gsg().get_driver_version()]
- drv_maj = base.win.get_gsg().get_driver_version_major()
- drv_min = base.win.get_gsg().get_driver_version_minor()
- drv = 'driver version: {maj}.{min}'
- messages += [drv.format(maj=drv_maj, min=drv_min)]
- fullscreen = None
- if isinstance(base.win, GraphicsWindow):
- fullscreen = base.win.get_properties().get_fullscreen()
- messages += ['fullscreen: ' + str(fullscreen)]
- def resolution():
- if not isinstance(base.win, GraphicsWindow):
- return 800, 600
- win_prop = base.win.get_properties()
- return win_prop.get_x_size(), win_prop.get_y_size()
- res_x, res_y = resolution()
- res_tmpl = 'resolution: {res_x}x{res_y}'
- messages += [res_tmpl.format(res_x=res_x, res_y=res_y)]
- list(map(self.log, messages))
+++ /dev/null
-from direct.fsm.FSM import FSM
-from direct.showbase.DirectObject import DirectObject
-from ya2.observer import Subject
-
-
-class Colleague(Subject):
-
- eng = None
-
- def __init__(self, mediator):
- Subject.__init__(self)
- self.mediator = mediator # refactor: remove it
-
- def destroy(self):
- self.mediator = None
- Subject.destroy(self)
-
-
-class FsmColleague(FSM, Colleague):
-
- def __init__(self, mediator):
- FSM.__init__(self, self.__class__.__name__)
- Colleague.__init__(self, mediator)
-
- def destroy(self):
- if self.state: self.cleanup()
- Colleague.destroy(self)
-
-
-class EventColleague(Colleague, DirectObject):
-
- def destroy(self):
- self.ignoreAll()
- Colleague.destroy(self)
-
-
-class AudioColleague(Colleague): pass
-
-
-class AiColleague(Colleague): pass
-
-
-class GfxColleague(Colleague): pass
-
-
-class GuiColleague(Colleague): pass
-
-
-class LogicColleague(Colleague):
-
- def on_start(self): pass
-
-
-class PhysColleague(Colleague): pass
-
-
-class GODirector:
-
- def __init__(self, tgt_obj, init_lst, end_cb):
- self.__obj = tgt_obj
- tgt_obj.attach(self.on_comp_blt)
- self.end_cb = end_cb
- self.completed = [False for _ in init_lst]
- self.pending = {}
- self.__init_lst = init_lst
- for idx, _ in enumerate(init_lst): self.__process_lst(tgt_obj, idx)
-
- def __process_lst(self, obj, idx):
- if not self.__init_lst[idx]:
- self.end_lst(idx)
- return
- comp_info = self.__init_lst[idx].pop(0)
- attr_name, cls, arguments = comp_info
- self.pending[cls.__name__] = idx
- setattr(obj, attr_name, cls(*arguments))
-
- def on_comp_blt(self, obj):
- self.__process_lst(obj.mediator, self.pending[obj.__class__.__name__])
-
- def end_lst(self, idx):
- self.completed[idx] = True
- if all(self.completed):
- if self.end_cb: self.end_cb()
- self.destroy()
-
- def destroy(self):
- self.__obj.detach(self.on_comp_blt)
- self.__obj = self.end_cb = self.__init_lst = None
-
-
-class GameObject(Subject): pass
+++ /dev/null
-import datetime
-from logging import debug, info
-from os import getcwd
-from os.path import exists, dirname
-from panda3d.core import get_model_path, AntialiasAttrib, PandaNode, \
- LightRampAttrib, Camera, OrthographicLens, NodePath, OmniBoundingVolume, \
- AmbientLight as P3DAmbientLight, Spotlight as P3DSpotlight, Point2, \
- Point3, Texture
-from direct.filter.CommonFilters import CommonFilters
-from direct.actor.Actor import Actor
-# from ya2.lib.p3d.p3d import LibP3d
-
-
-def set_srgb(model):
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
-
-
-# class RenderToTexture:
-
-# def __init__(self, size=(256, 256)):
-# self.__set_buffer(size)
-# self.__set_display_region()
-# self.__set_camera()
-# self.__set_root()
-# self.display_region.set_camera(self.camera)
-
-# def __set_buffer(self, size):
-# self.buffer = base.win.make_texture_buffer('result buffer', size[0],
-# size[1])
-# self.buffer.set_sort(-100)
-
-# def __set_display_region(self):
-# self.display_region = self.buffer.make_display_region()
-# self.display_region.set_sort(20)
-
-# def __set_camera(self):
-# self.camera = NodePath(Camera('camera 2d'))
-# lens = OrthographicLens()
-# lens.set_film_size(1, 1)
-# lens.set_near_far(-1000, 1000)
-# self.camera.node().set_lens(lens)
-
-# def __set_root(self):
-# self.root = NodePath('root')
-# self.root.set_depth_test(False)
-# self.root.set_depth_write(False)
-# self.camera.reparent_to(self.root)
-
-# @property
-# def texture(self): return self.buffer.get_texture()
-
-# def destroy(self):
-# base.graphicsEngine.remove_window(self.buffer)
-# if base.win: # if you close the window during a race
-# base.win.remove_display_region(self.display_region)
-# list(map(lambda node: node.remove_node(), [self.camera, self.root]))
-
-
-class P3dGfxMgr:
-
- def __init__(self, model_path, antialiasing, shaders, srgb):
- self.root = P3dNode(render)
- self.__srgb = srgb
- self.callbacks = {}
- self.filters = None
- get_model_path().append_directory(model_path)
- if LibP3d.runtime():
- root_dir = LibP3d.p3dpath(dirname(__file__))
- paths = [root_dir + '/' + model_path, root_dir]
- list(map(get_model_path().append_directory, paths))
- render.set_shader_auto()
- # render.set_two_sided(True) # it breaks shadows
- if antialiasing: render.set_antialias(AntialiasAttrib.MAuto)
- if shaders and base.win:
- self.filters = CommonFilters(base.win, base.cam)
-
- def load_model(self, filename, callback=None, anim=None):
- ext = '.bam' if exists(filename + '.bam') else ''
- if anim:
- anim_dct = {'anim': filename + '-Anim' + ext}
- node = P3dNode(self.set_srgb(Actor(filename + ext, anim_dct)))
- elif callback:
- callb = lambda model: callback(P3dNode(self.set_srgb(model)))
- node = loader.loadModel(filename + ext, callback=callb)
- else:
- node = P3dNode(self.set_srgb(
- loader.loadModel(LibP3d.p3dpath(filename + ext))))
- return node
-
- def set_srgb(self, model):
- if self.__srgb:
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
- return model
-
- @staticmethod
- def toggle_aa():
- aa_not_none = render.get_antialias() != AntialiasAttrib.MNone
- if render.has_antialias() and aa_not_none:
- render.clear_antialias()
- else: render.set_antialias(AntialiasAttrib.MAuto, 1)
-
- def set_toon(self):
- tmp_node = NodePath(PandaNode('temp node'))
- tmp_node.set_attrib(LightRampAttrib.make_single_threshold(.5, .4))
- tmp_node.set_shader_auto()
- base.cam.node().set_initial_state(tmp_node.get_state())
- self.filters.set_cartoon_ink(separation=1)
-
- def set_bloom(self):
- if not base.win: return
- self.filters.setBloom(
- blend=(.3, .4, .3, 0), mintrigger=.6, maxtrigger=1.0, desat=.6,
- intensity=1.0, size='medium')
- # default: (.3, .4, .3, 0), .6, 1, .6, 1, 'medium'
-
- @staticmethod
- def pos2d(node):
- p3d = base.cam.get_relative_point(node.node, Point3(0, 0, 0))
- p2d = Point2()
- return p2d if base.camLens.project(p3d, p2d) else None
-
- @staticmethod
- def screen_coord(pos):
- new_node = NodePath('temp')
- new_node.set_pos(pos)
- coord3d = new_node.get_pos(base.cam)
- new_node.remove_node()
- coord2d = Point2()
- base.camLens.project(coord3d, coord2d)
- coord_r2d = Point3(coord2d[0], 0, coord2d[1])
- coord_a2d = base.aspect2d.get_relative_point(render2d, coord_r2d)
- return coord_a2d[0], coord_a2d[2]
-
- @staticmethod
- def world_from_to(pos):
- p_from, p_to = Point3(), Point3() # in camera coordinates
- base.camLens.extrude(pos, p_from, p_to)
- p_from = render.get_relative_point(base.cam, p_from) # global coords
- p_to = render.get_relative_point(base.cam, p_to) # global coords
- return p_from, p_to
-
- @property
- def shader_support(self):
- return base.win.get_gsg().get_supports_basic_shaders()
-
- def screenshot(self, path=None):
- time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
- #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
- #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
- res = base.screenshot(path or ("pmachines%s.png" % time), False)
- info('screenshot %s (%s; %s)' % (path or ("pmachines%s.png" % time), res, getcwd()))
-
- @staticmethod
- def enable_shader(): render.set_shader_auto()
-
- @staticmethod
- def disable_shader(): render.set_shader_off()
-
- @staticmethod
- def print_stats(two_d=True, three_d=True, analyze=True, ls=True):
- '''Print graphics stats. They use standard output (from p3d).'''
- info = []
- if two_d and analyze:
- info +=[('render2d.analyze', base.render2d.analyze)]
- if three_d and analyze:
- info +=[('render.analyze', base.render.analyze)]
- if two_d and ls:
- info +=[('render2d.ls', base.render2d.ls)]
- if three_d and ls:
- info +=[('render.ls', base.render.ls)]
- for elm in info:
- print('\n\n#####\n%s()' % elm[0])
- elm[1]()
-
-
-# class P3dNode:
-
-# def __init__(self, nodepath):
-# self.nodepath = nodepath
-# self.node.set_python_tag('libnode', self)
-
-# def set_collide_mask(self, mask): return self.node.set_collide_mask(mask)
-# def set_x(self, val): return self.node.set_x(val)
-# def set_y(self, val): return self.node.set_y(val)
-# def set_z(self, val): return self.node.set_z(val)
-# def set_hpr(self, val): return self.node.set_hpr(val)
-# def set_h(self, val): return self.node.set_h(val)
-# def set_p(self, val): return self.node.set_p(val)
-# def set_r(self, val): return self.node.set_r(val)
-# def set_scale(self, val): return self.node.set_scale(val)
-# def set_transparency(self, val): return self.node.set_transparency(val)
-# def set_alpha_scale(self, val): return self.node.set_alpha_scale(val)
-# def set_texture(self, texturestage, texture):
-# return self.node.set_texture(texturestage, texture)
-# def has_tag(self, name): return self.node.has_tag(name)
-# def get_tag(self, name): return self.node.get_tag(name)
-# def get_python_tag(self, name): return self.node.get_python_tag(name)
-# def remove_node(self): return self.node.remove_node()
-# def flatten_strong(self): return self.node.flatten_strong()
-# def clear_model_nodes(self): return self.node.clear_model_nodes()
-# def show(self): return self.node.show()
-# def set_depth_offset(self, val): return self.node.set_depth_offset(val)
-# def loop(self, val): return self.node.loop(val)
-# def cleanup(self): return self.node.cleanup()
-# def write_bam_file(self, fname): return self.node.write_bam_file(fname)
-
-# def attach_node(self, name):
-# return P3dNode(self.node.attach_new_node(name))
-
-# def add_shape(self, shape):
-# return self.node.node().add_shape(shape._mesh_shape)
-# #TODO: don't access a protected member
-
-# @property
-# def name(self): return self.node.get_name()
-
-# @property
-# def node(self): return self.nodepath
-
-# @property
-# def p3dnode(self): return self.node.node()
-
-# def set_pos(self, pos): return self.node.set_pos(pos._vec)
-# #TODO: don't access a protected member
-
-# def get_pos(self, other=None):
-# return self.node.get_pos(* [] if other is None else [other.node])
-
-# @property
-# def x(self): return self.node.get_x()
-
-# @property
-# def y(self): return self.node.get_y()
-
-# @property
-# def z(self): return self.node.get_z()
-
-# @property
-# def hpr(self): return self.node.get_hpr()
-
-# @property
-# def h(self): return self.node.get_h()
-
-# @property
-# def p(self): return self.node.get_p()
-
-# @property
-# def r(self): return self.node.get_r()
-
-# @property
-# def scale(self): return self.node.get_scale()
-
-# @property
-# def is_empty(self): return self.node.is_empty()
-
-# def get_relative_vector(self, node, vec):
-# return self.node.get_relative_vector(node.node, vec)
-
-# def set_material(self, mat): return self.node.set_material(mat, 1)
-
-# def set_python_tag(self, name, val):
-# return self.node.set_python_tag(name, val)
-
-# def get_distance(self, other_node):
-# return self.node.get_distance(other_node.node)
-
-# def reparent_to(self, parent): return self.node.reparent_to(parent.node)
-
-# def wrt_reparent_to(self, parent):
-# return self.node.wrt_reparent_to(parent.node)
-
-# @staticmethod
-# def __get_pandanode(nodepath):
-# if nodepath.has_python_tag('libnode'):
-# return nodepath.get_python_tag('libnode')
-# return P3dNode(nodepath)
-
-# def find_all_matches(self, name):
-# nodes = self.node.find_all_matches(name)
-# return [self.__get_pandanode(node) for node in nodes]
-
-# def find(self, name):
-# model = self.node.find(name)
-# if model: return self.__get_pandanode(model)
-
-# def optimize(self):
-# self.node.prepare_scene(base.win.get_gsg()) # crash with texture.set_format
-# self.node.premunge_scene(base.win.get_gsg())
-
-# def hide(self, mask=None):
-# return self.node.hide(*[] if mask is None else [mask])
-
-# @property
-# def tight_bounds(self): return self.node.get_tight_bounds()
-
-# @property
-# def parent(self): return self.node.get_parent()
-
-# @property
-# def children(self): return self.node.get_children()
-
-# def destroy(self): return self.node.remove_node()
-
-
-# class P3dAnimNode:
-
-# def __init__(self, filepath, anim_dct):
-# self.node = Actor(filepath, anim_dct)
-
-# def loop(self, val): return self.node.loop(val)
-
-# def reparent_to(self, node): self.node.reparent_to(node)
-
-# @property
-# def name(self): return self.node.get_name()
-
-# def optimize(self):
-# self.node.prepare_scene(base.win.get_gsg())
-# self.node.premunge_scene(base.win.get_gsg())
-
-# def set_omni(self):
-# self.node.node().set_bounds(OmniBoundingVolume())
-# self.node.node().set_final(True)
-
-# def destroy(self): self.node.cleanup()
-
-
-# class P3dAmbientLight:
-
-# def __init__(self, color):
-# ambient_lgt = P3DAmbientLight('ambient light')
-# ambient_lgt.set_color(color)
-# self.ambient_np = render.attach_new_node(ambient_lgt)
-# render.set_light(self.ambient_np)
-
-# def destroy(self):
-# render.clear_light(self.ambient_np)
-# self.ambient_np.remove_node()
-
-
-# class P3dSpotlight:
-
-# def __init__(self, mask=None):
-# self.spot_lgt = render.attach_new_node(P3DSpotlight('spot'))
-# snode = self.spot_lgt.node()
-# snode.set_scene(render)
-# snode.set_shadow_caster(True, 1024, 1024)
-# snode.get_lens().set_fov(40)
-# snode.get_lens().set_near_far(20, 200)
-# if mask: snode.set_camera_mask(mask)
-# render.set_light(self.spot_lgt)
-
-# def set_pos(self, pos): return self.spot_lgt.set_pos(*pos)
-
-# def look_at(self, pos): return self.spot_lgt.look_at(*pos)
-
-# def set_color(self, color): return self.spot_lgt.set_color(*color)
-
-# def destroy(self):
-# render.clear_light(self.spot_lgt)
-# self.spot_lgt.remove_node()
+++ /dev/null
-from inspect import getmro
-from panda3d.core import TextNode, Texture
-from direct.gui.DirectGuiGlobals import FLAT, ENTER, EXIT, DISABLED, NORMAL, \
- B1PRESS
-from direct.showbase.DirectObject import DirectObject
-from direct.gui.DirectButton import DirectButton
-from direct.gui.DirectCheckButton import DirectCheckButton
-from direct.gui.DirectOptionMenu import DirectOptionMenu
-from direct.gui.OnscreenImage import OnscreenImage
-from direct.gui.DirectSlider import DirectSlider
-from direct.gui.DirectEntry import DirectEntry, ENTRY_FOCUS_STATE
-from direct.gui.DirectLabel import DirectLabel
-from direct.gui.DirectFrame import DirectFrame
-from direct.gui.OnscreenText import OnscreenText
-from direct.gui.DirectScrolledFrame import DirectScrolledFrame
-from ya2.observer import Subject
-# from ya2.lib.ivals import Seq, Wait, PosIval, Func
-
-
-class CommonBase:
-
- def set_widget(self):
- from ya2.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \
- CheckBtn, Entry, Img, Text, ScrolledFrame
- from ya2.lib.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \
- OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \
- ScrolledFrameMixin
- self.__class__ = self.__class__ # for pylint
- libwdg2wdg = {
- FrameMixin: [Frame],
- ScrolledFrameMixin: [ScrolledFrame],
- SliderMixin: [Slider],
- BtnMixin: [Btn, Label],
- OptionMenuMixin: [OptionMenu],
- CheckBtnMixin: [CheckBtn],
- EntryMixin: [Entry],
- ImgMixin: [Img, Text]}
- for libwdg, wdgcls in libwdg2wdg.items():
- if any(cls in getmro(self.__class__) for cls in wdgcls):
- par_cls = libwdg
- clsname = self.__class__.__name__ + 'Widget'
- self.__class__ = type(clsname, (self.__class__, par_cls), {})
- self.init(self)
- if not hasattr(self, 'bind'): return
- bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)]
- list(map(lambda args: self.bind(*args), bind_args))
-
- def set_enter_transition(self):
- start_pos = self.get_pos()
- pos = self.pos - (3.6, 0)
- self.set_pos((pos.x, 1, pos.y))
- Seq(
- Wait(abs(pos.y - 1) / 4),
- PosIval(self.get_np(), .5, start_pos)
- ).start()
-
- def set_exit_transition(self, destroy):
- start_pos = self.get_pos()
- end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- seq = Seq(
- Wait(abs(self.pos.y - 1) / 4),
- PosIval(self.get_np(), .5, end_pos),
- Func(self.destroy if destroy else self.hide))
- if not destroy: seq += Func(self.set_pos, start_pos)
- seq.start()
-
- def translate(self):
- if hasattr(self, 'bind_transl'): self.wdg['text'] = self.bind_transl
-
-
-class P3dImg(CommonBase):
-
- def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False,
- foreground=False, parent=None):
- self.img = OnscreenImage(
- filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent)
- if background: self.img.set_bin('background', 10)
- alpha_formats = [12] # panda3d.core.texture.Frgba
- if self.img.get_texture().get_format() in alpha_formats:
- self.img.set_transparency(True)
- if foreground: self.img.set_bin('gui-popup', 50)
-
- def reparent_to(self, node): return self.img.reparent_to(node)
- def show(self): return self.img.show()
- def hide(self): return self.img.hide()
- def set_shader(self, shader): return self.img.set_shader(shader)
- def set_shader_input(self, name, val):
- return self.img.set_shader_input(name, val)
- def set_texture(self, texturestage, texture):
- return self.img.set_texture(texturestage, texture)
-
- def set_exit_transition(self, destroy):
- start_pos = self.get_pos()
- end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- seq = Seq(
- Wait(abs(self.pos.y - 1) / 4),
- PosIval(self.get_np(), .5, end_pos),
- Func(self.destroy if destroy else self.hide))
- if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2]))
- seq.start()
-
- def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1])
-
- def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else [])
-
- @property
- def parent(self): return self.img.get_parent()
-
- @property
- def hidden(self): return self.img.is_hidden()
-
- def set_transparent(self): return self.img.set_transparency(True)
-
- def destroy(self): self.img = self.img.destroy()
-
-
-# class P3dBase(CommonBase):
-
-# def __init__(self, tra_src=None, tra_tra=None):
-# # self.text_src_tra = None # it breaks the gui
-# if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra)
-
-# def set_pos(self, pos): return self.wdg.set_pos(pos)
-# def show(self): return self.wdg.show()
-# def hide(self): return self.wdg.hide()
-
-# def bind_tra(self, text_src, text_transl):
-# # text_transl is not used, anyway we need it since we have this kind of
-# # use: self.bind_transl('example str', _('example str'))
-# # this allows to change translations on the fly keeping the source
-# # text for remapping it later
-# # TODO: try reverse mapping? i.e. retrieve the src string from the
-# # translated one
-# self.text_src_tra = text_src
-# self.text_tra_tra = text_transl
-# tra = lambda self: _(self.text_tra_tra)
-# self.__class__.bind_transl = property(tra)
-# self['text'] = self.bind_transl
-
-# def get_pos(self, pos=None):
-# return self.wdg.get_pos(*[pos] if pos else [])
-
-# def __setitem__(self, key, value): self.wdg[key] = value
-
-# def __getitem__(self, key): return self.wdg[key]
-
-# def get_np(self): return self.wdg
-
-# @property
-# def hidden(self): return self.wdg.is_hidden()
-
-# def destroy(self): self.wdg.destroy()
-
-
-# class P3dAbs(P3dBase):
-
-# def get_value(self): return self.wdg.getValue()
-# def initialiseoptions(self): return self.wdg.initialiseoptions()
-# def set_z(self, val): return self.wdg.set_z(val)
-# def set_shader(self, shader): return self.wdg.set_shader(shader)
-# def set_shader_input(self, name, val):
-# return self.wdg.set_shader_input(name, val)
-# def set_transparency(self, val): return self.wdg.set_transparency(val)
-# def bind(self, evt, mth): return self.wdg.bind(evt, mth)
-
-# def attachNewNode(self, gui_itm, sort_order):
-# # it won't work if we name it attach_node. hopefully this will be
-# # possible when we'll use decorators in place of mixins
-# return self.wdg.attachNewNode(gui_itm, sort_order)
-
-# @property
-# def is_enabled(self): return self.wdg['state'] != DISABLED
-
-
-# class P3dBtn(P3dAbs):
-
-# def __init__(
-# self, text='', parent=None, pos=(0, 0), scale=(1, 1),
-# cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None,
-# text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None,
-# over_snd=None, extra_args=None, frame_texture=None, img=None,
-# tra_src=None, tra_tra=None, text_scale=1.0):
-# str2par = {'bottomcenter': base.a2dBottomCenter}
-# parent = str2par.get(parent, parent)
-# extra_args = extra_args or []
-# self.wdg = DirectButton(
-# text=text, parent=parent, pos=(pos[0], 1, pos[1]),
-# scale=(scale[0], 1, scale[1]), command=cmd,
-# frameSize=frame_size, clickSound=click_snd, text_fg=text_fg,
-# frameColor=frame_col, text_font=text_font, rolloverSound=over_snd,
-# extraArgs=extra_args, frameTexture=frame_texture, image=img,
-# text_scale=text_scale)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-# self['relief'] = FLAT
-# args = [(ENTER, self._on_enter), (EXIT, self._on_exit)]
-# list(map(lambda args: self.bind(*args), args))
-
-# def _on_enter(self, pos): pass # pos comes from mouse
-
-# def _on_exit(self, pos): pass # pos comes from mouse
-
-# # we add these with the mixins
-# # def enable(self): self['state'] = NORMAL
-
-# # def disable(self): self['state'] = DISABLED
-
-
-# class P3dSlider(P3dAbs):
-
-# def __init__(
-# self, parent=None, pos=(0, 0), scale=1, val=0,
-# frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1),
-# cmd=None, range_=(0, 1), tra_src=None, tra_tra=None):
-# self.wdg = DirectSlider(
-# parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val,
-# frameColor=frame_col, thumb_frameColor=thumb_frame_col,
-# command=cmd, range=range_)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-# class P3dCheckBtn(P3dAbs):
-
-# def __init__(
-# self, pos=(0, 0), text='', indicator_val=False,
-# indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1),
-# scale=(1, 1, 1), click_snd=None, over_snd=None,
-# text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None,
-# tra_tra=None):
-# self.wdg = DirectCheckButton(
-# pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val,
-# indicator_frameColor=indicator_frame_col,
-# frameColor=frame_col, scale=scale, clickSound=click_snd,
-# rolloverSound=over_snd, text_fg=text_fg, text_font=text_font,
-# command=cmd)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-# class P3dOptionMenu(P3dAbs):
-
-# def __init__(
-# self, text='', items=None, pos=(0, 0), scale=(1, 1, 1),
-# initialitem='', cmd=None, frame_size=(-1, 1, -1, 1),
-# click_snd=None, over_snd=None, text_may_change=False,
-# text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1),
-# frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1),
-# text_scale=.05, popup_marker_col=(1, 1, 1, 1),
-# item_relief=None, item_text_font=None, text_font=None,
-# tra_src=None, tra_tra=None):
-# items = items or []
-# self.wdg = DirectOptionMenu(
-# text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale,
-# initialitem=initialitem, command=cmd, frameSize=frame_size,
-# clickSound=click_snd, rolloverSound=over_snd,
-# textMayChange=text_may_change, text_fg=text_fg,
-# item_frameColor=item_frame_col, frameColor=frame_col,
-# highlightColor=highlight_col, text_scale=text_scale,
-# popupMarker_frameColor=popup_marker_col,
-# item_relief=item_relief, item_text_font=item_text_font,
-# text_font=text_font)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-# def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
-
-# @property
-# def curr_val(self): return self.wdg.get()
-
-# @property
-# def curr_idx(self): return self.wdg.selectedIndex
-
-
-# class P3dEntry(P3dAbs, DirectObject, Subject):
-
-# def __init__(
-# self, scale=.05, pos=(0, 0), entry_font=None, width=12,
-# frame_col=(1, 1, 1, 1), initial_text='', obscured=False,
-# cmd=None, focus_in_cmd=None, focus_in_args=None,
-# focus_out_cmd=None, focus_out_args=None, parent=None,
-# tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None,
-# on_click=None):
-# self.__focused = False
-# self.__focus_in_cmd = focus_in_cmd
-# self.__focus_out_cmd = focus_out_cmd
-# DirectObject.__init__(self)
-# Subject.__init__(self)
-# focus_in_args = focus_in_args or []
-# focus_out_args = focus_out_args or []
-# self.wdg = DirectEntry(
-# scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font,
-# width=width, frameColor=frame_col, initialText=initial_text,
-# obscured=obscured, command=cmd, focusInCommand=self._focus_in_cmd,
-# focusInExtraArgs=focus_in_args,
-# focusOutCommand=self._focus_out_cmd,
-# focusOutExtraArgs=focus_out_args, parent=parent,
-# text_fg=text_fg)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-# if on_tab:
-# self.on_tab_cb = on_tab
-# self.accept('tab-up', self.on_tab)
-# if on_click: self.wdg.bind(B1PRESS, on_click)
-
-# def set(self, txt): return self.wdg.set(txt)
-
-# def _focus_in_cmd(self, *args):
-# self.__focused = True
-# if self.__focus_in_cmd: self.__focus_in_cmd(*args)
-# self.notify('on_entry_enter')
-
-# def _focus_out_cmd(self, *args):
-# self.__focused = False
-# if self.__focus_out_cmd: self.__focus_out_cmd(*args)
-# self.notify('on_entry_exit')
-
-# def on_tab(self):
-# if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
-
-# @property
-# def focused(self): return self.__focused
-
-# @property
-# def text(self): return self.wdg.get()
-
-# def enter_text(self, txt):
-# return self.wdg.enterText(txt)
-
-# def enable(self): self['state'] = NORMAL
-
-# def disable(self): self['state'] = DISABLED
-
-# def destroy(self):
-# self.ignore('tab-up')
-# self.on_tab_cb = None
-# Subject.destroy(self)
-# P3dAbs.destroy(self)
-
-
-# class P3dLabel(P3dAbs):
-
-# def __init__(
-# self, text='', pos=(0, 0), parent=None, text_wordwrap=12,
-# text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05,
-# frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None, hpr=(0, 0, 0)):
-# self.wdg = DirectLabel(
-# text=text, pos=(pos[0], 1, pos[1]), parent=parent,
-# text_wordwrap=text_wordwrap, text_align=text_align,
-# text_fg=text_fg, text_font=text_font, scale=scale,
-# frameColor=frame_col, hpr=hpr)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-# def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority)
-
-# def set_x(self, x): return self.wdg.set_x(x)
-
-# def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
-
-
-# class P3dTxt(P3dBase):
-
-# def __init__(
-# self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None,
-# fg=(1, 1, 1, 1), font=None, align=None, tra_src=None,
-# tra_tra=None):
-# str2par = {'bottomleft': base.a2dBottomLeft,
-# 'bottomright': base.a2dBottomRight,
-# 'leftcenter': base.a2dLeftCenter}
-# str2al = {'left': TextNode.A_left, 'right': TextNode.A_right,
-# 'center': TextNode.A_center}
-# if parent and parent in str2par: parent = str2par[parent]
-# if align: align = str2al[align]
-# self.wdg = OnscreenText(
-# text=txt, pos=pos, scale=scale, wordwrap=wordwrap,
-# parent=parent, fg=fg, font=font, align=align)
-# P3dBase.__init__(self, tra_src, tra_tra)
-
-# def set_r(self, r): return self.wdg.set_r(r)
-
-
-# class P3dFrame(P3dAbs):
-
-# def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1),
-# pos=(0, 0), parent=None, texture_coord=False):
-# P3dAbs.__init__(self)
-# self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col,
-# pos=(pos[0], 1, pos[1]), parent=parent)
-# if texture_coord: self.wdg['frameTexture'] = Texture()
-
-
-# class P3dScrolledFrame(P3dAbs):
-
-# def __init__(
-# self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1),
-# scrollbar_width=.05, frame_col=(1, 1, 1, 1),
-# pos=(0, 0), parent='topleft'):
-# P3dAbs.__init__(self)
-# par2p3d = {'topleft': base.a2dTopLeft}
-# if parent and parent in par2p3d: parent = par2p3d[parent]
-# self.wdg = DirectScrolledFrame(
-# frameSize=frame_sz,
-# canvasSize=canvas_sz,
-# scrollBarWidth=scrollbar_width,
-# frameColor=frame_col,
-# pos=(pos[0], 1, pos[1]),
-# parent=parent)
-
-# @property
-# def canvas(self): return self.wdg.getCanvas()
+++ /dev/null
-import sys
-from logging import info
-from os.path import exists, dirname
-from os import getcwd, _exit
-from glob import glob
-from pathlib import Path
-from panda3d.core import loadPrcFileData, Texture, TextPropertiesManager, \
- TextProperties, PandaSystem, Filename, WindowProperties, GraphicsWindow
-from panda3d.bullet import get_bullet_version
-from direct.showbase.ShowBase import ShowBase
-from direct.showbase.DirectObject import DirectObject
-from direct.task.Task import Task
-#from gltf import patch_loader
-
-
-# class LibShowBase(ShowBase): pass
-
-
-class LibP3d(DirectObject):
-
- task_cont = Task.cont
-
- def __init__(self):
- DirectObject.__init__(self)
- self.__end_cb = self.__notify = None
- self.__logged_keys = {}
-
- @staticmethod
- def runtime(): return not exists('main.py')
-
- @staticmethod
- def configure():
- loadPrcFileData('', 'notify-level-ya2 info')
- # loadPrcFileData('', 'gl-version 3 2')
-
- @staticmethod
- def fixpath(path):
- home = '/home/flavio'
- if sys.platform == 'win32' and not exists(exists(home + '/.wine/')):
- if path.startswith('/'): path = path[1] + ':\\' + path[3:]
- path = path.replace('/', '\\')
- return path
-
- @staticmethod
- def p3dpath(path): return Filename.fromOsSpecific(path)
-
- @property
- def last_frame_dt(self): return globalClock.get_dt()
-
- @property
- def build_version(self):
- appimg_mnt = glob('/tmp/.mount_Yocto*')
- if appimg_mnt:
- #with open(appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
- with open(self.curr_path + '/assets/bld_version.txt') as fver:
- return fver.read().strip()
- try:
- with open(self.curr_path + '/assets/bld_version.txt') as fver:
- return fver.read().strip()
- except FileNotFoundError:
- info(self.curr_path + '/assets/bld_version.txt')
- return 'notfound'
-
- @property
- def is_appimage(self):
- par_path = str(Path(__file__).parent.absolute())
- is_appimage = par_path.startswith('/tmp/.mount_Yocto')
- return is_appimage and par_path.endswith('/usr/bin')
-
- @property
- def curr_path(self):
- if sys.platform == 'darwin':
- return dirname(__file__) + '/../Resources/'
- # return dirname(__file__)
- par_path = str(Path(__file__).parent.absolute())
- if self.is_appimage:
- return str(Path(par_path).absolute())
- is_snap = par_path.startswith('/snap/')
- is_snap = is_snap and par_path.endswith('/x1')
- if is_snap:
- return str(Path(par_path).absolute())
- #return getcwd()
- curr_path = dirname(__file__)
- info('current path: %s' % curr_path)
- return curr_path
-
- @staticmethod
- def send(msg): return messenger.send(msg)
-
- @staticmethod
- def do_later(time, meth, args=None):
- args = args or []
- return taskMgr.doMethodLater(
- time, lambda meth, args: meth(*args), meth.__name__, [meth, args])
-
- @staticmethod
- def add_task(mth, priority=0):
- return taskMgr.add(mth, mth.__name__, priority)
-
- @staticmethod
- def remove_task(tsk): taskMgr.remove(tsk)
-
- def init(self, green=(.2, .8, .2, 1), red=(.8, .2, .2, 1), end_cb=None):
- LibShowBase()
- base.disableMouse()
- #patch_loader(base.loader)
- self.__end_cb = end_cb
- self.__init_win()
- self.__init_fonts(green, red)
- self.__set_roots()
- self.accept('aspectRatioChanged', self.on_aspect_ratio_changed)
-
- @staticmethod
- def __set_roots():
- base.a2dTopQuarter = base.aspect2d.attachNewNode('a2dTopQuarter')
- base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
- base.a2dTopThirdQuarter = \
- base.aspect2d.attachNewNode('a2dTopThirdQuarter')
- base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
- base.a2dCenterQuarter = base.aspect2d.attachNewNode('a2dCenterQuarter')
- base.a2dCenterQuarter.set_pos(base.a2dLeft / 2, 0, 0)
- base.a2dCenterThirdQuarter = \
- base.aspect2d.attachNewNode('a2dCenterThirdQuarter')
- base.a2dCenterThirdQuarter.set_pos(base.a2dRight / 2, 0, 0)
- base.a2dBottomQuarter = base.aspect2d.attachNewNode('a2dBottomQuarter')
- base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
- base.a2dBottomThirdQuarter = \
- base.aspect2d.attachNewNode('a2dBottomThirdQuarter')
- base.a2dBottomThirdQuarter.set_pos(
- base.a2dRight / 2, 0, base.a2dBottom)
-
- @staticmethod
- def on_aspect_ratio_changed():
- base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
- base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
- base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
- base.a2dBottomThirdQuarter.set_pos(
- base.a2dRight / 2, 0, base.a2dBottom)
-
- @property
- def has_window(self): return bool(base.win)
-
- @property
- def resolution(self):
- if not isinstance(base.win, GraphicsWindow):
- return 800, 600
- win_prop = base.win.get_properties()
- return win_prop.get_x_size(), win_prop.get_y_size()
-
- @property
- def resolutions(self):
- d_i = base.pipe.get_display_information()
-
- def res(idx):
- return d_i.get_display_mode_width(idx), \
- d_i.get_display_mode_height(idx)
- ret = [res(idx) for idx in range(d_i.get_total_display_modes())]
- return ret if ret else [self.resolution]
-
- @staticmethod
- def toggle_fullscreen():
- props = WindowProperties()
- props.set_fullscreen(not base.win.is_fullscreen())
- base.win.request_properties(props)
-
- @staticmethod
- def set_resolution(res, fullscreen=None):
- props = WindowProperties()
- props.set_size(res)
- if fullscreen: props.set_fullscreen(True)
- if isinstance(base.win, GraphicsWindow):
- base.win.request_properties(props)
-
- def __init_win(self):
- if base.win and isinstance(base.win, GraphicsWindow):
- base.win.set_close_request_event('window-closed')
- # not headless
- self.accept('window-closed', self.__on_end)
-
- @staticmethod
- def __init_fonts(green=(.2, .8, .2, 1), red=(.8, .2, .2, 1)):
- tp_mgr = TextPropertiesManager.get_global_ptr()
- for namecol, col in zip(['green', 'red'], [green, red]):
- props = TextProperties()
- props.set_text_color(col)
- tp_mgr.set_properties(namecol, props)
- for namesize, col in zip(['small', 'smaller'], [.46, .72]):
- props = TextProperties()
- props.set_text_scale(.46)
- tp_mgr.set_properties(namesize, props)
- tp_italic = TextProperties()
- tp_italic.set_slant(.2)
- tp_mgr.set_properties('italic', tp_italic)
-
- def __on_end(self):
- base.closeWindow(base.win)
- if self.__end_cb: self.__end_cb()
- _exit(0)
-
- @staticmethod
- def load_font(filepath, outline=True):
- font = base.loader.loadFont(filepath)
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- if outline: font.set_outline((0, 0, 0, 1), .8, .2)
- return font
-
- @staticmethod
- def log(msg): print(msg)
-
- @property
- def version(self): return PandaSystem.get_version_string()
-
- @property
- def lib_commit(self): return PandaSystem.get_git_commit()
-
- @property
- def phys_version(self): return get_bullet_version()
-
- @property
- def user_appdata_dir(self): return Filename.get_user_appdata_directory()
-
- @property
- def driver_vendor(self): return base.win.get_gsg().get_driver_vendor()
-
- @property
- def driver_renderer(self): return base.win.get_gsg().get_driver_renderer()
-
- @property
- def driver_shader_version_major(self):
- return base.win.get_gsg().get_driver_shader_version_major()
-
- @property
- def driver_shader_version_minor(self):
- return base.win.get_gsg().get_driver_shader_version_minor()
-
- @property
- def driver_version(self): return base.win.get_gsg().get_driver_version()
-
- @property
- def driver_version_major(self):
- return base.win.get_gsg().get_driver_version_major()
-
- @property
- def driver_version_minor(self):
- return base.win.get_gsg().get_driver_version_minor()
-
- @property
- def fullscreen(self):
- if isinstance(base.win, GraphicsWindow):
- return base.win.get_properties().get_fullscreen()
-
- @property
- def volume(self): return base.sfxManagerList[0].get_volume()
-
- @volume.setter
- def volume(self, vol): base.sfxManagerList[0].set_volume(vol)
-
- @property
- def mousepos(self):
- mwn = base.mouseWatcherNode
- if not mwn: return 0, 0
- if not mwn.hasMouse(): return 0, 0
- return mwn.get_mouse_x(), mwn.get_mouse_y()
-
- @property
- def aspect_ratio(self): return base.getAspectRatio()
-
- @staticmethod
- def set_icon(filename):
- props = WindowProperties()
- props.set_icon_filename(filename)
- if isinstance(base.win, GraphicsWindow):
- base.win.requestProperties(props)
-
- @staticmethod
- def __set_std_cursor(show):
- props = WindowProperties()
- props.set_cursor_hidden(not show)
- if isinstance(base.win, GraphicsWindow):
- base.win.requestProperties(props)
-
- @staticmethod
- def show_std_cursor(): LibP3d.__set_std_cursor(True)
-
- @staticmethod
- def hide_std_cursor(): LibP3d.__set_std_cursor(False)
-
- @staticmethod
- def find_geoms(model, name): # no need to be cached
- geoms = model.node.find_all_matches('**/+GeomNode')
- is_nm = lambda geom: geom.get_name().startswith(name)
- named_geoms = [geom for geom in geoms if is_nm(geom)]
- return [ng for ng in named_geoms if name in ng.get_name()]
-
- @staticmethod
- def load_sfx(filepath, loop=False):
- sfx = loader.loadSfx(filepath)
- sfx.set_loop(loop)
- return sfx
-
- def remap_code(self, key):
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- self.__log_key('not found a code mapping for %s' %
- key, key, 'not_found')
- return key
-
- def remap_str(self, key):
- if not base.win: # when launched with --version
- return key
- #if isinstance(base.win, GraphicsBuffer):
- # return key
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if str(key).lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- self.__log_key('not found a string mapping for %s' %
- key, key, kmap.get_mapped_button(i).get_name())
- return key
-
- def __log_key(self, msg, key1, key2):
- if key1 in self.__logged_keys and self.__logged_keys[key1] == key2:
- return
- self.__logged_keys[key1] = key2
- print(msg)
-
- def destroy(self): pass
+++ /dev/null
-class ObsInfo:
-
- def __init__(self, mth, sort, args):
- self.mth = mth
- self.sort = sort
- self.args = args
-
- def __repr__(self): return str(self.mth)
-
-
-class Subject:
-
- def __init__(self):
- self.observers = {}
-
- def attach(self, obs_meth, sort=10, rename='', args=None):
- args = args or []
- onm = rename or obs_meth.__name__
- if onm not in self.observers: self.observers[onm] = []
- self.observers[onm] += [ObsInfo(obs_meth, sort, args)]
- sorted_obs = sorted(self.observers[onm], key=lambda obs: obs.sort)
- self.observers[onm] = sorted_obs
-
- def detach(self, obs_meth, lambda_call=None):
- if isinstance(obs_meth, str):
- onm = obs_meth
- observers = [obs for obs in self.observers[onm]
- if obs.mth == lambda_call]
- else:
- onm = obs_meth.__name__
- observers = [obs for obs in self.observers[onm]
- if obs.mth == obs_meth]
- if not observers: raise Exception
- list(map(self.observers[onm].remove, observers))
-
- def notify(self, meth, *args, **kwargs):
- if meth not in self.observers: return # no obs for this notification
- for obs in self.observers[meth][:]:
- if obs in self.observers[meth]: # if an obs removes another one
- try:
- act_args = obs.args + list(args)
- obs.mth(*act_args, **kwargs)
- except SystemError:
- print('Quit')
- import sys; sys.exit()
-
- def observing(self, obs_meth):
- if callable(obs_meth): obs_meth = obs_meth.__name__
- return obs_meth in self.observers and self.observers[obs_meth]
-
- def destroy(self): self.observers = None
-
-
-class Observer: pass
--- /dev/null
+import datetime
+from logging import debug, info
+from os import getcwd
+from os.path import exists, dirname
+from panda3d.core import get_model_path, AntialiasAttrib, PandaNode, \
+ LightRampAttrib, Camera, OrthographicLens, NodePath, OmniBoundingVolume, \
+ AmbientLight as P3DAmbientLight, Spotlight as P3DSpotlight, Point2, \
+ Point3, Texture
+from direct.filter.CommonFilters import CommonFilters
+from direct.actor.Actor import Actor
+# from ya2.lib.p3d.p3d import LibP3d
+
+
+def set_srgb(model):
+ for texture in model.find_all_textures():
+ if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
+ texture.set_format(Texture.F_srgb_alpha)
+ elif texture.get_format() in [Texture.F_rgb]:
+ texture.set_format(Texture.F_srgb)
+
+
+# class RenderToTexture:
+
+# def __init__(self, size=(256, 256)):
+# self.__set_buffer(size)
+# self.__set_display_region()
+# self.__set_camera()
+# self.__set_root()
+# self.display_region.set_camera(self.camera)
+
+# def __set_buffer(self, size):
+# self.buffer = base.win.make_texture_buffer('result buffer', size[0],
+# size[1])
+# self.buffer.set_sort(-100)
+
+# def __set_display_region(self):
+# self.display_region = self.buffer.make_display_region()
+# self.display_region.set_sort(20)
+
+# def __set_camera(self):
+# self.camera = NodePath(Camera('camera 2d'))
+# lens = OrthographicLens()
+# lens.set_film_size(1, 1)
+# lens.set_near_far(-1000, 1000)
+# self.camera.node().set_lens(lens)
+
+# def __set_root(self):
+# self.root = NodePath('root')
+# self.root.set_depth_test(False)
+# self.root.set_depth_write(False)
+# self.camera.reparent_to(self.root)
+
+# @property
+# def texture(self): return self.buffer.get_texture()
+
+# def destroy(self):
+# base.graphicsEngine.remove_window(self.buffer)
+# if base.win: # if you close the window during a race
+# base.win.remove_display_region(self.display_region)
+# list(map(lambda node: node.remove_node(), [self.camera, self.root]))
+
+
+class P3dGfxMgr:
+
+ def __init__(self, model_path, antialiasing, shaders, srgb):
+ self.root = P3dNode(render)
+ self.__srgb = srgb
+ self.callbacks = {}
+ self.filters = None
+ get_model_path().append_directory(model_path)
+ if LibP3d.runtime():
+ root_dir = LibP3d.p3dpath(dirname(__file__))
+ paths = [root_dir + '/' + model_path, root_dir]
+ list(map(get_model_path().append_directory, paths))
+ render.set_shader_auto()
+ # render.set_two_sided(True) # it breaks shadows
+ if antialiasing: render.set_antialias(AntialiasAttrib.MAuto)
+ if shaders and base.win:
+ self.filters = CommonFilters(base.win, base.cam)
+
+ def load_model(self, filename, callback=None, anim=None):
+ ext = '.bam' if exists(filename + '.bam') else ''
+ if anim:
+ anim_dct = {'anim': filename + '-Anim' + ext}
+ node = P3dNode(self.set_srgb(Actor(filename + ext, anim_dct)))
+ elif callback:
+ callb = lambda model: callback(P3dNode(self.set_srgb(model)))
+ node = loader.loadModel(filename + ext, callback=callb)
+ else:
+ node = P3dNode(self.set_srgb(
+ loader.loadModel(LibP3d.p3dpath(filename + ext))))
+ return node
+
+ def set_srgb(self, model):
+ if self.__srgb:
+ for texture in model.find_all_textures():
+ if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
+ texture.set_format(Texture.F_srgb_alpha)
+ elif texture.get_format() in [Texture.F_rgb]:
+ texture.set_format(Texture.F_srgb)
+ return model
+
+ @staticmethod
+ def toggle_aa():
+ aa_not_none = render.get_antialias() != AntialiasAttrib.MNone
+ if render.has_antialias() and aa_not_none:
+ render.clear_antialias()
+ else: render.set_antialias(AntialiasAttrib.MAuto, 1)
+
+ def set_toon(self):
+ tmp_node = NodePath(PandaNode('temp node'))
+ tmp_node.set_attrib(LightRampAttrib.make_single_threshold(.5, .4))
+ tmp_node.set_shader_auto()
+ base.cam.node().set_initial_state(tmp_node.get_state())
+ self.filters.set_cartoon_ink(separation=1)
+
+ def set_bloom(self):
+ if not base.win: return
+ self.filters.setBloom(
+ blend=(.3, .4, .3, 0), mintrigger=.6, maxtrigger=1.0, desat=.6,
+ intensity=1.0, size='medium')
+ # default: (.3, .4, .3, 0), .6, 1, .6, 1, 'medium'
+
+ @staticmethod
+ def pos2d(node):
+ p3d = base.cam.get_relative_point(node.node, Point3(0, 0, 0))
+ p2d = Point2()
+ return p2d if base.camLens.project(p3d, p2d) else None
+
+ @staticmethod
+ def screen_coord(pos):
+ new_node = NodePath('temp')
+ new_node.set_pos(pos)
+ coord3d = new_node.get_pos(base.cam)
+ new_node.remove_node()
+ coord2d = Point2()
+ base.camLens.project(coord3d, coord2d)
+ coord_r2d = Point3(coord2d[0], 0, coord2d[1])
+ coord_a2d = base.aspect2d.get_relative_point(render2d, coord_r2d)
+ return coord_a2d[0], coord_a2d[2]
+
+ @staticmethod
+ def world_from_to(pos):
+ p_from, p_to = Point3(), Point3() # in camera coordinates
+ base.camLens.extrude(pos, p_from, p_to)
+ p_from = render.get_relative_point(base.cam, p_from) # global coords
+ p_to = render.get_relative_point(base.cam, p_to) # global coords
+ return p_from, p_to
+
+ @property
+ def shader_support(self):
+ return base.win.get_gsg().get_supports_basic_shaders()
+
+ def screenshot(self, path=None):
+ time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
+ #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
+ #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
+ res = base.screenshot(path or ("pmachines%s.png" % time), False)
+ info('screenshot %s (%s; %s)' % (path or ("pmachines%s.png" % time), res, getcwd()))
+
+ @staticmethod
+ def enable_shader(): render.set_shader_auto()
+
+ @staticmethod
+ def disable_shader(): render.set_shader_off()
+
+ @staticmethod
+ def print_stats(two_d=True, three_d=True, analyze=True, ls=True):
+ '''Print graphics stats. They use standard output (from p3d).'''
+ info = []
+ if two_d and analyze:
+ info +=[('render2d.analyze', base.render2d.analyze)]
+ if three_d and analyze:
+ info +=[('render.analyze', base.render.analyze)]
+ if two_d and ls:
+ info +=[('render2d.ls', base.render2d.ls)]
+ if three_d and ls:
+ info +=[('render.ls', base.render.ls)]
+ for elm in info:
+ print('\n\n#####\n%s()' % elm[0])
+ elm[1]()
+
+
+# class P3dNode:
+
+# def __init__(self, nodepath):
+# self.nodepath = nodepath
+# self.node.set_python_tag('libnode', self)
+
+# def set_collide_mask(self, mask): return self.node.set_collide_mask(mask)
+# def set_x(self, val): return self.node.set_x(val)
+# def set_y(self, val): return self.node.set_y(val)
+# def set_z(self, val): return self.node.set_z(val)
+# def set_hpr(self, val): return self.node.set_hpr(val)
+# def set_h(self, val): return self.node.set_h(val)
+# def set_p(self, val): return self.node.set_p(val)
+# def set_r(self, val): return self.node.set_r(val)
+# def set_scale(self, val): return self.node.set_scale(val)
+# def set_transparency(self, val): return self.node.set_transparency(val)
+# def set_alpha_scale(self, val): return self.node.set_alpha_scale(val)
+# def set_texture(self, texturestage, texture):
+# return self.node.set_texture(texturestage, texture)
+# def has_tag(self, name): return self.node.has_tag(name)
+# def get_tag(self, name): return self.node.get_tag(name)
+# def get_python_tag(self, name): return self.node.get_python_tag(name)
+# def remove_node(self): return self.node.remove_node()
+# def flatten_strong(self): return self.node.flatten_strong()
+# def clear_model_nodes(self): return self.node.clear_model_nodes()
+# def show(self): return self.node.show()
+# def set_depth_offset(self, val): return self.node.set_depth_offset(val)
+# def loop(self, val): return self.node.loop(val)
+# def cleanup(self): return self.node.cleanup()
+# def write_bam_file(self, fname): return self.node.write_bam_file(fname)
+
+# def attach_node(self, name):
+# return P3dNode(self.node.attach_new_node(name))
+
+# def add_shape(self, shape):
+# return self.node.node().add_shape(shape._mesh_shape)
+# #TODO: don't access a protected member
+
+# @property
+# def name(self): return self.node.get_name()
+
+# @property
+# def node(self): return self.nodepath
+
+# @property
+# def p3dnode(self): return self.node.node()
+
+# def set_pos(self, pos): return self.node.set_pos(pos._vec)
+# #TODO: don't access a protected member
+
+# def get_pos(self, other=None):
+# return self.node.get_pos(* [] if other is None else [other.node])
+
+# @property
+# def x(self): return self.node.get_x()
+
+# @property
+# def y(self): return self.node.get_y()
+
+# @property
+# def z(self): return self.node.get_z()
+
+# @property
+# def hpr(self): return self.node.get_hpr()
+
+# @property
+# def h(self): return self.node.get_h()
+
+# @property
+# def p(self): return self.node.get_p()
+
+# @property
+# def r(self): return self.node.get_r()
+
+# @property
+# def scale(self): return self.node.get_scale()
+
+# @property
+# def is_empty(self): return self.node.is_empty()
+
+# def get_relative_vector(self, node, vec):
+# return self.node.get_relative_vector(node.node, vec)
+
+# def set_material(self, mat): return self.node.set_material(mat, 1)
+
+# def set_python_tag(self, name, val):
+# return self.node.set_python_tag(name, val)
+
+# def get_distance(self, other_node):
+# return self.node.get_distance(other_node.node)
+
+# def reparent_to(self, parent): return self.node.reparent_to(parent.node)
+
+# def wrt_reparent_to(self, parent):
+# return self.node.wrt_reparent_to(parent.node)
+
+# @staticmethod
+# def __get_pandanode(nodepath):
+# if nodepath.has_python_tag('libnode'):
+# return nodepath.get_python_tag('libnode')
+# return P3dNode(nodepath)
+
+# def find_all_matches(self, name):
+# nodes = self.node.find_all_matches(name)
+# return [self.__get_pandanode(node) for node in nodes]
+
+# def find(self, name):
+# model = self.node.find(name)
+# if model: return self.__get_pandanode(model)
+
+# def optimize(self):
+# self.node.prepare_scene(base.win.get_gsg()) # crash with texture.set_format
+# self.node.premunge_scene(base.win.get_gsg())
+
+# def hide(self, mask=None):
+# return self.node.hide(*[] if mask is None else [mask])
+
+# @property
+# def tight_bounds(self): return self.node.get_tight_bounds()
+
+# @property
+# def parent(self): return self.node.get_parent()
+
+# @property
+# def children(self): return self.node.get_children()
+
+# def destroy(self): return self.node.remove_node()
+
+
+# class P3dAnimNode:
+
+# def __init__(self, filepath, anim_dct):
+# self.node = Actor(filepath, anim_dct)
+
+# def loop(self, val): return self.node.loop(val)
+
+# def reparent_to(self, node): self.node.reparent_to(node)
+
+# @property
+# def name(self): return self.node.get_name()
+
+# def optimize(self):
+# self.node.prepare_scene(base.win.get_gsg())
+# self.node.premunge_scene(base.win.get_gsg())
+
+# def set_omni(self):
+# self.node.node().set_bounds(OmniBoundingVolume())
+# self.node.node().set_final(True)
+
+# def destroy(self): self.node.cleanup()
+
+
+# class P3dAmbientLight:
+
+# def __init__(self, color):
+# ambient_lgt = P3DAmbientLight('ambient light')
+# ambient_lgt.set_color(color)
+# self.ambient_np = render.attach_new_node(ambient_lgt)
+# render.set_light(self.ambient_np)
+
+# def destroy(self):
+# render.clear_light(self.ambient_np)
+# self.ambient_np.remove_node()
+
+
+# class P3dSpotlight:
+
+# def __init__(self, mask=None):
+# self.spot_lgt = render.attach_new_node(P3DSpotlight('spot'))
+# snode = self.spot_lgt.node()
+# snode.set_scene(render)
+# snode.set_shadow_caster(True, 1024, 1024)
+# snode.get_lens().set_fov(40)
+# snode.get_lens().set_near_far(20, 200)
+# if mask: snode.set_camera_mask(mask)
+# render.set_light(self.spot_lgt)
+
+# def set_pos(self, pos): return self.spot_lgt.set_pos(*pos)
+
+# def look_at(self, pos): return self.spot_lgt.look_at(*pos)
+
+# def set_color(self, color): return self.spot_lgt.set_color(*color)
+
+# def destroy(self):
+# render.clear_light(self.spot_lgt)
+# self.spot_lgt.remove_node()
--- /dev/null
+from inspect import getmro
+from panda3d.core import TextNode, Texture
+from direct.gui.DirectGuiGlobals import FLAT, ENTER, EXIT, DISABLED, NORMAL, \
+ B1PRESS
+from direct.showbase.DirectObject import DirectObject
+from direct.gui.DirectButton import DirectButton
+from direct.gui.DirectCheckButton import DirectCheckButton
+from direct.gui.DirectOptionMenu import DirectOptionMenu
+from direct.gui.OnscreenImage import OnscreenImage
+from direct.gui.DirectSlider import DirectSlider
+from direct.gui.DirectEntry import DirectEntry, ENTRY_FOCUS_STATE
+from direct.gui.DirectLabel import DirectLabel
+from direct.gui.DirectFrame import DirectFrame
+from direct.gui.OnscreenText import OnscreenText
+from direct.gui.DirectScrolledFrame import DirectScrolledFrame
+from ya2.patterns.observer import Subject
+# from ya2.lib.ivals import Seq, Wait, PosIval, Func
+
+
+class CommonBase:
+
+ def set_widget(self):
+ from ya2.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \
+ CheckBtn, Entry, Img, Text, ScrolledFrame
+ from ya2.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \
+ OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \
+ ScrolledFrameMixin
+ self.__class__ = self.__class__ # for pylint
+ libwdg2wdg = {
+ FrameMixin: [Frame],
+ ScrolledFrameMixin: [ScrolledFrame],
+ SliderMixin: [Slider],
+ BtnMixin: [Btn, Label],
+ OptionMenuMixin: [OptionMenu],
+ CheckBtnMixin: [CheckBtn],
+ EntryMixin: [Entry],
+ ImgMixin: [Img, Text]}
+ for libwdg, wdgcls in libwdg2wdg.items():
+ if any(cls in getmro(self.__class__) for cls in wdgcls):
+ par_cls = libwdg
+ clsname = self.__class__.__name__ + 'Widget'
+ self.__class__ = type(clsname, (self.__class__, par_cls), {})
+ self.init(self)
+ if not hasattr(self, 'bind'): return
+ bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)]
+ list(map(lambda args: self.bind(*args), bind_args))
+
+ def set_enter_transition(self):
+ start_pos = self.get_pos()
+ pos = self.pos - (3.6, 0)
+ self.set_pos((pos.x, 1, pos.y))
+ Seq(
+ Wait(abs(pos.y - 1) / 4),
+ PosIval(self.get_np(), .5, start_pos)
+ ).start()
+
+ def set_exit_transition(self, destroy):
+ start_pos = self.get_pos()
+ end_pos = (self.pos.x + 3.6, 1, self.pos.y)
+ seq = Seq(
+ Wait(abs(self.pos.y - 1) / 4),
+ PosIval(self.get_np(), .5, end_pos),
+ Func(self.destroy if destroy else self.hide))
+ if not destroy: seq += Func(self.set_pos, start_pos)
+ seq.start()
+
+ def translate(self):
+ if hasattr(self, 'bind_transl'): self.wdg['text'] = self.bind_transl
+
+
+class P3dImg(CommonBase):
+
+ def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False,
+ foreground=False, parent=None):
+ self.img = OnscreenImage(
+ filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent)
+ if background: self.img.set_bin('background', 10)
+ alpha_formats = [12] # panda3d.core.texture.Frgba
+ if self.img.get_texture().get_format() in alpha_formats:
+ self.img.set_transparency(True)
+ if foreground: self.img.set_bin('gui-popup', 50)
+
+ def reparent_to(self, node): return self.img.reparent_to(node)
+ def show(self): return self.img.show()
+ def hide(self): return self.img.hide()
+ def set_shader(self, shader): return self.img.set_shader(shader)
+ def set_shader_input(self, name, val):
+ return self.img.set_shader_input(name, val)
+ def set_texture(self, texturestage, texture):
+ return self.img.set_texture(texturestage, texture)
+
+ def set_exit_transition(self, destroy):
+ start_pos = self.get_pos()
+ end_pos = (self.pos.x + 3.6, 1, self.pos.y)
+ seq = Seq(
+ Wait(abs(self.pos.y - 1) / 4),
+ PosIval(self.get_np(), .5, end_pos),
+ Func(self.destroy if destroy else self.hide))
+ if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2]))
+ seq.start()
+
+ def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1])
+
+ def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else [])
+
+ @property
+ def parent(self): return self.img.get_parent()
+
+ @property
+ def hidden(self): return self.img.is_hidden()
+
+ def set_transparent(self): return self.img.set_transparency(True)
+
+ def destroy(self): self.img = self.img.destroy()
+
+
+# class P3dBase(CommonBase):
+
+# def __init__(self, tra_src=None, tra_tra=None):
+# # self.text_src_tra = None # it breaks the gui
+# if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra)
+
+# def set_pos(self, pos): return self.wdg.set_pos(pos)
+# def show(self): return self.wdg.show()
+# def hide(self): return self.wdg.hide()
+
+# def bind_tra(self, text_src, text_transl):
+# # text_transl is not used, anyway we need it since we have this kind of
+# # use: self.bind_transl('example str', _('example str'))
+# # this allows to change translations on the fly keeping the source
+# # text for remapping it later
+# # TODO: try reverse mapping? i.e. retrieve the src string from the
+# # translated one
+# self.text_src_tra = text_src
+# self.text_tra_tra = text_transl
+# tra = lambda self: _(self.text_tra_tra)
+# self.__class__.bind_transl = property(tra)
+# self['text'] = self.bind_transl
+
+# def get_pos(self, pos=None):
+# return self.wdg.get_pos(*[pos] if pos else [])
+
+# def __setitem__(self, key, value): self.wdg[key] = value
+
+# def __getitem__(self, key): return self.wdg[key]
+
+# def get_np(self): return self.wdg
+
+# @property
+# def hidden(self): return self.wdg.is_hidden()
+
+# def destroy(self): self.wdg.destroy()
+
+
+# class P3dAbs(P3dBase):
+
+# def get_value(self): return self.wdg.getValue()
+# def initialiseoptions(self): return self.wdg.initialiseoptions()
+# def set_z(self, val): return self.wdg.set_z(val)
+# def set_shader(self, shader): return self.wdg.set_shader(shader)
+# def set_shader_input(self, name, val):
+# return self.wdg.set_shader_input(name, val)
+# def set_transparency(self, val): return self.wdg.set_transparency(val)
+# def bind(self, evt, mth): return self.wdg.bind(evt, mth)
+
+# def attachNewNode(self, gui_itm, sort_order):
+# # it won't work if we name it attach_node. hopefully this will be
+# # possible when we'll use decorators in place of mixins
+# return self.wdg.attachNewNode(gui_itm, sort_order)
+
+# @property
+# def is_enabled(self): return self.wdg['state'] != DISABLED
+
+
+# class P3dBtn(P3dAbs):
+
+# def __init__(
+# self, text='', parent=None, pos=(0, 0), scale=(1, 1),
+# cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None,
+# text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None,
+# over_snd=None, extra_args=None, frame_texture=None, img=None,
+# tra_src=None, tra_tra=None, text_scale=1.0):
+# str2par = {'bottomcenter': base.a2dBottomCenter}
+# parent = str2par.get(parent, parent)
+# extra_args = extra_args or []
+# self.wdg = DirectButton(
+# text=text, parent=parent, pos=(pos[0], 1, pos[1]),
+# scale=(scale[0], 1, scale[1]), command=cmd,
+# frameSize=frame_size, clickSound=click_snd, text_fg=text_fg,
+# frameColor=frame_col, text_font=text_font, rolloverSound=over_snd,
+# extraArgs=extra_args, frameTexture=frame_texture, image=img,
+# text_scale=text_scale)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+# self['relief'] = FLAT
+# args = [(ENTER, self._on_enter), (EXIT, self._on_exit)]
+# list(map(lambda args: self.bind(*args), args))
+
+# def _on_enter(self, pos): pass # pos comes from mouse
+
+# def _on_exit(self, pos): pass # pos comes from mouse
+
+# # we add these with the mixins
+# # def enable(self): self['state'] = NORMAL
+
+# # def disable(self): self['state'] = DISABLED
+
+
+# class P3dSlider(P3dAbs):
+
+# def __init__(
+# self, parent=None, pos=(0, 0), scale=1, val=0,
+# frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1),
+# cmd=None, range_=(0, 1), tra_src=None, tra_tra=None):
+# self.wdg = DirectSlider(
+# parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val,
+# frameColor=frame_col, thumb_frameColor=thumb_frame_col,
+# command=cmd, range=range_)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+
+
+# class P3dCheckBtn(P3dAbs):
+
+# def __init__(
+# self, pos=(0, 0), text='', indicator_val=False,
+# indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1),
+# scale=(1, 1, 1), click_snd=None, over_snd=None,
+# text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None,
+# tra_tra=None):
+# self.wdg = DirectCheckButton(
+# pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val,
+# indicator_frameColor=indicator_frame_col,
+# frameColor=frame_col, scale=scale, clickSound=click_snd,
+# rolloverSound=over_snd, text_fg=text_fg, text_font=text_font,
+# command=cmd)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+
+
+# class P3dOptionMenu(P3dAbs):
+
+# def __init__(
+# self, text='', items=None, pos=(0, 0), scale=(1, 1, 1),
+# initialitem='', cmd=None, frame_size=(-1, 1, -1, 1),
+# click_snd=None, over_snd=None, text_may_change=False,
+# text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1),
+# frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1),
+# text_scale=.05, popup_marker_col=(1, 1, 1, 1),
+# item_relief=None, item_text_font=None, text_font=None,
+# tra_src=None, tra_tra=None):
+# items = items or []
+# self.wdg = DirectOptionMenu(
+# text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale,
+# initialitem=initialitem, command=cmd, frameSize=frame_size,
+# clickSound=click_snd, rolloverSound=over_snd,
+# textMayChange=text_may_change, text_fg=text_fg,
+# item_frameColor=item_frame_col, frameColor=frame_col,
+# highlightColor=highlight_col, text_scale=text_scale,
+# popupMarker_frameColor=popup_marker_col,
+# item_relief=item_relief, item_text_font=item_text_font,
+# text_font=text_font)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+
+# def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
+
+# @property
+# def curr_val(self): return self.wdg.get()
+
+# @property
+# def curr_idx(self): return self.wdg.selectedIndex
+
+
+# class P3dEntry(P3dAbs, DirectObject, Subject):
+
+# def __init__(
+# self, scale=.05, pos=(0, 0), entry_font=None, width=12,
+# frame_col=(1, 1, 1, 1), initial_text='', obscured=False,
+# cmd=None, focus_in_cmd=None, focus_in_args=None,
+# focus_out_cmd=None, focus_out_args=None, parent=None,
+# tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None,
+# on_click=None):
+# self.__focused = False
+# self.__focus_in_cmd = focus_in_cmd
+# self.__focus_out_cmd = focus_out_cmd
+# DirectObject.__init__(self)
+# Subject.__init__(self)
+# focus_in_args = focus_in_args or []
+# focus_out_args = focus_out_args or []
+# self.wdg = DirectEntry(
+# scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font,
+# width=width, frameColor=frame_col, initialText=initial_text,
+# obscured=obscured, command=cmd, focusInCommand=self._focus_in_cmd,
+# focusInExtraArgs=focus_in_args,
+# focusOutCommand=self._focus_out_cmd,
+# focusOutExtraArgs=focus_out_args, parent=parent,
+# text_fg=text_fg)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+# if on_tab:
+# self.on_tab_cb = on_tab
+# self.accept('tab-up', self.on_tab)
+# if on_click: self.wdg.bind(B1PRESS, on_click)
+
+# def set(self, txt): return self.wdg.set(txt)
+
+# def _focus_in_cmd(self, *args):
+# self.__focused = True
+# if self.__focus_in_cmd: self.__focus_in_cmd(*args)
+# self.notify('on_entry_enter')
+
+# def _focus_out_cmd(self, *args):
+# self.__focused = False
+# if self.__focus_out_cmd: self.__focus_out_cmd(*args)
+# self.notify('on_entry_exit')
+
+# def on_tab(self):
+# if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
+
+# @property
+# def focused(self): return self.__focused
+
+# @property
+# def text(self): return self.wdg.get()
+
+# def enter_text(self, txt):
+# return self.wdg.enterText(txt)
+
+# def enable(self): self['state'] = NORMAL
+
+# def disable(self): self['state'] = DISABLED
+
+# def destroy(self):
+# self.ignore('tab-up')
+# self.on_tab_cb = None
+# Subject.destroy(self)
+# P3dAbs.destroy(self)
+
+
+# class P3dLabel(P3dAbs):
+
+# def __init__(
+# self, text='', pos=(0, 0), parent=None, text_wordwrap=12,
+# text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05,
+# frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None, hpr=(0, 0, 0)):
+# self.wdg = DirectLabel(
+# text=text, pos=(pos[0], 1, pos[1]), parent=parent,
+# text_wordwrap=text_wordwrap, text_align=text_align,
+# text_fg=text_fg, text_font=text_font, scale=scale,
+# frameColor=frame_col, hpr=hpr)
+# P3dAbs.__init__(self, tra_src, tra_tra)
+
+# def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority)
+
+# def set_x(self, x): return self.wdg.set_x(x)
+
+# def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
+
+
+# class P3dTxt(P3dBase):
+
+# def __init__(
+# self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None,
+# fg=(1, 1, 1, 1), font=None, align=None, tra_src=None,
+# tra_tra=None):
+# str2par = {'bottomleft': base.a2dBottomLeft,
+# 'bottomright': base.a2dBottomRight,
+# 'leftcenter': base.a2dLeftCenter}
+# str2al = {'left': TextNode.A_left, 'right': TextNode.A_right,
+# 'center': TextNode.A_center}
+# if parent and parent in str2par: parent = str2par[parent]
+# if align: align = str2al[align]
+# self.wdg = OnscreenText(
+# text=txt, pos=pos, scale=scale, wordwrap=wordwrap,
+# parent=parent, fg=fg, font=font, align=align)
+# P3dBase.__init__(self, tra_src, tra_tra)
+
+# def set_r(self, r): return self.wdg.set_r(r)
+
+
+# class P3dFrame(P3dAbs):
+
+# def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1),
+# pos=(0, 0), parent=None, texture_coord=False):
+# P3dAbs.__init__(self)
+# self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col,
+# pos=(pos[0], 1, pos[1]), parent=parent)
+# if texture_coord: self.wdg['frameTexture'] = Texture()
+
+
+# class P3dScrolledFrame(P3dAbs):
+
+# def __init__(
+# self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1),
+# scrollbar_width=.05, frame_col=(1, 1, 1, 1),
+# pos=(0, 0), parent='topleft'):
+# P3dAbs.__init__(self)
+# par2p3d = {'topleft': base.a2dTopLeft}
+# if parent and parent in par2p3d: parent = par2p3d[parent]
+# self.wdg = DirectScrolledFrame(
+# frameSize=frame_sz,
+# canvasSize=canvas_sz,
+# scrollBarWidth=scrollbar_width,
+# frameColor=frame_col,
+# pos=(pos[0], 1, pos[1]),
+# parent=parent)
+
+# @property
+# def canvas(self): return self.wdg.getCanvas()
--- /dev/null
+import sys
+from logging import info
+from os.path import exists, dirname
+from os import getcwd, _exit
+from glob import glob
+from pathlib import Path
+from panda3d.core import loadPrcFileData, Texture, TextPropertiesManager, \
+ TextProperties, PandaSystem, Filename, WindowProperties, GraphicsWindow
+from panda3d.bullet import get_bullet_version
+from direct.showbase.ShowBase import ShowBase
+from direct.showbase.DirectObject import DirectObject
+from direct.task.Task import Task
+#from gltf import patch_loader
+
+
+# class LibShowBase(ShowBase): pass
+
+
+class LibP3d(DirectObject):
+
+ task_cont = Task.cont
+
+ def __init__(self):
+ DirectObject.__init__(self)
+ self.__end_cb = self.__notify = None
+ self.__logged_keys = {}
+
+ @staticmethod
+ def runtime(): return not exists('main.py')
+
+ @staticmethod
+ def configure():
+ loadPrcFileData('', 'notify-level-ya2 info')
+ # loadPrcFileData('', 'gl-version 3 2')
+
+ @staticmethod
+ def fixpath(path):
+ home = '/home/flavio'
+ if sys.platform == 'win32' and not exists(exists(home + '/.wine/')):
+ if path.startswith('/'): path = path[1] + ':\\' + path[3:]
+ path = path.replace('/', '\\')
+ return path
+
+ @staticmethod
+ def p3dpath(path): return Filename.fromOsSpecific(path)
+
+ @property
+ def last_frame_dt(self): return globalClock.get_dt()
+
+ @property
+ def build_version(self):
+ appimg_mnt = glob('/tmp/.mount_Yocto*')
+ if appimg_mnt:
+ #with open(appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
+ with open(self.curr_path + '/assets/bld_version.txt') as fver:
+ return fver.read().strip()
+ try:
+ with open(self.curr_path + '/assets/bld_version.txt') as fver:
+ return fver.read().strip()
+ except FileNotFoundError:
+ info(self.curr_path + '/assets/bld_version.txt')
+ return 'notfound'
+
+ @property
+ def is_appimage(self):
+ par_path = str(Path(__file__).parent.absolute())
+ is_appimage = par_path.startswith('/tmp/.mount_Yocto')
+ return is_appimage and par_path.endswith('/usr/bin')
+
+ @property
+ def curr_path(self):
+ if sys.platform == 'darwin':
+ return dirname(__file__) + '/../Resources/'
+ # return dirname(__file__)
+ par_path = str(Path(__file__).parent.absolute())
+ if self.is_appimage:
+ return str(Path(par_path).absolute())
+ is_snap = par_path.startswith('/snap/')
+ is_snap = is_snap and par_path.endswith('/x1')
+ if is_snap:
+ return str(Path(par_path).absolute())
+ #return getcwd()
+ curr_path = dirname(__file__)
+ info('current path: %s' % curr_path)
+ return curr_path
+
+ @staticmethod
+ def send(msg): return messenger.send(msg)
+
+ @staticmethod
+ def do_later(time, meth, args=None):
+ args = args or []
+ return taskMgr.doMethodLater(
+ time, lambda meth, args: meth(*args), meth.__name__, [meth, args])
+
+ @staticmethod
+ def add_task(mth, priority=0):
+ return taskMgr.add(mth, mth.__name__, priority)
+
+ @staticmethod
+ def remove_task(tsk): taskMgr.remove(tsk)
+
+ def init(self, green=(.2, .8, .2, 1), red=(.8, .2, .2, 1), end_cb=None):
+ LibShowBase()
+ base.disableMouse()
+ #patch_loader(base.loader)
+ self.__end_cb = end_cb
+ self.__init_win()
+ self.__init_fonts(green, red)
+ self.__set_roots()
+ self.accept('aspectRatioChanged', self.on_aspect_ratio_changed)
+
+ @staticmethod
+ def __set_roots():
+ base.a2dTopQuarter = base.aspect2d.attachNewNode('a2dTopQuarter')
+ base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
+ base.a2dTopThirdQuarter = \
+ base.aspect2d.attachNewNode('a2dTopThirdQuarter')
+ base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
+ base.a2dCenterQuarter = base.aspect2d.attachNewNode('a2dCenterQuarter')
+ base.a2dCenterQuarter.set_pos(base.a2dLeft / 2, 0, 0)
+ base.a2dCenterThirdQuarter = \
+ base.aspect2d.attachNewNode('a2dCenterThirdQuarter')
+ base.a2dCenterThirdQuarter.set_pos(base.a2dRight / 2, 0, 0)
+ base.a2dBottomQuarter = base.aspect2d.attachNewNode('a2dBottomQuarter')
+ base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
+ base.a2dBottomThirdQuarter = \
+ base.aspect2d.attachNewNode('a2dBottomThirdQuarter')
+ base.a2dBottomThirdQuarter.set_pos(
+ base.a2dRight / 2, 0, base.a2dBottom)
+
+ @staticmethod
+ def on_aspect_ratio_changed():
+ base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
+ base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
+ base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
+ base.a2dBottomThirdQuarter.set_pos(
+ base.a2dRight / 2, 0, base.a2dBottom)
+
+ @property
+ def has_window(self): return bool(base.win)
+
+ @property
+ def resolution(self):
+ if not isinstance(base.win, GraphicsWindow):
+ return 800, 600
+ win_prop = base.win.get_properties()
+ return win_prop.get_x_size(), win_prop.get_y_size()
+
+ @property
+ def resolutions(self):
+ d_i = base.pipe.get_display_information()
+
+ def res(idx):
+ return d_i.get_display_mode_width(idx), \
+ d_i.get_display_mode_height(idx)
+ ret = [res(idx) for idx in range(d_i.get_total_display_modes())]
+ return ret if ret else [self.resolution]
+
+ @staticmethod
+ def toggle_fullscreen():
+ props = WindowProperties()
+ props.set_fullscreen(not base.win.is_fullscreen())
+ base.win.request_properties(props)
+
+ @staticmethod
+ def set_resolution(res, fullscreen=None):
+ props = WindowProperties()
+ props.set_size(res)
+ if fullscreen: props.set_fullscreen(True)
+ if isinstance(base.win, GraphicsWindow):
+ base.win.request_properties(props)
+
+ def __init_win(self):
+ if base.win and isinstance(base.win, GraphicsWindow):
+ base.win.set_close_request_event('window-closed')
+ # not headless
+ self.accept('window-closed', self.__on_end)
+
+ @staticmethod
+ def __init_fonts(green=(.2, .8, .2, 1), red=(.8, .2, .2, 1)):
+ tp_mgr = TextPropertiesManager.get_global_ptr()
+ for namecol, col in zip(['green', 'red'], [green, red]):
+ props = TextProperties()
+ props.set_text_color(col)
+ tp_mgr.set_properties(namecol, props)
+ for namesize, col in zip(['small', 'smaller'], [.46, .72]):
+ props = TextProperties()
+ props.set_text_scale(.46)
+ tp_mgr.set_properties(namesize, props)
+ tp_italic = TextProperties()
+ tp_italic.set_slant(.2)
+ tp_mgr.set_properties('italic', tp_italic)
+
+ def __on_end(self):
+ base.closeWindow(base.win)
+ if self.__end_cb: self.__end_cb()
+ _exit(0)
+
+ @staticmethod
+ def load_font(filepath, outline=True):
+ font = base.loader.loadFont(filepath)
+ font.set_pixels_per_unit(60)
+ font.set_minfilter(Texture.FTLinearMipmapLinear)
+ if outline: font.set_outline((0, 0, 0, 1), .8, .2)
+ return font
+
+ @staticmethod
+ def log(msg): print(msg)
+
+ @property
+ def version(self): return PandaSystem.get_version_string()
+
+ @property
+ def lib_commit(self): return PandaSystem.get_git_commit()
+
+ @property
+ def phys_version(self): return get_bullet_version()
+
+ @property
+ def user_appdata_dir(self): return Filename.get_user_appdata_directory()
+
+ @property
+ def driver_vendor(self): return base.win.get_gsg().get_driver_vendor()
+
+ @property
+ def driver_renderer(self): return base.win.get_gsg().get_driver_renderer()
+
+ @property
+ def driver_shader_version_major(self):
+ return base.win.get_gsg().get_driver_shader_version_major()
+
+ @property
+ def driver_shader_version_minor(self):
+ return base.win.get_gsg().get_driver_shader_version_minor()
+
+ @property
+ def driver_version(self): return base.win.get_gsg().get_driver_version()
+
+ @property
+ def driver_version_major(self):
+ return base.win.get_gsg().get_driver_version_major()
+
+ @property
+ def driver_version_minor(self):
+ return base.win.get_gsg().get_driver_version_minor()
+
+ @property
+ def fullscreen(self):
+ if isinstance(base.win, GraphicsWindow):
+ return base.win.get_properties().get_fullscreen()
+
+ @property
+ def volume(self): return base.sfxManagerList[0].get_volume()
+
+ @volume.setter
+ def volume(self, vol): base.sfxManagerList[0].set_volume(vol)
+
+ @property
+ def mousepos(self):
+ mwn = base.mouseWatcherNode
+ if not mwn: return 0, 0
+ if not mwn.hasMouse(): return 0, 0
+ return mwn.get_mouse_x(), mwn.get_mouse_y()
+
+ @property
+ def aspect_ratio(self): return base.getAspectRatio()
+
+ @staticmethod
+ def set_icon(filename):
+ props = WindowProperties()
+ props.set_icon_filename(filename)
+ if isinstance(base.win, GraphicsWindow):
+ base.win.requestProperties(props)
+
+ @staticmethod
+ def __set_std_cursor(show):
+ props = WindowProperties()
+ props.set_cursor_hidden(not show)
+ if isinstance(base.win, GraphicsWindow):
+ base.win.requestProperties(props)
+
+ @staticmethod
+ def show_std_cursor(): LibP3d.__set_std_cursor(True)
+
+ @staticmethod
+ def hide_std_cursor(): LibP3d.__set_std_cursor(False)
+
+ @staticmethod
+ def find_geoms(model, name): # no need to be cached
+ geoms = model.node.find_all_matches('**/+GeomNode')
+ is_nm = lambda geom: geom.get_name().startswith(name)
+ named_geoms = [geom for geom in geoms if is_nm(geom)]
+ return [ng for ng in named_geoms if name in ng.get_name()]
+
+ @staticmethod
+ def load_sfx(filepath, loop=False):
+ sfx = loader.loadSfx(filepath)
+ sfx.set_loop(loop)
+ return sfx
+
+ def remap_code(self, key):
+ kmap = base.win.get_keyboard_map()
+ for i in range(kmap.get_num_buttons()):
+ if key.lower() == kmap.get_mapped_button_label(i).lower():
+ self.__log_key(
+ 'code mapping %s to key %s' %
+ (key, kmap.get_mapped_button(i)), key,
+ kmap.get_mapped_button(i))
+ return kmap.get_mapped_button(i)
+ for i in range(kmap.get_num_buttons()):
+ if key.lower() == kmap.get_mapped_button(i).get_name().lower():
+ self.__log_key(
+ 'code mapping %s to key %s' %
+ (key, kmap.get_mapped_button(i)), key,
+ kmap.get_mapped_button(i))
+ return kmap.get_mapped_button(i)
+ self.__log_key('not found a code mapping for %s' %
+ key, key, 'not_found')
+ return key
+
+ def remap_str(self, key):
+ if not base.win: # when launched with --version
+ return key
+ #if isinstance(base.win, GraphicsBuffer):
+ # return key
+ kmap = base.win.get_keyboard_map()
+ for i in range(kmap.get_num_buttons()):
+ if str(key).lower() == kmap.get_mapped_button_label(i).lower():
+ self.__log_key(
+ 'string mapping %s to key %s' %
+ (key, kmap.get_mapped_button(i).get_name()), key,
+ kmap.get_mapped_button(i).get_name())
+ return kmap.get_mapped_button(i).get_name()
+ for i in range(kmap.get_num_buttons()):
+ if key.lower() == kmap.get_mapped_button(i).get_name().lower():
+ self.__log_key(
+ 'string mapping %s to key %s' %
+ (key, kmap.get_mapped_button(i).get_name()), key,
+ kmap.get_mapped_button(i).get_name())
+ return kmap.get_mapped_button(i).get_name()
+ self.__log_key('not found a string mapping for %s' %
+ key, key, kmap.get_mapped_button(i).get_name())
+ return key
+
+ def __log_key(self, msg, key1, key2):
+ if key1 in self.__logged_keys and self.__logged_keys[key1] == key2:
+ return
+ self.__logged_keys[key1] = key2
+ print(msg)
+
+ def destroy(self): pass
--- /dev/null
+from direct.fsm.FSM import FSM
+from direct.showbase.DirectObject import DirectObject
+from ya2.patterns.observer import Subject
+
+
+class Colleague(Subject):
+
+ eng = None
+
+ def __init__(self, mediator):
+ Subject.__init__(self)
+ self.mediator = mediator # refactor: remove it
+
+ def destroy(self):
+ self.mediator = None
+ Subject.destroy(self)
+
+
+class FsmColleague(FSM, Colleague):
+
+ def __init__(self, mediator):
+ FSM.__init__(self, self.__class__.__name__)
+ Colleague.__init__(self, mediator)
+
+ def destroy(self):
+ if self.state: self.cleanup()
+ Colleague.destroy(self)
+
+
+class EventColleague(Colleague, DirectObject):
+
+ def destroy(self):
+ self.ignoreAll()
+ Colleague.destroy(self)
+
+
+class AudioColleague(Colleague): pass
+
+
+class AiColleague(Colleague): pass
+
+
+class GfxColleague(Colleague): pass
+
+
+class GuiColleague(Colleague): pass
+
+
+class LogicColleague(Colleague):
+
+ def on_start(self): pass
+
+
+class PhysColleague(Colleague): pass
+
+
+class GODirector:
+
+ def __init__(self, tgt_obj, init_lst, end_cb):
+ self.__obj = tgt_obj
+ tgt_obj.attach(self.on_comp_blt)
+ self.end_cb = end_cb
+ self.completed = [False for _ in init_lst]
+ self.pending = {}
+ self.__init_lst = init_lst
+ for idx, _ in enumerate(init_lst): self.__process_lst(tgt_obj, idx)
+
+ def __process_lst(self, obj, idx):
+ if not self.__init_lst[idx]:
+ self.end_lst(idx)
+ return
+ comp_info = self.__init_lst[idx].pop(0)
+ attr_name, cls, arguments = comp_info
+ self.pending[cls.__name__] = idx
+ setattr(obj, attr_name, cls(*arguments))
+
+ def on_comp_blt(self, obj):
+ self.__process_lst(obj.mediator, self.pending[obj.__class__.__name__])
+
+ def end_lst(self, idx):
+ self.completed[idx] = True
+ if all(self.completed):
+ if self.end_cb: self.end_cb()
+ self.destroy()
+
+ def destroy(self):
+ self.__obj.detach(self.on_comp_blt)
+ self.__obj = self.end_cb = self.__init_lst = None
+
+
+class GameObject(Subject): pass
--- /dev/null
+class ObsInfo:
+
+ def __init__(self, mth, sort, args):
+ self.mth = mth
+ self.sort = sort
+ self.args = args
+
+ def __repr__(self): return str(self.mth)
+
+
+class Subject:
+
+ def __init__(self):
+ self.observers = {}
+
+ def attach(self, obs_meth, sort=10, rename='', args=None):
+ args = args or []
+ onm = rename or obs_meth.__name__
+ if onm not in self.observers: self.observers[onm] = []
+ self.observers[onm] += [ObsInfo(obs_meth, sort, args)]
+ sorted_obs = sorted(self.observers[onm], key=lambda obs: obs.sort)
+ self.observers[onm] = sorted_obs
+
+ def detach(self, obs_meth, lambda_call=None):
+ if isinstance(obs_meth, str):
+ onm = obs_meth
+ observers = [obs for obs in self.observers[onm]
+ if obs.mth == lambda_call]
+ else:
+ onm = obs_meth.__name__
+ observers = [obs for obs in self.observers[onm]
+ if obs.mth == obs_meth]
+ if not observers: raise Exception
+ list(map(self.observers[onm].remove, observers))
+
+ def notify(self, meth, *args, **kwargs):
+ if meth not in self.observers: return # no obs for this notification
+ for obs in self.observers[meth][:]:
+ if obs in self.observers[meth]: # if an obs removes another one
+ try:
+ act_args = obs.args + list(args)
+ obs.mth(*act_args, **kwargs)
+ except SystemError:
+ print('Quit')
+ import sys; sys.exit()
+
+ def observing(self, obs_meth):
+ if callable(obs_meth): obs_meth = obs_meth.__name__
+ return obs_meth in self.observers and self.observers[obs_meth]
+
+ def destroy(self): self.observers = None
+
+
+class Observer: pass
--- /dev/null
+from panda3d.core import GraphicsWindow, WindowProperties
+from ya2.p3d.gui import P3dImg as Img
+from ya2.patterns.gameobject import GameObject
+
+
+class MouseCursorFacade:
+
+ def show(self):
+ if not self.eng.cfg.dev_cfg.functional_test:
+ return self.cursor_img.show()
+ def hide(self): return self.cursor_img.hide()
+
+
+class MouseCursor(GameObject, MouseCursorFacade):
+
+ def __init__(self, filepath, scale, color, hotspot):
+ GameObject.__init__(self)
+ MouseCursorFacade.__init__(self)
+ if not filepath: return
+ self.__set_std_cursor(False)
+ self.cursor_img = Img(filepath, scale=scale, foreground=True)
+ self.cursor_img.img.set_color(color)
+ #if self.eng.cfg.dev_cfg.functional_test:
+ # self.cursor_img.hide()
+ self.hotspot_dx = scale[0] * (1 - 2 * hotspot[0])
+ self.hotspot_dy = scale[2] * (1 - 2 * hotspot[1])
+ #self.eng.attach_obs(self.on_frame)
+ #self.eng.attach_obs(self.on_frame_unpausable)
+ self._tsk = taskMgr.add(self.__on_frame, 'on frame cursor')
+
+ @staticmethod
+ def __set_std_cursor(show):
+ props = WindowProperties()
+ props.set_cursor_hidden(not show)
+ if isinstance(base.win, GraphicsWindow):
+ base.win.requestProperties(props)
+
+ #def show_standard(self): self.eng.lib.show_std_cursor()
+
+ #def hide_standard(self): self.eng.lib.hide_std_cursor()
+
+ #def cursor_top(self):
+ # self.cursor_img.reparent_to(self.cursor_img.parent)
+
+ def __on_frame(self, task):
+ mwn = base.mouseWatcherNode
+ if not mwn or not mwn.hasMouse():
+ return task.again
+ mouse = mwn.get_mouse_x(), mwn.get_mouse_y()
+ h_x = mouse[0] * base.getAspectRatio() + self.hotspot_dx
+ self.cursor_img.set_pos((h_x, mouse[1] - self.hotspot_dy))
+ return task.again
+
+ #def on_frame(self):
+ # if not self.eng.pause.paused: self.__on_frame()
+
+ #def on_frame_unpausable(self):
+ # if self.eng.pause.paused: self.__on_frame()
+
+ def set_image(self, img):
+ self.cursor_img.img.set_texture(loader.load_texture(img), 1)
+
+ def destroy(self):
+ taskMgr.remove(self._tsk)
+ self.cursor_img.destroy()
--- /dev/null
+import sys
+from logging import info
+from os import makedirs
+from os.path import dirname
+from collections.abc import Mapping
+from configparser import ConfigParser
+from json import load, dumps
+from ya2.patterns.gameobject import GameObject
+from ya2.p3d.p3d import LibP3d
+
+
+class DctFile(GameObject):
+
+ def __init__(self, fpath, default_dct=None, persistent=True):
+ GameObject.__init__(self)
+ default_dct = default_dct or {}
+ if sys.platform == 'darwin' and LibP3d.runtime():
+ fpath = dirname(__file__) + '/' + fpath
+ self.fpath = fpath
+ self.persistent = persistent
+ try:
+ #with open(fpath) as json: fdct = load(json)
+ config = ConfigParser()
+ config.read(fpath)
+ fdct = {section: dict(config.items(section)) for section in config.sections()}
+ fdct = self.__typed_dct(fdct)
+ self.dct = self.__add_default(default_dct, fdct)
+ except IOError: self.dct = default_dct
+
+ @staticmethod
+ def __typed_dct(dct):
+ def convert_single_val(val):
+ try: return int(val)
+ except ValueError:
+ try: return float(val)
+ except ValueError:
+ if not val or val[0] != '[':
+ return val
+ else:
+ raise ValueError
+ def converted(val):
+ try: return convert_single_val(val)
+ except ValueError:
+ return [elm.strip() for elm in val[1:-1].split(',')]
+ new_dct = {}
+ for section, sec_dct in dct.items():
+ for key, val in sec_dct.items():
+ if section not in new_dct:
+ new_dct[section] = {}
+ new_dct[section][key] = converted(val)
+ return new_dct
+
+ @staticmethod
+ def __add_default(dct, upd):
+ for key, val in upd.items():
+ if isinstance(val, Mapping):
+ dct[key] = DctFile.__add_default(dct.get(key, {}), val)
+ else: dct[key] = upd[key]
+ return dct
+
+ @staticmethod
+ def deepupdate(dct, new_dct):
+ for key, val in new_dct.items():
+ if isinstance(val, Mapping):
+ dct[key] = DctFile.deepupdate(dct.get(key, {}), val)
+ else: dct[key] = val
+ return dct
+
+ def store(self):
+ info('storing %s' % self.fpath)
+ if not self.persistent: return
+ #json_str = dumps(self.dct, sort_keys=True, indent=4,
+ # separators=(',', ': '))
+ #with open(self.fpath, 'w') as json: json.write(json_str)
+ fdct = {}
+ for section, sec_dct in self.dct.items():
+ if section not in fdct:
+ fdct[section] = {}
+ for key, val in sec_dct.items():
+ if type(val) == list:
+ fdct[section][key] = '[%s]' % ', '.join(val)
+ else:
+ fdct[section][key] = val
+ config = ConfigParser()
+ for key in self.dct:
+ config[key] = fdct[key]
+ if dirname(self.fpath):
+ makedirs(dirname(self.fpath), exist_ok=True)
+ with open(self.fpath, 'w') as ini_file:
+ config.write(ini_file)
+
+ def __getitem__(self, arg): return self.dct[arg]
+
+ def __setitem__(self, arg, val): self.dct[arg] = val
+
+ def __delitem__(self, arg): del self.dct[arg]
--- /dev/null
+import datetime
+from os import getcwd, system
+from logging import debug, info
+from pathlib import Path
+from shutil import rmtree
+from os import makedirs
+from os.path import join, exists
+from glob import glob
+from sys import exit
+from multiprocessing.connection import Listener
+from threading import Thread
+from panda3d.core import Filename
+from direct.gui.OnscreenText import OnscreenText
+from ya2.patterns.gameobject import GameObject
+from ya2.build.build import _branch
+
+
+class ListenerThread(Thread):
+
+ def __init__(self, callbacks):
+ Thread.__init__(self)
+ address = ('localhost', 6000)
+ self._listener = Listener(address)
+ self._listener._listener._socket.settimeout(15)
+ try:
+ self._conn = self._listener.accept()
+ except TimeoutError:
+ info('listener timeout')
+ self._callbacks = callbacks
+
+ def run(self):
+ running = hasattr(self, '_conn')
+ while running:
+ try:
+ msg = self._conn.recv()
+ if msg[0] == 'screenshot':
+ taskMgr.doMethodLater(.01, self._callbacks[0], 'cb0', [msg[1]])
+ elif msg[0] == 'enforce_res':
+ taskMgr.doMethodLater(.01, self._callbacks[1], 'cb1', [msg[1]])
+ elif msg[0] == 'verify':
+ taskMgr.doMethodLater(.01, self._callbacks[2], 'cb2')
+ elif msg[0] == 'set_idx':
+ taskMgr.doMethodLater(.01, self._callbacks[3], 'cb3', [msg[1]])
+ elif msg[0] == 'enforce_resolution':
+ taskMgr.doMethodLater(.01, self._callbacks[4], 'cb4', [msg[1]])
+ except EOFError:
+ running = False
+
+
+class FunctionalTest(GameObject):
+
+ def __init__(self, ref):
+ super().__init__()
+ self._listener = ListenerThread([self._do_screenshot, self._do_enforce_res, self.__verify, self._set_idx, self._do_enforce_resolution])
+ self._listener.start()
+ self.txt = OnscreenText('', fg=(1, 0, 0, 1), scale=.16)
+ #self._path = ''
+ #if self.eng.is_appimage:
+ self._path = str(Filename().get_user_appdata_directory())
+ self._path += '/pmachines/'
+ self._path += 'tests/functional%s/' % ('_ref' if ref else '')
+ home = '/home/flavio' # we must force this for wine
+ # if self._path.startswith('/c/users/') and exists(str(Path.home()) + '/.local/share/flatpak-wine601/default/'):
+ # self._path = str(Path.home()) + '/.local/share/flatpak-wine601/default/drive_' + self._path[1:]
+ if self._path.startswith('/c/users/') and exists(home + '/.wine/'):
+ self._path = home + '/.wine/drive_' + self._path[1:]
+ if ref:
+ self._path = join(
+ Filename().get_user_appdata_directory(),
+ 'pmachines/tests/functional_ref_%s/' % _branch())
+ self._fnames = []
+ #taskMgr.add(self.on_frame_unpausable, 'on-frame-unpausable')
+ #self._do_screenshots(idx)
+
+ def _set_idx(self, idx):
+ if int(idx) == 1:
+ rmtree(self._path, ignore_errors=True)
+ info('creating dir: %s' % self._path)
+ makedirs(self._path, exist_ok=True)
+
+ def _do_screenshot(self, name):
+ self._fnames += [self._path + name]
+ #time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
+ #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
+ #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
+ res = base.screenshot(self._path + name, False)
+ info('screenshot %s (%s; %s)' % (self._path + name, res, getcwd()))
+
+ def _do_enforce_res(self, res):
+ info('enforce_res %s' % res)
+ messenger.send('enforce_res', [res])
+
+ def _do_enforce_resolution(self, res):
+ info('enforce resolution %s (callback)' % res)
+ messenger.send('enforce_resolution', [res])
+
+ #def _screenshot(self, time, name):
+ #self._fnames += [self._path + name + '.png']
+ #self._tasks += [(
+ # self._curr_time + time,
+ # lambda: self._do_screenshot(self._path + name + '.png'),
+ # 'screenshot: %s' % name)]
+ #def txt(show_hide):
+ # self.txt['text'] = name
+ # (self.txt.show if show_hide else self.txt.hide)()
+ #self._tasks += [(
+ # self._curr_time + time + .1,
+ # lambda: txt(True),
+ # 'screenshot: %s (show)' % name)]
+ #self._tasks += [(
+ # self._curr_time + time + FunctionalTest.evt_time - .1,
+ # lambda: txt(False),
+ # 'screenshot: %s (hide)' % name)]
+ #self._curr_time += time
+
+ #def __keypress(self, key):
+ #'''Emulates a keypress'''
+ #dev = base.win.getInputDevice(0)
+ #dev.buttonDown(key)
+ #dev.buttonUp(key)
+
+ #def __char_entered(self, char):
+ #'''Emulates a character being entered.'''
+ #dev = base.win.getInputDevice(0)
+ #dev.keystroke(ord(char))
+
+ # def _event(self, time, evt, messenger_evt=False, append_up=True, mouse_args=None):
+ # def _append_up(evt_name):
+ # return evt + ('' if evt.endswith('-up') or not append_up else '-up')
+ # def cback_char(_evt):
+ # self.__char_entered(_evt)
+ # def cback_keyp(_evt):
+ # self.__keypress(_evt)
+ # self.__keypress('raw-' + _evt)
+ # cback = lambda: (cback_char(evt) if len(evt) == 1 else cback_keyp(evt))
+ # if evt in ['mousemove', 'mouseclick', 'mousedrag']:
+ # if evt == 'mousemove':
+ # cback = lambda: self.__mouse_move(*mouse_args)
+ # elif evt == 'mouseclick':
+ # cback = lambda: self.__mouse_click(*mouse_args)
+ # elif evt == 'mousedrag':
+ # cback = lambda: self.__mouse_drag(*mouse_args)
+ # if messenger_evt:
+ # cback = lambda: messenger.send(_append_up(evt))
+ # self._tasks += [(
+ # self._curr_time + time,
+ # cback,
+ # 'event: %s' % evt)]
+ # def txt(show_hide):
+ # self.txt['text'] = evt
+ # (self.txt.show if show_hide else self.txt.hide)()
+ # self._tasks += [(
+ # self._curr_time + time + .2,
+ # lambda: txt(True),
+ # 'event: %s (show)' % evt)]
+ # self._tasks += [(
+ # self._curr_time + time + .8,
+ # lambda: txt(False),
+ # 'event: %s (hide)' % evt)]
+ # self._curr_time += time
+
+ # def _enforce_res(self, time, res):
+ # cback = lambda: messenger.send('enforce_res', [res])
+ # self._tasks += [(
+ # self._curr_time + time,
+ # cback,
+ # 'enforce res: %s' % res)]
+ # self._curr_time += time
+
+ def __verify(self, task):
+ files = glob(self._path + '*')
+ for fname in self._fnames:
+ info('verifying %s' % fname)
+ assert exists(fname)
+
+ #def on_frame_unpausable(self, task):
+ #self._process_conn()
+ #for tsk in self._tasks:
+ # #if self._prev_time <= tsk[0] < self.eng.event.unpaused_time:
+ # if self._prev_time <= tsk[0] < globalClock.getFrameTime():
+ # debug('%s %s' % (tsk[0], tsk[2]))
+ # tsk[1]()
+ #self._prev_time = globalClock.getFrameTime() # self.eng.event.unpaused_time
+ #return task.cont
+
+ # def _do_screenshots_1(self):
+ # info('_do_screenshots_1')
+ # self._screenshot(FunctionalTest.start_time, 'main_menu')
+ # self._do_screenshots_credits()
+ # self._do_screenshots_options()
+ # self._do_screenshots_exit()
+
+ # def _do_screenshots_credits(self):
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'credits_menu')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'main_menu_back_from_credits')
+ # # # go to credits
+ # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'main_menu_highlight')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'credits_menu')
+ # # # go to supporters
+ # # self._event(FunctionalTest.evt_time, 'joypad0-face_a', True)
+ # # self._screenshot(FunctionalTest.screenshot_time, 'supporters_menu')
+ # # # back to main
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'joypad0-face_b', True)
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+
+ # def _do_screenshots_options(self):
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 300), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu')
+ # # languages
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 60), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'open_languages')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(980, 120), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_italian')
+ # # volume
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(740, 163), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_1')
+ # # antialiasing
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 440), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_no')
+ # # shadows
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 540), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'shadows_no')
+ # # test aa and shadows
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(900, 490), 'left']) # close instructions
+ # self._screenshot(FunctionalTest.screenshot_time, 'aa_no_shadows_no')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(25, 740), 'left']) # home
+
+ # def _do_screenshots_restore_options(self):
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 300), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_restored')
+ # # languages
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 60), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'open_languages_restored')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(980, 20), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_english')
+ # # volume
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(719, 163), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_drag_2')
+ # # fullscreen
+ # # the first one is because of the windowed mode in test
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, 'fullscreen')
+ # # self._event(8 + FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 250), 'left'])
+ # # self._screenshot(8 + FunctionalTest.screenshot_time, 'back_from_fullscreen')
+ # # resolution
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 340), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, 'resolutions')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1020, 160), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, '1440x900')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(740, 400), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, 'resolutions_2')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1110, 80), 'left'])
+ # # self._screenshot(FunctionalTest.screenshot_time, '1360x768')
+ # # antialiasing
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 440), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing_yes')
+ # # shadows
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 540), 'left'])
+ # self._screenshot(FunctionalTest.screenshot_time, 'shadows_yes')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
+
+ # # # go to options
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'options_menu')
+ # # # language
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'language_open')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'language_highlight')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'language_it')
+ # # # volume
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_right')
+ # # self._event(FunctionalTest.evt_time, 'arrow_right')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'volume')
+ # # # car's number
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'cars_open')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'cars_changed')
+ # # # back
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+
+ # def _do_screenshots_play(self):
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
+ # self._screenshot(FunctionalTest.screenshot_time, 'play_menu')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 680), 'left']) # back
+ # self._screenshot(FunctionalTest.screenshot_time, 'back_from_play')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino scene
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_instructions')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(25, 740), 'left']) # home
+ # self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_scene')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(70, 740), 'left']) # info
+ # self._screenshot(FunctionalTest.screenshot_time, 'info')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (430, 280), 'left']) # drag a piece
+ # self._screenshot(FunctionalTest.screenshot_time, 'domino_dragged')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1220, 740), 'left']) # rewind
+ # self._screenshot(FunctionalTest.screenshot_time, 'rewind')
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (550, 380), 'left']) # drag a piece
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(630, 450), 'left']) # home
+ # self._screenshot(FunctionalTest.screenshot_time, 'home_back_from_fail')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 140), 'left']) # play
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(230, 160), 'left']) # domino
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(850, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (550, 380), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_2')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (570, 380), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(570, 355), (605, 355), 'right']) # rotate the piece
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(35, 60), (715, 380), 'left']) # drag a piece
+ # self._enforce_res(FunctionalTest.evt_time, 'win')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino')
+ # self._enforce_res(FunctionalTest.evt_time, '')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_box')
+ # # scene 2
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(880, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 620), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 540), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 620), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (710, 540), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (705, 460), 'left']) # drag a box
+ # self._enforce_res(FunctionalTest.evt_time, 'win')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box')
+ # self._enforce_res(FunctionalTest.evt_time, '')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_box_domino')
+ # # scene 3
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(930, 485), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 440), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 360), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_box_domino')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (910, 440), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (835, 250), 'left']) # drag a box
+ # self._enforce_res(FunctionalTest.evt_time, 'win')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_box_domino')
+ # self._enforce_res(FunctionalTest.evt_time, '')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_basketball')
+ # # scene 4
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(870, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(55, 50), (650, 310), 'left']) # drag a ball
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_basketball')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(55, 50), (380, 50), 'left']) # drag a ball
+ # self._enforce_res(FunctionalTest.evt_time, 'win')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_basketball')
+ # self._enforce_res(FunctionalTest.evt_time, '')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
+ # self._screenshot(FunctionalTest.screenshot_time, 'scene_domino_box_basketball')
+ # # scene 5
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(865, 490), 'left']) # close instructions
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (580, 440), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(30, 60), (590, 370), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_domino_box_basketball')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 450), 'left']) # replay
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(65, 60), (580, 440), 'left']) # drag a box
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(30, 60), (660, 440), 'left']) # drag a piece
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(660, 425), (625, 425), 'right']) # rotate a piece
+ # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(660, 435), (650, 445), 'left']) # drag a piece
+ # self._enforce_res(FunctionalTest.evt_time, 'win')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1340, 740), 'left']) # play
+ # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_domino_box_basketball')
+ # self._enforce_res(FunctionalTest.evt_time, '')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(735, 450), 'left']) # next
+ # # self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_tooter')
+ # # # scene 6
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(820, 455), 'left']) # close instructions
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (490, 300), 'left']) # drag a box
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
+ # # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_tooter')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(640, 420), 'left']) # replay
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (490, 150), 'left']) # drag a box
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(515, 115), (515, 122), 'right']) # rotate a box
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
+ # # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_tooter')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(690, 420), 'left']) # next
+ # # self._screenshot(FunctionalTest.screenshot_time, 'scene_teeter_domino_box_basketball')
+ # # # scene 7
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(880, 455), 'left']) # close instructions
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (155, 180), 'left']) # drag a box
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
+ # # self._screenshot(16 + FunctionalTest.screenshot_time, 'fail_teeter_domino_box_basketball')
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(640, 420), 'left']) # replay
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(60, 60), (170, 80), 'left']) # drag a box
+ # # self._event(FunctionalTest.evt_time, 'mousedrag', False, False, [(195, 50), (195, 80), 'right']) # rotate a box
+ # # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(1260, 695), 'left']) # play
+ # # self._screenshot(16 + FunctionalTest.screenshot_time, 'win_teeter_domino_box_basketball')
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(630, 450), 'left']) # home
+ # self._screenshot(FunctionalTest.screenshot_time, 'home_from_play')
+
+ # def _do_screenshots_exit(self):
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # self._verify()
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._exit()
+ # self._event(FunctionalTest.evt_time, 'mouseclick', False, False, [(680, 600), 'left'])
+
+
+ # def _do_screenshots_2(self):
+ # info('_do_screenshots_2')
+ # self._screenshot(FunctionalTest.start_time, 'main_menu_2')
+ # self._do_screenshots_restore_options()
+ # self._do_screenshots_play()
+ # self._do_screenshots_exit()
+ # # self._do_screenshots_game()
+ # # self._do_screenshots_end()
+
+ # # def _do_screenshots_restore_options(self):
+ # # # go to options
+ # # self._event(FunctionalTest.evt_time, 'joypad0-dpad_down', True)
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'options_menu_restored')
+ # # # # language
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'language_en_restored')
+ # # # # volume
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_left')
+ # # self._event(FunctionalTest.evt_time, 'arrow_left')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'volume_restored')
+ # # # car's number
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'cars_restored')
+ # # # graphics settings
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'graphics_settings')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'antialiasing')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'shadows')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'fog')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'normal_mapping')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'occlusion')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # # input
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'input')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_rec')
+ # # self._event(FunctionalTest.evt_time, '8', True, False)
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_changed')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up', True, False)
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_restored')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'w', True, False)
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_already')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p1_already_closed')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p2')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p3')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'keyboard_p4')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+
+ # # def _do_screenshots_game(self):
+ # # # single player
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'single_player_menu')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'track_page')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'car_page_start')
+ # # self._event(FunctionalTest.evt_time, 'arrow_left')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'car_page_sel')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_start')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_left')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_left')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(FunctionalTest.evt_time, 'arrow_up')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._event(FunctionalTest.evt_time, 'backspace')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry_empty')
+ # # self._event(FunctionalTest.evt_time, 'f')
+ # # self._event(FunctionalTest.evt_time, 'l')
+ # # self._event(FunctionalTest.evt_time, 'a')
+ # # self._event(FunctionalTest.evt_time, 'v')
+ # # self._event(FunctionalTest.evt_time, 'i')
+ # # self._event(FunctionalTest.evt_time, 'o')
+ # # self._event(FunctionalTest.evt_time, 'enter')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_entry_full')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_right')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'driver_page_sel')
+ # # # some ai tests
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._event(40, 'escape-up')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'ingame_menu')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'race_back')
+ # # self._event(FunctionalTest.evt_time, 'escape-up')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'ingame_sel')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'main_page_back_race')
+
+ # # def _do_screenshots_end(self):
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'exit_page')
+ # # self._event(FunctionalTest.evt_time, 'arrow_down')
+ # # self._screenshot(FunctionalTest.screenshot_time, 'exit_page_sel')
+ # # self._verify()
+ # # self._event(FunctionalTest.evt_time, 'rcontrol')
+ # # self._exit()
+
+ # def _do_screenshots(self, idx):
+ # [self._do_screenshots_1, self._do_screenshots_2][int(idx) - 1]()
--- /dev/null
+from logging import info
+from os.path import join, exists, dirname
+from gettext import translation
+from pathlib import Path
+from ya2.patterns.gameobject import GameObject
+import sys
+
+
+def is_runtime(): return not exists('main.py')
+
+
+def is_appimage():
+ par_path = str(Path(__file__).parent.absolute())
+ is_appimage = par_path.startswith('/tmp/.mount_Pmachines')
+ return is_appimage and par_path.endswith('/usr/bin')
+
+
+def curr_path():
+ if not is_runtime(): return ''
+ if sys.platform == 'darwin':
+ return dirname(__file__) + '/../Resources/'
+ # return dirname(__file__)
+ par_path = str(Path(__file__).parent.absolute())
+ if is_appimage():
+ return str(Path(par_path).absolute())
+ is_snap = par_path.startswith('/snap/')
+ is_snap = is_snap and par_path.endswith('/x1')
+ if is_snap:
+ return str(Path(par_path).absolute())
+ #return getcwd()
+ curr_path = dirname(__file__)
+ info('current path: %s' % curr_path)
+ return curr_path + '/'
+
+
+class LangMgr(GameObject):
+
+ def __init__(self, lang, domain, dpath):
+ GameObject.__init__(self)
+ self.lang = lang
+ self.domain = domain
+ self.dpath = join(curr_path(), dpath)
+ info('language: %s, %s' % (self.domain, self.dpath))
+ self.set_lang(lang)
+
+ @property
+ def lang_codes(self):
+ return [lang[1] for lang in self.eng.cfg.lang_cfg.languages]
+
+ def set_lang(self, lang):
+ self.lang = lang
+ args = lang, self.domain, self.dpath
+ info('setting language %s, %s, %s' % args)
+ tra = translation(self.domain, self.dpath, [lang], fallback=True)
+ tra.install()
--- /dev/null
+from logging import basicConfig, info, INFO, DEBUG, getLogger
+from configparser import ConfigParser
+from sys import platform, argv
+from platform import system
+from pathlib import Path
+from glob import glob
+from json import load, dumps
+#from datetime import datetime
+from pprint import pprint
+from os import getcwd, environ
+from os.path import exists, dirname
+from traceback import print_stack
+from sys import version_info
+# from platform import system, release, architecture, platform, processor, \
+# version, machine
+# from multiprocessing import cpu_count
+from panda3d.core import Filename, GraphicsWindow, PandaSystem
+from panda3d.bullet import get_bullet_version
+from ya2.patterns.gameobject import Colleague
+from ya2.p3d.p3d import LibP3d
+import sys
+
+
+lev = INFO
+opt_path = ''
+if platform in ['win32', 'linux'] and not exists('main.py'):
+ # it is the deployed version for windows
+ opt_path = str(Filename.get_user_appdata_directory()) + '/pmachines'
+opath = LibP3d.fixpath(opt_path + '/options.ini') if opt_path else \
+ 'options.ini'
+if exists(opath):
+ with open(opath) as json_file:
+ #optfile = load(json_file)
+ optfile = ConfigParser()
+ optfile.read(opath)
+ # optfile['development']['verbose'] and int(optfile['development']['verbose']) or \
+ if optfile['development']['verbose_log'] and int(optfile['development']['verbose_log']):
+ lev = DEBUG
+
+basicConfig(level=lev, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
+getLogger().setLevel(lev) # it doesn't work otherwise
+
+
+class LogMgrBase(Colleague): # headless log manager
+
+ @staticmethod
+ def init_cls():
+ return LogMgr if base.win else LogMgrBase
+
+ def __init__(self, mediator):
+ Colleague.__init__(self, mediator)
+ self.log_cfg()
+
+ def log(self, msg, verbose=False):
+ if verbose and not self.eng.cfg.dev_cfg.verbose_log: return
+ info(msg)
+
+ @property
+ def is_appimage(self):
+ par_path = str(Path(__file__).parent.absolute())
+ is_appimage = par_path.startswith('/tmp/.mount_Pmachi')
+ return is_appimage and par_path.endswith('/usr/bin')
+
+ # @property
+ # def curr_path(self):
+ # # this is different from the music's one since it does not work
+ # # with the version in windows
+ # if sys.platform == 'darwin':
+ # return dirname(__file__) + '/../Resources/'
+ # # return dirname(__file__)
+ # par_path = str(Path(__file__).parent.absolute())
+ # if self.is_appimage:
+ # return str(Path(par_path).absolute())
+ # is_snap = par_path.startswith('/snap/')
+ # is_snap = is_snap and par_path.endswith('/x1')
+ # if is_snap:
+ # return str(Path(par_path).absolute())
+ # #return getcwd()
+ # #curr_path = dirname(__file__)
+ # curr_path = str(Path(__file__).parent.parent.parent.absolute())
+ # info('current path: %s' % curr_path)
+ # return curr_path
+
+ @property
+ def curr_path(self):
+ if system() == 'Windows':
+ return ''
+ if exists('main.py'):
+ return ''
+ else:
+ par_path = str(Path(__file__).parent.absolute())
+ if self.is_appimage:
+ par_path = str(Path(par_path).absolute())
+ par_path += '/'
+ return par_path
+
+ @property
+ def build_version(self):
+ appimg_mnt = glob('/tmp/.mount_Pmachi*')
+ if appimg_mnt:
+ #with open(appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
+ with open(self.curr_path + 'assets/bld_version.txt') as fver:
+ return fver.read().strip()
+ try:
+ with open(self.curr_path + 'assets/bld_version.txt') as fver:
+ return fver.read().strip()
+ except FileNotFoundError:
+ info('not found ' + self.curr_path + 'assets/bld_version.txt')
+ return 'notfound'
+
+ def log_cfg(self):
+ if '--version' in argv:
+ path = str(Filename.get_user_appdata_directory())
+ home = '/home/flavio' # we must force this for wine
+ if path.startswith('/c/users/') and exists(home + '/.wine/'):
+ path = home + '/.wine/drive_' + path[1:]
+ info('writing %s' % path + '/pmachines/obs_version.txt')
+ with open(path + '/pmachines/obs_version.txt', 'w') as f:
+ #f.write(self.eng.logic.version)
+ f.write(self.build_version)
+ if not platform.startswith('win'):
+ from os import ttyname # here because it doesn't work on windows
+ import sys
+ try:
+ with open(ttyname(0), 'w') as fout:
+ sys.stdout = fout
+ print('version: ' + self.build_version) # self.eng.logic.version)
+ except OSError: # it doesn't work with crontab
+ print('version: ' + self.build_version)
+ messages = ['version: ' + self.build_version] # self.eng.logic.version]
+ messages += ['argv[0]: %s' % argv[0]]
+ messages += ['getcwd: %s' % getcwd()]
+ messages += ['__file__: %s' % __file__]
+ for elm in environ.items():
+ messages += ['env::%s: %s' % elm]
+ # os_info = (system(), release(), version())
+ # messages += ['operative system: %s %s %s' % os_info]
+ # messages += ['architecture: ' + str(architecture())]
+ # messages += ['machine: ' + machine()]
+ # messages += ['platform: ' + platform()]
+ # messages += ['processor: ' + processor()]
+ # try:
+ # messages += ['cores: ' + str(cpu_count())]
+ # except NotImplementedError: # on Windows
+ # messages += ['cores: not implemented']
+ lib_ver = PandaSystem.get_version_string()
+ try:
+ import psutil
+ mem = psutil.virtual_memory().total / 1000000000.0
+ messages += ['memory: %s GB' % round(mem, 2)]
+ except ImportError: info("can't import psutil") # windows
+ lib_commit = PandaSystem.get_git_commit()
+ py_ver = [str(elm) for elm in version_info[:3]]
+ messages += ['python version: %s' % '.'.join(py_ver)]
+ messages += ['panda version: %s %s' % (lib_ver, lib_commit)]
+ messages += ['bullet version: ' + str(get_bullet_version())]
+ messages += ['appdata: ' + str(Filename.get_user_appdata_directory())]
+ if base.win and isinstance(base.win, GraphicsWindow): # not headless
+ print(base.win.get_keyboard_map())
+ list(map(self.log, messages))
+
+ @staticmethod
+ def log_tasks():
+ info('tasks: %s' % taskMgr.getAllTasks())
+ info('do-laters: %s' % taskMgr.getDoLaters())
+
+ @staticmethod
+ def plog(obj):
+ print('\n\n')
+ print_stack()
+ pprint(obj)
+ print('\n\n')
+
+
+class LogMgr(LogMgrBase):
+
+ def log_cfg(self):
+ LogMgrBase.log_cfg(self)
+ messages = [base.win.get_gsg().get_driver_vendor()]
+ messages += [base.win.get_gsg().get_driver_renderer()]
+ shad_maj = base.win.get_gsg().get_driver_shader_version_major()
+ shad_min = base.win.get_gsg().get_driver_shader_version_minor()
+ messages += ['shader: {maj}.{min}'.format(maj=shad_maj, min=shad_min)]
+ messages += [base.win.get_gsg().get_driver_version()]
+ drv_maj = base.win.get_gsg().get_driver_version_major()
+ drv_min = base.win.get_gsg().get_driver_version_minor()
+ drv = 'driver version: {maj}.{min}'
+ messages += [drv.format(maj=drv_maj, min=drv_min)]
+ fullscreen = None
+ if isinstance(base.win, GraphicsWindow):
+ fullscreen = base.win.get_properties().get_fullscreen()
+ messages += ['fullscreen: ' + str(fullscreen)]
+ def resolution():
+ if not isinstance(base.win, GraphicsWindow):
+ return 800, 600
+ win_prop = base.win.get_properties()
+ return win_prop.get_x_size(), win_prop.get_y_size()
+ res_x, res_y = resolution()
+ res_tmpl = 'resolution: {res_x}x{res_y}'
+ messages += [res_tmpl.format(res_x=res_x, res_y=res_y)]
+ list(map(self.log, messages))