--- /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()