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 lib.dictfile import DctFile
-from lib.lib.p3d.p3d import LibP3d
-from lib.engine.lang import LangMgr
-from lib.engine.log import LogMgr
-from lib.engine.functional import FunctionalTest
+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):
from itertools import product
from panda3d.core import NodePath
-from lib.lib.p3d.gfx import set_srgb
+from ya2.lib.p3d.gfx import set_srgb
class Background:
Plane, Vec3, BitMask32
from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
from direct.gui.OnscreenText import OnscreenText
-from lib.lib.p3d.gfx import P3dGfxMgr, set_srgb
+from ya2.lib.p3d.gfx import P3dGfxMgr, set_srgb
class Command:
from direct.gui.DirectGuiGlobals import FLAT
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
-from lib.engine.gui.cursor import MouseCursor
+from ya2.engine.gui.cursor import MouseCursor
from game.scene import Scene
from panda3d.bullet import BulletWorld
from direct.showbase.DirectObject import DirectObject
from game.items.background import Background
from game.sidepanel import SidePanel
-from lib.engine.gui.cursor import MouseCursor
-from lib.lib.p3d.gfx import P3dGfxMgr
+from ya2.engine.gui.cursor import MouseCursor
+from ya2.lib.p3d.gfx import P3dGfxMgr
class Scene(DirectObject):
from textwrap import dedent
from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, \
GeomVertexWriter, GeomTriangles, GeomNode, Shader, Point3, Plane, Vec3
-from lib.lib.p3d.gfx import P3dGfxMgr
+from ya2.lib.p3d.gfx import P3dGfxMgr
class SidePanel:
+++ /dev/null
-from pathlib import Path
-import sys
-sys.path.append(str(Path(__file__).parent.parent))
+++ /dev/null
-import bpy, sys, os
-
-filepath = os.path.abspath(sys.argv[-1])
-bpy.ops.export_scene.gltf(
- filepath=filepath,
- export_format='GLTF_SEPARATE',
- export_extras=True,
- export_tangents=True,
- use_selection=True)
+++ /dev/null
-'''Tools for making the builds.'''
-from os import walk, chdir, getcwd
-from os.path import join, getsize, exists, dirname, getmtime, sep
-from subprocess import Popen, PIPE, run
-from logging import debug
-from time import strftime
-from pathlib import Path
-from hashlib import md5
-
-
-#TODO refactor: make class BuilderTools
-
-
-def exec_cmd(cmd):
- '''Synchronously executes a command and returns its output.'''
- #ret = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()
- #return ret[0].decode('utf-8').strip()
- proc = run(cmd, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
- return proc.stdout.strip() + proc.stderr.strip()
-
-
-def _branch():
- '''Returns the current branch.'''
- git_branch = exec_cmd('git symbolic-ref HEAD').split('/')[-1].strip()
- print('git_branch result: %s' % git_branch)
- branches = ['master', 'rc', 'stable']
- if git_branch in branches:
- print('git_branch: %s' % git_branch)
- return git_branch
- root = str(Path(dirname(dirname(__file__))).parent) + '/'
- if 'itch' in __file__.split(sep):
- root = str(Path(dirname(__file__))) + '/'
- if __file__ == '/app/bin/pmachines': # flatpak
- root = '/app/bin/'
- for branch in branches:
- try:
- print('try: %s' % root + 'assets/bld_version.txt')
- with open(root + 'assets/bld_version.txt') as fver:
- ver = fver.read()
- print('ver: %s' % ver)
- #if branch in ver:
- b2c = {'master': 'a', 'rc': 'r', 'stable': '.'}
- if ver[1] == b2c[branch]:
- return branch
- except FileNotFoundError:
- print('file not found: %s' % root + 'assets/bld_version.txt')
-
-
-def _commit():
- '''Returns the current branch.'''
- git_commit = exec_cmd('git rev-parse HEAD')[:7]
- print('git_commit result: %s' % git_commit)
- if not git_commit.startswith("Can't r"):
- return git_commit
- root = str(Path(dirname(dirname(__file__))).parent) + '/'
- if 'itch' in __file__.split(sep):
- root = str(Path(dirname(__file__))) + '/'
- if __file__ == '/app/bin/pmachines': # flatpak
- root = '/app/bin/'
- try:
- print('try: %s' % root + 'assets/bld_version.txt')
- with open(root + 'assets/bld_version.txt') as fver:
- ver = fver.read()
- print('ver: %s' % ver)
- return ver.split('-')[1]
- except FileNotFoundError:
- print('file not found: %s' % root + 'assets/bld_version.txt')
-
-
-def _version():
- '''Computes the version of the current build.'''
- day = strftime('%y%m%d')
- root = str(Path(dirname(dirname(__file__))).parent) + '/'
- if __file__ == '/app/bin/pmachines': # flatpak
- root = '/app/bin/'
- if _branch() == 'stable':
- pref, _ver = '', ''
- if exists(root + 'assets/version.txt'):
- with open(root + 'assets/version.txt') as fver:
- pref = fver.read().strip() + '-' # + _branch() + '-'
- _ver = fver.read().strip()
- ret_ver = _ver or ('0.' + day)
- else:
- #try: we want an error!
- pref = {'master': 'a', 'rc': 'rc', '': 'runtime'}[_branch()]
- #except KeyError:
- # pref = 'notfound'
- ret_ver = '0%s%s' % (pref, day)
- pref = ret_ver
- bld_ver = pref + '-' + _commit()
- try:
- with open(root + 'assets/bld_version.txt', 'w') as fver:
- fver.write(bld_ver)
- except OSError:
- print("we can't write inside flatpaks, but we don't need it")
- return ret_ver
-
-
-def files(_extensions, excl_dirs=None, excl_ends_with=None, root_path='.'):
- '''Retrieves filenames in root_path with _extensions, with filters.'''
- return [join(root, fname)
- for root, _, fnames in walk(root_path)
- for fname in __files_ext(fnames, _extensions)
- if not any(e_d in root.split('/') for e_d in excl_dirs or []) and
- not any(fname.endswith(e_e) for e_e in excl_ends_with or [])]
-
-
-def __files_ext(fnames, _extensions):
- return [fname for fname in fnames
- if any(fname.endswith('.' + ext) for ext in _extensions)]
-
-
-def __to_be_built_single(src, tgt):
- if getmtime(tgt) > getmtime(src):
- print('%s is newer than %s: do not build' % (tgt, src))
- return False
- with open(src, 'rb') as f:
- src_content = f.read()
- with open(tgt, 'rb') as f:
- tgt_content = f.read()
- hash_src = md5(src_content).hexdigest()
- hash_tgt = md5(tgt_content).hexdigest()
- cache = {}
- lines = []
- if exists('hash_cache.txt'):
- with open('hash_cache.txt') as f:
- lines = f.readlines()
- for line in lines:
- line_spl = line.split()
- hash = line_spl[-1]
- fname = ' '.join(line_spl[:-1])
- cache[fname] = hash
- if src in cache and tgt in cache:
- if hash_src == cache[src] and \
- hash_tgt == cache[tgt]:
- print('%s and %s are in the cache: do not build' % (tgt, src))
- return False
- print('%s and %s are not up-to-date: building...' % (src, tgt))
- return True
-
-
-def to_be_built(tgt, srcs):
- '''Should tgt be built (i.e. is it older?) from sources srcs?'''
- if not exists(tgt):
- print(tgt + ' does not exist: building...')
- return True
- return any(__to_be_built_single(src, tgt) for src in srcs)
-
-
-class InsideDir:
- '''Context manager for working inside a directory.'''
-
- def __init__(self, dir_):
- self.dir = dir_
- self.old_dir = getcwd()
-
- def __enter__(self):
- chdir(self.dir)
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- chdir(self.old_dir)
-
-
-bld_dpath = 'build/'
-branch = _branch()
-ver = _version()
-win_fpath = '{dst_dir}{appname}-%s-windows.exe' % branch
-#osx_fpath = '{dst_dir}{appname}-%s-osx.zip' % branch
-#flatpak_fpath = '{dst_dir}{appname}-%s-flatpak' % branch
-appimage_fpath = '{dst_dir}{appname}-%s-appimage' % branch
-docs_fpath = '{dst_dir}{appname}-%s-docs.tar.gz' % branch
+++ /dev/null
---- /home/flavio/yocto/builder/venv/lib/python3.7/site-packages/direct/dist/commands_src.py 2021-02-16 07:15:48.000000000 +0100
-+++ /home/flavio/yocto/builder/venv/lib/python3.7/site-packages/direct/dist/commands.py 2021-03-11 10:17:03.770413010 +0100
-@@ -1532,4 +1532,8 @@
- nsi.write(' !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n')
- nsi.write(' RMDir /r "$SMPROGRAMS\\$StartMenuFolder"\n')
- nsi.write('SectionEnd\n')
-+
-+ nsi.write('Function .onInit\n')
-+ nsi.write(' ExecWait \'\"$INSTDIR\\Uninstall.exe /S\"\'\n')
-+ nsi.write('FunctionEnd\n')
- nsi.close()
-
- cmd = ['makensis']
+++ /dev/null
-'''This module creates the documentation using pydoc.'''
-from os import system, mkdir, remove, rename
-from os.path import exists
-from shutil import rmtree, make_archive
-from lib.build.build import InsideDir
-from pathlib import Path
-from re import match, findall, sub
-from glob import glob
-
-
-#TODO refactor: make class DocsBuilder
-
-
-def bld_docs():
- '''Builds the docs (inside a zip file).'''
- system('python -m pydoc -w ./')
- rmtree('docs', ignore_errors=True)
- Path('docs').mkdir(exist_ok=True)
- [rename(fname, 'docs/' + fname) for fname in glob('*.html')]
- for fname in glob('docs/*.html'):
- out_lines = []
- with open(fname) as fhtml:
- lines = fhtml.readlines()
- for line in lines:
- occurs = findall('"#[0-9A-Fa-f]{6}"', line)
- new_line = line
- for occur in occurs:
- red = int(occur[2:4], 16) / 255
- green = int(occur[4:6], 16) / 255
- blue = int(occur[6:8], 16) / 255
- new_col = .2989 * red + .5870 * green + .1140 * blue
- new_col = hex(int(round(new_col * 255)))[2:]
- new_col = '"#%s%s%s"' % (new_col, new_col, new_col)
- new_line = sub('"#[0-9A-Fa-f]{6}"', new_col, new_line)
- out_lines += [new_line]
- with open(fname, 'w') as fhtml:
- fhtml.write(''.join(out_lines))
- Path('build').mkdir(exist_ok=True)
- rmtree('build/docs', ignore_errors=True)
- rename('docs', 'build/docs')
- with InsideDir('build'):
- exists('docs.zip') and remove('docs.zip')
- make_archive('docs', 'zip', '.', 'docs')
- rmtree('docs')
+++ /dev/null
-from os.path import dirname
-from sys import executable
-from lib.build.mtprocesser import ProcesserMgr
-
-
-#TODO refactor: make class ImagesBuilder
-
-
-def bld_images(files, cores):
- mp_mgr = ProcesserMgr(cores)
- list(map(__bld_img, [(str(src), mp_mgr) for src in files]))
- mp_mgr.run()
-
-
-def __bld_img(fname_mp_mgr):
- fname, mp_mgr = fname_mp_mgr
- curr_path = dirname(__file__)
- mp_mgr.add('convert "%s" "%s"' % (fname, fname[:-3] + 'dds'))
+++ /dev/null
-#!/bin/bash
-
-#virtualenv venv
-#. ./venv/bin/activate
-#pip install --upgrade pip
-#pip install --upgrade setuptools
-#pip install panda3d -i https://archive.panda3d.org/branches/deploy-ng --upgrade
-python setup.py "$@"
+++ /dev/null
-'''Tools for l10n.'''
-from os import system, makedirs, remove
-from os.path import exists
-from shutil import move, copy
-from lib.build.build import files
-
-
-class LanguageBuilder:
- '''Tools for building files for l10n.'''
-
- @staticmethod
- def mo(tgt, lng_dir_code, appname):
- '''Builds the mo file in the lng_dir_code directory.'''
- lng_code = tgt[len(lng_dir_code):].split('/')[0]
- lng_dir = lng_dir_code + lng_code + '/LC_MESSAGES/'
- cmd = 'msgfmt -o {lng_dir}{appname}.mo assets/locale/po/{lng_code}.po'
- system(cmd.format(lng_dir=lng_dir, appname=appname, lng_code=lng_code))
-
- @staticmethod
- def pot(appname, pot_path):
- '''Builds the pot file in the lng_dir_code directory.'''
- src_files = ' '.join(files(['py']))
- cmd_tmpl = 'xgettext -ci18n -d {appname} -L python ' + \
- '-o {pot_path}{appname}.pot '
- system(cmd_tmpl.format(appname=appname, pot_path=pot_path) + src_files)
-
- @staticmethod
- def merge(lng_code, tgt_path, lng_dir, appname):
- '''Merges the new strings with the previous ones.'''
- lng_base_dir = LanguageBuilder.__prepare(lng_dir, lng_code, appname)
- LanguageBuilder.__merge(lng_base_dir, lng_code, appname, tgt_path)
- LanguageBuilder.__postprocess(lng_code)
-
- @staticmethod
- def __prepare(lng_base_dir, lng, appname):
- '''Prepares a directory for working with languages.'''
- makedirs(lng_base_dir + lng + '/LC_MESSAGES', exist_ok=True)
- lng_dir = lng_base_dir + lng + '/LC_MESSAGES/'
- if not exists('assets/locale/po/' + lng + '.po'):
- lines_to_fix = ['CHARSET/UTF-8', 'ENCODING/8bit']
- [LanguageBuilder.__fix_line(line, lng_dir, appname) for line in lines_to_fix]
- copy(lng_dir + appname + '.pot', lng_dir + appname + '.po')
- return lng_dir
-
- @staticmethod
- def __fix_line(line, lng_dir, appname):
- '''Fixes po files (misaligned entries).'''
- cmd_tmpl = "sed 's/{line}/' {lng_dir}{appname}.pot > " + \
- "{lng_dir}{appname}tmp.po"
- system(cmd_tmpl.format(line=line, lng_dir=lng_dir, appname=appname))
- move(lng_dir + appname + 'tmp.po', lng_dir + appname + '.pot')
-
- @staticmethod
- def __merge(lng_dir, lng_code, appname, tgt_path):
- '''Manages the msgmerge's invokation.'''
- print('merge', lng_dir)
- cmd = 'msgmerge -o {lng_dir}{appname}merge.po ' + \
- '{tgt_path}{lng_code}.po {tgt_path}{appname}.pot'
- cmd = cmd.format(lng_dir=lng_dir, lng_code=lng_code, appname=appname,
- tgt_path=tgt_path)
- system(cmd)
- copy(lng_dir + appname + 'merge.po', 'assets/locale/po/%s.po' % lng_code)
- poname_tmpl = '{lng_dir}{appname}merge.po'
- remove(poname_tmpl.format(lng_dir=lng_dir, appname=appname))
-
- @staticmethod
- def __postprocess(lng_code):
- '''Fixes po files at the end of the building process.'''
- lines = open('assets/locale/po/%s.po' % lng_code, 'r').readlines()
- with open('assets/locale/po/%s.po' % lng_code, 'w') as outf:
- for line in lines:
- po_str = '"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\\n"\n'
- outf.write(po_str if line.startswith(po_str[:20]) else line)
+++ /dev/null
-'''Provides tools for building models.'''
-from logging import info
-from os import system, walk, makedirs
-from os.path import exists, basename, dirname
-from multiprocessing import Pool
-from glob import glob
-from hashlib import md5
-from shutil import copyfile, move, rmtree
-from lib.build.mtprocesser import ProcesserMgr
-from lib.build.build import to_be_built
-
-
-class ModelsBuilder():
-
- def __init__(self):
- self._cache_files = [] # for avoiding rebuilding the same file
-
- def build(self, blend_path, cores):
- '''Builds the models i.e. creates glTF and bam files from blend
- ones.'''
- args = []
- for root, _, fnames in walk(blend_path):
- for fname in [fname for fname in fnames if fname.endswith('.blend')]:
- if '/prototypes/' not in root:
- args += [(root, fname)]
- with Pool() as p:
- p.starmap(self._export_blend, args)
- # caching is broken now: it is based on the previous
- # non-multiprocessing approach
- # i should evaluate if fix it or just change the blend_path for building
- # only specific models
- cache, lines = [], []
- if exists('hash_cache.txt'):
- with open('hash_cache.txt') as fhash:
- lines = fhash.readlines()
- for line in lines: # line's e.g. assets/path/to/gltf_or_png.ext 68ced1
- line_spl = line.split()
- hashval = line_spl[-1]
- fname = ' '.join(line_spl[:-1])
- if fname not in self._cache_files:
- cache += [(fname, hashval)]
- for cfile in self._cache_files:
- cache += [(cfile, md5(open(cfile, 'rb').read()).hexdigest())]
- cache = cache[-2048:]
- with open('hash_cache.txt', 'w') as fhash:
- fhash.write('\n'.join([' '.join(line) for line in cache]))
-
- def _export_blend(self, root, fname):
- '''Exports blend files to glTF and bam formats.'''
- if self._export_gltf(root, fname):
- self._export_bam(root, fname)
-
- def _export_gltf(self, root, fname):
- '''Exports glTF files from blend ones.'''
- _fname = '%s/%s' % (root, fname)
- pgltf = 'assets/models/gltf/'
- new_dir = root.replace('assets/models/blend/', pgltf)
- rmtree(new_dir, ignore_errors=True)
- makedirs(new_dir)
- #files_before = [basename(gname) for gname in glob('./*')]
- cmd = 'blender %s --background --python lib/build/blend2gltf.py '
- cmd += '-- %s.gltf'
- cmd = cmd % (_fname, new_dir + '/' + fname[:-6])
- gltf_name = _fname.replace('assets/models/blend/', pgltf)
- gltf_name = gltf_name.replace('.blend', '.gltf')
- if not to_be_built(gltf_name, [_fname]):
- return False
- system(cmd)
- self._cache_files += [_fname, gltf_name]
- #files_after = [basename(gname) for gname in glob('./*')]
- #new_files = [nnm for nnm in files_after if nnm not in files_before]
- #new_dir = root.replace('assets/models/blend/', pgltf)
- #rmtree(new_dir, ignore_errors=True)
- #makedirs(new_dir)
- #for mname in new_files:
- # new_name = '%s/%s' % (new_dir, mname)
- # move(mname, new_name)
- # info('move %s %s' % (mname, new_name))
- # # blender rewrites metal files: let's restore them
- # metal_files = [fnm for fnm in glob(new_dir + '/*') if 'metal' in fnm]
- # for metal_file in metal_files:
- # src = metal_file.replace(pgltf, 'assets/models/')
- # if not exists(src):
- # src = metal_file.replace(pgltf, 'assets/models/prototypes/')
- # src_split = src.split('/')
- # src_tracks_idx = src_split.index('tracks')
- # before = src_split[:src_tracks_idx]
- # after = src_split[src_tracks_idx + 2:]
- # src = '/'.join(before + after)
- # copyfile(src, metal_file)
- return True
-
- def _export_bam(self, root, fname):
- '''Exports bam files from glTF ones.'''
- _fname = '%s/%s' % (root, fname)
- gltf_name = (_fname[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
- bam_name = (_fname[:-5] + 'bam').replace('/blend/', '/bam/', 1)
- cmd_args = gltf_name, bam_name
- # use dds files in place of png/jpg in gltf2bam
- copyfile(gltf_name, gltf_name + '.tmp')
- with open(gltf_name) as fgltf:
- lines = fgltf.readlines()
- deps = []
- for line in lines:
- if ('.png' in line or '.jpg' in line) and '"uri"' in line:
- rln = line[line.index('"uri"') + 9:].rstrip(',\n"')
- tname = '%s/%s' % (root, rln)
- deps += [tname.replace('/models/blend/', '/models/gltf/', 1)]
- for dep in deps:
- tgt = dep.replace('/gltf/', '/bam/', 1)
- tgt = tgt.replace('.png', '.dds').replace('.jpg', '.dds')
- makedirs(dirname(tgt), exist_ok=True)
- info('convert %s %s' % (dep, tgt))
- system('convert %s %s' % (dep, tgt))
- rpl = lambda lin: lin.replace('.png', '.dds').replace('.jpg', '.dds').replace('/png', '/dds').replace('/jpg', '/dds')
- with open(gltf_name, 'w') as fgltf:
- fgltf.write(''.join([rpl(line) for line in lines]))
- makedirs(dirname(bam_name), exist_ok=True)
- if to_be_built(bam_name, deps):
- system('gltf2bam %s %s' % cmd_args)
- self._cache_files += [bam_name] + deps
+++ /dev/null
-'''A multi-threaded command dispatcher.'''
-from datetime import datetime
-from multiprocessing import cpu_count
-from threading import Thread, RLock
-from os import system
-from logging import info, debug
-
-
-class ProcesserThread(Thread):
- '''A thread which asynchronously processes commands from a command list.'''
-
- def __init__(self, cmd_lst, lock):
- '''The constructor.
- cmd_lst: commands that can be exectuted from serveral processers
- lock: shared lock between processers for accessing the command list'''
- Thread.__init__(self)
- self.cmd_lst = cmd_lst
- self.lock = lock
-
- def run(self):
- '''The thread's logics.'''
- while True:
- with self.lock:
- if not self.cmd_lst:
- return
- cmd = self.cmd_lst.pop(0)
- info('%s %s' % (datetime.now().strftime("%H:%M:%S"), cmd))
- system(cmd)
-
-
-class SyncProcesser:
- '''Synchronously processes a command list.'''
-
- def __init__(self, cmd_lst):
- '''The constructor.
- cmd_lst: the list that must be executed'''
- self.cmd_lst = cmd_lst
-
- def run(self):
- '''The processer's logics.'''
- for cmd in self.cmd_lst:
- before_str = datetime.now().strftime("(executing) %H:%M:%S")
- info('%s %s' % (before_str, cmd))
- system(cmd)
- after_str = datetime.now().strftime("(executed) %H:%M:%S")
- debug('%s %s' % (after_str, cmd))
-
-
-class ProcesserMgr:
- '''Synchronously processes commands that are submitted (eventually) using
- multiple threads.'''
-
- def __init__(self, cores):
- '''The constructor.
- cores: how many cpu cores are used to process the commands'''
- try:
- self.cores = cpu_count()
- except NotImplementedError:
- self.cores = 1
- self.cores = cores if cores else int(self.cores / 4 + 1)
- debug('processer-mgr: using %s cores' % self.cores)
- self.cmd_lst = []
-
- def add(self, cmd):
- '''Adds cmd to the list that will be processed.'''
- self.cmd_lst += [cmd]
-
- def run(self):
- '''Performs the commands that have been added.'''
- if self.cores != 1:
- threads, lock = [], RLock()
- threads = [ProcesserThread(self.cmd_lst, lock)
- for _ in range(self.cores)]
- [thread.start() for thread in threads]
- [thread.join() for thread in threads]
- else:
- SyncProcesser(self.cmd_lst).run()
+++ /dev/null
-from os import system
-from glob import glob
-from importlib import import_module
-from inspect import isclass
-from multiprocessing import Pool
-from game.scene import Scene
-
-
-def do_screenshot(cls):
- system('python main.py --screenshot ' + cls.__name__)
-
-
-def bld_screenshots(scene_classes):
- with Pool() as p:
- p.map(do_screenshot, scene_classes)
+++ /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 lib.gameobject import GameObject
-from lib.lib.builder 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
-from lib.gameobject import AudioColleague
-from lib.lib.p3d.audio import P3dSound
-
-
-AudioSound = P3dSound
-
-
-class EngineAudio(AudioColleague):
-
- def __init__(self, mediator, vol=1.0):
- AudioColleague.__init__(self, mediator)
- self.set_volume(vol)
-
- def set_volume(self, vol): self.eng.lib.volume = vol
+++ /dev/null
-from threading import Lock
-
-
-class CallbackMux:
- # this is a sort of "multiplexer" i.e. it manages callbacks from threads
- # and redirect them to the main thread (this prevents deadlocks)
-
- def __init__(self):
- self.lock = Lock()
- self.callbacks = []
- taskMgr.add(self.process_callbacks, 'processing callbacks')
-
- def add_cb(self, func, args=None):
- args = args or []
- with self.lock: self.callbacks += [(func, args)]
-
- def process_callbacks(self, task):
- with self.lock:
- callbacks = self.callbacks[:]
- self.callbacks = []
- for func, args in callbacks: func(*args)
- return task.cont
+++ /dev/null
-class Clock:
-
- def __init__(self, pause):
- self.__paused_time = 0
- self.__curr_stopped_time = 0
- pause.logic.attach(self.on_pause)
- pause.logic.attach(self.on_resume)
-
- @property
- def time(self): return globalClock.get_frame_time() - self.__paused_time
-
- def on_pause(self): self.__curr_stopped_time = globalClock.get_frame_time()
-
- def on_resume(self):
- self.__paused_time += \
- globalClock.get_frame_time() - self.__curr_stopped_time
+++ /dev/null
-from panda3d.core import load_prc_file_data
-from lib.lib.builder import LibP3d
-
-
-class GuiCfg:
-
- def __init__(self, fps=False, win_size='1280 720', win_orig=None,
- win_title='lib', fullscreen=False, sync_video=None,
- antialiasing=False, shaders=True, volume=1, fixed_fps=0):
- self.fps = fps
- self.win_size = win_size
- self.win_title = win_title
- self.win_orig = win_orig
- self.fullscreen = fullscreen
- self.sync_video = LibP3d.runtime() if sync_video is None \
- else sync_video
- self.antialiasing = antialiasing
- self.shaders = shaders
- self.volume = volume
- self.fixed_fps = fixed_fps
-
-
-class ProfilingCfg:
-
- def __init__(self, profiling=False, pyprof_percall=False):
- self.profiling = profiling # profiling with panda3d's tools
- self.pyprof_percall = pyprof_percall
-
-
-class LangCfg:
-
- def __init__(self, lang='en', lang_path='assets/locale',
- lang_domain='lib_game', languages=[('English', 'en')]):
- self.lang = lang
- self.lang_path = lang_path
- self.lang_domain = lang_domain
- self.languages = languages
-
-
-class CursorCfg:
-
- def __init__(self, cursor_hidden=False, cursor_path='',
- cursor_scale=(1, 1, 1), cursor_color=(1, 1, 1, 1),
- cursor_hotspot=(0, 0)):
- self.cursor_hidden = cursor_hidden
- self.cursor_path = cursor_path
- self.cursor_scale = cursor_scale
- self.cursor_color = cursor_color
- self.cursor_hotspot = cursor_hotspot
-
-
-class DevCfg:
-
- def __init__(
- self, mt_render=False, model_path='assets/models', excluded='',
- shaders_dev=False, pbr=False, gamma=1.0, menu_joypad=True,
- verbose='', verbose_log=False, xmpp_server='', start_wp='',
- port=9099, server='localhost:9098', srgb=False, opengl_3_2=False,
- gl_debug=False, async_textures=False, show_buffers=False,
- anisotropic=8, pbr_normal=True, pbr_occlusion=True,
- pbr_shadows=True, pbr_exposure=True, pbr_msaa_samples=4,
- pbr_fog=True, offscreen=False, directx=False,
- functional_test=False, functional_ref=False):
- self.multithreaded_render = mt_render # multithreaded rendering
- self.model_path = model_path
- self.excluded = excluded
- self.shaders_dev = shaders_dev
- self.pbr = pbr
- self.pbr_normal = pbr_normal
- self.pbr_occlusion = pbr_occlusion
- self.pbr_shadows = pbr_shadows
- self.pbr_exposure = pbr_exposure
- self.pbr_msaa_samples = pbr_msaa_samples
- self.pbr_fog = pbr_fog
- self.gamma = gamma
- self.directx = directx
- self.menu_joypad = menu_joypad
- self.verbose = verbose
- self.verbose_log = verbose_log
- self.xmpp_server = xmpp_server
- self.port = port
- self.server = server
- self.start_wp = start_wp
- self.srgb = srgb
- self.opengl_3_2 = opengl_3_2
- self.gl_debug = gl_debug
- self.async_textures = async_textures
- self.show_buffers = show_buffers
- self.anisotropic = anisotropic
- self.offscreen = offscreen
- self.functional_test = functional_test
- self.functional_ref = functional_ref
-
-
-class Cfg:
-
- def __init__(self, gui_cfg=None, profiling_cfg=None, lang_cfg=None,
- cursor_cfg=None, dev_cfg=None):
- self.gui_cfg = gui_cfg or GuiCfg()
- self.profiling_cfg = profiling_cfg or ProfilingCfg()
- self.lang_cfg = lang_cfg or LangCfg()
- self.cursor_cfg = cursor_cfg or CursorCfg()
- self.dev_cfg = dev_cfg or DevCfg()
- self.__configure()
-
- @staticmethod
- def __set(key, val): load_prc_file_data('', key + ' ' + str(val))
-
- def __configure(self):
- cfginfo = [
- ('texture-anisotropic-degree', self.dev_cfg.anisotropic),
- # ('client-sleep', 0.001),
- ('texture-minfilter', 'linear_mipmap_linear'),
- ('gl-coordinate-system', 'default'),
- ('textures-power-2', 'down'),
- ('textures-auto-power-2', 1),
- ('show-frame-rate-meter', int(self.gui_cfg.fps)),
- ('hardware-animated-vertices', 'true'),
- ('x-init-threads', 'true'),
- # temp workaround for mtrendering (linux)
- ('basic-shaders-only', 'false'),
- ('default-model-extension', '.bam'),
- #('compressed-textures', 1), # particles don't work
- #('model-cache-textures', 1),
- #('model-cache-compressed-textures', 1),
- #('bam-version', '6 45'),
- ('audio-ouput-rate', 44100)]
- if self.gui_cfg.win_size:
- cfginfo += [('win-size', self.gui_cfg.win_size)]
- if self.gui_cfg.win_orig:
- cfginfo += [('win-origin', self.gui_cfg.win_orig)]
- if self.dev_cfg.srgb:
- cfginfo += [('framebuffer-srgb', 'true')]
- if self.dev_cfg.opengl_3_2:
- cfginfo += [('gl-version', '3 2')]
- if self.dev_cfg.gl_debug:
- cfginfo += [('gl-debug', 1)]
- if self.dev_cfg.show_buffers:
- cfginfo += [('show-buffers', 'true')]
- if self.dev_cfg.async_textures:
- cfginfo += [
- ('preload-textures', 0),
- ('preload-simple-textures', 1),
- ('texture-compression', 1),
- ('allow-incomplete-render', 1)]
- if self.dev_cfg.directx:
- cfginfo += [
- ('load-display', 'pandadx9')]
- cfginfo += [
- ('window-title', self.gui_cfg.win_title),
- ('cursor-hidden', int(self.cursor_cfg.cursor_hidden)),
- ('sync-video', int(self.gui_cfg.sync_video)),
- ('framebuffer-multisample', 1),
- ('multisamples', 2)]
- if self.dev_cfg.multithreaded_render:
- cfginfo += [('threading-model', '/Draw')]
- if self.dev_cfg.offscreen:
- cfginfo += [('window-type', 'offscreen')]
- if self.profiling_cfg.profiling:
- cfginfo += [
- ('want-pstats', 1),
- ('task-timer-verbose', 1),
- ('pstats-tasks', 1),
- ('gl-finish', 1),
- ('pstats-host', '127.0.0.1')]
- for verb in self.dev_cfg.verbose.split(';'):
- if not verb: continue
- verb_el = verb.strip().split()
- if verb_el[0] == 'direct':
- cfginfo += [
- ('default-directnotify-level', verb_el[1])]
- elif verb_el[0] == 'panda':
- cfginfo += [
- ('notify-level', verb_el[1])]
- else:
- cfginfo += [
- ('notify-level-' + verb_el[0], verb_el[1])]
- list(map(lambda args: self.__set(*args), cfginfo))
+++ /dev/null
-from sys import path
-from os.path import dirname, realpath
-path.append(dirname(realpath(__file__)) + '/../thirdparty')
-
-from lib.lib.builder import LibBuilder
-from lib.engine.pause import PauseMgr
-from lib.engine.profiler import AbsProfiler
-from lib.engine.shader import ShaderMgr
-from lib.engine.log import LogMgr
-from lib.engine.font import FontMgr
-from lib.engine.phys import PhysMgr
-from lib.engine.gfx import EngineGfx
-from lib.engine.network.server import Server
-from lib.engine.network.client import Client
-from lib.engine.gui.gui import EngineGui
-from lib.engine.logic import EngineLogic
-from lib.engine.event import EngineEvent
-from lib.engine.audio import EngineAudio
-from lib.engine.lang import LangMgr
-from lib.gameobject import GameObject, Colleague
-from lib.engine.enginefacade import EngineFacade
-from lib.engine.configuration import Cfg
-from lib.engine.cbmux import CallbackMux
-from lib.engine.clock import Clock
-
-
-class Engine(GameObject, EngineFacade):
-
- network_priority = -39
-
- def __init__(self, cfg=None, end_cb=None, client_cls=None):
- self.lib = LibBuilder.build()
- self.lib.configure()
- self.lib.init(end_cb=end_cb)
- Colleague.eng = GameObject.eng = self
- cfg = cfg or Cfg() # use a default conf if not provided
- self.shader_mgr = ShaderMgr(cfg.dev_cfg.shaders_dev, cfg.dev_cfg.gamma)
- self.profiler = AbsProfiler.build(cfg.profiling_cfg.pyprof_percall)
- self.font_mgr = FontMgr()
- self.server = Server(cfg.dev_cfg.port)
- client_cls = client_cls or Client
- self.client = client_cls(cfg.dev_cfg.port, cfg.dev_cfg.server)
- self.cb_mux = CallbackMux()
- self.logic = EngineLogic(self, cfg)
- self.log_mgr = LogMgr.init_cls()(self)
- self.gfx = EngineGfx(self, cfg.dev_cfg.model_path,
- cfg.gui_cfg.antialiasing,
- cfg.gui_cfg.shaders,
- cfg.gui_cfg.fixed_fps,
- cfg.dev_cfg.srgb)
- self.phys_mgr = PhysMgr(self)
- self.event = EngineEvent(self, cfg.dev_cfg.menu_joypad,
- cfg.dev_cfg.functional_test)
- self.gui = EngineGui.init_cls()(self)
- self.audio = EngineAudio(self, cfg.gui_cfg.volume)
- self.pause = PauseMgr(self)
- self.lang_mgr = LangMgr(cfg.lang_cfg.lang,
- cfg.lang_cfg.lang_domain,
- cfg.lang_cfg.lang_path)
- GameObject.__init__(self)
- self.clock = Clock(self.pause)
-
- def destroy(self):
- GameObject.destroy(self)
- self.lib.destroy()
- self.shader_mgr.destroy()
- self.profiler.destroy()
- self.font_mgr.destroy()
- self.server.destroy()
- self.client.destroy()
- # self.xmpp.destroy()
- self.logic.destroy()
- self.log_mgr.destroy()
- self.gfx.destroy()
- self.phys_mgr.destroy()
- self.event.destroy()
- self.gui.destroy()
- self.audio.destroy()
- self.pause.destroy()
- self.lang_mgr.destroy()
- self.lib = self.shader_mgr = self.profiler = self.font_mgr = \
- self.server = self.client = None
- base.destroy()
+++ /dev/null
-from math import pi
-
-
-class EngineFacade:
-
- @property
- def version(self): return self.logic.version
-
- @property
- def curr_path(self): return self.logic.curr_path
-
- @property
- def is_appimage(self): return self.logic.is_appimage
-
- @property
- def cfg(self): return self.logic.cfg
-
- @property
- def is_runtime(self): return self.logic.is_runtime
-
- @property
- def languages(self): return self.logic.cfg.lang_cfg.languages
-
- @property
- def resolutions(self): return self.gui.resolutions
-
- @property
- def closest_resolution(self): return self.gui.closest_resolution
-
- @property
- def joystick_mgr(self): return self.event.joystick_mgr
-
- @property
- def curr_time(self): return self.clock.time
-
- def attach_obs(self, obs_meth, sort=10, rename='', args=None):
- args = args or []
- return self.event.attach(obs_meth, sort, rename, args)
-
- def detach_obs(self, obs_meth, lambda_call=None):
- return self.event.detach(obs_meth, lambda_call)
- def attach_node(self, name): return self.gfx.root.attach_node(name)
- def particle(
- self, parent, texture, color=(1, 1, 1, 1), ampl=pi/6, ray=.5,
- rate=.0001, gravity=-.85, vel=3.8, part_duration=1.0,
- autodestroy=None, size=10):
- return self.gfx.particle(
- parent, texture, color, ampl, ray, rate, gravity, vel,
- part_duration, autodestroy, size)
- def init_gfx(self): return self.gfx.init()
- def clean_gfx(self): return self.gfx.clean()
-
- @staticmethod
- def set_cam_pos(pos): return base.camera.set_pos(pos)
-
- def load_font(self, fpath, outline=True):
- return self.eng.font_mgr.load_font(fpath, outline)
- def open_browser(self, url): return self.gui.open_browser(url)
-
- def toggle_pause(self, show_frm=True):
- return self.pause.logic.toggle(show_frm)
-
- def play(self): return self.audio.play()
- def set_volume(self, vol): return self.audio.set_volume(vol)
- def show_cursor(self): return self.gui.cursor.show()
- def show_standard_cursor(self): return self.gui.cursor.show_standard()
- def hide_cursor(self): return self.gui.cursor.hide()
- def hide_standard_cursor(self): return self.gui.cursor.hide_standard()
- def cursor_top(self): return self.gui.cursor.cursor_top()
- def set_amb_lgt(self, col): return self.shader_mgr.set_amb_lgt(col)
-
- def set_dir_lgt(self, col, direction):
- return self.shader_mgr.set_dir_lgt(col, direction)
-
- def set_shadow_lgt(self, direction):
- return self.shader_mgr.set_shadow_lgt(direction)
-
- def clear_lights(self): return self.shader_mgr.clear_lights()
- def toggle_shader(self): return self.shader_mgr.toggle_shader()
-
- def set_resolution(self, res, fullscreen=None):
- return self.gui.set_resolution(res, fullscreen)
-
- def toggle_fullscreen(self): return self.gui.toggle_fullscreen()
- def send(self, msg): return self.lib.send(msg)
-
- def do_later(self, time, meth, args=None):
- return self.lib.do_later(time, meth, args)
-
- def add_task(self, mth, priority=0):
- return self.lib.add_task(mth, priority)
-
- def remove_task(self, tsk): return self.lib.remove_task(tsk)
- def log(self, msg, verbose=False): return self.log_mgr.log(msg, verbose)
- def log_tasks(self): return self.log_mgr.log_tasks()
-
- def rm_do_later(self, tsk):
- self.pause.remove_task(tsk)
- return self.lib.remove_task(tsk)
-
- def load_model(self, filename, callback=None, anim=None):
- return self.gfx.load_model(filename, callback, anim)
+++ /dev/null
-from time import time
-from logging import info
-from lib.gameobject import EventColleague
-from lib.engine.joystick import JoystickMgr
-
-
-class EngineEvent(EventColleague):
-
- def __init__(self, mediator, emulate_keyboard, functional_test):
- EventColleague.__init__(self, mediator)
- self.unpaused_time = 0
- self._prev_time = time()
- self.eng.add_task(self.__on_frame)
- taskMgr.setupTaskChain('unpausable')
- mth = self.__on_frame_unpausable
- taskMgr.add(mth, 'unpausable', taskChain='unpausable')
- self.joystick_mgr = JoystickMgr(emulate_keyboard, functional_test)
-
- def __on_frame(self, task): # unused task
- self.notify('on_start_frame')
- self.notify('on_frame')
- self.notify('on_end_frame')
- return self.eng.lib.task_cont
-
- def __on_frame_unpausable(self, task):
- self.unpaused_time += time() - self._prev_time
- self._prev_time = time()
- try:
- self.notify('on_frame_unpausable')
- return task.cont
- except AttributeError: info("engine has been destroyed")
-
- @staticmethod
- def key2desc(keystr):
- if not keystr.startswith('raw-'): return keystr
- keystr = keystr[4:]
- kmap = base.win.get_keyboard_map()
- virt_key = kmap.get_mapped_button(keystr)
- return (kmap.get_mapped_button_label(keystr) or str(virt_key)).lower()
-
- @staticmethod
- def desc2key(desc):
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if kmap.get_mapped_button_label(i).lower() == desc:
- return str(kmap.get_mapped_button(i))
- return desc
-
- def destroy(self):
- self.joystick_mgr.destroy()
- EventColleague.destroy(self)
+++ /dev/null
-from lib.gameobject import GameObject
-
-
-class FontMgr(GameObject):
-
- def __init__(self):
- GameObject.__init__(self)
- self.__fonts = {}
-
- def load_font(self, fpath, outline=True):
- if fpath not in self.__fonts:
- self.__fonts[fpath] = self.eng.lib.load_font(fpath, outline)
- return self.__fonts[fpath]
-
- def destroy(self):
- self.__fonts = None
- GameObject.destroy(self)
+++ /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 lib.gameobject import GameObject
-from lib.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 math import pi
-from panda3d.core import ClockObject
-from lib.gameobject import GfxColleague
-from lib.engine.particle import Particle
-from lib.lib.p3d.gfx import P3dGfxMgr, P3dAnimNode, P3dAmbientLight, \
- P3dSpotlight
-
-
-GfxMgr = P3dGfxMgr
-AnimNode = P3dAnimNode
-AmbientLight = P3dAmbientLight
-Spotlight = P3dSpotlight
-
-
-class EngineGfx(GfxColleague):
-
- def __init__(self, mediator, model_path, antialiasing, shaders, fps, srgb):
- GfxColleague.__init__(self, mediator)
- self.gfx_mgr = GfxMgr(model_path, antialiasing, shaders, srgb)
- self.root = None
- self.part2eff = {}
- if fps: self.set_frame_rate(fps)
- # if self.mediator.cfg.gui_cfg.shaders and \
- # self.eng.lib.version.startswith('1.10'):
- # self.set_toon()
- # self.set_bloom()
-
- def init(self):
- self.root = self.gfx_mgr.root.attach_node('world')
-
- def clean(self): self.root.remove_node()
-
- def load_model(self, filename, callback=None, anim=None):
- try: return self.gfx_mgr.load_model(filename, callback, anim)
- except OSError:
- return self.gfx_mgr.load_model(filename + '.bam', callback, anim)
-
- def set_toon(self): self.gfx_mgr.set_toon()
-
- def set_bloom(self): self.gfx_mgr.set_bloom()
-
- def print_stats(self, two_d=True, three_d=True, analyze=True, ls=True):
- self.gfx_mgr.print_stats(two_d, three_d, analyze, ls)
-
- @staticmethod
- def set_frame_rate(fps):
- globalClock.setMode(ClockObject.MLimited)
- globalClock.set_frame_rate(fps)
- # base.set_sleep(.01)
-
- @staticmethod
- def particle(parent, texture, color=(1, 1, 1, 1), ampl=pi/6, ray=.5,
- rate=.0001, gravity=-.85, vel=3.8, part_duration=1.0,
- autodestroy=None, size=10):
- return Particle(parent, texture, color, ampl, ray, rate, gravity, vel,
- part_duration, autodestroy, size)
+++ /dev/null
-from sys import platform
-from os import environ, system
-from webbrowser import open_new_tab
-
-
-class BrowserStrategy:
-
- @staticmethod
- def open(url): open_new_tab(url)
-
-
-class BrowserStrategyLinux(BrowserStrategy):
-
- @staticmethod
- def open(url):
- environ['LD_LIBRARY_PATH'] = ''
- system('xdg-open ' + url)
-
-
-class Browser:
-
- @staticmethod
- def open(url):
- cls = BrowserStrategyLinux if platform.startswith('linux') else \
- BrowserStrategy
- cls.open(url)
+++ /dev/null
-from os import name
-from lib.lib.gui import Frame
-from lib.lib.p3d.shader import load_shader
-from lib.gameobject import GameObject
-
-
-class Circle(Frame, GameObject):
-
- def __init__(self, size=.4, pos=(0, 0), parent=None, ray=.4, thickness=.05,
- col_start=(1, 1, 1, 1), col_end=(1, 1, 1, 1)):
- GameObject.__init__(self)
- Frame.__init__(self, pos=(pos[0], pos[1]), texture_coord=True,
- frame_size=(-size, size, -size, size), parent=parent)
- path = 'assets/shaders/'
- shader = load_shader(path + 'filter.vert', path + 'circle.frag')
- drv_lst = [self.eng.lib.driver_vendor, self.eng.lib.driver_renderer,
- self.eng.lib.driver_version]
- is_nvidia = any('nvidia' in drv.lower() for drv in drv_lst)
- if shader and not (name == 'nt' and is_nvidia):
- self.set_shader(shader)
- args = [('ray', ray), ('width', thickness), ('progress', 0),
- ('color_start', col_start), ('color_end', col_end)]
- list(map(lambda arg: self.set_shader_input(*arg), args))
- else: self['frameColor'] = (1, 1, 1, 0)
- self.set_transparency(True)
-
- @property
- def progress(self): return self.get_shader_input('progress')
-
- @progress.setter
- def progress(self, val): self.set_shader_input('progress', val)
-
- def destroy(self):
- Frame.destroy(self)
- GameObject.destroy(self)
+++ /dev/null
-from panda3d.core import GraphicsWindow, WindowProperties
-from lib.lib.gui import Img
-from lib.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 lib.gameobject import GuiColleague
-from lib.engine.gui.cursor import MouseCursor
-from lib.engine.gui.browser import Browser
-
-
-up = (0, 1)
-down = (0, -1)
-left = (-1, 0)
-right = (1, 0)
-
-
-class EngineGuiBase(GuiColleague): # no win: EngineGui strictly manages win
-
- @staticmethod
- def init_cls():
- return EngineGui if EngineGuiBase.eng.lib.has_window else EngineGuiBase
-
- @staticmethod
- def open_browser(url): Browser.open(url)
-
- @property
- def resolutions(self):
- return sorted(list(set(self.eng.lib.resolutions)))
-
- @property
- def closest_resolution(self):
- def distance(res):
- curr_res = self.eng.lib.resolution
- return abs(res[0] - curr_res[0]) + abs(res[1] - curr_res[1])
-
- try:
- return min(self.resolutions, key=distance)
- except ValueError: # sometimes we have empty resolutions
- return self.eng.lib.resolution
-
- def set_resolution_check(self, res):
- res_msg = 'resolutions: {curr} (current), {res} (wanted)'
- info(res_msg.format(curr=self.eng.lib.resolution, res=res))
- if self.eng.lib.resolution == res: return
- retry = 'second attempt: {curr} (current) {res} (wanted)'
- info(retry.format(curr=self.eng.lib.resolution, res=res))
- self.set_resolution(res, False)
-
- def toggle_fullscreen(self):
- self.set_resolution(self.closest_resolution)
- self.eng.lib.toggle_fullscreen()
-
-
-class EngineGui(EngineGuiBase):
-
- def __init__(self, mediator):
- EngineGuiBase.__init__(self, mediator)
- cfg = self.eng.cfg
- res_strings = cfg.gui_cfg.win_size.split()
- res_ints = tuple(int(size) for size in res_strings)
- self.set_resolution(res_ints, fullscreen=cfg.gui_cfg.fullscreen)
- cur_cfg = cfg.cursor_cfg
- self.cursor = MouseCursor(
- cur_cfg.cursor_path, cur_cfg.cursor_scale, cur_cfg.cursor_color,
- cur_cfg.cursor_hotspot)
-
- def set_resolution(self, res, check=True, fullscreen=None):
- info('setting resolution ' + str(res))
- self.eng.lib.set_resolution(res, fullscreen)
- if check: self.eng.do_later(3.0, self.set_resolution_check, [res])
+++ /dev/null
-from lib.lib.gui import Btn
-from lib.lib.p3d.shader import load_shader
-
-
-class ImgBtn(Btn):
-
- def __init__(self, *args, **kwargs):
- Btn.__init__(self, *args, **kwargs)
- shader_dirpath = 'assets/shaders/'
- shader = load_shader(shader_dirpath + 'filter.vert',
- shader_dirpath + 'imgbtn.frag')
- if shader:
- self.set_shader(shader)
- shader_args = [('col_offset', 0), ('enable', 1)]
- list(map(lambda args: self.set_shader_input(*args), shader_args))
- self.set_transparency(True)
-
- def _on_enter(self, pos): # pos comes from mouse
- self.set_shader_input('col_offset', .25)
-
- def _on_exit(self, pos): # pos comes from mouse
- self.set_shader_input('col_offset', 0)
-
- def enable(self):
- super().enable()
- self.set_shader_input('enable', 1)
-
- def disable(self):
- super().disable()
- self.set_shader_input('enable', .2)
+++ /dev/null
-from lib.lib.gui import Text, Img
-from lib.engine.gui.page import Page, PageGui, PageFacade
-from lib.engine.gui.imgbtn import ImgBtn
-
-
-class MainPageGui(PageGui):
-
- def build(self, back_btn=True, exit_behav=False):
- #self.__build_social()
- self.__build_version()
- self.__build_dependencies()
- self._set_widgets()
- self.transition_enter()
-
- def __build_social(self):
- sites = self.props.gameprops.social_sites
- menu_props = self.props.gameprops.menu_props
- left = (len(sites) - 1) / 2.0 * .15
- buttons = [
- ImgBtn(
- parent='bottomcenter',
- scale=(.06, .06),
- pos=(-left + i*.15, .1),
- frame_col=(1, 1, 1, 1),
- frame_texture=menu_props.social_imgs_dirpath % site[0],
- cmd=self.eng.open_browser,
- extra_args=[site[1]],
- **menu_props.imgbtn_args)
- for i, site in enumerate(sites)]
- self.add_widgets(buttons)
-
- def __build_version(self):
- txt = Text(
- _('version: ') + self.eng.version, parent='bottomleft',
- pos=(.02, .02), scale=.04, fg=(.8, .8, .8, 1), align='left',
- font=self.props.gameprops.menu_props.font, wordwrap=256)
- self.add_widgets([txt])
-
- def __build_dependencies(self):
- txt = Text(
- _('made with heart with panda3d, panda3d-simplepbr, panda3d-gltf'),
- parent='bottomright', pos=(-.09, .02), scale=.04, wordwrap=128,
- fg=(.8, .8, .8, 1), align='right',
- font=self.props.gameprops.menu_props.font)
- img = Img(
- 'assets/images/gui/p3d.dds', scale=.04,
- parent=base.a2dBottomRight, pos=(-.04, .04))
- self.add_widgets([txt, img])
-
-
-class MainPage(Page, PageFacade):
- gui_cls = MainPageGui
-
- def __init__(self, mainpage_props):
- Page.__init__(self, mainpage_props)
- PageFacade.__init__(self)
+++ /dev/null
-from direct.gui.DirectGuiGlobals import FLAT
-from lib.gameobject import GuiColleague, LogicColleague, GameObject
-from lib.lib.gui import Img
-from lib.engine.audio import AudioSound
-
-
-class NavInfoPerPlayer:
-
- def __init__(self, left, right, up, down, fire):
- self.left = left
- self.right = right
- self.up = up
- self.down = down
- self.fire = fire
-
-
-class NavInfo:
-
- def __init__(self, navinfo_lst):
- self.navinfo_lst = navinfo_lst
-
-
-class MenuProps(GameObject):
-
- def __init__(
- self, font_path, text_active_col, text_normal_col, text_err_col,
- text_scale, btn_size, btn_col, background_img_path, over_sfx_path,
- click_sfx_path, social_imgs_dirpath, nav):
- GameObject.__init__(self)
- self.__font_path = font_path
- self.text_active_col = text_active_col
- self.text_normal_col = text_normal_col
- self.text_err_col = text_err_col
- self.text_scale = text_scale
- self.btn_size = btn_size
- self.btn_col = btn_col
- self.background_img_path = background_img_path
- self.__over_sfx_path = over_sfx_path
- self.__click_sfx_path = click_sfx_path
- self.social_imgs_dirpath = social_imgs_dirpath
- self.nav = nav
-
- @property
- def font(self): return self.eng.font_mgr.load_font(self.__font_path)
-
- @property
- def over_sfx(self): return AudioSound(self.__over_sfx_path).snd
-
- @property
- def click_sfx(self): return AudioSound(self.__click_sfx_path).snd
-
- @property
- def btn_args(self): # it may be used without a menu e.g. results
- return {
- 'scale': (self.text_scale, self.text_scale),
- 'text_font': self.font,
- 'text_fg': self.text_active_col,
- 'frame_col': self.btn_col,
- 'frame_size': self.btn_size,
- 'over_snd': self.over_sfx,
- 'click_snd': self.click_sfx}
-
- @property
- def imgbtn_args(self):
- return {
- 'over_snd': self.over_sfx,
- 'click_snd': self.click_sfx}
-
- @property
- def label_args(self):
- return {
- 'scale': self.text_scale,
- 'text_fg': self.text_normal_col,
- 'text_font': self.font,
- 'frame_col': (1, 1, 1, 0)}
-
- @property
- def option_args(self):
- tfg = self.text_active_col
- return {
- 'scale': self.text_scale,
- 'text_font': self.font,
- 'text_fg': tfg,
- 'frame_col': self.btn_col,
- 'frame_size': self.btn_size,
- 'over_snd': self.over_sfx,
- 'click_snd': self.click_sfx,
- 'text_scale': .85,
- 'item_text_font': self.font,
- 'item_frame_col': tfg,
- 'item_relief': FLAT,
- 'popup_marker_col': self.btn_col,
- 'text_may_change': 1,
- 'highlight_col': (tfg[0] * 1.2, tfg[1] * 1.2, tfg[2] * 1.2, .2)}
-
- @property
- def checkbtn_args(self):
- return {
- 'scale': self.text_scale,
- 'text_font': self.font,
- 'text_fg': self.text_active_col,
- 'frame_col': self.btn_col,
- 'over_snd': self.over_sfx,
- 'click_snd': self.click_sfx}
-
- @property
- def text_args(self):
- return {
- 'scale': self.text_scale,
- 'fg': self.text_normal_col,
- 'font': self.font}
-
-
-class MenuGui(GuiColleague):
-
- def __init__(self, mediator, menu_props):
- GuiColleague.__init__(self, mediator)
- self.menu_props = menu_props
- self.background = None
- if not self.menu_props.background_img_path: return
- self.background = Img(self.menu_props.background_img_path,
- scale=(1.77778, 1, 1.0),
- background=True)
-
- def destroy(self):
- if self.background: self.background.destroy()
- self.menu_props = self.background = None
- GuiColleague.destroy(self)
-
-
-class MenuLogic(LogicColleague):
-
- def __init__(self, mediator):
- LogicColleague.__init__(self, mediator)
- self.pages = []
-
- def push_page(self, page):
- if self.pages:
- self.pages[-1].hide()
- if len(self.pages) > 1: # first page doesn't go back
- self.pages[-1].detach_obs(self.on_back)
- self.pages[-1].detach_obs(self.on_quit)
- self.pages += [page]
- list(map(
- page.attach_obs, [self.on_back, self.on_quit, self.on_push_page]))
-
- def enable(self): self.pages[-1].enable()
-
- def enable_navigation(self): self.pages[-1].enable_navigation()
-
- def disable(self): self.pages[-1].disable()
-
- def disable_navigation(self): self.pages[-1].disable_navigation()
-
- def on_push_page(self, page_code, args=None): pass
-
- def __back_quit_tmpl(self, idx, fun):
- page = self.pages.pop()
- list(map(page.detach_obs, [self.on_back, self.on_quit]))
- page.destroy()
- fun()
- self.pages[idx].show()
- list(map(self.pages[idx].attach_obs, [self.on_back, self.on_quit]))
-
- def on_back(self):
- self.__back_quit_tmpl(-1, lambda: None)
-
- def on_quit(self):
- def __on_quit():
- while len(self.pages) > 1:
- page = self.pages.pop()
- page.destroy()
- self.__back_quit_tmpl(0, __on_quit)
-
- def destroy(self):
- list(map(lambda page: page.destroy(), self.pages))
- self.pages = None
- LogicColleague.destroy(self)
-
-
-class MenuFacade:
-
- def push_page(self, page): return self.logic.push_page(page)
- def attach_obs(self, obs_meth, sort=10, rename='', args=None):
- return self.gui.attach(obs_meth, sort, rename, args or [])
- def detach_obs(self, obs_meth, lambda_call=None):
- return self.gui.detach(obs_meth, lambda_call)
- def enable(self): return self.gui.enable()
- def enable_navigation(self): return self.gui.enable_navigation()
-
-
-class Menu(GameObject, MenuFacade):
- gui_cls = MenuGui
- logic_cls = MenuLogic
-
- def __init__(self, menu_props):
- GameObject.__init__(self)
- self.logic = self.logic_cls(self)
- self.__menu_props = menu_props
- self._build_gui()
-
- def _build_gui(self):
- self.gui = self.gui_cls(self, self.__menu_props)
-
- def destroy(self):
- self.logic.destroy()
- self.gui.destroy()
- GameObject.destroy(self)
+++ /dev/null
-from inspect import getmro
-from lib.lib.gui import Btn, Slider, CheckBtn, OptionMenu, Entry
-from lib.engine.vec import Vec2
-from lib.engine.gui.gui import left, right, up, down
-from lib.gameobject import GameObject, GuiColleague, EventColleague
-from lib.engine.gui.imgbtn import ImgBtn
-
-
-class PageGui(GuiColleague):
-
- def __init__(self, mediator, menu_props, players=[0]):
- GuiColleague.__init__(self, mediator)
- self.enable_tsk = None
- self._back_btn = None
- self.menu_props = menu_props
- self.players = players
- self.widgets = []
- self.build()
- self.translate()
- self.curr_wdgs = []
- for player in players:
- self.curr_wdgs += [
- self.__next_wdg((-.1, -1), player, Vec2(-3.6, 1))]
- if self.curr_wdgs[-1]:
- self.curr_wdgs[-1].on_wdg_enter(None, player)
-
- def build(self, back_btn=True, exit_behav=False):
- if back_btn: self.__build_back_btn(exit_behav)
- self._set_widgets()
- self._set_entries()
- self.transition_enter()
- self.eng.cursor_top()
-
- def add_widgets(self, widgets): self.widgets += widgets
-
- def on_arrow(self, direction, player):
- if not self.curr_wdgs[player]: return
- if self.curr_wdgs[player].__class__.__name__ == 'P3dEntryWidget' and \
- self.curr_wdgs[player].focused: return
- processed_cmd = self.curr_wdgs[player].on_arrow(direction)
- # e.g. up/down in a combobox or left/right in a slider
- if processed_cmd: return
- next_wdg = self.__next_wdg(direction, player)
- if not next_wdg: return
- self.focus(next_wdg, player)
-
- def on_enter(self, player):
- if not self.curr_wdgs[player]: return
- arg = player if len(self.players) > 1 else None
- if self.curr_wdgs[player].on_enter(arg): self.enable([player])
- # wdg.on_enter returns True when it is an option widget
-
- @property
- def buttons(self):
- is_btn = lambda wdg: Btn in getmro(wdg.__class__)
- return [wdg for wdg in self.widgets if is_btn(wdg)]
-
- def focus(self, wdg, player):
- self.curr_wdgs[player].on_wdg_exit(None, player)
- self.curr_wdgs[player] = wdg
- self.curr_wdgs[player].on_wdg_enter(None, player)
-
- def __direction_dot_dwg(self, wdg, direction, player, start=None):
- if start: start_pos = start
- else: start_pos = self.curr_wdgs[player].pos
- return (wdg.pos - start_pos).normalized.dot(direction)
-
- def __next_weight(self, wdg, direction, player, start=None):
- if start: start_pos = start
- else: start_pos = self.curr_wdgs[player].global_pos
- dot = self.__direction_dot_dwg(wdg, direction, player, start)
- if direction in [(-1, 0), (1, 0)]:
- proj_dist = abs(wdg.global_pos.x - start_pos.x)
- else: proj_dist = abs(wdg.global_pos.y - start_pos.y)
- weights = [.5, .5] if direction in [left, right] else [.1, .9]
- return weights[0] * (dot * dot) + weights[1] * (1 - proj_dist)
-
- def __next_wdg(self, direction, player, start=None):
- # interactive classes
- iclss = [Btn, CheckBtn, Slider, OptionMenu, ImgBtn, Entry]
- inter = lambda wdg: any(pcl in iclss for pcl in getmro(wdg.__class__))
- allwdgs = [wdg for wdg in self.widgets if inter(wdg)]
- wdgs = list(filter(lambda wdg: wdg.is_enabled, allwdgs))
- if player < len(self.curr_wdgs) and self.curr_wdgs[player] \
- and self.curr_wdgs[player] in wdgs:
- # the last check for this case: multiple players appear on the
- # same button, one player clicks it, another moves from it
- wdgs.remove(self.curr_wdgs[player])
- mth = self.__direction_dot_dwg
- in_direction = lambda wdg: mth(wdg, direction, player, start) > .1
- dirwdgs = list(filter(in_direction, wdgs))
- if not dirwdgs: return None
- nextweight = lambda wdg: \
- self.__next_weight(wdg, direction, player, start)
- return max(dirwdgs, key=nextweight)
-
- def _set_widgets(self):
- list(map(lambda wdg: wdg.set_widget(), self.widgets))
-
- def _set_entries(self):
- for wdg in self.widgets:
- if wdg.__class__.__name__ == 'P3dEntryWidget':
- wdg.attach(self.on_entry_enter)
- wdg.attach(self.on_entry_exit)
-
- def on_entry_enter(self):
- if self.menu_props: # i.e. not destroyed
- self.disable_navigation(self.players)
-
- def on_entry_exit(self):
- if self.menu_props: # i.e. not destroyed
- self.enable_navigation(self.players)
-
- def transition_enter(self):
- self.translate()
- list(map(lambda wdg: wdg.set_enter_transition(), self.widgets))
- self.enable(self.players)
-
- def translate(self): list(map(lambda wdg: wdg.translate(), self.widgets))
-
- def enable_navigation(self, players):
- if self.enable_tsk: self.eng.rm_do_later(self.enable_tsk)
- self.enable_tsk = self.eng.do_later(
- .01, self.enable_navigation_aux, [players])
-
- def update_navigation(self):
- self.disable_navigation(self.players)
- self.enable_navigation(self.players)
-
- def enable_navigation_aux(self, players):
- navs = []
- for player in players:
- nav = self.menu_props.nav.navinfo_lst[player]
- evts = [
- (self.eng.lib.remap_str(nav.left), self.on_arrow,
- [left, player]),
- (self.eng.lib.remap_str(nav.right), self.on_arrow,
- [right, player]),
- (self.eng.lib.remap_str(nav.up), self.on_arrow, [up, player]),
- (self.eng.lib.remap_str(nav.down), self.on_arrow,
- [down, player]),
- (self.eng.lib.remap_str(nav.fire), self.on_enter, [player])]
- def append_up(evt): return evt + ('' if evt.endswith('-up') else '-up')
- evts = [(append_up(evt[0]), evt[1], evt[2]) for evt in evts]
- navs += [nav]
- list(map(lambda args: self.mediator.event.accept(*args), evts))
- self.eng.joystick_mgr.bind_keyboard(navs)
- if self.eng.cfg.dev_cfg.menu_joypad and self._back_btn:
- self.mediator.event.accept('joypad0-face_b-up', self.__back_wrapper)
-
- def __back_wrapper(self):
- if not self.eng.joystick_mgr.is_recording: self._back_btn['command']()
-
- def disable_navigation(self, players):
- if self.enable_tsk:
- self.enable_tsk = self.eng.rm_do_later(self.enable_tsk)
- for player in players:
- nav = self.menu_props.nav.navinfo_lst[player]
- # evts = [nav.left, nav.right, nav.up, nav.down, nav.fire]
- evts = [
- self.eng.lib.remap_str(nav.left),
- self.eng.lib.remap_str(nav.right),
- self.eng.lib.remap_str(nav.up),
- self.eng.lib.remap_str(nav.down),
- self.eng.lib.remap_str(nav.fire)]
- def append_up(evt): return evt + ('' if evt.endswith('-up') else '-up')
- evts = [append_up(evt) for evt in evts]
- self.eng.joystick_mgr.unbind_keyboard()
- list(map(self.mediator.event.ignore, evts))
- self.mediator.event.ignore('joypad0-face_b-up')
-
- def enable(self, players):
- self.enable_navigation(players)
- list(map(lambda wdg: wdg.enable(), self.widgets))
-
- def disable(self, players):
- if self.enable_tsk:
- self.enable_tsk = self.eng.rm_do_later(self.enable_tsk)
- self.disable_navigation(players)
- list(map(lambda wdg: wdg.disable(), self.widgets))
-
- def transition_exit(self, destroy=True):
- list(map(lambda wdg: wdg.set_exit_transition(destroy), self.widgets))
- self.disable(self.players)
-
- def __build_back_btn(self, exit_behav):
- tra_src = 'Quit' if exit_behav else 'Back'
- tra_tra = _('Quit') if exit_behav else _('Back')
- callback = self._on_quit if exit_behav else self._on_back
- btn = Btn(text='', pos=(0, -.85), cmd=callback,
- tra_src=tra_src, tra_tra=tra_tra, **self.menu_props.btn_args)
- self.widgets += [btn]
- self._back_btn = btn
-
- def _on_back(self, player=0):
- self.notify('on_back', self.__class__.__name__)
-
- def _on_quit(self): self.notify('on_quit', self.__class__.__name__)
-
- def show(self):
- visible_widgets = [wdg for wdg in self.widgets if wdg.was_visible]
- list(map(lambda wdg: wdg.show(), visible_widgets))
- self.transition_enter()
-
- def hide(self):
- for wdg in self.widgets: wdg.was_visible = not wdg.hidden
- self.transition_exit(False)
- self.notify('on_hide')
-
- def destroy(self):
- self.transition_exit()
- self.menu_props = None
-
-
-class PageEvent(EventColleague):
-
- def on_back(self): pass
-
- def on_quit(self): pass
-
-
-class PageFacade:
-
- def show(self): return self.gui.show()
- def hide(self): return self.gui.hide()
- def enable(self, players): return self.gui.enable(players)
- def disable(self, players): return self.gui.disable(players)
-
- def enable_navigation(self, players):
- return self.gui.enable_navigation(players)
-
- def disable_navigation(self, players):
- return self.gui.disable_navigation(players)
-
- def attach_obs(self, obs_meth, sort=10, rename='', args=None):
- return self.gui.attach(obs_meth, sort, rename, args or [])
-
- def detach_obs(self, obs_meth, lambda_call=None):
- return self.gui.detach(obs_meth, lambda_call)
-
-
-class Page(GameObject, PageFacade):
-
- gui_cls = PageGui
- event_cls = PageEvent
-
- def __init__(self, menu_props, players=[0]):
- PageFacade.__init__(self)
- self.menu_props = menu_props
- self.players = players
- GameObject.__init__(self)
- self._build_event()
- self._build_gui()
- list(map(self.gui.attach, [self.on_hide, self.on_back, self.on_quit]))
-
- def _build_event(self):
- self.event = self.event_cls(self)
-
- def _build_gui(self):
- self.gui = self.gui_cls(self, self.menu_props, self.players)
-
- def on_hide(self): self.event.ignoreAll()
-
- def on_back(self, cls_name, args=None): self.event.on_back() # unused arg
-
- def on_quit(self, cls_name): self.event.on_quit() # unused arg
-
- def destroy(self):
- self.event.destroy()
- self.gui.destroy()
- bases = [basecls for basecls in Page.__bases__
- if basecls != PageFacade]
- for cls in bases: cls.destroy(self)
+++ /dev/null
-from lib.gameobject import GameObject
-from lib.lib.p3d.joystick import P3dJoystickMgr as JoystickMgrLib
-
-
-class JoystickState:
-
- def __init__(self):
- self.x = self.y = self.b0 = self.b1 = self.b2 = self.b3 = \
- self.dpad_l = self.dpad_r = self.dpad_u = self.dpad_d = \
- self.ltrigger = self.rtrigger = self.ltrigger_known = \
- self.rtrigger_known = self.lshoulder = self.rshoulder = \
- self.lstick = self.rstick = 0
- #TODO: rename bi to btni
-
-
-class JoystickMgr(GameObject):
-
- def __init__(self, emulate_keyboard, functional_test):
- GameObject.__init__(self)
- self.emulate_keyboard = emulate_keyboard
- self._fun_tst = functional_test
- self.old = [JoystickState() for i in range(3)]
- self.nav = None
- self.is_recording = False
- self.joystick_lib = JoystickMgrLib()
- self.joystick_lib.init_joystick()
- self.eng.do_later(.01, self.eng.attach_obs, [self.on_frame])
- # eng.event doesn't exist
- #if self.emulate_keyboard:
- self.set_keyboard_emulation()
-
- def set_keyboard_emulation(self):
- num_joysticks =1 if self._fun_tst else self.joystick_lib.num_joysticks
- for i in range(num_joysticks):
- base.accept('joypad%s-dpad_left-up' % i, self.__keyb_evt, [i, 'left'])
- base.accept('joypad%s-dpad_right-up' % i, self.__keyb_evt, [i, 'right'])
- base.accept('joypad%s-dpad_up-up' % i, self.__keyb_evt, [i, 'up'])
- base.accept('joypad%s-dpad_down-up' % i, self.__keyb_evt, [i, 'down'])
- base.accept('joypad%s-face_a-up' % i, self.__keyb_evt, [i, 'fire'])
-
- def __keyb_evt(self, i, evt):
- if not self.is_recording and self.nav:
- self.eng.send(str(getattr(self.nav[i], evt)) + '-up')
- # if the user chose a number
-
- def on_frame(self):
- #if not self.emulate_keyboard: return
- for i in range(self.joystick_lib.num_joysticks): self.__process(i)
-
- def __process(self, i):
- j_x, j_y, btn0, btn1, btn2, btn3, dpad_l, dpad_r, dpad_u, dpad_d, \
- trigger_l, trigger_r, shoulder_l, shoulder_r, stick_l, stick_r, \
- trigger_l_known, trigger_r_known = \
- self.joystick_lib.get_joystick(i)
- # if not self.is_recording:
- # if self.old[i].x <= -.4 <= j_x or self.old[i].dpad_l and \
- # not dpad_l:
- # if self.nav and i < len(self.nav) and self.nav[i]:
- # self.eng.send(self.nav[i].left)
- # if self.old[i].x >= .4 >= j_x or self.old[i].dpad_r and not dpad_r:
- # if self.nav and i < len(self.nav) and self.nav[i]:
- # self.eng.send(self.nav[i].right)
- # if self.old[i].y >= .4 >= j_y or self.old[i].dpad_d and not dpad_d:
- # if self.nav and i < len(self.nav) and self.nav[i]:
- # self.eng.send(self.nav[i].down)
- # if self.old[i].y <= -.4 <= j_y or self.old[i].dpad_u and not dpad_u:
- # if self.nav and i < len(self.nav) and self.nav[i]:
- # self.eng.send(self.nav[i].up)
- # if self.old[i].b0 and not btn0:
- # if self.nav and i < len(self.nav) and self.nav[i] and \
- # not self.is_recording:
- # self.eng.send(self.nav[i].fire)
- # self.eng.send('joypad%s_face_x' % i)
- # if self.old[i].b1 and not btn1:
- # self.eng.send('joypad%s_face_y' % i)
- # if self.old[i].b2 and not btn2:
- # self.eng.send('joypad%s_face_a' % i)
- # if self.old[i].b3 and not btn3:
- # self.eng.send('joypad%s_face_b' % i)
- if self.old[i].ltrigger and not trigger_l and not trigger_l_known:
- #self.eng.send('joypad_trigger_l')
- self.eng.send('joypad%s-ltrigger-up' % i)
- if self.old[i].rtrigger and not trigger_r and not trigger_r_known:
- #self.eng.send('joypad_trigger_r')
- self.eng.send('joypad%s-rtrigger-up' % i)
- # if self.old[i].shoulder_l and not shoulder_l:
- # self.eng.send('joypad_shoulder_l')
- # self.eng.send('joypad%s_shoulder_l' % i)
- # if self.old[i].shoulder_r and not shoulder_r:
- # self.eng.send('joypad_shoulder_r')
- # self.eng.send('joypad%s_shoulder_r' % i)
- # if self.old[i].stick_l and not stick_l:
- # self.eng.send('joypad_stick_l')
- # self.eng.send('joypad%s_stick_l' % i)
- # if self.old[i].stick_r and not stick_r:
- # self.eng.send('joypad_stick_r')
- # self.eng.send('joypad%s_stick_r' % i)
- self.old[i].x, self.old[i].y, self.old[i].b0, self.old[i].b1, \
- self.old[i].b2, self.old[i].b3, self.old[i].dpad_l, \
- self.old[i].dpad_r, self.old[i].dpad_u, self.old[i].dpad_d, \
- self.old[i].ltrigger, self.old[i].rtrigger, \
- self.old[i].lshoulder, self.old[i].rshoulder, \
- self.old[i].lstick, self.old[i].rstick = \
- j_x, j_y, btn0, btn1, btn2, btn3, dpad_l, dpad_r, dpad_u, dpad_d, \
- trigger_l, trigger_r, shoulder_l, shoulder_r, stick_l, stick_r
-
- def get_joystick(self, player_idx):
- x, y, face_a, face_b, face_x, face_y, dpadl, dpadr, dpadu, dpadd, triggl, \
- triggr, shl, shr, st_l, st_r, trl_k, trr_k= \
- self.joystick_lib.get_joystick(player_idx)
- jstate = JoystickState()
- jstate.x = x
- jstate.y = y
- jstate.face_a = face_a
- jstate.face_b = face_b
- jstate.face_x = face_x
- jstate.face_y = face_y
- jstate.dpad_l = dpadl
- jstate.dpad_r = dpadr
- jstate.dpad_u = dpadu
- jstate.dpad_d = dpadd
- jstate.ltrigger = triggl
- jstate.ltrigger_known = trl_k
- jstate.rtrigger = triggr
- jstate.rtrigger_known = trr_k
- jstate.lshoulder = shl
- jstate.rshoulder = shr
- jstate.lstick = st_l
- jstate.rstick = st_r
- return jstate
-
- def get_joystick_val(self, player_idx, code):
- j_x, j_y, btn0, btn1, btn2, btn3, dpad_l, dpad_r, dpad_u, dpad_d, \
- trigger_l, trigger_r, shoulder_l, shoulder_r, stick_l, stick_r = \
- self.joystick_lib.get_joystick(player_idx)
- code2val = {
- 'face_x': btn0,
- 'face_y': btn1,
- 'face_a': btn2,
- 'face_b': btn3,
- 'dpad_l': dpad_l,
- 'dpad_r': dpad_r,
- 'dpad_u': dpad_u,
- 'dpad_d': dpad_d,
- 'trigger_l': trigger_l,
- 'trigger_r': trigger_r,
- 'shoulder_l': shoulder_l,
- 'shoulder_r': shoulder_r,
- 'stick_l': stick_l,
- 'stick_r': stick_r}
- return code2val[code]
-
- def bind_keyboard(self, nav): self.nav = nav
-
- def unbind_keyboard(self): self.nav = None
-
- def destroy(self):
- try: self.eng.detach_obs(self.on_frame)
- except KeyError: pass
- # it happens in unit tests since it destroys in the same frame
- # remove this catch when i've refactored the object's building
- # and i don't use the director anymore
- self.joystick_lib.destroy()
- GameObject.destroy(self)
+++ /dev/null
-from logging import info
-from os.path import join, exists, dirname
-from gettext import translation
-from pathlib import Path
-from lib.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 lib.gameobject import Colleague
-from lib.lib.builder 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 os.path import exists
-from logging import info
-from sys import argv
-from lib.gameobject import LogicColleague
-from lib.engine.configuration import Cfg
-from lib.gameobject import GameObject
-from lib.computer_proxy import ComputerProxy, compute_once
-
-
-class VersionChecker(GameObject, ComputerProxy):
-
- def __init__(self):
- GameObject.__init__(self)
- ComputerProxy.__init__(self)
-
- @compute_once
- def is_uptodate(self):
- return True # currently the server part is not active
- self.eng.client.register_rpc('srv_version')
- try: ver = self.eng.client.srv_version()
- except AttributeError:
- print("can't retrieve the version")
- return True
- major, minor, build = ver.split('.')
- major, minor, build = int(major), int(minor), int(build)
- curr_ver = self.eng.version
- if curr_ver == 'deploy-ng': return True
- info('versions: %s %s' % (curr_ver, ver))
- return curr_ver >= ver
- # curr_major, curr_minor, curr_build = curr_ver.split('-')[0].split('.')
- # curr_major = int(curr_major)
- # curr_minor = int(curr_minor)
- # curr_build = int(curr_build)
- # return curr_major > major or \
- # curr_major == major and curr_minor > minor or \
- # curr_major == major and curr_minor == minor and curr_build >= build
-
- def destroy(self):
- GameObject.destroy(self)
- # ComputerProxy.destroy(self) # raises an exception
-
-
-class EngineLogic(LogicColleague):
-
- @staticmethod
- def cmd_line():
- return [arg for arg in iter(argv[1:]) if not arg.startswith('-psn_')]
-
- def __init__(self, mediator, cfg=None):
- LogicColleague.__init__(self, mediator)
- self.cfg = cfg or Cfg() # use a default conf if not provided
-
- @property
- def version(self):
- #if not self.is_runtime:
- # if not exists('assets/version.txt'): return '-'
- # with open('assets/version.txt') as fver:
- # return fver.read().strip() + '-source'
- # ^ --version goes here
- return self.mediator.lib.build_version
-
- @property
- def is_runtime(self):
- return self.mediator.lib.runtime()
-
- @property
- def curr_path(self):
- return self.mediator.lib.curr_path + '/' \
- if self.is_runtime else ''
-
- @property
- def is_appimage(self):
- return self.mediator.lib.is_appimage
-
- def destroy(self):
- self.cfg = None
- LogicColleague.destroy(self)
+++ /dev/null
-from struct import Struct, calcsize, unpack
-
-
-class BinaryData:
-
- @staticmethod
- def pack(lst):
- acc_fmt = '!'
- acc_elems = []
- acc_header = ''
- acc_header = BinaryData._header_lst(lst, acc_header)
- lst = [acc_header] + lst
- acc_fmt, acc_elems = BinaryData._pack_lst(lst, acc_fmt, acc_elems)
- msg_struct = Struct(acc_fmt)
- msg_data = msg_struct.pack(*acc_elems)
- return msg_struct.size, msg_data
-
- @staticmethod
- def _header_elm(elm, acc_header):
- if elm is None: add = 'n'
- elif isinstance(elm, bool): add = 'b'
- elif isinstance(elm, int): add = 'i'
- elif isinstance(elm, float): add = 'f'
- elif isinstance(elm, str): add = 's'
- elif isinstance(elm, dict): add = '{}'
- elif isinstance(elm, tuple) or isinstance(elm, list):
- add = BinaryData._header_lst(elm, acc_header)
- return acc_header + add
-
- @staticmethod
- def _header_lst(elm, acc_header):
- add = '('
- for sub_elm in elm:
- add += BinaryData._header_elm(sub_elm, acc_header)
- add += ')'
- return acc_header + add
-
- @staticmethod
- def _pack_lst(lst, acc_fmt, acc_elems):
- add_fmt, add_elems = '', []
- for sub_elm in lst:
- elm_fmt, elm_elems = BinaryData._pack_elm(sub_elm, '', [])
- add_fmt += elm_fmt
- add_elems += elm_elems
- return acc_fmt + add_fmt, acc_elems + add_elems
-
- @staticmethod
- def _pack_elm(elm, acc_fmt, acc_elems):
- if elm is None:
- add_fmt = ''
- add_elems = []
- elif isinstance(elm, bool):
- add_fmt = '?'
- add_elems = [elm]
- elif isinstance(elm, int):
- add_fmt = 'i'
- add_elems = [elm]
- elif isinstance(elm, float):
- add_fmt = 'f'
- add_elems = [elm]
- elif isinstance(elm, str):
- b_str = bytes(elm, 'utf-8')
- add_fmt = 'i%ds' % len(b_str)
- add_elems = [len(b_str), b_str]
- elif isinstance(elm, tuple) or isinstance(elm, list):
- add_fmt, add_elems = BinaryData._pack_lst(elm, '', [])
- elif isinstance(elm, dict): add_fmt, add_elems = '', []
- return acc_fmt + add_fmt, acc_elems + add_elems
-
- @staticmethod
- def unpack(data):
- header_length, data = BinaryData.unpack_helper('!i', data)
- header_length = header_length[0]
- header, data = BinaryData.unpack_helper('!%ds' % header_length, data)
- header = header[0].decode('utf-8')
- vals = []
- curr_lst = vals
-
- def parent(sublist, lst):
- if sublist in lst: return lst
- for _subl in [elm for elm in lst if isinstance(elm, list)]:
- if parent(sublist, _subl): return parent(sublist, _subl)
- for elm in header:
- if elm == '(':
- curr_lst += [[]]
- curr_lst = curr_lst[-1]
- elif elm == ')':
- curr_lst = parent(curr_lst, vals)
- elif elm == '{': pass
- elif elm == '}': curr_lst += [{}]
- else:
- val, data = BinaryData._unpack_elm(elm, data)
- curr_lst += [val]
- return vals[0]
-
- @staticmethod
- def _unpack_elm(elm, data):
- if elm == 'n':
- val, data = [None], data
- val = val[0]
- elif elm == 'b':
- val, data = BinaryData.unpack_helper('!?', data)
- val = val[0]
- elif elm == 'i':
- val, data = BinaryData.unpack_helper('!i', data)
- val = val[0]
- elif elm == 'f':
- val, data = BinaryData.unpack_helper('!f', data)
- val = val[0]
- elif elm == 's':
- s_len, data = BinaryData.unpack_helper('!i', data)
- val, data = BinaryData.unpack_helper('!%ds' % s_len, data)
- val = val[0].decode('utf-8')
- return val, data
-
- @staticmethod
- def unpack_helper(fmt, data):
- size = calcsize(fmt)
- return unpack(fmt, data[:size]), data[size:]
+++ /dev/null
-from queue import Queue
-from lib.engine.network.network import AbsNetwork, NetworkThread, msg_rpc_call
-from lib.engine.network.binary import BinaryData
-
-
-class ClientThread(NetworkThread):
-
- def __init__(self, srv_addr, eng, port):
- self.srv_addr = srv_addr
- NetworkThread.__init__(self, eng, port)
- self.msgs = Queue()
- self.rpc_ret = Queue()
-
- def _configure_socket(self):
- self.tcp_sock.connect((self.srv_addr, self.port))
-
- def _rpc_cb(self, data, sock):
- self.rpc_ret.put(data)
-
- def _queue(self, sock):
- return self.msgs
-
- def send_msg(self, msg, receiver=None): self.msgs.put(msg)
-
- def do_rpc(self, funcname, *args, **kwargs):
- args = list(args)
- msg_size, msg_data = BinaryData.pack(
- [msg_rpc_call, funcname, args, kwargs])
- self.msgs.put((msg_size, msg_data))
- return self.rpc_ret.get()
-
-
-class Client(AbsNetwork):
-
- def __init__(self, port, srv_addr):
- AbsNetwork.__init__(self, port)
- self.srv_addr = srv_addr
- self._functions = []
-
- def start(self, read_cb):
- return AbsNetwork.start(self, read_cb)
-
- def _bld_netw_thr(self):
- srv, port = self.srv_addr.split(':')
- return ClientThread(srv, self.eng, int(port))
-
- def _configure_udp(self): pass
-
- def send_udp(self, data_lst, sender):
- host, port = self.srv_addr.split(':')
- msg_size, msg_data = BinaryData.pack([sender] + data_lst)
- self.udp_sock.sendto(msg_data, (host, int(port)))
-
- def register_rpc(self, funcname): self._functions += [funcname]
-
- def unregister_rpc(self, funcname): self._functions.remove(funcname)
-
- def __getattr__(self, attr):
- if attr not in self._functions: raise AttributeError(attr)
-
- def do_rpc(*args, **kwargs):
- return self.netw_thr.do_rpc(attr, *args, **kwargs)
- return do_rpc
+++ /dev/null
-from socket import socket, AF_INET, SOCK_DGRAM, error, SOCK_STREAM, \
- SOL_SOCKET, SO_REUSEADDR
-from traceback import print_exc
-from logging import info
-from select import select
-from time import sleep
-from queue import Empty
-from threading import Thread
-from struct import Struct, error as unpack_error
-from _thread import interrupt_main
-from lib.gameobject import GameObject
-from lib.engine.network.binary import BinaryData
-
-
-msg_rpc_call, msg_rpc_answ = range(2)
-
-
-class _ConnectionError(Exception): pass
-
-
-class NetworkThread(Thread):
-
- def __init__(self, eng, port):
- Thread.__init__(self)
- self.port = port
- self.daemon = True
- self.eng = eng
- self.is_running = True
- self.size_struct = Struct('!I')
- self.tcp_sock = socket(AF_INET, SOCK_STREAM)
- self.tcp_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
- self._configure_socket()
- self.connections = [self.tcp_sock]
-
- def run(self):
- while self.is_running:
- sleep(.001)
- try:
- readable, writable, exceptional = select(
- self.connections, self.connections, self.connections, 1)
- for sock in readable: self._process_read(sock)
- for sock in writable: self._process_write(sock)
- for sock in exceptional: print('exception', sock.getpeername())
- except (error, AttributeError) as exc: print_exc()
- # AttributeError happens when the server user exits from a race,
- # then destroy is being called but _process_read is still alive
- # and self.eng.cb_mux.add_cb is invoked, but self.eng in None
- except Exception as exc:
- print_exc()
- interrupt_main()
-
- def _process_read(self, sock):
- try:
- data = self.recv_one_msg(sock)
- if data:
- try:
- msg = BinaryData.unpack(data)
- if msg[0] == msg_rpc_call:
- funcname, args, kwargs = msg[1:]
- self._rpc_cb(funcname, args, kwargs, sock)
- elif msg[0] == msg_rpc_answ:
- self._rpc_cb(msg[1], sock)
- else:
- args = [msg, sock]
- self.eng.cb_mux.add_cb(self.read_cb, args)
- except unpack_error as exc:
- print(exc)
- print_exc()
- except (_ConnectionError, TypeError) as exc:
- print_exc()
- self.notify('on_disconnected', sock)
- self.connections.remove(sock)
-
- def _process_write(self, sock):
- try:
- msg_size, msg_data = self._queue(sock).get_nowait()
- sock.sendall(self.size_struct.pack(msg_size))
- sock.sendall(msg_data)
- except Empty: pass
-
- def recv_one_msg(self, sock):
- lengthbuf = self.recvall(sock, self.size_struct.size)
- try: length = self.size_struct.unpack(lengthbuf)[0]
- except unpack_error as exc:
- print(exc)
- raise _ConnectionError()
- return self.recvall(sock, length)
-
- @staticmethod
- def recvall(sock, cnt):
- buf = b''
- while cnt:
- newbuf = sock.recv(cnt)
- if not newbuf: return None
- buf, cnt = buf + newbuf, cnt - len(newbuf)
- return buf
-
- def destroy(self):
- self.is_running = False
- self.tcp_sock.close()
- self.eng = self.tcp_sock = self.connections = None
-
-
-class AbsNetwork(GameObject):
-
- rate = .1
- _public_addr = None
- _local_addr = None
-
- def __init__(self, port):
- GameObject.__init__(self)
- self.netw_thr = self.read_cb = self.udp_sock = self.tcp_sock = \
- self.udp_sock = None
- self.port = port
- self.addr2conn = {}
-
- def start(self, read_cb):
- self.eng.attach_obs(self.on_frame, 1)
- self.read_cb = read_cb
- self.udp_sock = socket(AF_INET, SOCK_DGRAM)
- self.udp_sock.setblocking(0)
- self._configure_udp()
- try:
- self.netw_thr = self._bld_netw_thr()
- self.netw_thr.start()
- self.netw_thr.read_cb = read_cb
- args = self.__class__.__name__, self.port
- info('%s is up, port %s' % args)
- return True
- except ValueError: # e.g. empty server
- info("can't start the network")
-
- def register_cb(self, callback):
- self.read_cb = callback
- self.netw_thr.read_cb = callback
-
- def send(self, data_lst, receiver=None):
- dgram = BinaryData.pack(data_lst)
- self.netw_thr.send_msg(dgram, receiver)
-
- def on_frame(self): self.process_udp()
-
- @property
- def is_active(self):
- observers = self.eng.event.observers.values()
- return self.on_frame in [obs.mth for olst in observers for obs in olst]
-
- def stop(self):
- if not self.netw_thr:
- info('%s was already stopped' % self.__class__.__name__)
- return
- self.udp_sock.close()
- self.netw_thr.destroy()
- self.udp_sock = self.tcp_sock = self.netw_thr = None
- self.eng.detach_obs(self.on_frame)
- self.addr2conn = {}
- info('%s has been stopped' % self.__class__.__name__)
-
- def process_udp(self):
- try: dgram, conn = self.udp_sock.recvfrom(8192)
- except error: return
- self.on_udp_pck(dgram, conn)
- dgram = BinaryData.unpack(dgram)
- sender, payload = dgram[0], dgram[1:]
- self.read_cb(payload, conn)
-
- def on_udp_pck(self, dgram, conn): pass
-
- def destroy(self):
- self.stop()
- info('%s has been destroyed' % self.__class__.__name__)
- GameObject.destroy(self)
+++ /dev/null
-from socket import error
-from queue import Queue
-from lib.engine.network.network import AbsNetwork, NetworkThread, \
- msg_rpc_answ
-from lib.engine.network.binary import BinaryData
-from lib.gameobject import GameObject
-
-
-class ServerThread(NetworkThread, GameObject):
-
- def __init__(self, eng, rpc_cb, port):
- NetworkThread.__init__(self, eng, port)
- GameObject.__init__(self)
- self.rpc_cb = rpc_cb
- self.conn2msgs = {}
-
- def _configure_socket(self):
- self.tcp_sock.setblocking(0)
- self.tcp_sock.bind(('', self.port))
- self.tcp_sock.listen(1)
-
- def _process_read(self, sock):
- if sock is self.tcp_sock:
- conn, addr = sock.accept()
- conn.setblocking(1) # required on osx
- self.connections += [conn]
- self.conn2msgs[conn] = Queue()
- self.notify('on_connected', conn)
- else:
- NetworkThread._process_read(self, sock)
-
- def _rpc_cb(self, funcname, args, kwargs, sock):
- self.eng.cb_mux.add_cb(self.rpc_cb, [funcname, args, kwargs, sock])
-
- def _queue(self, sock):
- return self.conn2msgs[sock]
-
- def send_msg(self, conn, msg):
- self.conn2msgs[conn].put(msg)
-
-
-class Server(AbsNetwork):
-
- def __init__(self, port):
- AbsNetwork.__init__(self, port)
- self.conn_cb = None
- self.fname2ref = {}
-
- @property
- def connections(self): return self.netw_thr.connections[1:]
-
- def start(self, read_cb, conn_cb):
- #TODO: parameters differ from overridden start
- AbsNetwork.start(self, read_cb)
- self.conn_cb = conn_cb
- self.netw_thr.attach(self.on_connected)
- self.netw_thr.attach(self.on_disconnected)
-
- def on_connected(self, conn):
- self.notify('on_connected', conn)
-
- def on_disconnected(self, conn):
- self.notify('on_disconnected', conn)
-
- def _bld_netw_thr(self):
- return ServerThread(self.eng, self.rpc_cb, self.port)
-
- def _configure_udp(self): self.udp_sock.bind(('', self.port))
-
- def send(self, data_lst, receiver=None):
- receivers = [cln for cln in self.connections if cln == receiver]
- dests = receivers if receiver else self.connections
- dgram = BinaryData.pack(data_lst)
- list(map(lambda cln: self.netw_thr.send_msg(cln, dgram), dests))
-
- def rpc_cb(self, funcname, args, kwargs, conn):
- kwargs = kwargs or {}
- kwargs['sender'] = conn
- ret = self.fname2ref[funcname](*args, **kwargs)
- msg_size, msg_data = BinaryData.pack([msg_rpc_answ, ret])
- self.netw_thr.send_msg(conn, (msg_size, msg_data))
-
- def register_rpc(self, func): self.fname2ref[func.__name__] = func
-
- def unregister_rpc(self, func): del self.fname2ref[func.__name__]
-
- def on_udp_pck(self, dgram, conn):
- sender = BinaryData.unpack(dgram)[0]
- if sender not in self.addr2conn: self.addr2conn[sender] = conn
-
- def process_udp(self):
- try: dgram, conn = self.udp_sock.recvfrom(8192)
- except error: return
- try:
- dgram = BinaryData.unpack(dgram)
- sender, payload = dgram[0], dgram[1:]
- self.read_cb(payload, sender)
- except IndexError as exc: print(exc)
-
- def send_udp(self, data_lst, receiver):
- if receiver[0] not in self.addr2conn: return
- msg_size, msg_data = BinaryData.pack(['server'] + data_lst)
- self.udp_sock.sendto(msg_data, self.addr2conn[receiver[0]])
+++ /dev/null
-# from math import pi
-# from ..gameobject import GameObject
-from lib.lib.p3d.particle import P3dParticle
-Particle = P3dParticle
-
-
-# class Particle(GameObject):
-
-# def __init__(self, emitter, texture, npart, color=(1, 1, 1, 1), ampl=pi/6,
-# ray=.5, rate=.0001, gravity=-.85, vel=3.8, part_lifetime=1.0,
-# autodestroy=None):
-# if not self.eng.lib.version.startswith('1.10'): return
-# GameObject.__init__(self)
-# LibParticle(
-# emitter, texture, npart, color, ampl, ray, rate, gravity, vel,
-# part_lifetime, autodestroy)
+++ /dev/null
-from direct.gui.DirectFrame import DirectFrame
-from lib.gameobject import GuiColleague, LogicColleague, GameObject, \
- Colleague
-from lib.lib.p3d.pause import P3dPause
-LibPause = P3dPause
-
-
-class PauseGui(GuiColleague):
-
- def __init__(self, mediator):
- GuiColleague.__init__(self, mediator)
- self.pause_frm = None
-
- def toggle(self, show_frm=True):
- if not self.mediator.logic._pause.paused:
- #TODO: don't access protected members
- if show_frm:
- self.pause_frm = DirectFrame(frameColor=(.3, .3, .3, .7),
- frameSize=(-1.8, 1.8, -1, 1))
- else:
- if self.pause_frm: self.pause_frm.destroy()
-
- def destroy(self):
- if self.pause_frm: self.pause_frm = self.pause_frm.destroy()
- GuiColleague.destroy(self)
-
-
-class PauseLogic(LogicColleague):
-
- def __init__(self, mediator):
- LogicColleague.__init__(self, mediator)
- self._pause = LibPause()
-
- def remove_task(self, tsk):
- self._pause.remove_task(tsk)
-
- def pause(self):
- self.notify('on_pause')
- return self._pause.pause()
-
- def resume(self):
- self.notify('on_resume')
- return self._pause.resume()
-
- def toggle(self, show_frm=True):
- self.mediator.gui.toggle(show_frm)
- (self.resume if self._pause.paused else self.pause)()
-
- def destroy(self):
- self._pause.destroy()
- LogicColleague.destroy(self)
-
-
-class PauseFacade:
-
- @property
- def paused(self):
- return self.logic._pause.paused
- #TODO: don't access protected members
-
-
-class PauseMgr(GameObject, Colleague, PauseFacade):
-
- def __init__(self, mediator):
- GameObject.__init__(self)
- Colleague.__init__(self, mediator)
- self.gui = PauseGui(self)
- self.logic = PauseLogic(self)
-
- def remove_task(self, tsk):
- return self.logic.remove_task(tsk)
-
- def destroy(self):
- self.gui = self.gui.destroy()
- self.logic = self.logic.destroy()
- GameObject.destroy(self)
- Colleague.destroy(self)
+++ /dev/null
-from logging import info
-from lib.gameobject import Colleague
-from lib.lib.bullet.bullet import (
- BulletPhysWorld, BulletTriangleMesh, BulletTriangleMeshShape,
- BulletRigidBodyNode, BulletGhostNode)
-
-
-PhysWorld = BulletPhysWorld
-TriangleMesh = BulletTriangleMesh
-TriangleMeshShape = BulletTriangleMeshShape
-RigidBodyNode = BulletRigidBodyNode
-GhostNode = BulletGhostNode
-
-
-class CollInfo:
-
- def __init__(self, node, time):
- self.node = node
- self.time = time
-
-
-class PhysFacade:
-
- def attach_rigid_body(self, rbnode):
- return self.root.attach_rigid_body(rbnode)
-
- def remove_rigid_body(self, rbnode):
- return self.root.remove_rigid_body(rbnode)
-
- def attach_ghost(self, gnode): return self.root.attach_ghost(gnode)
- def remove_ghost(self, gnode): return self.root.remove_ghost(gnode)
- def attach_vehicle(self, vehicle): return self.root.attach_vehicle(vehicle)
- def remove_vehicle(self, vehicle): return self.root.remove_vehicle(vehicle)
-
- def ray_test_all(self, from_pos, to_pos, mask=None):
- return self.root.ray_test_all(from_pos, to_pos, mask)
-
- def ray_test_closest(self, from_pos, to_pos, mask=None):
- return self.root.ray_test_closest(from_pos, to_pos, mask)
-
-
-class PhysMgr(Colleague, PhysFacade):
-
- def __init__(self, mediator):
- Colleague.__init__(self, mediator)
- self.collision_objs = [] # objects to be processed
- self.__obj2coll = {} # {obj: [(node, coll_time), ...], ...}
- self.root = None
- self.__debug_np = None
- PhysFacade.__init__(self)
-
- def reset(self):
- self.collision_objs = []
- self.__obj2coll = {}
- self.root = PhysWorld()
- self.root.set_gravity((0, 0, -8.5))
- self.root.init_debug()
-
- def start(self):
- self.eng.attach_obs(self.on_frame, 2)
-
- def on_frame(self):
- self.root.do_phys(self.eng.lib.last_frame_dt, 10, 1/180.0)
- self.__do_collisions()
-
- def ray_test_closest(self, top, bottom):
- #TODO: differs from PhysFacade's signature
- return self.root.ray_test_closest(top, bottom)
-
- def add_collision_obj(self, node): self.collision_objs += [node]
-
- def remove_collision_obj(self, node):
- try: self.collision_objs.remove(node)
- except ValueError:
- info("can't remove collision object %s" % node)
- # it may happen with weapons during pause
-
- def stop(self):
- self.root.stop()
- self.root = None
- self.eng.detach_obs(self.on_frame)
-
- def __do_collisions(self):
- to_clear = self.collision_objs[:]
- # identical collisions are ignored for .25 seconds
- for obj in self.collision_objs:
- if obj not in self.__obj2coll: self.__obj2coll[obj] = []
- # for contact in self.root.get_contacts(obj):
- # this doesn't work in 1.9, the following works
- # odd, this doesn't work too
- # for contact in self.root.wld.contact_test(obj).get_contacts():
- result = self.root._wld.contact_test(obj)
- #TODO: access a protected member
- for contact in result.get_contacts():
- self.__process_contact(obj, contact.get_node0(), to_clear)
- self.__process_contact(obj, contact.get_node1(), to_clear)
- for obj in to_clear:
- if obj in self.__obj2coll: # it may be that it isn't here e.g.
- # when you fire a rocket while you're very close to the prev
- # car and the rocket is removed suddenly
- for coll in self.__obj2coll[obj]:
- if self.eng.curr_time - coll.time > .25:
- self.__obj2coll[obj].remove(coll)
-
- def __process_contact(self, obj, node, to_clear):
- if node == obj: return
- if obj in to_clear: to_clear.remove(obj)
- if node in [coll.node for coll in self.__obj2coll[obj]]: return
- self.__obj2coll[obj] += [CollInfo(node, self.eng.curr_time)]
- self.eng.event.notify('on_collision', obj, node)
-
- def toggle_dbg(self):
- if self.root: self.root.toggle_dbg()
+++ /dev/null
-from os.path import exists
-
-
-if not exists('main.pyo'): # we don't deploy cProfile
- from cProfile import Profile
- from pstats import Stats
- from io import StringIO
-
-
-class AbsProfiler:
-
- @staticmethod
- def build(percall):
- prof_cls = AbsProfiler
- if not exists('main.pyo'):
- prof_cls = PerCallProfiler if percall else Profiler
- return prof_cls(percall)
-
- def __init__(self, percall): pass
-
- def printstats(self): pass
-
- def toggle(self): pass
-
- def destroy(self): pass
-
-
-class Profiler(AbsProfiler):
-
- def __init__(self, percall):
- AbsProfiler.__init__(self, percall)
- self.percall = percall
- self.is_profiling = False # we can't infer from cProfile
- self.prof = Profile()
- self.stats = None
-
- def toggle(self):
- if not self.is_profiling: self.__enable()
- else:
- self.__disable()
- self.printstats()
-
- def __enable(self):
- self.prof.enable()
- self.is_profiling = True
-
- def __disable(self):
- self.prof.disable()
- self.is_profiling = False
-
- def printstats(self):
- self.prof.disable()
- sio = StringIO()
- self.stats = Stats(self.prof, stream=sio).sort_stats('cumulative')
- self.stats.print_stats()
- self._print_lines(sio)
-
- @staticmethod
- def _print_lines(sio): print(sio.getvalue())
-
-
-class PerCallProfiler(Profiler):
-
- def _print_lines(self, sio):
- lines = sio.getvalue().split('\n')
- header_lines = lines[:5]
- content_lines = [line.split() for line in lines[5:] if line]
- sorted_lines = sorted(content_lines, key=lambda line: line[4])
- sorted_lines = reversed(sorted_lines)
- # line[4] is the percall value
- joined_lines = ['\t'.join(line) for line in sorted_lines]
- print('\n'.join(header_lines + joined_lines))
+++ /dev/null
-from lib.lib.p3d.shader import P3dShaderMgr
-
-
-ShaderMgr = P3dShaderMgr
+++ /dev/null
-from lib.lib.p3d.vec import P3dVec2, P3dVec3
-Vec = P3dVec3
-Vec2 = P3dVec2
+++ /dev/null
-# class Facade(object):
-
-# # def _fwd_mth(self, mth_name, tgt_mth):
-# # def fun(*args, **kwargs): return tgt_mth(*args, **kwargs)
-# # setattr(self, mth_name, fun)
-
-# # def _fwd_prop(self, prop_name, tgt_prop):
-# # setattr(self.__class__, prop_name, property(lambda self: tgt_prop))
-
-# def __init__(self, prop_lst=[], mth_lst=[]):
-# list(map(lambda args: self.__fwd_prop(*args), prop_lst))
-# list(map(lambda args: self.__fwd_mth(*args), mth_lst))
-# # try detecting if the forwarded item is a prop or a method, so we
-# # can pass only a single list
-
-# def __fwd_mth(self, mth_name, tgt_mth):
-# def fun(*args, **kwargs): return tgt_mth(self)(*args, **kwargs)
-# setattr(self, mth_name, fun)
-
-# def __fwd_prop(self, prop_name, tgt_prop):
-# setattr(self.__class__, prop_name, property(tgt_prop))
-
-# def destroy(self): pass
+++ /dev/null
-from abc import ABCMeta
-from lib.gameobject import LogicColleague, GameObject
-from lib.engine.engine import Engine
-
-
-class GameLogic(LogicColleague):
-
- def on_start(self): pass
-
-
-class GameFacade:
-
- def demand(self, tgt_state, *args):
- return self.fsm.demand(tgt_state, *args)
-
-
-class GameBase(GameObject, GameFacade): # it doesn't manage the window
- __metaclass__ = ABCMeta
-
- def __init__(self, cfg, client_cls=None):
- self.logic = LogicColleague(self)
- self.eng = Engine(cfg, self.destroy, client_cls)
- GameObject.__init__(self)
-
- def destroy(self):
- self.logic.destroy()
- GameObject.destroy(self)
- # self.eng = self.eng.destroy()
- self.eng.server.destroy()
- self.eng.client.destroy()
-
-
-class Game(GameBase): # it adds the window
-
- def run(self):
- self.logic.on_start()
- base.run()
+++ /dev/null
-from direct.fsm.FSM import FSM
-from direct.showbase.DirectObject import DirectObject
-from lib.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
-from lib.lib.p3d.p3d import LibP3d
-
-
-class LibBuilder:
- '''This classe builds the implementation of the library abstraction (for
- the Dependency Inversion Principle).'''
-
- @staticmethod
- def build():
- '''This method actually builds the library implementation.
- Now it builds Panda3D's implementation layer, but it may be used as a
- dispatcher (e.g. for new Panda3D versions).'''
- return LibP3d()
+++ /dev/null
-from panda3d.bullet import \
- BulletWorld as BWorld, \
- BulletDebugNode as BDebugNode, \
- BulletTriangleMesh as BTriangleMesh, \
- BulletTriangleMeshShape as BTriangleMeshShape, \
- BulletRigidBodyNode as BRigidBodyNode, \
- BulletGhostNode as BGhostNode
-
-
-class BulletPhysWorld:
-
- def __init__(self):
- self._wld = BWorld()
- self.__debug_np = None
-
- def attach_rigid_body(self, rbnode):
- return self._wld.attach_rigid_body(rbnode)
-
- def remove_rigid_body(self, rbnode):
- return self._wld.remove_rigid_body(rbnode)
-
- def attach_ghost(self, gnode): return self._wld.attach_ghost(gnode)
- def remove_ghost(self, gnode): return self._wld.remove_ghost(gnode)
- def attach_vehicle(self, vehicle): return self._wld.attach_vehicle(vehicle)
- def remove_vehicle(self, vehicle): return self._wld.remove_vehicle(vehicle)
-
- def ray_test_closest(self, from_pos, to_pos, mask=None):
- if mask is not None:
- res = self._wld.ray_test_closest(from_pos, to_pos, mask)
- else: res = self._wld.ray_test_closest(from_pos, to_pos)
- return res
-
- def do_phys(self, dt, max_substeps, stepsize):
- return self._wld.do_physics(dt, max_substeps, stepsize)
-
- def set_gravity(self, vec): return self._wld.set_gravity(vec)
-
- def init_debug(self):
- debug_node = BDebugNode('Debug')
- debug_node.show_bounding_boxes(True)
- self.__debug_np = render.attach_new_node(debug_node)
- self._wld.set_debug_node(self.__debug_np.node())
-
- def stop(self): self.__debug_np.remove_node()
-
- def ray_test_all(self, pt_a, pt_b, mask=None):
- args = [pt_a._vec, pt_b._vec, mask] if mask else [pt_a._vec, pt_b._vec]
- #TODO: access to protected member
- return self._wld.ray_test_all(*args)
-
- def toggle_dbg(self):
- hidden = self.__debug_np.is_hidden()
- (self.__debug_np.show if hidden else self.__debug_np.hide)()
-
-
-class BulletTriangleMesh:
-
- def __init__(self):
- self._mesh = BTriangleMesh()
-
- def add_geom(self, geom, rm_dupl, xform):
- return self._mesh.add_geom(geom, rm_dupl, xform)
-
-
-class BulletTriangleMeshShape:
-
- def __init__(self, mesh, dynamic):
- self._mesh_shape = BTriangleMeshShape(mesh._mesh, dynamic=dynamic)
- #TODO: access to protected member
-
-
-class BulletRigidBodyNode:
-
- def __init__(self, name): self._node = BRigidBodyNode(name)
-
-
-class BulletGhostNode:
-
- def __init__(self, name): self._node = BGhostNode(name)
+++ /dev/null
-'''This module binds abstract GUI classes and actual implementation classes
-(for the Dependency Inversion Principle).'''
-from lib.lib.p3d.gui import P3dImg, P3dBtn, P3dSlider, P3dCheckBtn, \
- P3dOptionMenu, P3dEntry, P3dLabel, P3dTxt, P3dFrame, P3dScrolledFrame
-
-
-Img = P3dImg
-Btn = P3dBtn
-Slider = P3dSlider
-CheckBtn = P3dCheckBtn
-OptionMenu = P3dOptionMenu
-Entry = P3dEntry
-Label = P3dLabel
-Text = P3dTxt
-Frame = P3dFrame
-ScrolledFrame = P3dScrolledFrame
+++ /dev/null
-'''This module binds abstract interval classes and actual implementation
-classes (for the Dependency Inversion Principle).'''
-from lib.lib.p3d.ivals import P3dSeq, P3dWait, P3dPosIval, P3dFunc
-
-
-Seq = P3dSeq
-Wait = P3dWait
-PosIval = P3dPosIval
-Func = P3dFunc
+++ /dev/null
-from panda3d.core import AudioSound
-
-
-class P3dSound:
-
- def __init__(self, filepath):
- self.snd = loader.loadSfx(filepath)
-
- def stop(self): return self.snd.stop()
- def set_loop(self, val): return self.snd.set_loop(val)
- def set_volume(self, vol): return self.snd.set_volume(vol)
- def set_play_rate(self, rate): return self.snd.set_play_rate(rate)
-
- def play(self):
- if self.snd.status() != AudioSound.PLAYING: return self.snd.play()
- return None
-
- @property
- def playing(self): return self.snd.status() == AudioSound.PLAYING
+++ /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 lib.lib.p3d.p3d import LibP3d
-
-
-def set_srgb(model):
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
-
-
-class RenderToTexture:
-
- def __init__(self, size=(256, 256)):
- self.__set_buffer(size)
- self.__set_display_region()
- self.__set_camera()
- self.__set_root()
- self.display_region.set_camera(self.camera)
-
- def __set_buffer(self, size):
- self.buffer = base.win.make_texture_buffer('result buffer', size[0],
- size[1])
- self.buffer.set_sort(-100)
-
- def __set_display_region(self):
- self.display_region = self.buffer.make_display_region()
- self.display_region.set_sort(20)
-
- def __set_camera(self):
- self.camera = NodePath(Camera('camera 2d'))
- lens = OrthographicLens()
- lens.set_film_size(1, 1)
- lens.set_near_far(-1000, 1000)
- self.camera.node().set_lens(lens)
-
- def __set_root(self):
- self.root = NodePath('root')
- self.root.set_depth_test(False)
- self.root.set_depth_write(False)
- self.camera.reparent_to(self.root)
-
- @property
- def texture(self): return self.buffer.get_texture()
-
- def destroy(self):
- base.graphicsEngine.remove_window(self.buffer)
- if base.win: # if you close the window during a race
- base.win.remove_display_region(self.display_region)
- list(map(lambda node: node.remove_node(), [self.camera, self.root]))
-
-
-class P3dGfxMgr:
-
- def __init__(self, model_path, antialiasing, shaders, srgb):
- self.root = P3dNode(render)
- self.__srgb = srgb
- self.callbacks = {}
- self.filters = None
- get_model_path().append_directory(model_path)
- if LibP3d.runtime():
- root_dir = LibP3d.p3dpath(dirname(__file__))
- paths = [root_dir + '/' + model_path, root_dir]
- list(map(get_model_path().append_directory, paths))
- render.set_shader_auto()
- # render.set_two_sided(True) # it breaks shadows
- if antialiasing: render.set_antialias(AntialiasAttrib.MAuto)
- if shaders and base.win:
- self.filters = CommonFilters(base.win, base.cam)
-
- def load_model(self, filename, callback=None, anim=None):
- ext = '.bam' if exists(filename + '.bam') else ''
- if anim:
- anim_dct = {'anim': filename + '-Anim' + ext}
- node = P3dNode(self.set_srgb(Actor(filename + ext, anim_dct)))
- elif callback:
- callb = lambda model: callback(P3dNode(self.set_srgb(model)))
- node = loader.loadModel(filename + ext, callback=callb)
- else:
- node = P3dNode(self.set_srgb(
- loader.loadModel(LibP3d.p3dpath(filename + ext))))
- return node
-
- def set_srgb(self, model):
- if self.__srgb:
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
- return model
-
- @staticmethod
- def toggle_aa():
- aa_not_none = render.get_antialias() != AntialiasAttrib.MNone
- if render.has_antialias() and aa_not_none:
- render.clear_antialias()
- else: render.set_antialias(AntialiasAttrib.MAuto, 1)
-
- def set_toon(self):
- tmp_node = NodePath(PandaNode('temp node'))
- tmp_node.set_attrib(LightRampAttrib.make_single_threshold(.5, .4))
- tmp_node.set_shader_auto()
- base.cam.node().set_initial_state(tmp_node.get_state())
- self.filters.set_cartoon_ink(separation=1)
-
- def set_bloom(self):
- if not base.win: return
- self.filters.setBloom(
- blend=(.3, .4, .3, 0), mintrigger=.6, maxtrigger=1.0, desat=.6,
- intensity=1.0, size='medium')
- # default: (.3, .4, .3, 0), .6, 1, .6, 1, 'medium'
-
- @staticmethod
- def pos2d(node):
- p3d = base.cam.get_relative_point(node.node, Point3(0, 0, 0))
- p2d = Point2()
- return p2d if base.camLens.project(p3d, p2d) else None
-
- @staticmethod
- def screen_coord(pos):
- new_node = NodePath('temp')
- new_node.set_pos(pos)
- coord3d = new_node.get_pos(base.cam)
- new_node.remove_node()
- coord2d = Point2()
- base.camLens.project(coord3d, coord2d)
- coord_r2d = Point3(coord2d[0], 0, coord2d[1])
- coord_a2d = base.aspect2d.get_relative_point(render2d, coord_r2d)
- return coord_a2d[0], coord_a2d[2]
-
- @staticmethod
- def world_from_to(pos):
- p_from, p_to = Point3(), Point3() # in camera coordinates
- base.camLens.extrude(pos, p_from, p_to)
- p_from = render.get_relative_point(base.cam, p_from) # global coords
- p_to = render.get_relative_point(base.cam, p_to) # global coords
- return p_from, p_to
-
- @property
- def shader_support(self):
- return base.win.get_gsg().get_supports_basic_shaders()
-
- def screenshot(self, path=None):
- time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
- #res = base.win.save_screenshot(Filename(path or ("yocto%s.png" % time)))
- #debug('screenshot %s (%s)' % (path or ("yocto%s.png" % time), res))
- res = base.screenshot(path or ("pmachines%s.png" % time), False)
- info('screenshot %s (%s; %s)' % (path or ("pmachines%s.png" % time), res, getcwd()))
-
- @staticmethod
- def enable_shader(): render.set_shader_auto()
-
- @staticmethod
- def disable_shader(): render.set_shader_off()
-
- @staticmethod
- def print_stats(two_d=True, three_d=True, analyze=True, ls=True):
- '''Print graphics stats. They use standard output (from p3d).'''
- info = []
- if two_d and analyze:
- info +=[('render2d.analyze', base.render2d.analyze)]
- if three_d and analyze:
- info +=[('render.analyze', base.render.analyze)]
- if two_d and ls:
- info +=[('render2d.ls', base.render2d.ls)]
- if three_d and ls:
- info +=[('render.ls', base.render.ls)]
- for elm in info:
- print('\n\n#####\n%s()' % elm[0])
- elm[1]()
-
-
-class P3dNode:
-
- def __init__(self, nodepath):
- self.nodepath = nodepath
- self.node.set_python_tag('libnode', self)
-
- def set_collide_mask(self, mask): return self.node.set_collide_mask(mask)
- def set_x(self, val): return self.node.set_x(val)
- def set_y(self, val): return self.node.set_y(val)
- def set_z(self, val): return self.node.set_z(val)
- def set_hpr(self, val): return self.node.set_hpr(val)
- def set_h(self, val): return self.node.set_h(val)
- def set_p(self, val): return self.node.set_p(val)
- def set_r(self, val): return self.node.set_r(val)
- def set_scale(self, val): return self.node.set_scale(val)
- def set_transparency(self, val): return self.node.set_transparency(val)
- def set_alpha_scale(self, val): return self.node.set_alpha_scale(val)
- def set_texture(self, texturestage, texture):
- return self.node.set_texture(texturestage, texture)
- def has_tag(self, name): return self.node.has_tag(name)
- def get_tag(self, name): return self.node.get_tag(name)
- def get_python_tag(self, name): return self.node.get_python_tag(name)
- def remove_node(self): return self.node.remove_node()
- def flatten_strong(self): return self.node.flatten_strong()
- def clear_model_nodes(self): return self.node.clear_model_nodes()
- def show(self): return self.node.show()
- def set_depth_offset(self, val): return self.node.set_depth_offset(val)
- def loop(self, val): return self.node.loop(val)
- def cleanup(self): return self.node.cleanup()
- def write_bam_file(self, fname): return self.node.write_bam_file(fname)
-
- def attach_node(self, name):
- return P3dNode(self.node.attach_new_node(name))
-
- def add_shape(self, shape):
- return self.node.node().add_shape(shape._mesh_shape)
- #TODO: don't access a protected member
-
- @property
- def name(self): return self.node.get_name()
-
- @property
- def node(self): return self.nodepath
-
- @property
- def p3dnode(self): return self.node.node()
-
- def set_pos(self, pos): return self.node.set_pos(pos._vec)
- #TODO: don't access a protected member
-
- def get_pos(self, other=None):
- return self.node.get_pos(* [] if other is None else [other.node])
-
- @property
- def x(self): return self.node.get_x()
-
- @property
- def y(self): return self.node.get_y()
-
- @property
- def z(self): return self.node.get_z()
-
- @property
- def hpr(self): return self.node.get_hpr()
-
- @property
- def h(self): return self.node.get_h()
-
- @property
- def p(self): return self.node.get_p()
-
- @property
- def r(self): return self.node.get_r()
-
- @property
- def scale(self): return self.node.get_scale()
-
- @property
- def is_empty(self): return self.node.is_empty()
-
- def get_relative_vector(self, node, vec):
- return self.node.get_relative_vector(node.node, vec)
-
- def set_material(self, mat): return self.node.set_material(mat, 1)
-
- def set_python_tag(self, name, val):
- return self.node.set_python_tag(name, val)
-
- def get_distance(self, other_node):
- return self.node.get_distance(other_node.node)
-
- def reparent_to(self, parent): return self.node.reparent_to(parent.node)
-
- def wrt_reparent_to(self, parent):
- return self.node.wrt_reparent_to(parent.node)
-
- @staticmethod
- def __get_pandanode(nodepath):
- if nodepath.has_python_tag('libnode'):
- return nodepath.get_python_tag('libnode')
- return P3dNode(nodepath)
-
- def find_all_matches(self, name):
- nodes = self.node.find_all_matches(name)
- return [self.__get_pandanode(node) for node in nodes]
-
- def find(self, name):
- model = self.node.find(name)
- if model: return self.__get_pandanode(model)
-
- def optimize(self):
- self.node.prepare_scene(base.win.get_gsg()) # crash with texture.set_format
- self.node.premunge_scene(base.win.get_gsg())
-
- def hide(self, mask=None):
- return self.node.hide(*[] if mask is None else [mask])
-
- @property
- def tight_bounds(self): return self.node.get_tight_bounds()
-
- @property
- def parent(self): return self.node.get_parent()
-
- @property
- def children(self): return self.node.get_children()
-
- def destroy(self): return self.node.remove_node()
-
-
-class P3dAnimNode:
-
- def __init__(self, filepath, anim_dct):
- self.node = Actor(filepath, anim_dct)
-
- def loop(self, val): return self.node.loop(val)
-
- def reparent_to(self, node): self.node.reparent_to(node)
-
- @property
- def name(self): return self.node.get_name()
-
- def optimize(self):
- self.node.prepare_scene(base.win.get_gsg())
- self.node.premunge_scene(base.win.get_gsg())
-
- def set_omni(self):
- self.node.node().set_bounds(OmniBoundingVolume())
- self.node.node().set_final(True)
-
- def destroy(self): self.node.cleanup()
-
-
-class P3dAmbientLight:
-
- def __init__(self, color):
- ambient_lgt = P3DAmbientLight('ambient light')
- ambient_lgt.set_color(color)
- self.ambient_np = render.attach_new_node(ambient_lgt)
- render.set_light(self.ambient_np)
-
- def destroy(self):
- render.clear_light(self.ambient_np)
- self.ambient_np.remove_node()
-
-
-class P3dSpotlight:
-
- def __init__(self, mask=None):
- self.spot_lgt = render.attach_new_node(P3DSpotlight('spot'))
- snode = self.spot_lgt.node()
- snode.set_scene(render)
- snode.set_shadow_caster(True, 1024, 1024)
- snode.get_lens().set_fov(40)
- snode.get_lens().set_near_far(20, 200)
- if mask: snode.set_camera_mask(mask)
- render.set_light(self.spot_lgt)
-
- def set_pos(self, pos): return self.spot_lgt.set_pos(*pos)
-
- def look_at(self, pos): return self.spot_lgt.look_at(*pos)
-
- def set_color(self, color): return self.spot_lgt.set_color(*color)
-
- def destroy(self):
- render.clear_light(self.spot_lgt)
- self.spot_lgt.remove_node()
+++ /dev/null
-from inspect import getmro
-from panda3d.core import TextNode, Texture
-from direct.gui.DirectGuiGlobals import FLAT, ENTER, EXIT, DISABLED, NORMAL, \
- B1PRESS
-from direct.showbase.DirectObject import DirectObject
-from direct.gui.DirectButton import DirectButton
-from direct.gui.DirectCheckButton import DirectCheckButton
-from direct.gui.DirectOptionMenu import DirectOptionMenu
-from direct.gui.OnscreenImage import OnscreenImage
-from direct.gui.DirectSlider import DirectSlider
-from direct.gui.DirectEntry import DirectEntry, ENTRY_FOCUS_STATE
-from direct.gui.DirectLabel import DirectLabel
-from direct.gui.DirectFrame import DirectFrame
-from direct.gui.OnscreenText import OnscreenText
-from direct.gui.DirectScrolledFrame import DirectScrolledFrame
-from lib.observer import Subject
-from lib.lib.ivals import Seq, Wait, PosIval, Func
-
-
-class CommonBase:
-
- def set_widget(self):
- from lib.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \
- CheckBtn, Entry, Img, Text, ScrolledFrame
- from lib.lib.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \
- OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \
- ScrolledFrameMixin
- self.__class__ = self.__class__ # for pylint
- libwdg2wdg = {
- FrameMixin: [Frame],
- ScrolledFrameMixin: [ScrolledFrame],
- SliderMixin: [Slider],
- BtnMixin: [Btn, Label],
- OptionMenuMixin: [OptionMenu],
- CheckBtnMixin: [CheckBtn],
- EntryMixin: [Entry],
- ImgMixin: [Img, Text]}
- for libwdg, wdgcls in libwdg2wdg.items():
- if any(cls in getmro(self.__class__) for cls in wdgcls):
- par_cls = libwdg
- clsname = self.__class__.__name__ + 'Widget'
- self.__class__ = type(clsname, (self.__class__, par_cls), {})
- self.init(self)
- if not hasattr(self, 'bind'): return
- bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)]
- list(map(lambda args: self.bind(*args), bind_args))
-
- def set_enter_transition(self):
- start_pos = self.get_pos()
- pos = self.pos - (3.6, 0)
- self.set_pos((pos.x, 1, pos.y))
- Seq(
- Wait(abs(pos.y - 1) / 4),
- PosIval(self.get_np(), .5, start_pos)
- ).start()
-
- def set_exit_transition(self, destroy):
- start_pos = self.get_pos()
- end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- seq = Seq(
- Wait(abs(self.pos.y - 1) / 4),
- PosIval(self.get_np(), .5, end_pos),
- Func(self.destroy if destroy else self.hide))
- if not destroy: seq += Func(self.set_pos, start_pos)
- seq.start()
-
- def translate(self):
- if hasattr(self, 'bind_transl'): self.wdg['text'] = self.bind_transl
-
-
-class P3dImg(CommonBase):
-
- def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False,
- foreground=False, parent=None):
- self.img = OnscreenImage(
- filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent)
- if background: self.img.set_bin('background', 10)
- alpha_formats = [12] # panda3d.core.texture.Frgba
- if self.img.get_texture().get_format() in alpha_formats:
- self.img.set_transparency(True)
- if foreground: self.img.set_bin('gui-popup', 50)
-
- def reparent_to(self, node): return self.img.reparent_to(node)
- def show(self): return self.img.show()
- def hide(self): return self.img.hide()
- def set_shader(self, shader): return self.img.set_shader(shader)
- def set_shader_input(self, name, val):
- return self.img.set_shader_input(name, val)
- def set_texture(self, texturestage, texture):
- return self.img.set_texture(texturestage, texture)
-
- def set_exit_transition(self, destroy):
- start_pos = self.get_pos()
- end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- seq = Seq(
- Wait(abs(self.pos.y - 1) / 4),
- PosIval(self.get_np(), .5, end_pos),
- Func(self.destroy if destroy else self.hide))
- if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2]))
- seq.start()
-
- def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1])
-
- def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else [])
-
- @property
- def parent(self): return self.img.get_parent()
-
- @property
- def hidden(self): return self.img.is_hidden()
-
- def set_transparent(self): return self.img.set_transparency(True)
-
- def destroy(self): self.img = self.img.destroy()
-
-
-class P3dBase(CommonBase):
-
- def __init__(self, tra_src=None, tra_tra=None):
- # self.text_src_tra = None # it breaks the gui
- if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra)
-
- def set_pos(self, pos): return self.wdg.set_pos(pos)
- def show(self): return self.wdg.show()
- def hide(self): return self.wdg.hide()
-
- def bind_tra(self, text_src, text_transl):
- # text_transl is not used, anyway we need it since we have this kind of
- # use: self.bind_transl('example str', _('example str'))
- # this allows to change translations on the fly keeping the source
- # text for remapping it later
- # TODO: try reverse mapping? i.e. retrieve the src string from the
- # translated one
- self.text_src_tra = text_src
- self.text_tra_tra = text_transl
- tra = lambda self: _(self.text_tra_tra)
- self.__class__.bind_transl = property(tra)
- self['text'] = self.bind_transl
-
- def get_pos(self, pos=None):
- return self.wdg.get_pos(*[pos] if pos else [])
-
- def __setitem__(self, key, value): self.wdg[key] = value
-
- def __getitem__(self, key): return self.wdg[key]
-
- def get_np(self): return self.wdg
-
- @property
- def hidden(self): return self.wdg.is_hidden()
-
- def destroy(self): self.wdg.destroy()
-
-
-class P3dAbs(P3dBase):
-
- def get_value(self): return self.wdg.getValue()
- def initialiseoptions(self): return self.wdg.initialiseoptions()
- def set_z(self, val): return self.wdg.set_z(val)
- def set_shader(self, shader): return self.wdg.set_shader(shader)
- def set_shader_input(self, name, val):
- return self.wdg.set_shader_input(name, val)
- def set_transparency(self, val): return self.wdg.set_transparency(val)
- def bind(self, evt, mth): return self.wdg.bind(evt, mth)
-
- def attachNewNode(self, gui_itm, sort_order):
- # it won't work if we name it attach_node. hopefully this will be
- # possible when we'll use decorators in place of mixins
- return self.wdg.attachNewNode(gui_itm, sort_order)
-
- @property
- def is_enabled(self): return self.wdg['state'] != DISABLED
-
-
-class P3dBtn(P3dAbs):
-
- def __init__(
- self, text='', parent=None, pos=(0, 0), scale=(1, 1),
- cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None,
- text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None,
- over_snd=None, extra_args=None, frame_texture=None, img=None,
- tra_src=None, tra_tra=None, text_scale=1.0):
- str2par = {'bottomcenter': base.a2dBottomCenter}
- parent = str2par.get(parent, parent)
- extra_args = extra_args or []
- self.wdg = DirectButton(
- text=text, parent=parent, pos=(pos[0], 1, pos[1]),
- scale=(scale[0], 1, scale[1]), command=cmd,
- frameSize=frame_size, clickSound=click_snd, text_fg=text_fg,
- frameColor=frame_col, text_font=text_font, rolloverSound=over_snd,
- extraArgs=extra_args, frameTexture=frame_texture, image=img,
- text_scale=text_scale)
- P3dAbs.__init__(self, tra_src, tra_tra)
- self['relief'] = FLAT
- args = [(ENTER, self._on_enter), (EXIT, self._on_exit)]
- list(map(lambda args: self.bind(*args), args))
-
- def _on_enter(self, pos): pass # pos comes from mouse
-
- def _on_exit(self, pos): pass # pos comes from mouse
-
- # we add these with the mixins
- # def enable(self): self['state'] = NORMAL
-
- # def disable(self): self['state'] = DISABLED
-
-
-class P3dSlider(P3dAbs):
-
- def __init__(
- self, parent=None, pos=(0, 0), scale=1, val=0,
- frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1),
- cmd=None, range_=(0, 1), tra_src=None, tra_tra=None):
- self.wdg = DirectSlider(
- parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val,
- frameColor=frame_col, thumb_frameColor=thumb_frame_col,
- command=cmd, range=range_)
- P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-class P3dCheckBtn(P3dAbs):
-
- def __init__(
- self, pos=(0, 0), text='', indicator_val=False,
- indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1),
- scale=(1, 1, 1), click_snd=None, over_snd=None,
- text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None,
- tra_tra=None):
- self.wdg = DirectCheckButton(
- pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val,
- indicator_frameColor=indicator_frame_col,
- frameColor=frame_col, scale=scale, clickSound=click_snd,
- rolloverSound=over_snd, text_fg=text_fg, text_font=text_font,
- command=cmd)
- P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-class P3dOptionMenu(P3dAbs):
-
- def __init__(
- self, text='', items=None, pos=(0, 0), scale=(1, 1, 1),
- initialitem='', cmd=None, frame_size=(-1, 1, -1, 1),
- click_snd=None, over_snd=None, text_may_change=False,
- text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1),
- frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1),
- text_scale=.05, popup_marker_col=(1, 1, 1, 1),
- item_relief=None, item_text_font=None, text_font=None,
- tra_src=None, tra_tra=None):
- items = items or []
- self.wdg = DirectOptionMenu(
- text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale,
- initialitem=initialitem, command=cmd, frameSize=frame_size,
- clickSound=click_snd, rolloverSound=over_snd,
- textMayChange=text_may_change, text_fg=text_fg,
- item_frameColor=item_frame_col, frameColor=frame_col,
- highlightColor=highlight_col, text_scale=text_scale,
- popupMarker_frameColor=popup_marker_col,
- item_relief=item_relief, item_text_font=item_text_font,
- text_font=text_font)
- P3dAbs.__init__(self, tra_src, tra_tra)
-
- def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
-
- @property
- def curr_val(self): return self.wdg.get()
-
- @property
- def curr_idx(self): return self.wdg.selectedIndex
-
-
-class P3dEntry(P3dAbs, DirectObject, Subject):
-
- def __init__(
- self, scale=.05, pos=(0, 0), entry_font=None, width=12,
- frame_col=(1, 1, 1, 1), initial_text='', obscured=False,
- cmd=None, focus_in_cmd=None, focus_in_args=None,
- focus_out_cmd=None, focus_out_args=None, parent=None,
- tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None,
- on_click=None):
- self.__focused = False
- self.__focus_in_cmd = focus_in_cmd
- self.__focus_out_cmd = focus_out_cmd
- DirectObject.__init__(self)
- Subject.__init__(self)
- focus_in_args = focus_in_args or []
- focus_out_args = focus_out_args or []
- self.wdg = DirectEntry(
- scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font,
- width=width, frameColor=frame_col, initialText=initial_text,
- obscured=obscured, command=cmd, focusInCommand=self._focus_in_cmd,
- focusInExtraArgs=focus_in_args,
- focusOutCommand=self._focus_out_cmd,
- focusOutExtraArgs=focus_out_args, parent=parent,
- text_fg=text_fg)
- P3dAbs.__init__(self, tra_src, tra_tra)
- if on_tab:
- self.on_tab_cb = on_tab
- self.accept('tab-up', self.on_tab)
- if on_click: self.wdg.bind(B1PRESS, on_click)
-
- def set(self, txt): return self.wdg.set(txt)
-
- def _focus_in_cmd(self, *args):
- self.__focused = True
- if self.__focus_in_cmd: self.__focus_in_cmd(*args)
- self.notify('on_entry_enter')
-
- def _focus_out_cmd(self, *args):
- self.__focused = False
- if self.__focus_out_cmd: self.__focus_out_cmd(*args)
- self.notify('on_entry_exit')
-
- def on_tab(self):
- if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
-
- @property
- def focused(self): return self.__focused
-
- @property
- def text(self): return self.wdg.get()
-
- def enter_text(self, txt):
- return self.wdg.enterText(txt)
-
- def enable(self): self['state'] = NORMAL
-
- def disable(self): self['state'] = DISABLED
-
- def destroy(self):
- self.ignore('tab-up')
- self.on_tab_cb = None
- Subject.destroy(self)
- P3dAbs.destroy(self)
-
-
-class P3dLabel(P3dAbs):
-
- def __init__(
- self, text='', pos=(0, 0), parent=None, text_wordwrap=12,
- text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05,
- frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None, hpr=(0, 0, 0)):
- self.wdg = DirectLabel(
- text=text, pos=(pos[0], 1, pos[1]), parent=parent,
- text_wordwrap=text_wordwrap, text_align=text_align,
- text_fg=text_fg, text_font=text_font, scale=scale,
- frameColor=frame_col, hpr=hpr)
- P3dAbs.__init__(self, tra_src, tra_tra)
-
- def set_bin(self, bin_name, priority): return self.wdg.set_bin(bin_name, priority)
-
- def set_x(self, x): return self.wdg.set_x(x)
-
- def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
-
-
-class P3dTxt(P3dBase):
-
- def __init__(
- self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None,
- fg=(1, 1, 1, 1), font=None, align=None, tra_src=None,
- tra_tra=None):
- str2par = {'bottomleft': base.a2dBottomLeft,
- 'bottomright': base.a2dBottomRight,
- 'leftcenter': base.a2dLeftCenter}
- str2al = {'left': TextNode.A_left, 'right': TextNode.A_right,
- 'center': TextNode.A_center}
- if parent and parent in str2par: parent = str2par[parent]
- if align: align = str2al[align]
- self.wdg = OnscreenText(
- text=txt, pos=pos, scale=scale, wordwrap=wordwrap,
- parent=parent, fg=fg, font=font, align=align)
- P3dBase.__init__(self, tra_src, tra_tra)
-
- def set_r(self, r): return self.wdg.set_r(r)
-
-
-class P3dFrame(P3dAbs):
-
- def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1),
- pos=(0, 0), parent=None, texture_coord=False):
- P3dAbs.__init__(self)
- self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col,
- pos=(pos[0], 1, pos[1]), parent=parent)
- if texture_coord: self.wdg['frameTexture'] = Texture()
-
-
-class P3dScrolledFrame(P3dAbs):
-
- def __init__(
- self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1),
- scrollbar_width=.05, frame_col=(1, 1, 1, 1),
- pos=(0, 0), parent='topleft'):
- P3dAbs.__init__(self)
- par2p3d = {'topleft': base.a2dTopLeft}
- if parent and parent in par2p3d: parent = par2p3d[parent]
- self.wdg = DirectScrolledFrame(
- frameSize=frame_sz,
- canvasSize=canvas_sz,
- scrollBarWidth=scrollbar_width,
- frameColor=frame_col,
- pos=(pos[0], 1, pos[1]),
- parent=parent)
-
- @property
- def canvas(self): return self.wdg.getCanvas()
+++ /dev/null
-from direct.interval.MetaInterval import Sequence
-from direct.interval.FunctionInterval import Func, Wait
-from direct.interval.LerpInterval import LerpPosInterval
-
-
-class P3dSeq:
-
- def __init__(self, *ivals):
- self.seq = Sequence(*[ival._ival for ival in ivals])
- #TODO: don't access a protected member
-
- def start(self): return self.seq.start()
-
- def __add__(self, ival):
- self.seq.append(ival._ival) #TODO: don't access a protected member
- return self.seq
-
-
-class P3dWait:
-
- def __init__(self, time): self._ival = Wait(time)
-
-
-class P3dPosIval:
-
- def __init__(self, node, time=1.0, pos=(0, 0, 0), blend_type='ease'):
- btype = {'ease': 'easeInOut'}[blend_type]
- self._ival = LerpPosInterval(node, time, pos=pos, blendType=btype)
-
-
-class P3dFunc:
-
- def __init__(self, fun, *args): self._ival = Func(fun, *args)
+++ /dev/null
-from panda3d.core import InputDevice
-
-
-class P3dJoystickMgr:
-
- def __init__(self):
- self.joysticks = []
- self.curr_vibration = {}
- self.__is_vibrating = [False, False, False, False]
-
- def init_joystick(self):
- for i, dev in enumerate(base.devices.getDevices(InputDevice.DeviceClass.gamepad)):
- base.attachInputDevice(dev, prefix='joypad%s' % i)
- taskMgr.add(self._update, 'update joysticks')
- # pygame.init()
- # joystick.init()
- # self.joysticks = [
- # joystick.Joystick(idx) for idx in range(joystick.get_count())]
- # list(map(lambda joystick: joystick.init(), self.joysticks))
-
- @property
- def num_joysticks(self):
- return len(base.devices.getDevices(InputDevice.DeviceClass.gamepad))
-
- @staticmethod
- def get_joystick(player_idx):
- devices = base.devices.getDevices(InputDevice.DeviceClass.gamepad)
- if player_idx > len(devices) - 1:
- return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- gamepad = devices[player_idx]
- face_a = gamepad.findButton('face_a')
- face_b = gamepad.findButton('face_b')
- face_x = gamepad.findButton('face_x')
- face_y = gamepad.findButton('face_y')
- dpad_l = gamepad.findButton('dpad_left')
- dpad_r = gamepad.findButton('dpad_right')
- dpad_u = gamepad.findButton('dpad_up')
- dpad_d = gamepad.findButton('dpad_down')
- trigger_l = gamepad.findButton('ltrigger')
- trigger_r = gamepad.findButton('rtrigger')
- shoulder_l = gamepad.findButton('lshoulder')
- shoulder_r = gamepad.findButton('rshoulder')
- stick_l = gamepad.findButton('lstick')
- stick_r = gamepad.findButton('rstick')
- left_x = gamepad.findAxis(InputDevice.Axis.left_x)
- left_y = gamepad.findAxis(InputDevice.Axis.left_y)
- trigger_l_axis = gamepad.findAxis(InputDevice.Axis.left_trigger)
- trigger_r_axis = gamepad.findAxis(InputDevice.Axis.right_trigger)
- trigger_l_known = trigger_l.known
- trigger_r_known = trigger_r.known
- return (left_x.value, -left_y.value, face_a.pressed, face_b.pressed,
- face_x.pressed, face_y.pressed,
- dpad_l.pressed, dpad_r.pressed, dpad_u.pressed, dpad_d.pressed,
- trigger_l.pressed or trigger_l_axis.value > .5,
- trigger_r.pressed or trigger_r_axis.value > .5,
- shoulder_l.pressed, shoulder_r.pressed, stick_l.pressed,
- stick_r.pressed, trigger_l_known, trigger_r_known)
- # for _ in pygame.event.get(): pass
- # if not self.joysticks: return 0, 0, 0, 0
- # jstick = self.joysticks[0]
- # axis, btn = jstick.get_axis, jstick.get_button
- # return axis(0), axis(1), btn(0), btn(1)
-
- def set_vibration(self, player_idx, code, time=-1):
- devices = base.devices.getDevices(InputDevice.DeviceClass.gamepad)
- if player_idx < 0 or player_idx > len(devices) - 1: return
- if player_idx in self.curr_vibration and \
- code in self.curr_vibration[player_idx]: return
- if player_idx not in self.curr_vibration:
- self.curr_vibration[player_idx] = {}
- self.curr_vibration[player_idx][code] = time
-
- def clear_vibration(self, player_idx, code=None):
- devices = base.devices.getDevices(InputDevice.DeviceClass.gamepad)
- if player_idx < 0 or player_idx > len(devices) - 1: return
- if player_idx not in self.curr_vibration or \
- code not in self.curr_vibration[player_idx]: return
- if code is None: del self.curr_vibration[player_idx]
- else: del self.curr_vibration[player_idx][code]
-
- def _update(self, task):
- devices = base.devices.getDevices(InputDevice.DeviceClass.gamepad)
- for player_idx in self.curr_vibration:
- for code in self.curr_vibration[player_idx]:
- if self.curr_vibration[player_idx][code] != -1:
- dt = globalClock.getDt()
- self.curr_vibration[player_idx][code] -= dt
- for player_idx in self.curr_vibration:
- for code in list(self.curr_vibration[player_idx])[:]:
- if self.curr_vibration[player_idx][code] != -1:
- if self.curr_vibration[player_idx][code] < 0:
- del self.curr_vibration[player_idx][code]
- for player_idx in list(self.curr_vibration)[:]:
- if not self.curr_vibration[player_idx]:
- del self.curr_vibration[player_idx]
- for player_idx, dev in enumerate(devices):
- gamepad = devices[player_idx]
- if player_idx in self.curr_vibration and \
- not self.__is_vibrating[player_idx]:
- gamepad.set_vibration(.2, .4)
- self.__is_vibrating[player_idx] = True
- elif player_idx not in self.curr_vibration:
- gamepad.set_vibration(0, 0)
- self.__is_vibrating[player_idx] = False
- return task.cont
-
- def destroy(self):
- pass
- # joystick.quit()
- # pygame.quit()
- # self.joysticks = []
+++ /dev/null
-import sys
-from logging import info
-from os.path import exists, dirname
-from os import getcwd, _exit
-from glob import glob
-from pathlib import Path
-from panda3d.core import loadPrcFileData, Texture, TextPropertiesManager, \
- TextProperties, PandaSystem, Filename, WindowProperties, GraphicsWindow
-from panda3d.bullet import get_bullet_version
-from direct.showbase.ShowBase import ShowBase
-from direct.showbase.DirectObject import DirectObject
-from direct.task.Task import Task
-#from gltf import patch_loader
-
-
-class LibShowBase(ShowBase): pass
-
-
-class LibP3d(DirectObject):
-
- task_cont = Task.cont
-
- def __init__(self):
- DirectObject.__init__(self)
- self.__end_cb = self.__notify = None
- self.__logged_keys = {}
-
- @staticmethod
- def runtime(): return not exists('main.py')
-
- @staticmethod
- def configure():
- loadPrcFileData('', 'notify-level-ya2 info')
- # loadPrcFileData('', 'gl-version 3 2')
-
- @staticmethod
- def fixpath(path):
- home = '/home/flavio'
- if sys.platform == 'win32' and not exists(exists(home + '/.wine/')):
- if path.startswith('/'): path = path[1] + ':\\' + path[3:]
- path = path.replace('/', '\\')
- return path
-
- @staticmethod
- def p3dpath(path): return Filename.fromOsSpecific(path)
-
- @property
- def last_frame_dt(self): return globalClock.get_dt()
-
- @property
- def build_version(self):
- appimg_mnt = glob('/tmp/.mount_Yocto*')
- if appimg_mnt:
- #with open(appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
- with open(self.curr_path + '/assets/bld_version.txt') as fver:
- return fver.read().strip()
- try:
- with open(self.curr_path + '/assets/bld_version.txt') as fver:
- return fver.read().strip()
- except FileNotFoundError:
- info(self.curr_path + '/assets/bld_version.txt')
- return 'notfound'
-
- @property
- def is_appimage(self):
- par_path = str(Path(__file__).parent.absolute())
- is_appimage = par_path.startswith('/tmp/.mount_Yocto')
- return is_appimage and par_path.endswith('/usr/bin')
-
- @property
- def curr_path(self):
- if sys.platform == 'darwin':
- return dirname(__file__) + '/../Resources/'
- # return dirname(__file__)
- par_path = str(Path(__file__).parent.absolute())
- if self.is_appimage:
- return str(Path(par_path).absolute())
- is_snap = par_path.startswith('/snap/')
- is_snap = is_snap and par_path.endswith('/x1')
- if is_snap:
- return str(Path(par_path).absolute())
- #return getcwd()
- curr_path = dirname(__file__)
- info('current path: %s' % curr_path)
- return curr_path
-
- @staticmethod
- def send(msg): return messenger.send(msg)
-
- @staticmethod
- def do_later(time, meth, args=None):
- args = args or []
- return taskMgr.doMethodLater(
- time, lambda meth, args: meth(*args), meth.__name__, [meth, args])
-
- @staticmethod
- def add_task(mth, priority=0):
- return taskMgr.add(mth, mth.__name__, priority)
-
- @staticmethod
- def remove_task(tsk): taskMgr.remove(tsk)
-
- def init(self, green=(.2, .8, .2, 1), red=(.8, .2, .2, 1), end_cb=None):
- LibShowBase()
- base.disableMouse()
- #patch_loader(base.loader)
- self.__end_cb = end_cb
- self.__init_win()
- self.__init_fonts(green, red)
- self.__set_roots()
- self.accept('aspectRatioChanged', self.on_aspect_ratio_changed)
-
- @staticmethod
- def __set_roots():
- base.a2dTopQuarter = base.aspect2d.attachNewNode('a2dTopQuarter')
- base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
- base.a2dTopThirdQuarter = \
- base.aspect2d.attachNewNode('a2dTopThirdQuarter')
- base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
- base.a2dCenterQuarter = base.aspect2d.attachNewNode('a2dCenterQuarter')
- base.a2dCenterQuarter.set_pos(base.a2dLeft / 2, 0, 0)
- base.a2dCenterThirdQuarter = \
- base.aspect2d.attachNewNode('a2dCenterThirdQuarter')
- base.a2dCenterThirdQuarter.set_pos(base.a2dRight / 2, 0, 0)
- base.a2dBottomQuarter = base.aspect2d.attachNewNode('a2dBottomQuarter')
- base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
- base.a2dBottomThirdQuarter = \
- base.aspect2d.attachNewNode('a2dBottomThirdQuarter')
- base.a2dBottomThirdQuarter.set_pos(
- base.a2dRight / 2, 0, base.a2dBottom)
-
- @staticmethod
- def on_aspect_ratio_changed():
- base.a2dTopQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dTop)
- base.a2dTopThirdQuarter.set_pos(base.a2dRight / 2, 0, base.a2dTop)
- base.a2dBottomQuarter.set_pos(base.a2dLeft / 2, 0, base.a2dBottom)
- base.a2dBottomThirdQuarter.set_pos(
- base.a2dRight / 2, 0, base.a2dBottom)
-
- @property
- def has_window(self): return bool(base.win)
-
- @property
- def resolution(self):
- if not isinstance(base.win, GraphicsWindow):
- return 800, 600
- win_prop = base.win.get_properties()
- return win_prop.get_x_size(), win_prop.get_y_size()
-
- @property
- def resolutions(self):
- d_i = base.pipe.get_display_information()
-
- def res(idx):
- return d_i.get_display_mode_width(idx), \
- d_i.get_display_mode_height(idx)
- ret = [res(idx) for idx in range(d_i.get_total_display_modes())]
- return ret if ret else [self.resolution]
-
- @staticmethod
- def toggle_fullscreen():
- props = WindowProperties()
- props.set_fullscreen(not base.win.is_fullscreen())
- base.win.request_properties(props)
-
- @staticmethod
- def set_resolution(res, fullscreen=None):
- props = WindowProperties()
- props.set_size(res)
- if fullscreen: props.set_fullscreen(True)
- if isinstance(base.win, GraphicsWindow):
- base.win.request_properties(props)
-
- def __init_win(self):
- if base.win and isinstance(base.win, GraphicsWindow):
- base.win.set_close_request_event('window-closed')
- # not headless
- self.accept('window-closed', self.__on_end)
-
- @staticmethod
- def __init_fonts(green=(.2, .8, .2, 1), red=(.8, .2, .2, 1)):
- tp_mgr = TextPropertiesManager.get_global_ptr()
- for namecol, col in zip(['green', 'red'], [green, red]):
- props = TextProperties()
- props.set_text_color(col)
- tp_mgr.set_properties(namecol, props)
- for namesize, col in zip(['small', 'smaller'], [.46, .72]):
- props = TextProperties()
- props.set_text_scale(.46)
- tp_mgr.set_properties(namesize, props)
- tp_italic = TextProperties()
- tp_italic.set_slant(.2)
- tp_mgr.set_properties('italic', tp_italic)
-
- def __on_end(self):
- base.closeWindow(base.win)
- if self.__end_cb: self.__end_cb()
- _exit(0)
-
- @staticmethod
- def load_font(filepath, outline=True):
- font = base.loader.loadFont(filepath)
- font.set_pixels_per_unit(60)
- font.set_minfilter(Texture.FTLinearMipmapLinear)
- if outline: font.set_outline((0, 0, 0, 1), .8, .2)
- return font
-
- @staticmethod
- def log(msg): print(msg)
-
- @property
- def version(self): return PandaSystem.get_version_string()
-
- @property
- def lib_commit(self): return PandaSystem.get_git_commit()
-
- @property
- def phys_version(self): return get_bullet_version()
-
- @property
- def user_appdata_dir(self): return Filename.get_user_appdata_directory()
-
- @property
- def driver_vendor(self): return base.win.get_gsg().get_driver_vendor()
-
- @property
- def driver_renderer(self): return base.win.get_gsg().get_driver_renderer()
-
- @property
- def driver_shader_version_major(self):
- return base.win.get_gsg().get_driver_shader_version_major()
-
- @property
- def driver_shader_version_minor(self):
- return base.win.get_gsg().get_driver_shader_version_minor()
-
- @property
- def driver_version(self): return base.win.get_gsg().get_driver_version()
-
- @property
- def driver_version_major(self):
- return base.win.get_gsg().get_driver_version_major()
-
- @property
- def driver_version_minor(self):
- return base.win.get_gsg().get_driver_version_minor()
-
- @property
- def fullscreen(self):
- if isinstance(base.win, GraphicsWindow):
- return base.win.get_properties().get_fullscreen()
-
- @property
- def volume(self): return base.sfxManagerList[0].get_volume()
-
- @volume.setter
- def volume(self, vol): base.sfxManagerList[0].set_volume(vol)
-
- @property
- def mousepos(self):
- mwn = base.mouseWatcherNode
- if not mwn: return 0, 0
- if not mwn.hasMouse(): return 0, 0
- return mwn.get_mouse_x(), mwn.get_mouse_y()
-
- @property
- def aspect_ratio(self): return base.getAspectRatio()
-
- @staticmethod
- def set_icon(filename):
- props = WindowProperties()
- props.set_icon_filename(filename)
- if isinstance(base.win, GraphicsWindow):
- base.win.requestProperties(props)
-
- @staticmethod
- def __set_std_cursor(show):
- props = WindowProperties()
- props.set_cursor_hidden(not show)
- if isinstance(base.win, GraphicsWindow):
- base.win.requestProperties(props)
-
- @staticmethod
- def show_std_cursor(): LibP3d.__set_std_cursor(True)
-
- @staticmethod
- def hide_std_cursor(): LibP3d.__set_std_cursor(False)
-
- @staticmethod
- def find_geoms(model, name): # no need to be cached
- geoms = model.node.find_all_matches('**/+GeomNode')
- is_nm = lambda geom: geom.get_name().startswith(name)
- named_geoms = [geom for geom in geoms if is_nm(geom)]
- return [ng for ng in named_geoms if name in ng.get_name()]
-
- @staticmethod
- def load_sfx(filepath, loop=False):
- sfx = loader.loadSfx(filepath)
- sfx.set_loop(loop)
- return sfx
-
- def remap_code(self, key):
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- self.__log_key('not found a code mapping for %s' %
- key, key, 'not_found')
- return key
-
- def remap_str(self, key):
- if not base.win: # when launched with --version
- return key
- #if isinstance(base.win, GraphicsBuffer):
- # return key
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if str(key).lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- self.__log_key('not found a string mapping for %s' %
- key, key, kmap.get_mapped_button(i).get_name())
- return key
-
- def __log_key(self, msg, key1, key2):
- if key1 in self.__logged_keys and self.__logged_keys[key1] == key2:
- return
- self.__logged_keys[key1] = key2
- print(msg)
-
- def destroy(self): pass
+++ /dev/null
-from math import pi, sin, cos
-from array import array
-from random import uniform
-from itertools import chain
-from logging import info
-from panda3d.core import Geom, GeomVertexFormat, GeomVertexData, GeomPoints, \
- OmniBoundingVolume, GeomNode, Vec3, ShaderAttrib, TexGenAttrib, \
- TextureStage, Texture, GeomEnums, NodePath
-from lib.lib.p3d.shader import load_shader
-from lib.lib.p3d.gfx import P3dNode
-from lib.gameobject import GameObject
-
-
-class P3dParticle(GameObject):
-
- _vdata = {} # don't regenerate input structures
-
- def __init__(
- self, emitter, texture, color=(1, 1, 1, 1), ampl=pi/6,
- ray=.5, rate=.001, gravity=-9.81, vel=1.0, part_duration=1.0,
- autodestroy=None, size=10):
- GameObject.__init__(self)
- self.__tex_pos = self.__tex_curr_pos = self.__tex_times = \
- self.__tex_start_vel = self.__tex_curr_vel = self.__emitternode = \
- None
- self.__texture = texture
- self.__color = color
- self.__ampl = ampl
- self.__ray = ray
- self.__rate = rate
- self.__gravity = gravity
- self.__vel = vel
- self.__part_duration = part_duration
- self.__size = size
- self.__npart = int(round(part_duration * 1 / rate))
- if emitter.__class__ != P3dNode: # emitter is a position
- self.__emitternode = P3dNode(NodePath('tmp'))
- self.__emitternode.set_pos(emitter)
- self.__emitternode.reparent_to(self.eng.gfx.root)
- emitter = self.__emitternode
- self.__emitter = emitter
- self.__old_pos = (0, 0, 0)
- self._nodepath = render.attach_new_node(self.__node())
- self._nodepath.set_transparency(True)
- self._nodepath.set_bin('fixed', 0)
- self.__set_shader()
- self._nodepath.set_render_mode_thickness(10)
- self._nodepath.set_tex_gen(TextureStage.getDefault(),
- TexGenAttrib.MPointSprite)
- self._nodepath.set_depth_write(False)
- self.upd_tsk = taskMgr.add(self._update, 'update')
- if autodestroy: self.eng.do_later(autodestroy, self.destroy)
-
- def __node(self):
- points = GeomPoints(GeomEnums.UH_static)
- points.add_next_vertices(self.__npart)
- geom = Geom(self.__vdata())
- geom.add_primitive(points)
- geom.set_bounds(OmniBoundingVolume())
- node = GeomNode('node')
- node.add_geom(geom)
- return node
-
- def __vdata(self):
- entry = (self.__texture, self.__npart, self.__color, self.__ampl,
- self.__ray, self.__rate, self.__gravity)
- if entry in P3dParticle._vdata:
- vdata, pos, times, vels = P3dParticle._vdata[entry]
- self.__set_textures(pos, times, vels)
- return vdata
- pos, times, vels = self.__init_textures()
- self.__set_textures(pos, times, vels)
- format_ = GeomVertexFormat.get_empty()
- vdata = GeomVertexData('abc', format_, GeomEnums.UH_static)
- P3dParticle._vdata[self.__texture, self.__npart, self.__color,
- self.__ampl, self.__ray, self.__rate,
- self.__gravity] = \
- vdata, pos, times, vels
- return P3dParticle._vdata[self.__texture, self.__npart, self.__color,
- self.__ampl, self.__ray, self.__rate,
- self.__gravity][0]
-
- def __init_textures(self):
- positions = [self.__rnd_pos() for i in range(self.__npart)]
- pos_lst = [[pos.x, pos.y, pos.z, 1] for pos in positions]
- pos_lst = list(chain.from_iterable(pos_lst))
- emission_times = [
- (self.__rate * i, 0, 0, 0) for i in range(self.__npart)]
- times_lst = list(chain.from_iterable(emission_times))
- velocities = self.__init_velocities()
- vel_lst = [[v_vel[0], v_vel[1], v_vel[2], 1] for v_vel in velocities]
- vel_lst = list(chain.from_iterable(vel_lst))
- return pos_lst, times_lst, vel_lst
-
- def __set_textures(self, pos_lst, times_lst, vel_lst):
- self.__tex_pos = self.__buff_tex(pos_lst)
- self.__tex_curr_pos = self.__buff_tex(pos_lst)
- self.__tex_times = self.__buff_tex(times_lst)
- self.__tex_start_vel = self.__buff_tex(vel_lst)
- self.__tex_curr_vel = self.__buff_tex(vel_lst)
-
- def __buff_tex(self, vals):
- data = array('f', vals)
- tex = Texture('tex')
- tex.setup_buffer_texture(
- self.__npart, Texture.T_float, Texture.F_rgba32,
- GeomEnums.UH_static)
- tex.set_ram_image(data)
- return tex
-
- def __rnd_pos(self):
- ro = uniform(0, self.__ray)
- alpha = uniform(0, 2 * pi)
- return Vec3(ro * cos(alpha), ro * sin(alpha), 0)
-
- def __init_velocities(self):
- vels = []
- for _ in range(self.__npart):
- vec = self.__rnd_vel()
- vels += [(vec.x, vec.y, vec.z)]
- return vels
-
- def __rnd_vel(self):
- theta = uniform(0, self.__ampl)
- phi = uniform(0, 2 * pi)
- vec = Vec3(
- sin(theta) * cos(phi),
- sin(theta) * sin(phi),
- cos(theta))
- return vec * uniform(self.__vel * .8, self.__vel * 1.2)
-
- def __set_shader(self):
- path = 'assets/shaders/'
- shader = load_shader(path + 'particle.vert', path + 'particle.frag')
- if not shader: return
- self._nodepath.set_shader(shader)
- sha_attr = ShaderAttrib.make(shader)
- sha_attr = sha_attr.set_flag(ShaderAttrib.F_shader_point_size, True)
- self._nodepath.set_attrib(sha_attr)
- img = loader.loadTexture('assets/images/game/%s.dds' % self.__texture)
- self._nodepath.set_shader_inputs(
- start_pos=self.__tex_pos,
- positions=self.__tex_curr_pos,
- emitter_old_pos=self.__old_pos,
- emitter_pos=self.__emitter.get_pos(P3dNode(render)),
- start_vel=self.__tex_start_vel,
- velocities=self.__tex_curr_vel,
- accel=(0, 0, self.__gravity),
- start_time=globalClock.get_frame_time(),
- emission_times=self.__tex_times,
- part_duration=self.__part_duration,
- emitting=1,
- col=self.__color,
- image=img,
- size=self.__size)
-
- def _update(self, task):
- if self.__emitter and not self.__emitter.is_empty:
- pos = self.__emitter.get_pos(P3dNode(render))
- else: pos = (0, 0, 0)
- try:
- self._nodepath.set_shader_inputs(
- emitter_old_pos=self.__old_pos,
- emitter_pos=pos)
- self.__old_pos = pos
- return task.again
- except AttributeError:
- # _nodepath may be None on menu/pause
- info('_nodepath: %s' % self._nodepath)
-
- def destroy(self, now=False):
- #TODO: the signature differs from the parent's one
- try:
- self._nodepath.set_shader_input('emitting', 0)
- except AttributeError:
- # _nodepath may be None on menu/pause
- info('_nodepath: %s' % self._nodepath)
- self.eng.do_later(0 if now else 1.2 * self.__part_duration,
- self.__destroy)
-
- def __destroy(self):
- try:
- self.upd_tsk = taskMgr.remove(self.upd_tsk)
- except TypeError:
- info("can't remove %s" % self.upd_tsk)
- # it may happen on pause/menu
- try:
- self._nodepath = self._nodepath.remove_node()
- except AttributeError:
- info("_nodepath %s" % self._nodepath)
- # it may happen on pause/menu
- if self.__emitternode:
- self.__emitternode = self.__emitternode.destroy()
- GameObject.destroy(self)
+++ /dev/null
-from os import pardir # pardir is .. (parent directory)
-from os.path import dirname, abspath, join
-from sys import modules
-from direct.task import Task
-from direct.interval.IntervalGlobal import ivalMgr
-from lib.gameobject import GameObject
-
-
-class TaskDec:
-
- paused_taskchain = 'paused tasks'
-
- def __init__(self, tsk):
- self.tsk = tsk
- path = dirname(modules[Task.__name__].__file__)
- self.__direct_dir = abspath(join(path, pardir)) # path of direct.*
-
- def process(self):
- func = self.tsk.get_function() # ordinary tasks
- mod = func.__module__
- modfile = ''
- if "from '" in str(modules[mod]):
- modfile = str(modules[mod]).split("from '")[1][:-2]
- sys_mod = modfile.find(self.__direct_dir) < 0
- actor_ival = False
- if hasattr(func, 'im_class'):
- actor_ival = func.im_class.__name__ == 'ActorInterval'
- if mod.find('direct.interval') == 0 and not actor_ival:
- self.tsk.interval.pause() # python-based intervals
- return self.tsk
- if mod not in modules or sys_mod: return self.tsk
- return None
-
- def pause(self):
- tsk = self.tsk
- has_args = hasattr(tsk, 'getArgs')
- tsk.stored_extraArgs = tsk.get_args() if has_args else None
- if hasattr(tsk, 'getFunction'): tsk.stored_call = tsk.get_function()
- has_p = hasattr(tsk, '_priority')
- tsk.stored_priority = tsk._priority if has_p else tsk.get_sort()
- if hasattr(tsk, 'remainingTime'): tsk.remove() # do_later tasks
- else: # ordinary tasks
- tsk.lastactivetime = -tsk.time if hasattr(tsk, 'time') else 0
- tsk.setTaskChain(TaskDec.paused_taskchain)
-
- def __resume_do_later(self):
- tsk = self.tsk
- d_t = globalClock.get_real_time() - globalClock.get_frame_time()
- tmp_delay = tsk.remainingTime - d_t
- upon_death = tsk.uponDeath if hasattr(tsk, 'uponDeath') else None
- new_task = taskMgr.doMethodLater(
- tmp_delay, tsk.stored_call, tsk.name, uponDeath=upon_death,
- priority=tsk.stored_priority, extraArgs=tsk.stored_extraArgs)
- if hasattr(tsk, 'remainingTime'): new_task.delayTime = tsk.delayTime
-
- def resume(self):
- tsk = self.tsk
- if hasattr(tsk, 'interval'):
- tsk.interval.resume()
- if hasattr(tsk, 'stored_call'): tsk.set_function(tsk.stored_call)
- return
- if hasattr(tsk, 'remainingTime'):
- self.__resume_do_later()
- return
- tsk.set_delay(tsk.lastactivetime) # ordinary tasks
- tsk.set_task_chain('default')
- tsk.clear_delay() # to avoid assertion error on resume
-
-
-class P3dPause(GameObject):
-
- def __init__(self):
- GameObject.__init__(self)
- taskMgr.setupTaskChain(TaskDec.paused_taskchain, frameBudget=0)
- self.__paused_ivals = []
- self.__paused_tasks = []
-
- @property
- def paused(self):
- tsk = taskMgr.getTasksNamed('__on_frame')[0]
- return tsk.getTaskChain() == TaskDec.paused_taskchain
-
- def pause_tasks(self):
- is_tsk = lambda tsk: tsk and hasattr(tsk, 'getFunction')
- tasks = [TaskDec(tsk) for tsk in taskMgr.getTasks() if is_tsk(tsk)]
- tasks = [tsk for tsk in tasks
- if tsk.tsk.get_task_chain() != 'unpausable']
- namefilter = ['igLoop', 'dataLoop', 'ivalLoop', 'collisionLoop',
- 'garbageCollectStates', 'audioLoop',
- 'resetPrevTransform', 'eventManager']
- tasks = [tsk for tsk in tasks
- if tsk.tsk.get_name_prefix() not in namefilter]
- not_none = lambda tsk: tsk is not None
- paused_tasks = list(filter(not_none, [tsk.process() for tsk in tasks]))
- self.__paused_tasks = list(map(TaskDec, paused_tasks))
- for tsk in list(filter(is_tsk, taskMgr.getDoLaters())):
- self.__paused_tasks += [TaskDec(tsk)]
- tsk.remainingTime = tsk.wakeTime - globalClock.get_frame_time()
- list(map(lambda tsk: tsk.pause(), self.__paused_tasks))
-
- def remove_task(self, tsk):
- list(map(self.__paused_tasks.remove, [ptsk for ptsk in self.__paused_tasks if ptsk.tsk == tsk]))
-
- def pause(self):
- self.__paused_ivals = ivalMgr.getIntervalsMatching('*')
- self.pause_tasks()
- return self.paused
-
- def resume(self):
- list(map(lambda ival: ival.resume(), self.__paused_ivals))
- list(map(lambda tsk: tsk.resume(), self.__paused_tasks))
- return self.paused
-
- def destroy(self): GameObject.destroy(self)
+++ /dev/null
-from os.path import isfile, dirname
-from panda3d.core import AmbientLight, DirectionalLight, PointLight, \
- Spotlight, LVector4f, LVector3f, Vec3, Shader, TextureStage, \
- TexMatrixAttrib
-from direct.filter.FilterManager import FilterManager
-from lib.lib.builder import LibP3d
-
-
-def load_shader(vert, frag):
-
- def is_file(path):
- joinchar = '/' if LibP3d.runtime() and not path.startswith('/') else ''
- dpath = LibP3d.runtime() and dirname(__file__)
- return isfile((dpath or '') + joinchar + path)
- if is_file(vert) and is_file(frag):
- shader = Shader.load(Shader.SLGLSL, vert, frag)
- else: shader = Shader.make(Shader.SLGLSL, vert, frag)
- return shader
-
-
-class P3dShaderMgr:
-
- def __init__(self, shaders, gamma):
- self.filter_mgr = None
- self.gamma, self.buffer, self.lcam, self.lights = gamma, None, None, []
- if shaders: self.setup_post_fx()
-
- def __set_lgt(self, lgt, col):
- if type(col) in [int, float]: lgt.set_color_temperature(col)
- else: lgt.set_color(col)
- self.lights += [render.attach_new_node(lgt)]
- render.set_light(self.lights[-1])
-
- def set_amb_lgt(self, col):
- self.__set_lgt(AmbientLight('ambient light'), col)
-
- def set_dir_lgt(self, col, direction):
- self.__set_lgt(DirectionalLight('directional light'), col)
- self.lights[-1].set_hpr(*direction)
-
- def set_shadow_lgt(self, direction):
- self.__set_lgt(DirectionalLight('directional light'), (1, 1, 1, 1))
- self.lights[-1].node().set_shadow_caster(True, 8192, 8192)
- self.lights[-1].node().get_lens().set_film_size(2048, 2048)
- self.lights[-1].node().get_lens().set_near_far(1, 2048)
- #self.lights[-1].node().show_frustum()
- self.lights[-1].set_hpr(*direction)
- return self.lights[-1]
-
- def set_pnt_lgt(self, col, pos):
- self.__set_lgt(PointLight('point light'), col)
- self.lights[-1].set_pos(*pos)
-
- def set_spotlight(self, col, exp, cutoff, pos, look_at):
- self.__set_lgt(Spotlight('spotlight'), col)
- self.lights[-1].set_exponent(exp)
- self.lights[-1].get_lens().set_fov(cutoff, cutoff)
- self.lights[-1].set_pos(*pos)
- self.lights[-1].look_at(*look_at)
-
- @staticmethod
- def set_default_args(idx):
- pref = 'lights[%s].' % idx
- args = [(pref + 'pos', LVector4f(0, 0, 0, 1)),
- (pref + 'amb', LVector3f(0, 0, 0)),
- (pref + 'diff', LVector3f(0, 0, 0)),
- (pref + 'spec', LVector3f(0, 0, 0)),
- (pref + 'dir', LVector3f(0, 0, 0)),
- (pref + 'exp', .0),
- (pref + 'cutoff', .0)]
- list(map(lambda _args: render.set_shader_input(*_args), args))
-
- def set_lgt_args(self, idx, lgt):
- self.set_default_args(idx)
- ShaderSetter.build(lgt).set('lights[%s].' % idx, lgt)
-
- def clear_lights(self):
- for lgt in self.lights:
- base.render.clear_light(lgt)
- lgt.removeNode()
- self.lights = []
-
- def setup_post_fx(self):
- self.filter_mgr = FilterManager(base.win, base.cam)
- # rendered_scene = Texture()
- # aa_scene = Texture()
- # filtered_scene = Texture()
- # filter_quad = self.filter_mgr.renderQuadInto(colortex=filtered_scene)
- # aa_quad = self.filter_mgr.renderQuadInto(colortex=aa_scene)
- # final_quad = self.filter_mgr.renderSceneInto(colortex=rendered_scene)
- # filter_quad.set_shader(self.__load_shader('filter', 'sobel_filter'))
- # filter_quad.set_shader_input('in_tex', rendered_scene)
- # aa_quad.set_shader(self.__load_shader('fxaa', 'fxaa'))
- # aa_quad.set_shader_input('in_tex', filtered_scene)
- # final_quad.set_shader(self.__load_shader('filter', 'pass'))
- # final_quad.set_shader_input('gamma', self.gamma)
- # final_quad.set_shader_input('in_tex', aa_scene)
-
- @staticmethod
- def __load_shader(vshad, fshad):
- with open('assets/shaders/%s.vert' % vshad) as vfile:
- fvert = vfile.read()
- with open('assets/shaders/%s.frag' % fshad) as ffile:
- ffrag = ffile.read()
- return load_shader(fvert, ffrag)
-
- def apply(self):
- # winprops = WindowProperties.size(2048, 2048)
- # props = FrameBufferProperties()
- # props.set_rgb_color(1)
- # props.set_alpha_bits(1)
- # props.set_depth_bits(1)
- # lbuffer = base.graphicsEngine.make_output(
- # base.pipe, 'offscreen buffer', -2, props, winprops,
- # GraphicsPipe.BFRefuseWindow, base.win.getGsg(), base.win)
- # self.buffer = lbuffer
- # ldepthmap = Texture()
- # lbuffer.addRenderTexture(ldepthmap, GraphicsOutput.RTMBindOrCopy,
- # GraphicsOutput.RTPDepthStencil)
- # ldepthmap.set_minfilter(Texture.FTShadow)
- # ldepthmap.set_magfilter(Texture.FTShadow)
-
- # base.camLens.set_near_far(1.0, 10000)
- # base.camLens.set_fov(75)
-
- # self.lcam = base.makeCamera(lbuffer)
- # self.lcam.node().set_scene(render)
- # self.lcam.node().get_lens().set_fov(45)
- # self.lcam.node().get_lens().set_near_far(1, 100)
-
- # render.set_shader_input('light', self.lcam)
- # render.set_shader_input('depthmap', ldepthmap)
- # render.set_shader_input('ambient', .15, .15, .15, 1.0)
-
- # lci = NodePath(PandaNode('light camera initializer'))
- # lci.set_shader(self.__load_shader('caster', 'caster'))
- # self.lcam.node().set_initial_state(lci.get_state())
-
- # mci = NodePath(PandaNode('main camera initializer'))
- # # use PTALVecBaseX instead
- # # setShaderInput('vec3argname', PTALVecBase3(((0, 0, 0), (1, 1, 1))))
- render.set_shader(self.__main_shader())
- # render.set_shader_input('num_lights', len(self.lights))
- # self.set_shader_pars(render)
- # list(map(
- # lambda lgt: self.set_lgt_args(*lgt), enumerate(self.lights)))
- # mci.setShader(self.__main_shader())
- # base.cam.node().set_initial_state(mci.getState())
-
- # self.lcam.set_pos(15, 30, 45)
- # self.lcam.look_at(0, 15, 0)
- # self.lcam.node().get_lens().set_near_far(1, 100)
-
- def __main_shader(self):
- with open('assets/shaders/main.vert') as fvert:
- vert = fvert.read()
- with open('assets/shaders/main.frag') as ffrag:
- frag = ffrag.read()
- frag = frag.replace('<LIGHTS>', str(len(self.lights)))
- return load_shader(vert, frag)
-
- def toggle_shader(self):
- if render.get_shader():
- render.set_shader_off()
- render.set_shader_auto()
- return
- self.apply()
-
- def set_shader_pars(self, model):
- texture_stages = model.find_all_texture_stages()
- model.set_shader_input('gloss_slot', 0)
- model.set_shader_input('detail_slot', 0)
- model.set_shader_input('detail_scale', (1, 1))
- for tstage in texture_stages:
- if tstage.getSort() == 0: continue
- self.__set_slots(tstage, model, 1 if tstage.getSort() == 10 else 2)
-
- @staticmethod
- def __set_slots(tstage, model, slot):
- if tstage.getMode() == TextureStage.MGloss:
- model.set_shader_input('gloss_slot', slot)
- else:
- model.set_shader_input('detail_slot', slot)
- attrib_type = TexMatrixAttrib.get_class_type()
- for geom_np in model.find_all_matches('**/+GeomNode'):
- geom_node = geom_np.node()
- for i in range(geom_node.get_num_geoms()):
- state = geom_node.get_geom_state(i)
- if state.has_attrib(attrib_type):
- attrib = state.get_attrib(attrib_type)
- for j in range(attrib.get_num_stages()):
- stage = attrib.get_stage(j)
- scale = attrib.get_transform(stage).get_scale()
- model.set_shader_input('detail_scale', scale)
-
- def destroy(self): self.clear_lights()
-
-
-class ShaderSetter:
-
- @staticmethod
- def build(lgt):
- cls2sett = {
- AmbientLight: ShaderSetterAmbient,
- PointLight: ShaderSetterPointLight,
- DirectionalLight: ShaderSetterDirectionalLight,
- Spotlight: ShaderSetterSpotlight}
- return cls2sett[lgt.node().__class__]()
-
- @staticmethod
- def _set_pars(pref, lgt_pos, lgt):
- render.set_shader_input(pref + 'pos', lgt_pos)
- render.set_shader_input(pref + 'diff', lgt.node().get_color())
- render.set_shader_input(pref + 'spec', lgt.node().get_color())
-
-
-class ShaderSetterAmbient(ShaderSetter):
-
- @staticmethod
- def set(pref, lgt):
- render.set_shader_input(pref + 'amb', lgt.node().get_color())
-
-
-class ShaderSetterPointLight(ShaderSetter):
-
- @staticmethod
- def set(pref, lgt):
- lgt_pos = lgt.get_mat(base.cam).xform(LVector4f(0, 0, 0, 1))
- ShaderSetter._set_pars(pref, lgt_pos, lgt)
-
-
-class ShaderSetterDirectionalLight(ShaderSetter):
-
- @staticmethod
- def set(pref, lgt):
- lgt_vec = -render.get_relative_vector(lgt, Vec3(0, 1, 0))
- lgt_pos = LVector4f(lgt_vec[0], lgt_vec[1], lgt_vec[2], 0)
- ShaderSetter._set_pars(pref, lgt_pos, lgt)
-
-
-class ShaderSetterSpotlight(ShaderSetter):
-
- @staticmethod
- def set(pref, lgt):
- lgt_vec = base.cam.get_relative_vector(lgt, Vec3(0, 1, 0))
- lgt_pos = lgt.get_mat(base.cam).xform(LVector4f(0, 0, 0, 1))
- ShaderSetter._set_pars(pref, lgt_pos, lgt)
- render.set_shader_input(pref + 'dir', lgt_vec)
- render.set_shader_input(pref + 'exp', lgt.node().get_exponent())
- cutoff = lgt.node().get_lens().get_fov()[0]
- render.set_shader_input(pref + 'cutoff', cutoff)
+++ /dev/null
-from panda3d.core import Vec2, Vec3, Mat4, LVector2f, LVector3f
-
-
-class P3dVec2:
-
- attr_lst = ['x', 'y']
- p3d_cls = Vec2
-
- def __init__(self, *args):
- self._vec = self.p3d_cls(*args)
-
- @property
- def x(self): return self._vec.x
-
- @property
- def y(self): return self._vec.y
-
- @property
- def xy(self): return P3dVec2(self._vec.x, self._vec.y)
-
- def signed_angle_deg(self, vec):
- return self._vec.signed_angle_deg(LVector2f(vec.x, vec.y))
-
- def dot(self, other):
- if isinstance(other, tuple): other = self.__class__(*other)
- return self._vec.dot(other._vec)
- #TODO: don't access a protected member
-
- def __neg__(self):
- nvec = - self._vec
- return self.__class__(*[getattr(nvec, attr) for attr in self.attr_lst])
-
- def __add__(self, vec):
- if isinstance(vec, tuple): vec = self.__class__(*vec)
- svec = self._vec + vec._vec #TODO: don't access a protected member
- return self.__class__(*[getattr(svec, attr) for attr in self.attr_lst])
-
- def __sub__(self, vec):
- if isinstance(vec, tuple): vec = self.__class__(*vec)
- svec = self._vec - vec._vec #TODO: don't access a protected member
- return self.__class__(*[getattr(svec, attr) for attr in self.attr_lst])
-
- def __mul__(self, val):
- svec = self._vec * val
- return self.__class__(*[getattr(svec, attr) for attr in self.attr_lst])
-
- def normalize(self):
- self._vec.normalize()
- return self.__class__(*self.attrs)
-
- @property
- def attrs(self): return [getattr(self._vec, fld) for fld in self.attr_lst]
-
- @property
- def normalized(self):
- vec = self.p3d_cls(*self.attrs)
- vec.normalize()
- return self.__class__(*[getattr(vec, fld) for fld in self.attr_lst])
-
- def rotate(self, deg):
- rot_mat = Mat4()
- rot_mat.set_rotate_mat(deg, (0, 0, 1))
- self._vec = rot_mat.xform_vec(self._vec)
-
- def length(self): return self._vec.length()
-
- def __repr__(self):
- tmpl = '%s(' + \
- ', '.join(['%s' for _ in range(len(self.attr_lst))]) + ')'
- rnd = lambda x: round(x, 3)
- vals = [rnd(getattr(self._vec, attr)) for attr in self.attr_lst]
- pars = tuple([self.__class__.__name__] + vals)
- return tmpl % pars
-
-
-class P3dVec3(P3dVec2):
-
- attr_lst = ['x', 'y', 'z']
- p3d_cls = Vec3
-
- @property
- def z(self): return self._vec.z
-
- def signed_angle_deg(self, vec):
- v_up = LVector3f(0, 0, 1)
- return self._vec.signed_angle_deg(LVector3f(vec.x, vec.y, vec.z), v_up)
+++ /dev/null
-from panda3d.core import LVecBase4f
-from direct.gui.DirectGuiGlobals import NORMAL, DISABLED
-from lib.engine.vec import Vec2
-
-
-class WidgetMixin:
-
- highlight_color_offset = [
- LVecBase4f(.4, .4, 0, .4),
- LVecBase4f(0, 0, .4, .4),
- LVecBase4f(0, .4, 0, .4),
- LVecBase4f(.4, 0, 0, .4)]
-
- def __init__(self):
- self.start_txt_color = self.start_frame_color = None
- self.was_visible = True
- self.curr_offset = LVecBase4f(0, 0, 0, 0)
-
- def get_np(self): return self.img
-
- def enable(self): pass
-
- def disable(self): pass
-
- @property
- def pos(self):
- try: pos = self.get_pos(self.wdg.get_parent())
- except AttributeError: pos = self.get_pos(self.img.get_parent())
- return Vec2(pos[0], pos[2])
-
- @property
- def global_pos(self):
- pos = self.get_pos(render2d)
- return Vec2(pos[0], pos[2])
-
-
-class ImgMixin(WidgetMixin):
-
- def init(self, wdg): pass
-
-
-class FrameMixin(WidgetMixin):
-
- def init(self, wdg):
- self.curr_offset = LVecBase4f(0, 0, 0, 0)
- self.start_frame_color = wdg.get_np()['frameColor']
-
- def enable(self):
- self['state'] = NORMAL
- if hasattr(self, 'set_alpha_scale'): self.set_alpha_scale(1)
- self.get_np()['frameColor'] = self.start_frame_color
-
- def disable(self):
- self['state'] = DISABLED
- if hasattr(self, 'set_alpha_scale'): self.set_alpha_scale(.25)
- col = self.start_frame_color
- self.get_np()['frameColor'] = (col[0], col[1], col[2], col[3] * .4)
-
- def on_wdg_enter(self, pos=None, player=0): pass
-
- def on_wdg_exit(self, pos=None, player=0): pass
-
-
-class ScrolledFrameMixin(WidgetMixin):
-
- def init(self, wdg): pass
-
- def enable(self): self['state'] = NORMAL
-
- def disable(self): self['state'] = DISABLED
-
- def on_wdg_enter(self, pos=None, player=0): pass
-
- def on_wdg_exit(self, pos=None, player=0): pass
-
-
-class BtnMixin(FrameMixin):
-
- def init(self, wdg):
- FrameMixin.init(self, wdg)
- wdg = wdg.get_np()
- self.start_txt_color = wdg.component('text0').textNode.get_text_color()
- self.start_txt_scale = wdg.component('text0').textNode.get_text_scale()
-
- def on_arrow(self, direction): pass
-
- def on_wdg_enter(self, pos=None, player=0): # pos: mouse's position
- self.curr_offset += WidgetMixin.highlight_color_offset[player]
- col = LVecBase4f(self.start_frame_color)
- self.get_np()['frameColor'] = col + self.curr_offset
- self.get_np()['text_fg'] = self.start_txt_color + self.curr_offset
- self.get_np()['text_scale'] = self.start_txt_scale * 1.04
- self.get_np().set_shader_input('col_offset', self.curr_offset)
- self.get_np().component('text0').textNode.set_shadow(.064, .064)
- self.get_np().component('text0').textNode.set_shadow_color(.2, .2, 0, .8)
-
- def on_wdg_exit(self, pos=None, player=0): # pos: mouse's position
- self.curr_offset -= WidgetMixin.highlight_color_offset[player]
- col = LVecBase4f(self.start_frame_color)
- self.get_np()['frameColor'] = col + self.curr_offset
- self.get_np()['text_fg'] = self.start_txt_color
- self.get_np()['text_scale'] = self.start_txt_scale
- self.get_np()['frameColor'] = self.start_frame_color
- self.get_np().set_shader_input('col_offset', self.curr_offset)
- self.get_np().component('text0').textNode.set_shadow(0, 0)
- self.get_np().component('text0').textNode.set_shadow_color(1, 1, 1, 1)
-
- def on_enter(self, player):
- if self['command'] and self['state'] == NORMAL:
- lst_arg = [player] if player is not None else []
- self['command'](*self['extraArgs'] + lst_arg)
-
- def enable(self):
- FrameMixin.enable(self)
- t0n = self.get_np().component('text0').textNode
- t0n.set_text_color(self.start_txt_color)
- t0n.set_text_scale(self.start_txt_scale)
-
- def disable(self):
- FrameMixin.disable(self)
- col = self.start_txt_color
- self.get_np()['text_fg'] = (col[0], col[1], col[2], col[3] * .4)
- t0n = self.get_np().component('text0').textNode
- t0n.set_text_scale(self.start_txt_scale)
-
-
-class EntryMixin(FrameMixin):
-
- def on_arrow(self, direction): pass
-
- def on_wdg_enter(self, pos=None, player=0): # pos: mouse's position
- FrameMixin.on_wdg_enter(self, pos, player)
- self.curr_offset += WidgetMixin.highlight_color_offset[player]
- col = LVecBase4f(self.start_frame_color)
- self.get_np()['frameColor'] = col + self.curr_offset
- # self.get_np()['focus'] = 1 # it focuses it if mouse over
- # self.get_np().setFocus()
-
- def on_wdg_exit(self, pos=None, player=0): # pos: mouse's position
- FrameMixin.on_wdg_exit(self, pos, player)
- self.curr_offset -= WidgetMixin.highlight_color_offset[player]
- col = LVecBase4f(self.start_frame_color)
- self.get_np()['frameColor'] = col + self.curr_offset
- # self.get_np()['focus'] = 0
- # self.get_np().setFocus()
-
- def on_enter(self, player=0):
- self['focus'] = 1
- if self['command'] and self['state'] == NORMAL:
- self['command'](*self['extraArgs'])
-
-
-class CheckBtnMixin(BtnMixin):
-
- def on_enter(self, player=0):
- self['indicatorValue'] = not self['indicatorValue']
- BtnMixin.on_enter(self, player)
-
-
-class SliderMixin(FrameMixin):
-
- def on_arrow(self, direction):
- if direction in [(-1, 0), (1, 0)]:
- n_p = self.get_np()
- delta = (n_p['range'][1] - n_p['range'][0]) / 10.0
- n_p['value'] += -delta if direction == (-1, 0) else delta
- return direction in [(-1, 0), (1, 0)]
-
- def on_enter(self, player=0): pass
-
-
-class OptionMenuMixin(BtnMixin):
-
- def on_arrow(self, direction):
- is_hor = direction in [(-1, 0), (1, 0)]
- nodepath = self.get_np()
- if is_hor or nodepath.popupMenu.is_hidden(): return False
- old_idx = nodepath.highlightedIndex
- dir2offset = {(0, -1): 1, (0, 1): -1}
- idx = nodepath.highlightedIndex + dir2offset[direction]
- idx = min(len(nodepath['items']) - 1, max(0, idx))
- if old_idx == idx: return True
- fcol = nodepath.component('item%s' % idx)['frameColor']
- old_cmp = nodepath.component('item%s' % old_idx)
- nodepath._unhighlightItem(old_cmp, fcol)
- nodepath._highlightItem(nodepath.component('item%s' % idx), idx)
- return True
-
- def on_enter(self, player=0):
- nodepath = self.get_np()
- if nodepath.popupMenu.is_hidden():
- nodepath.showPopupMenu()
- nodepath._highlightItem(nodepath.component('item0'), 0)
- else:
- nodepath.selectHighlightedIndex()
- idx = nodepath.selectedIndex
- if nodepath['command']: nodepath['command'](nodepath['items'][idx])
- nodepath.hidePopupMenu()
- idx += -1 if idx else 1
- try:
- fcol = nodepath.component('item%s' % idx)['frameColor']
- curr_name = 'item%s' % nodepath.selectedIndex
- nodepath._unhighlightItem(nodepath.component(curr_name), fcol)
- except KeyError: # when there is only one element
- pass
- return not nodepath.popupMenu.is_hidden()
+++ /dev/null
-class ObsInfo:
-
- def __init__(self, mth, sort, args):
- self.mth = mth
- self.sort = sort
- self.args = args
-
- def __repr__(self): return str(self.mth)
-
-
-class Subject:
-
- def __init__(self):
- self.observers = {}
-
- def attach(self, obs_meth, sort=10, rename='', args=None):
- args = args or []
- onm = rename or obs_meth.__name__
- if onm not in self.observers: self.observers[onm] = []
- self.observers[onm] += [ObsInfo(obs_meth, sort, args)]
- sorted_obs = sorted(self.observers[onm], key=lambda obs: obs.sort)
- self.observers[onm] = sorted_obs
-
- def detach(self, obs_meth, lambda_call=None):
- if isinstance(obs_meth, str):
- onm = obs_meth
- observers = [obs for obs in self.observers[onm]
- if obs.mth == lambda_call]
- else:
- onm = obs_meth.__name__
- observers = [obs for obs in self.observers[onm]
- if obs.mth == obs_meth]
- if not observers: raise Exception
- list(map(self.observers[onm].remove, observers))
-
- def notify(self, meth, *args, **kwargs):
- if meth not in self.observers: return # no obs for this notification
- for obs in self.observers[meth][:]:
- if obs in self.observers[meth]: # if an obs removes another one
- try:
- act_args = obs.args + list(args)
- obs.mth(*act_args, **kwargs)
- except SystemError:
- print('Quit')
- import sys; sys.exit()
-
- def observing(self, obs_meth):
- if callable(obs_meth): obs_meth = obs_meth.__name__
- return obs_meth in self.observers and self.observers[obs_meth]
-
- def destroy(self): self.observers = None
-
-
-class Observer: pass
+++ /dev/null
-import sys
-
-if len(sys.argv) != 2:
- print('Usage: apply_gloss.py filename.egg')
- sys.exit(0)
-
-
-def __process_line(idx, line, _out_lines):
- if line.strip() != '<Scalar> envtype { GLOSS }':
- mth = __process_nongloss_line
- else: mth = __process_gloss_line
- return mth(idx, line, _out_lines)
-
-
-def __process_nongloss_line(idx, line, _out_lines):
- is_scal = line.strip().startswith('<Scalar> alpha-file { ')
- if not idx or not (line.strip() == _out_lines[-1].strip() and is_scal):
- _out_lines += [line.rstrip()]
- return _out_lines
-
-
-def __process_gloss_line(idx, line, _out_lines):
- _out_lines += [line.rstrip()]
- outl = ''
- for char in line:
- if char == ' ': outl += ' '
- else: break
- outl += '<Scalar> alpha-file { %s }' % lines[idx - 1].strip()
- return _out_lines + [outl]
-
-
-out_lines = []
-with open(sys.argv[1]) as fin:
- lines = fin.readlines()
- for _idx, _line in enumerate(lines):
- out_lines = __process_line(_idx, _line, out_lines)
-
-
-with open(sys.argv[1], 'w') as fout:
- list(map(lambda outl: fout.write(outl + '\n'), out_lines))
+++ /dev/null
-from sys import argv
-from os.path import abspath
-from os import system
-
-ao = abspath(argv[1])
-roughness = abspath(argv[2])
-metal = abspath(argv[3])
-fout = abspath(argv[4])
-
-system('cp %s %s' % (ao, fout))
-cmd = 'convert %s %s -alpha off -compose copy_green -composite %s' % (fout, roughness, fout)
-print(cmd)
-system(cmd)
-cmd = 'convert %s %s -alpha off -compose copy_blue -composite %s' % (fout, metal, fout)
-print(cmd)
-system(cmd)
+++ /dev/null
-class BlockReplacer:
-
- def __init__(self, out_lines, start_line, end_line, new_lines):
- self.out_lines = out_lines
- self.start_line = start_line
- self.end_line = end_line
- self.new_lines = new_lines
- self.is_replacing = False
-
- def process_line(self, line):
- if self.is_replacing and line.rstrip() == self.end_line:
- self.is_replacing = False
- return True
- if line.rstrip() == self.start_line:
- self.out_lines += self.new_lines
- self.is_replacing = True
- return self.is_replacing
-
-
-class Fixer:
-
- def __init__(self):
- self.out_lines = []
- with open('track.egg') as fin:
- self.lines = fin.readlines()
- self.replacers = []
- new_lines = [
- '<Texture> MASKOBJTrack {\n',
- ' "./tex/MASKOBJTrack.jpg"\n',
- ' <Scalar> combine-rgb { INTERPOLATE }\n',
- ' <Scalar> combine-rgb-source0 { PREVIOUS }\n',
- ' <Scalar> combine-rgb-operand0 { SRC-COLOR }\n',
- ' <Scalar> combine-rgb-source1 { LAST_SAVED_RESULT }\n',
- ' <Scalar> combine-rgb-operand1 { SRC-COLOR }\n',
- ' <Scalar> combine-rgb-source2 { TEXTURE }\n',
- ' <Scalar> combine-rgb-operand2 { SRC-COLOR }\n',
- ' <Scalar> minfilter { LINEAR_MIPMAP_LINEAR }\n',
- ' <Scalar> magfilter { LINEAR_MIPMAP_LINEAR }\n',
- ' <Scalar> wrap { REPEAT }\n',
- '}\n']
- rep_str = '<Texture> MASKOBJTrack {'
- rep = BlockReplacer(self.out_lines, rep_str, '}', new_lines)
- self.replacers += [rep]
-
- new_lines = [
- '<Texture> TEXREPOBJTrack1 {\n',
- ' "./tex/snowbackground.jpg"\n',
- ' <Scalar> envtype { MODULATE }\n']
- rep_str = '<Texture> TEXREPOBJTrack1 {'
- repl_str = ' <Scalar> envtype { MODULATE }'
- rep = BlockReplacer(self.out_lines, rep_str, repl_str, new_lines)
- self.replacers += [rep]
-
- new_lines = [
- '<Texture> TEXREPOBJTrack2 {\n',
- ' "./tex/Tileable ice ground texture.jpg"\n',
- ' <Scalar> envtype { MODULATE }\n',
- ' <Scalar> saved-result { 1 }\n']
- rep_str = '<Texture> TEXREPOBJTrack2 {'
- repl_str = ' <Scalar> envtype { MODULATE }'
- rep = BlockReplacer(self.out_lines, rep_str, repl_str, new_lines)
- self.replacers += [rep]
-
- new_lines = [
- ' <TRef> { TEXREPOBJTrack1 }\n',
- ' <TRef> { MASKOBJTrack }\n']
- rep = BlockReplacer(
- self.out_lines,
- ' <TRef> { MASKOBJTrack }',
- ' <TRef> { TEXREPOBJTrack1 }',
- new_lines)
- self.replacers += [rep]
-
- for line in self.lines:
- if not any(rep.process_line(line) for rep in self.replacers):
- self.out_lines += [line]
- with open('track_fixed.egg', 'w') as fout:
- list(map(fout.write, self.out_lines))
-
-
-Fixer()
+++ /dev/null
-# this kills yocto when it is being launched by geany
-from subprocess import Popen, PIPE
-from os import system
-
-
-def exec_cmd(cmd):
- ret = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()
- return '\n'.join(ret)
-
-
-processes_str = exec_cmd('ps aux | grep "python main.py"')
-processes = list(enumerate(processes_str.split('\n')))
-sh_cmd = ' /bin/sh -c python main.py'
-geany_row = [proc for proc in processes if proc[1].endswith(sh_cmd)][0][0]
-geany_pid = list(processes)[geany_row + 1][1].split()[1]
-system('kill -9 ' + geany_pid)
+++ /dev/null
-# this kills yocto's server
-from subprocess import Popen, PIPE
-from os import system
-
-
-def exec_cmd(cmd):
- ret = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()
- return '\n'.join(ret)
-
-
-grep = "grep -E 'python.*server.*yocto.*main.py|python.*yocto.*server.*main.py'"
-proc_line = exec_cmd('ps aux | ' + grep).split('\n')[0]
-srv_pid = proc_line.split()[1]
-system('kill -9 ' + srv_pid)
+++ /dev/null
-# python lib/tools/pdfsingle.py path/to/file.py
-from os import chdir, getcwd, system
-from os.path import dirname, basename, exists
-from sys import argv
-
-
-class InsideDir:
-
- def __init__(self, dir_):
- self.dir = dir_
- self.old_dir = getcwd()
-
- def __enter__(self):
- chdir(self.dir)
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- chdir(self.old_dir)
-
-
-filename = argv[1]
-name = basename(filename)
-path = dirname(filename)
-noext = name.rsplit('.', 1)[0]
-test_tmpl = "tail -n +1 {found} " + \
- "| sed 's/==> /# ==> /' > tmp.txt ; enscript --font=Courier10 " + \
- "--continuous-page-numbers --no-header --pretty-print=python " + \
- "-o - tmp.txt | psnup -2 -P letter -p a4 -m12 | ps2pdf - {name}.pdf ; rm tmp.txt"
- #"-o - tmp.txt | ps2pdf - {name}.pdf ; rm tmp.txt"
-found = filename
-with InsideDir('tests/' + path):
- if exists('test_' + name):
- found += ' lib/tests/%s/test_%s' % (path, name)
-test_cmd = test_tmpl.format(name=noext, found=found)
-system(test_cmd)
-#system('pdfnup --nup 2x1 -o {noext}.pdf {noext}.pdf'.format(noext=noext))
+++ /dev/null
-# usage: python lib/tools/process_models.py
-from os import system, walk
-from sys import executable
-
-
-for root, _, fnames in walk('assets/models'):
- for fname in [fname for fname in fnames if fname.endswith('.egg')]:
- _fname = root + '/' + fname
- system('egg-trans -nv 30 -o %s %s' % (_fname, _fname))
- system(executable + ' lib/tools/apply_gloss.py ' + _fname)
+++ /dev/null
-from os import listdir
-
-
-def __set_diffuse(fpath):
- out_lines = []
- with open(fpath) as fin:
- for line in fin.readlines():
- out_lines = __process_line(line, out_lines)
- with open(fpath, 'w') as fin:
- list(map(lambda outl: fin.write(outl + '\n'), out_lines))
-
-
-def __process_line(line, out_lines):
- if not line.strip().startswith('<Scalar> diff'):
- new_lines = [line.rstrip()]
- else: new_lines = [line.split(' { ')[0] + ' { 1.000000 }']
- return out_lines + new_lines
-
-
-list(map(__set_diffuse,
- [fname for fname in listdir('.') if fname.endswith('.egg')]))
'''This is the main file. This launches the application.'''
-import lib.engine.log # so logging's info/debug are logged
+import ya2.engine.log # so logging's info/debug are logged
from sys import argv
from panda3d.core import load_prc_file_data
if '--version' in argv:
#+CATEGORY: pmachines
#+TAGS: bug(b) calendar(c) waiting(w)
-* RED rename lib to ya2
+* RED remove unused code
* READY refactoring
* BACKLOG improve level domino box basketball: it can be solved trivially
* BACKLOG do intro video with moviepy
* BACKLOG optimize slow tests
+* BACKLOG implement functional tests with xmlrpc; retrieve the coordinates with rpc
* BACKLOG intro animation (from target item to start position)
* BACKLOG buttons of the scenes enabled sequentially
- [ ] each scene has a version
from setuptools.command.develop import develop
from multiprocessing import cpu_count
from direct.dist.commands import bdist_apps
-from lib.build.build import branch, files, ver, files, bld_dpath
-from lib.build.docs import bld_docs
-from lib.build.models import ModelsBuilder
-from lib.build.images import bld_images
-from lib.build.screenshots import bld_screenshots
-from lib.build.lang import LanguageBuilder
+from ya2.build.build import branch, files, ver, files, bld_dpath
+from ya2.build.docs import bld_docs
+from ya2.build.models import ModelsBuilder
+from ya2.build.images import bld_images
+from ya2.build.screenshots import bld_screenshots
+from ya2.build.lang import LanguageBuilder
from p3d_appimage import AppImageBuilder
from p3d_flatpak import FlatpakBuilder
-import lib.engine.log # so logging's info/debug are logged
+import ya2.engine.log # so logging's info/debug are logged
from game.app import PmachinesApp
print(msg)
cmd = 'patch --forward ' + \
'../venv/lib/python3.7/site-packages/direct/dist/commands.py' + \
- ' lib/build/commands.patch'
+ ' ya2/build/commands.patch'
system(cmd)
bdist_apps.run(self)
if not self.nolinux:
'assets/images/icon/icon32.png',
'assets/images/icon/icon16.png']},
'include_patterns': [
- '**/lib/licenses/*',
+ '**/ya2/licenses/*',
'**/licenses/*',
'**/*.bam',
'**/*.dds',
'''Create ref:
* M-x fla-set-fun-test
* rm options.ini
-* python main.py --functional-test --functional-ref & python -m lib.tools.functional_test.py 1
-* python main.py --functional-test --functional-ref & python -m lib.tools.functional_test.py 2
+* python main.py --functional-test --functional-ref & python -m ya2.tools.functional_test.py 1
+* python main.py --functional-test --functional-ref & python -m ya2.tools.functional_test.py 2
* M-x fla-unset-fun-test'''
from panda3d.core import load_prc_file_data
load_prc_file_data('', 'window-type none')
from panda3d.core import Filename
from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText
-from lib.gameobject import GameObject
-from lib.build.build import _branch
+from ya2.gameobject import GameObject
+from ya2.build.build import _branch
class FunctionalTest(GameObject):
from shutil import rmtree
from unittest import TestCase
from re import compile
-from lib.build.build import InsideDir, files, exec_cmd, _branch, _version, \
+from ya2.build.build import InsideDir, files, exec_cmd, _branch, _version, \
to_be_built
from os.path import exists
from shutil import rmtree, copy
from unittest import TestCase
-from lib.build.lang import LanguageBuilder
+from ya2.build.lang import LanguageBuilder
class LangTests(TestCase):
from unittest import TestCase
from itertools import product
from time import time
-from lib.build.models import ModelsBuilder
+from ya2.build.models import ModelsBuilder
class ModelsBuilderTests(TestCase):
from pathlib import Path
from os.path import exists
from unittest import TestCase
-from lib.build.mtprocesser import ProcesserMgr
+from ya2.build.mtprocesser import ProcesserMgr
class ProcesserMgrTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.engine.audio import EngineAudio
+from ya2.engine.engine import Engine
+from ya2.engine.audio import EngineAudio
class EngineAudioTests(TestCase):
from unittest import TestCase
from unittest.mock import MagicMock
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
+from ya2.engine.engine import Engine
class EngineCBMuxTests(TestCase):
from unittest import TestCase
from unittest.mock import MagicMock
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.engine.audio import EngineAudio
+from ya2.engine.engine import Engine
+from ya2.engine.audio import EngineAudio
class EngineClockTests(TestCase):
from unittest import TestCase
from unittest.mock import MagicMock
from panda3d.core import loadPrcFileData, ConfigVariableInt, ConfigVariableString
-from lib.engine.engine import Engine
-from lib.engine.configuration import Cfg
+from ya2.engine.engine import Engine
+from ya2.engine.configuration import Cfg
class EngineConfigurationTests(TestCase):
from unittest.mock import create_autospec
from unittest import TestCase
from panda3d.core import loadPrcFileData, NodePath, ConfigVariableBool
-from lib.engine.engine import Engine
-from lib.engine.configuration import Cfg, CursorCfg
+from ya2.engine.engine import Engine
+from ya2.engine.configuration import Cfg, CursorCfg
class ConfigurationTests(TestCase):
from unittest import TestCase
from unittest.mock import patch, create_autospec
from panda3d.core import loadPrcFileData, GraphicsWindow
-from lib.engine.engine import Engine
-from lib.engine.event import EngineEvent
+from ya2.engine.engine import Engine
+from ya2.engine.event import EngineEvent
class EngineEventTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData, DynamicTextFont
-from lib.engine.engine import Engine
+from ya2.engine.engine import Engine
class EngineFontTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.lib.p3d.gfx import P3dNode
+from ya2.engine.engine import Engine
+from ya2.lib.p3d.gfx import P3dNode
class EngineGfxTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.engine.joystick import JoystickMgr, JoystickState
-from lib.engine.gui.menu import NavInfoPerPlayer
+from ya2.engine.engine import Engine
+from ya2.engine.joystick import JoystickMgr, JoystickState
+from ya2.engine.gui.menu import NavInfoPerPlayer
class EngineJoystickTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.gameobject import GameObject
-from lib.engine.engine import Engine
-from lib.computer_proxy import ComputerProxy, compute_once, once_a_frame
+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):
from os import remove
from os.path import exists
from unittest import TestCase
-from lib.dictfile import DctFile
+from ya2.dictfile import DctFile
class DictFileTests(TestCase):
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.engine.configuration import Cfg
-from lib.game import GameLogic, Game
-from lib.gameobject import GameObject, FsmColleague, AudioColleague, \
+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
from unittest.mock import patch
from unittest import TestCase
from panda3d.core import loadPrcFileData
-from lib.engine.engine import Engine
-from lib.gameobject import AiColleague, AudioColleague, EventColleague, \
+from ya2.engine.engine import Engine
+from ya2.gameobject import AiColleague, AudioColleague, EventColleague, \
FsmColleague, GameObject, GfxColleague, GuiColleague, LogicColleague, \
PhysColleague, Colleague
sys.path.append(str(Path(__file__).parent.parent.parent))
from unittest import TestCase
from unittest.mock import MagicMock
-from lib.observer import Subject
+from ya2.observer import Subject
class Observed(Subject): pass
from os.path import exists, basename, join
from glob import glob
from panda3d.core import Filename
-from lib.build.build import exec_cmd, _branch, ver
+from ya2.build.build import exec_cmd, _branch, ver
class FunctionalTests(TestCase):
from unittest import TestCase
from setuptools.dist import Distribution
from setup import AbsCmd
-from lib.build.build import exec_cmd
+from ya2.build.build import exec_cmd
class SetupTests(TestCase):
--- /dev/null
+from pathlib import Path
+import sys
+sys.path.append(str(Path(__file__).parent.parent))
--- /dev/null
+import bpy, sys, os
+
+filepath = os.path.abspath(sys.argv[-1])
+bpy.ops.export_scene.gltf(
+ filepath=filepath,
+ export_format='GLTF_SEPARATE',
+ export_extras=True,
+ export_tangents=True,
+ use_selection=True)
--- /dev/null
+'''Tools for making the builds.'''
+from os import walk, chdir, getcwd
+from os.path import join, getsize, exists, dirname, getmtime, sep
+from subprocess import Popen, PIPE, run
+from logging import debug
+from time import strftime
+from pathlib import Path
+from hashlib import md5
+
+
+#TODO refactor: make class BuilderTools
+
+
+def exec_cmd(cmd):
+ '''Synchronously executes a command and returns its output.'''
+ #ret = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()
+ #return ret[0].decode('utf-8').strip()
+ proc = run(cmd, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
+ return proc.stdout.strip() + proc.stderr.strip()
+
+
+def _branch():
+ '''Returns the current branch.'''
+ git_branch = exec_cmd('git symbolic-ref HEAD').split('/')[-1].strip()
+ print('git_branch result: %s' % git_branch)
+ branches = ['master', 'rc', 'stable']
+ if git_branch in branches:
+ print('git_branch: %s' % git_branch)
+ return git_branch
+ root = str(Path(dirname(dirname(__file__))).parent) + '/'
+ if 'itch' in __file__.split(sep):
+ root = str(Path(dirname(__file__))) + '/'
+ if __file__ == '/app/bin/pmachines': # flatpak
+ root = '/app/bin/'
+ for branch in branches:
+ try:
+ print('try: %s' % root + 'assets/bld_version.txt')
+ with open(root + 'assets/bld_version.txt') as fver:
+ ver = fver.read()
+ print('ver: %s' % ver)
+ #if branch in ver:
+ b2c = {'master': 'a', 'rc': 'r', 'stable': '.'}
+ if ver[1] == b2c[branch]:
+ return branch
+ except FileNotFoundError:
+ print('file not found: %s' % root + 'assets/bld_version.txt')
+
+
+def _commit():
+ '''Returns the current branch.'''
+ git_commit = exec_cmd('git rev-parse HEAD')[:7]
+ print('git_commit result: %s' % git_commit)
+ if not git_commit.startswith("Can't r"):
+ return git_commit
+ root = str(Path(dirname(dirname(__file__))).parent) + '/'
+ if 'itch' in __file__.split(sep):
+ root = str(Path(dirname(__file__))) + '/'
+ if __file__ == '/app/bin/pmachines': # flatpak
+ root = '/app/bin/'
+ try:
+ print('try: %s' % root + 'assets/bld_version.txt')
+ with open(root + 'assets/bld_version.txt') as fver:
+ ver = fver.read()
+ print('ver: %s' % ver)
+ return ver.split('-')[1]
+ except FileNotFoundError:
+ print('file not found: %s' % root + 'assets/bld_version.txt')
+
+
+def _version():
+ '''Computes the version of the current build.'''
+ day = strftime('%y%m%d')
+ root = str(Path(dirname(dirname(__file__))).parent) + '/'
+ if __file__ == '/app/bin/pmachines': # flatpak
+ root = '/app/bin/'
+ if _branch() == 'stable':
+ pref, _ver = '', ''
+ if exists(root + 'assets/version.txt'):
+ with open(root + 'assets/version.txt') as fver:
+ pref = fver.read().strip() + '-' # + _branch() + '-'
+ _ver = fver.read().strip()
+ ret_ver = _ver or ('0.' + day)
+ else:
+ #try: we want an error!
+ pref = {'master': 'a', 'rc': 'rc', '': 'runtime'}[_branch()]
+ #except KeyError:
+ # pref = 'notfound'
+ ret_ver = '0%s%s' % (pref, day)
+ pref = ret_ver
+ bld_ver = pref + '-' + _commit()
+ try:
+ with open(root + 'assets/bld_version.txt', 'w') as fver:
+ fver.write(bld_ver)
+ except OSError:
+ print("we can't write inside flatpaks, but we don't need it")
+ return ret_ver
+
+
+def files(_extensions, excl_dirs=None, excl_ends_with=None, root_path='.'):
+ '''Retrieves filenames in root_path with _extensions, with filters.'''
+ return [join(root, fname)
+ for root, _, fnames in walk(root_path)
+ for fname in __files_ext(fnames, _extensions)
+ if not any(e_d in root.split('/') for e_d in excl_dirs or []) and
+ not any(fname.endswith(e_e) for e_e in excl_ends_with or [])]
+
+
+def __files_ext(fnames, _extensions):
+ return [fname for fname in fnames
+ if any(fname.endswith('.' + ext) for ext in _extensions)]
+
+
+def __to_be_built_single(src, tgt):
+ if getmtime(tgt) > getmtime(src):
+ print('%s is newer than %s: do not build' % (tgt, src))
+ return False
+ with open(src, 'rb') as f:
+ src_content = f.read()
+ with open(tgt, 'rb') as f:
+ tgt_content = f.read()
+ hash_src = md5(src_content).hexdigest()
+ hash_tgt = md5(tgt_content).hexdigest()
+ cache = {}
+ lines = []
+ if exists('hash_cache.txt'):
+ with open('hash_cache.txt') as f:
+ lines = f.readlines()
+ for line in lines:
+ line_spl = line.split()
+ hash = line_spl[-1]
+