"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"PO-Revision-Date: 2022-10-20 15:23+0200\n"
+"PO-Revision-Date: 2022-11-15 12:07+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: pmachines/scene.py:102
+#: pmachines/scene.py:105
msgid "Scene: "
msgstr "Scena: "
-#: pmachines/scene.py:624
+#: pmachines/scene.py:625
msgid "You win!"
msgstr "Hai vinto!"
-#: pmachines/scene.py:697
+#: pmachines/scene.py:702
msgid "You have failed!"
msgstr "Hai perso!"
+#: pmachines/editor/scene_list.py:34
+msgid "Write the file names (without the extension), one file for each line"
+msgstr "Scrivi i nomi dei file (senza estensione), uno per riga."
+
+#: pmachines/editor/scene_list.py:96 pmachines/editor/scene.py:240
+msgid "You have unsaved changes. Really quit?"
+msgstr "Hai modifiche non salvate, vuoi veramente uscire?"
+
+#: pmachines/editor/inspector.py:61 pmachines/editor/inspector.py:308
+#: pmachines/editor/inspector.py:436
+msgid "position"
+msgstr "posizione"
+
+#: pmachines/editor/inspector.py:62
+msgid "roll"
+msgstr "roll"
+
+#: pmachines/editor/inspector.py:63 pmachines/editor/start_items.py:54
+msgid "scale"
+msgstr "scala"
+
+#: pmachines/editor/inspector.py:64 pmachines/editor/start_items.py:55
+msgid "mass"
+msgstr "massa"
+
+#: pmachines/editor/inspector.py:65 pmachines/editor/start_items.py:56
+msgid "restitution"
+msgstr "rimbalzo"
+
+#: pmachines/editor/inspector.py:66 pmachines/editor/start_items.py:57
+msgid "friction"
+msgstr "frizione"
+
+#: pmachines/editor/inspector.py:67 pmachines/editor/inspector.py:309
+#: pmachines/editor/inspector.py:437 pmachines/editor/start_items.py:58
+msgid "id"
+msgstr "id"
+
+#: pmachines/editor/inspector.py:68 pmachines/editor/start_items.py:66
+msgid "strategy"
+msgstr "strategia"
+
+#: pmachines/editor/inspector.py:69 pmachines/editor/start_items.py:67
+msgid "strategy_args"
+msgstr "argomenti strategia"
+
+#: pmachines/editor/inspector.py:250 pmachines/editor/start_items.py:288
+msgid "There are errors in the strategy args."
+msgstr "Ci sono errori negli argomenti della strategia."
+
+#: pmachines/editor/scene.py:67
+msgid "Filename"
+msgstr "Filename"
+
+#: pmachines/editor/scene.py:82
+msgid "Name"
+msgstr "Nome"
+
+#: pmachines/editor/scene.py:97
+msgid "Description"
+msgstr "Descrizione"
+
+#: pmachines/editor/scene.py:165 pmachines/editor/scene.py:172
+msgid "new item"
+msgstr "nuovo oggetto"
+
+#: pmachines/editor/start_items.py:52
+msgid "class"
+msgstr "classe"
+
+#: pmachines/editor/start_items.py:53
+msgid "count"
+msgstr "quantità"
+
#: pmachines/gui/menu.py:95
msgid "Play"
msgstr "Gioca"
" \ 1scale\ 1Luisa Tenuta\ 2\n"
" \ 1scale\ 1Damiana Ercolani\ 2"
-#: pmachines/editor/scene_list.py:34
-msgid "Write the file names (without the extension), one file for each line"
-msgstr "Scrivi i nomi dei file (senza estensione), uno per riga."
-
-#: pmachines/editor/scene_list.py:96 pmachines/editor/scene.py:127
-msgid "You have unsaved changes. Really quit?"
-msgstr "Hai modifiche non salvate, vuoi veramente uscire?"
-
-#: pmachines/editor/inspector.py:43
-msgid "position"
-msgstr "posizione"
-
-#: pmachines/editor/inspector.py:44
-msgid "roll"
-msgstr "roll"
-
-#: pmachines/editor/inspector.py:45
-msgid "scale"
-msgstr "scala"
-
-#: pmachines/editor/inspector.py:46
-msgid "mass"
-msgstr "massa"
-
-#: pmachines/editor/inspector.py:47
-msgid "restitution"
-msgstr "rimbalzo"
-
-#: pmachines/editor/inspector.py:48
-msgid "friction"
-msgstr "frizione"
-
-#: pmachines/editor/scene.py:43
-msgid "Name"
-msgstr "Nome"
-
-#: pmachines/editor/scene.py:58
-msgid "Description"
-msgstr "Descrizione"
-
#~ msgid ""
#~ "Goal: the left box must hit the right box\n"
#~ "\n"
from ya2.utils.log import LogManagerBase
LogManagerBase.pre_init_logging()
from sys import argv
-from ya2.p3d.gfx import P3dGfxMgr
-if '--version' in argv: P3dGfxMgr.no_window()
+from ya2.utils.gui import GuiTools
+if '--version' in argv: GuiTools.no_window()
from os.path import exists
from p3d_appimage import AppImageBuilder
from pmachines.app import Pmachines
from os import makedirs
from multiprocessing import cpu_count
from panda3d.core import Filename, load_prc_file_data, AntialiasAttrib, \
- WindowProperties, LVector2i, TextNode
+ WindowProperties, LVector2i, TextNode, GraphicsBuffer
from panda3d.bullet import BulletWorld, BulletDebugNode
from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText
from pmachines.posmgr import PositionMgr
from pmachines.persistent import Persistent
from ya2.utils.dictfile import DctFile
-from ya2.p3d.p3d import LibP3d
+from ya2.utils.logics import LogicsTools
from ya2.utils.lang import LangMgr
from ya2.utils.log import LogMgr
from ya2.utils.functional import FunctionalTest
-from ya2.p3d.asserts import Assert
+from ya2.utils.asserts import Assert
class MainFsm(FSM):
def __do_asserts(self):
args = self._pmachines._args
- if not LibP3d.runtime() or args.functional_test or args.functional_ref:
+ if not LogicsTools.runtime() or args.functional_test or args.functional_ref:
Assert.assert_threads()
Assert.assert_tasks()
Assert.assert_render3d()
Assert.assert_events()
Assert.assert_buffers()
+ def enterOff(self):
+ self.ignore('new_scene')
+
class Pmachines:
self.log_mgr = LogMgr.init_cls()()
self._pos_mgr = PositionMgr()
self._prepare_window(args)
+ self._fsm = MainFsm(self)
+ self._fsm.demand('Start') # otherwise it is Off and cleanup in tests won't work
if args.update:
return
if args.functional_test:
self.lang_mgr = LangMgr(self._options['settings']['language'],
'pmachines',
'assets/locale/')
- self._fsm = MainFsm(self)
if args.functional_test or args.functional_ref:
FunctionalTest(args.functional_ref, self._pos_mgr)
- if not LibP3d.runtime() or args.functional_test or args.functional_ref:
+ if not LogicsTools.runtime() or args.functional_test or args.functional_ref:
self.__fps_lst = []
taskMgr.do_method_later(1.0, self.__assert_fps, 'assert_fps')
optfile = args.optfile if args.optfile else 'options.ini'
info('data path: %s' % data_path)
info('option file: %s' % optfile)
- info('fixed path: %s' % LibP3d.fixpath(data_path + '/' + optfile))
+ info('fixed path: %s' % LogicsTools.fixpath(data_path + '/' + optfile))
default_opt = {
'settings': {
'volume': 1,
'fps': 0,
'editor': 0,
'auto_start_editor': 0}}
- opt_path = LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile
+ opt_path = LogicsTools.fixpath(data_path + '/' + optfile) if data_path else optfile
opt_exists = exists(opt_path)
self._options = DctFile(
- LibP3d.fixpath(data_path + '/' + optfile) if data_path else optfile,
+ LogicsTools.fixpath(data_path + '/' + optfile) if data_path else optfile,
default_opt)
if not opt_exists:
self._options.store()
props.set_size(res)
props.set_fullscreen(fullscreen)
props.set_icon_filename('assets/images/icon/pmachines.ico')
- if not args.screenshot and not self.is_version_run and base.win:
+ if not args.screenshot and not self.is_version_run and base.win and not isinstance(base.win, GraphicsBuffer):
base.win.request_properties(props)
#gltf.patch_loader(base.loader)
if self._options['development']['simplepbr'] and not self.is_version_run and base.win:
assert not all(fps < fps_threshold for fps in self.__fps_lst), 'low fps %s' % self.__fps_lst
return task.again
+ def destroy(self):
+ self._fsm.cleanup()
+ self.base.destroy()
+
def run(self):
self.start()
self.base.run()
from direct.gui.DirectGuiGlobals import FLAT, NORMAL
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
-from ya2.p3d.gfx import P3dGfxMgr
from pmachines.items.item import ItemStrategy, FixedStrategy, StillStrategy
from pmachines.items.box import HitStrategy
from pmachines.items.domino import DownStrategy, UpStrategy
return img
def __on_item_rototranslated(self, np):
- pos = P3dGfxMgr.pos2d_p2d(np)
+ pos = np.pos2d_pixel()
self.__entries.position.set('%s %s' % (str(round(pos[0], 3)), str(round(pos[1], 3))))
self.__item.json['position'] = list(pos)
from pmachines.editor.scene_list import SceneList
from pmachines.editor.inspector import Inspector, PixelSpaceInspector, WorldSpaceInspector
from pmachines.editor.start_items import StartItems
-from ya2.p3d.gfx import P3dGfxMgr
+from ya2.utils.gfx import Point
class SceneEditor(DirectObject):
win_res = base.win.getXSize(), base.win.getYSize()
pos_win = (pos_pixel[0] / win_res[0] * 2 - 1,
1 - pos_pixel[1] / win_res[1] * 2)
- p_from, p_to = P3dGfxMgr.world_from_to(pos_win)
- hits = self.__world.ray_test_all(p_from, p_to).get_hits()
+ p_from, p_to = Point(pos_win).from_to_points()
for hit in self.__world.ray_test_all(p_from, p_to).get_hits():
if hit.get_node() == self.__mouse_plane_node:
pos = hit.get_hit_pos()
from direct.gui.DirectGuiGlobals import FLAT, NORMAL
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
-from pmachines.items.item import Item, ItemStrategy, FixedStrategy, StillStrategy
-from pmachines.items.box import HitStrategy
-from pmachines.items.domino import DownStrategy, UpStrategy
+from pmachines.items.item import Item, ItemStrategy
class StartItems(DirectObject):
from webbrowser import open_new_tab
from xmlrpc.client import ServerProxy
from panda3d.core import Texture, TextNode, WindowProperties, LVector2i, \
- TextProperties, TextPropertiesManager, NodePath
+ TextProperties, TextPropertiesManager
from direct.gui.DirectGui import DirectButton, DirectCheckButton, \
DirectOptionMenu, DirectSlider
from direct.gui.DirectGuiGlobals import FLAT
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from ya2.utils.cursor import MouseCursor
-from ya2.p3d.p3d import LibP3d
+from ya2.utils.gfx import GfxTools, DirectGuiMixin
class DirectOptionMenuTest(DirectOptionMenu):
self._widgets += [DirectButton(
text=_('Play'), pos=(0, 1, .6), command=self.on_play,
**self._common_btn)]
- self._pos_mgr.register('play', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('play', self._widgets[-1].pos_pixel())
self._widgets += [DirectButton(
text=_('Options'), pos=(0, 1, .2), command=self.on_options,
**self._common_btn)]
- self._pos_mgr.register('options', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('options', self._widgets[-1].pos_pixel())
self._widgets += [DirectButton(
text=_('Credits'), pos=(0, 1, -.2), command=self.on_credits,
**self._common_btn)]
- self._pos_mgr.register('credits', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('credits', self._widgets[-1].pos_pixel())
def btn_exit():
if self._fun_test:
self._widgets += [DirectButton(
text=_('Exit'), pos=(0, 1, -.6), command=lambda: btn_exit(),
**self._common_btn)]
- self._pos_mgr.register('exit', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('exit', self._widgets[-1].pos_pixel())
self._rearrange_width()
self.accept('enforce_resolution', self.enforce_res)
def lang_cb(comps):
self._pos_mgr.remove(['english', 'italian'])
for lng, btn in zip(['english', 'italian'], comps):
- pos = LibP3d.wdg_pos(btn)
+ pos = btn.pos_pixel()
self._pos_mgr.register(lng, (pos[0] + 5, pos[1]))
btn = DirectOptionMenuTest(
text=_('Language'), items=items, initialitem=inititem,
pos=(0, 1, .8), command=self.on_language, **self._common_opt)
+ btn.__class__ = type('DirectOptionMenuMixed', (DirectOptionMenu, DirectGuiMixin), {})
btn._show_cb = lang_cb
btn.popupMenu['frameColor'] = self._common_btn['frameColor']
btn.popupMenu['relief'] = self._common_btn['relief']
self._widgets += [btn]
- pos_lang = LibP3d.wdg_pos(self._widgets[-1])
+ pos_lang = self._widgets[-1].pos_pixel()
self._pos_mgr.register('languages', pos_lang)
self._widgets += [OnscreenText(
_('Volume'), pos=(-.1, .55), font=self._common['text_font'],
value=self._opt_file['settings']['volume'],
command=self.on_volume,
**self._common_slider)]
- vol_pos = LibP3d.wdg_pos(self._widgets[-1])
+ self._widgets[-1].__class__ = type('DirectSliderMixed', (DirectSlider, DirectGuiMixin), {})
+ vol_pos = self._widgets[-1].pos_pixel()
self._pos_mgr.register('volume', vol_pos)
- np_left = NodePath('left_slider')
+ np_left = GfxTools.build_empty_node('left_slider')
np_left.set_pos(self._widgets[-1].get_net_transform().get_pos())
np_left.set_x(np_left.get_x() - self._widgets[-1].get_scale()[0])
- lpos = LibP3d.wdg_pos(np_left)
+ lpos = np_left.pos_as_widget() # try with pos2d_pixel and remove pos_as_widget if ok
self._pos_mgr.register('volume_0', lpos)
self._slider = self._widgets[-1]
self._widgets += [DirectCheckButton(
indicator_relief=self._common_btn['relief'],
indicatorValue=self._opt_file['settings']['fullscreen'],
**self._common_btn)]
- self._pos_mgr.register('fullscreen', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectCheckButtonMixed', (DirectCheckButton, DirectGuiMixin), {})
+ self._pos_mgr.register('fullscreen', self._widgets[-1].pos_pixel())
res = self._opt_file['settings']['resolution']
d_i = base.pipe.get_display_information()
def _res(idx):
for tgt_res in ['1440x900', '1360x768']:
for btn in comps:
if btn['text'] == tgt_res:
- pos = LibP3d.wdg_pos(btn)
+ pos = btn.pos_pixel()
self._pos_mgr.register('res_' + tgt_res, (pos[0] + 5, pos[1]))
btn = DirectOptionMenuTest(
text=_('Resolution'), items=resolutions, initialitem=res,
pos=(0, 1, .05), command=self.on_resolution, **self._common_opt)
+ btn.__class__ = type('DirectOptionMenuMixed', (DirectOptionMenu, DirectGuiMixin), {})
btn._show_cb = res_cb
btn.popupMenu['frameColor'] = self._common_btn['frameColor']
btn.popupMenu['relief'] = self._common_btn['relief']
self._widgets += [btn]
- pos_res = LibP3d.wdg_pos(self._widgets[-1])
+ pos_res = self._widgets[-1].pos_pixel()
self._pos_mgr.register('resolutions', pos_res) # 680 365
self._pos_mgr.register('res_1440x900', [pos_res[0] + 320, pos_res[1] + 75])
self._pos_mgr.register('res_1360x768', [pos_res[0] + 430, pos_res[1] -285])
indicator_relief=self._common_btn['relief'],
indicatorValue=self._opt_file['settings']['antialiasing'],
**self._common_btn)]
- self._pos_mgr.register('aa', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectCheckButtonMixed', (DirectCheckButton, DirectGuiMixin), {})
+ self._pos_mgr.register('aa', self._widgets[-1].pos_pixel())
self._widgets += [DirectCheckButton(
text=_('Shadows'), pos=(0, 1, -.45), command=self.on_shadows,
indicator_frameColor=self._common_opt['highlightColor'],
indicator_relief=self._common_btn['relief'],
indicatorValue=self._opt_file['settings']['shadows'],
**self._common_btn)]
- self._pos_mgr.register('shadows', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectCheckButtonMixed', (DirectCheckButton, DirectGuiMixin), {})
+ self._pos_mgr.register('shadows', self._widgets[-1].pos_pixel())
self._widgets += [DirectButton(
text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
**self._common_btn)]
- self._pos_mgr.register('back', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('back', self._widgets[-1].pos_pixel())
self.accept('enforce_resolution', self.enforce_res)
def _set_credits(self):
self._widgets += [DirectButton(
text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
**self._common_btn)]
- self._pos_mgr.register('back', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('back', self._widgets[-1].pos_pixel())
self.accept('enforce_resolution', self.enforce_res)
def on_play(self):
command=self.start, extraArgs=[scene_name], text_wordwrap=6,
frameTexture='assets/images/scenes/%s.dds' % scene_name,
**new_cmn)]
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
name = scene_name.lower()
- self._pos_mgr.register(name, LibP3d.wdg_pos(self._widgets[-1]))
+ self._pos_mgr.register(name, self._widgets[-1].pos_pixel())
for j in range(4):
tnode = self._widgets[-1].component('text%s' % j).textNode
height = - tnode.getLineHeight() / 2
self._widgets += [DirectButton(
text=_('Back'), pos=(0, 1, -.8), command=self.on_back,
**self._common_btn)]
- self._pos_mgr.register('back', LibP3d.wdg_pos(self._widgets[-1]))
+ self._widgets[-1].__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('back', self._widgets[-1].pos_pixel())
def start(self, cls):
self._fsm.demand('Scene', cls)
from textwrap import dedent
from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, \
GeomVertexWriter, GeomTriangles, GeomNode, Shader, Point3, Plane, Vec3
-from ya2.p3d.gfx import P3dGfxMgr
+from ya2.utils.gfx import Point
class SidePanel:
self.update(items)
def update(self, items):
- p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+ p_from, p_to = Point((-1, 1)).from_to_points()
for hit in self._world.ray_test_all(p_from, p_to).get_hits():
if hit.get_node() == self._plane_node:
pos = hit.get_hit_pos()
bounds = item._np.get_tight_bounds()
if bounds[1][1] > y:
y = bounds[1][1]
- icorner = item.get_corner()
- icorner = P3dGfxMgr.screen_coord(icorner)
+ icorner = Point(item.get_corner())
+ icorner = icorner.screen_coord()
if icorner[0] > corner[0]:
corner = icorner[0], corner[1]
if icorner[1] < corner[1]:
from itertools import product
-from panda3d.core import NodePath
-from ya2.p3d.gfx import set_srgb
+from ya2.utils.gfx import GfxTools
class Background:
def __init__(self):
- self._root = NodePath('background_root')
+ self._root = GfxTools.build_empty_node('background_root')
self._root.reparent_to(render)
ncols, nrows = 16, 8
start_size, end_size = 5, 2.5
offset = 5
for col, row in product(range(ncols), range(nrows)):
- model = loader.load_model('assets/models/bam/background/background.bam')
+ model = GfxTools.build_model('assets/models/bam/background/background.bam')
model.set_scale(end_size / start_size)
model.reparent_to(self._root)
total_width, total_height = end_size * ncols, end_size * nrows
model.set_pos(left + end_size * col, offset, bottom + end_size * row)
self._root.clear_model_nodes()
self._root.flatten_strong()
- set_srgb(self._root)
+ self._root.set_srgb_textures()
def destroy(self):
self._root.remove_node()
from panda3d.bullet import BulletRigidBodyNode, BulletGhostNode
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
-from ya2.p3d.gfx import P3dGfxMgr, set_srgb
+from ya2.utils.gfx import GfxTools, Point
class Command:
else:
self.node = BulletRigidBodyNode(self.__class__.__name__)
self._set_shape(count)
- self._np = render.attach_new_node(self.node)
+ self._np = GfxTools.build_node_from_physics(self.node)
if count:
world.attach_ghost(self.node)
else:
world.attach_rigid_body(self.node)
- self._model = loader.load_model(model_path)
- set_srgb(self._model)
+ self._model = GfxTools.build_model(model_path)
+ self._model.set_srgb_textures()
self._model.flatten_light()
self._model.reparent_to(self._np)
self._np.set_scale(model_scale)
self._np.flatten_strong()
self._set_outline_model()
- set_srgb(self._outline_model)
+ self._outline_model.set_srgb_textures()
self._model.hide(BitMask32(0x01))
self._outline_model.hide(BitMask32(0x01))
self._start_drag_pos = None
self._np.set_pos(pos)
self._np.set_r(r)
self.__editing = False
+ self.__interactable = count
self.accept('editor-start', self.__editor_start)
self.accept('editor-stop', self.__editor_stop)
@property
def interactable(self):
- return self.__editing or self.count
+ return self.__editing or self.__interactable
def set_strategy(self, strategy):
self.strategy = strategy
def _repos(self):
- p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+ p_from, p_to = Point((-1, 1)).from_to_points()
for hit in self._world.ray_test_all(p_from, p_to).get_hits():
if hit.get_node() == self._plane_node:
pos = hit.get_hit_pos()
self._txt = OnscreenText(
str(self._count), font=font, scale=0.06, fg=(.9, .9, .9, 1))
pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
+ p2d = Point(pos).screen_coord()
self._txt['pos'] = p2d
self.repos_done = True
bounds = self._np.get_tight_bounds()
bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
pos = self._np.get_pos() + (bounds[1][0], bounds[0][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
+ p2d = Point(pos).screen_coord()
self._txt['pos'] = p2d
def get_bottom(self):
bounds = self._np.get_tight_bounds()
bounds = bounds[0] - self._np.get_pos(), bounds[1] - self._np.get_pos()
pos = self._np.get_pos() + (bounds[1][0], bounds[1][1], bounds[0][2])
- p2d = P3dGfxMgr.screen_coord(pos)
+ p2d = pos.screen_coord()
ar = base.get_aspect_ratio()
return p2d[1] if ar >= 1 else (p2d[1] * ar)
return bounds[1][0], bounds[1][1], bounds[0][2]
def _set_outline_model(self):
- self._outline_model = loader.load_model(self._model_path)
+ self._outline_model = GfxTools.build_model(self._model_path)
#clockw = CullFaceAttrib.MCullClockwise
#self._outline_model.set_attrib(CullFaceAttrib.make(clockw))
self._outline_model.set_attrib(CullFaceAttrib.make_reverse())
from json import loads
from collections import namedtuple
from panda3d.core import AmbientLight, Texture, TextPropertiesManager, \
- TextNode, Spotlight, PerspectiveLens, BitMask32, NodePath
+ TextNode, Spotlight, PerspectiveLens, BitMask32
from panda3d.bullet import BulletPlaneShape, BulletGhostNode
from direct.gui.OnscreenImage import OnscreenImage
from direct.gui.OnscreenText import OnscreenText
from pmachines.items.teetertooter import TeeterTooter
from pmachines.editor.scene import SceneEditor
from ya2.utils.cursor import MouseCursor
-from ya2.p3d.gfx import P3dGfxMgr
-from ya2.p3d.p3d import LibP3d
+from ya2.utils.gfx import GfxTools, DirectGuiMixin
+from ya2.utils.gui import GuiTools
class Scene(DirectObject):
frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1],
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
btn.set_transparency(True)
- self._pos_mgr.register(binfo[0], LibP3d.wdg_pos(btn))
+ self._pos_mgr.register(binfo[0], btn.pos_pixel())
btns += [btn]
if self.__editor:
self.__home_btn, self.__info_btn, self.__editor_btn, self.__right_btn = btns
def _unset_gui(self):
btns = [
- self.__home_btn, self.__info_btn, self.__right_btn,
+ self.__home_btn, self.__info_btn, self.__right_btn
#self.__next_btn, self.__prev_btn, self.__rewind_btn
]
+ if self.__editor: btns += [self.__editor_btn]
[btn.destroy() for btn in btns]
if self._dbg_items:
self._info_txt.destroy()
def _get_hits(self):
if not base.mouseWatcherNode.has_mouse(): return []
- p_from, p_to = P3dGfxMgr.world_from_to(base.mouseWatcherNode.get_mouse())
+ p_from, p_to = GuiTools.get_mouse().from_to_points()
return self._world.ray_test_all(p_from, p_to).get_hits()
def _update_info(self, item):
self._start_evt_time = None
self._set_win() if self._enforce_res == 'win' else self._set_fail()
if any(itm._overlapping for itm in self.items):
- self._cursor.cursor_img.img.set_color(.9, .1, .1, 1)
+ self._cursor.cursor_img.set_color(.9, .1, .1, 1)
else:
- self._cursor.cursor_img.img.set_color(.9, .9, .9, 1)
+ self._cursor.cursor_img.set_color(.9, .9, .9, 1)
return task.cont
def cb_inst(self, item):
relief=FLAT, frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
btn.set_transparency(True)
- self._pos_mgr.register('close_instructions', LibP3d.wdg_pos(btn))
+ self._pos_mgr.register('close_instructions', btn.pos_pixel())
def _set_win(self):
self.__persistent.save_scene(self.__json_name, self.version(self.__json_name))
relief=FLAT, frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
btn.set_transparency(True)
- self._pos_mgr.register('home_win', LibP3d.wdg_pos(btn))
+ self._pos_mgr.register('home_win', btn.pos_pixel())
imgs = [self.__load_img_btn('rewind', col) for col in colors]
btn = DirectButton(
image=imgs, scale=btn_scale,
relief=FLAT, frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- self._pos_mgr.register('replay', LibP3d.wdg_pos(btn))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('replay', btn.pos_pixel())
btn.set_transparency(True)
if self.__json_name:
enabled = self._scenes.index(self.__json_name) < len(self._scenes) - 1
frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
btn['state'] = NORMAL if enabled else DISABLED
- self._pos_mgr.register('next', LibP3d.wdg_pos(btn))
+ self._pos_mgr.register('next', btn.pos_pixel())
btn.set_transparency(True)
def _set_fail(self):
relief=FLAT, frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- self._pos_mgr.register('home_win', LibP3d.wdg_pos(btn))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('home_win', btn.pos_pixel())
btn.set_transparency(True)
imgs = [self.__load_img_btn('rewind', col) for col in colors]
btn = DirectButton(
relief=FLAT, frameColor=(.6, .6, .6, .08),
rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
- self._pos_mgr.register('replay', LibP3d.wdg_pos(btn))
+ btn.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
+ self._pos_mgr.register('replay', btn.pos_pixel())
btn.set_transparency(True)
def _on_restart(self, frm):
self.__home_btn, self.__info_btn, self.__right_btn,
#self.__next_btn, self.__prev_btn, self.__rewind_btn
]
+ if self.__editor: btns += [self.__editor_btn]
self.__btn_state = [btn['state'] for btn in btns]
for btn in btns:
btn['state'] = DISABLED
self.__home_btn, self.__info_btn, self.__right_btn,
#self.__next_btn, self.__prev_btn, self.__rewind_btn
]
+ if self.__editor: btns += [self.__editor_btn]
for btn, state in zip(btns, self.__btn_state):
btn['state'] = state
[itm.restore_state() for itm in self.__items]
def frame_after(task):
self._define_test_items()
for itm in self._test_items:
- self._pos_mgr.register(itm.name, P3dGfxMgr.pos2d_p2d(itm))
+ self._pos_mgr.register(itm.name, itm.pos2d_pixel())
taskMgr.doMethodLater(1.4, frame_after, 'frame after') # after the intro sequence
def _define_test_items(self):
self._set_test_item(item['id'], tuple(item['position']))
def _set_test_item(self, name, pos):
- self._test_items += [NodePath(name)]
+ self._test_items += [GfxTools.build_empty_node(name)]
self._test_items[-1].set_pos(pos[0], 0, pos[1])
def add_item(self, item):
#+CATEGORY: pmachines
#+TAGS: bug(b) calendar(c) waiting(w)
-* DOING editor
+* READY editor
- [X] edit level (button)
- [X] global level editor (name, instructions)
- [X] version is the hash of the json file without the version
- [X] left/right arrow
- [X] json
- [X] editing of test_items in the editor for functional tests
+- [ ] draggable frames
- [ ] define functional tests
+* BACKLOG test for wdg_pos
* BACKLOG tooltips for buttons
* BACKLOG teeter-tooter with constraints (real teeter tooter)
* BACKLOG magnet, road cone, bucket
_main._Main__pmachines._fsm.demand = MagicMock()
_main._Main__pmachines.run = MagicMock()
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__appimage_builder.update.assert_not_called()
with (patch.object(sys, 'argv', ['python -m unittest', '--update']),
patch.object(pmachines.app, 'argv', ['python -m unittest', '--update'])):
_main = Main()
_main._Main__appimage_builder.update = MagicMock()
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__appimage_builder.update.assert_called_once()
def test_version(self):
_main = Main()
_main._Main__run_game = MagicMock()
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__run_game.assert_called_once()
with (patch.object(main, 'argv', ['python -m unittest', '--version']),
patch.object(pmachines.app, 'argv', ['python -m unittest', '--version'])):
_main = Main()
_main._Main__run_game = MagicMock()
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__run_game.assert_not_called()
@patch.object(main, 'argv', ['python -m unittest'])
_main = Main()
_main._Main__pmachines.run = MagicMock()
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__pmachines.run.assert_called_once()
@patch.object(pmachines.app, 'argv', ['python -m unittest'])
_main = Main()
_main._Main__pmachines.run = MagicMock(side_effect=Exception)
_main.run()
- _main._Main__pmachines.base.destroy()
+ _main._Main__pmachines.destroy()
_main._Main__pmachines.run.trowed_exception()
print_exc_mock.assert_called_once()
+++ /dev/null
-from panda3d.core import load_prc_file_data
-load_prc_file_data('', 'window-type none')
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from os import remove
-from os.path import exists
-from glob import glob
-from unittest import TestCase
-from threading import Thread
-from panda3d.core import NodePath
-from direct.showbase.ShowBase import ShowBase
-from direct.showbase.DirectObject import DirectObject
-from ya2.p3d.asserts import Assert
-
-
-class TestApp(ShowBase): pass
-
-
-class AssertsTests(TestCase):
-
- def setUp(self):
- self.__app = TestApp()
-
- def tearDown(self):
- self.__app.destroy()
-
- def test_render3d(self):
- np = NodePath('new node')
- np.reparent_to(render)
- with self.assertRaises(Exception):
- Assert.assert_render3d()
- np.remove_node()
- Assert.assert_render3d()
-
- def test_render2d(self):
- np = NodePath('new node')
- np.reparent_to(render2d)
- with self.assertRaises(Exception):
- Assert.assert_render2d()
- np.remove_node()
- Assert.assert_render2d()
-
- def test_aspect2d(self):
- np = NodePath('new node')
- np.reparent_to(aspect2d)
- with self.assertRaises(Exception):
- Assert.assert_aspect2d()
- np.remove_node()
- Assert.assert_aspect2d()
-
- def test_events(self):
- d = DirectObject()
- d.accept('new event', self.__accept)
- with self.assertRaises(Exception):
- Assert.assert_events()
- d.ignore('new event')
- Assert.assert_events()
-
- def __accept(): pass
-
- def test_tasks(self):
- t = taskMgr.add(self.__new_task)
- with self.assertRaises(Exception):
- Assert.assert_tasks()
- taskMgr.remove(t)
- Assert.assert_tasks()
-
- def __new_task(self, task):
- return task.again
-
- def test_threads(self):
- self.__flag = False
- t = Thread(target=self.__while_flag)
- t.start()
- with self.assertRaises(Exception):
- Assert.assert_threads()
- self.__flag = True
- t.join()
- Assert.assert_threads()
-
- def __while_flag(self):
- while not self.__flag: pass
--- /dev/null
+from panda3d.core import load_prc_file_data
+load_prc_file_data('', 'window-type none')
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from unittest import TestCase
+from threading import Thread
+from panda3d.core import NodePath
+from direct.showbase.ShowBase import ShowBase
+from direct.showbase.DirectObject import DirectObject
+from ya2.utils.asserts import Assert
+
+
+class TestApp(ShowBase): pass
+
+
+class AssertsTests(TestCase):
+
+ def setUp(self):
+ self.__app = TestApp()
+
+ def tearDown(self):
+ self.__app.destroy()
+
+ def test_render3d(self):
+ np = NodePath('new node')
+ np.reparent_to(render)
+ with self.assertRaises(Exception):
+ Assert.assert_render3d()
+ np.remove_node()
+ Assert.assert_render3d()
+
+ def test_render2d(self):
+ np = NodePath('new node')
+ np.reparent_to(render2d)
+ with self.assertRaises(Exception):
+ Assert.assert_render2d()
+ np.remove_node()
+ Assert.assert_render2d()
+
+ def test_aspect2d(self):
+ np = NodePath('new node')
+ np.reparent_to(aspect2d)
+ with self.assertRaises(Exception):
+ Assert.assert_aspect2d()
+ np.remove_node()
+ Assert.assert_aspect2d()
+
+ def test_events(self):
+ d = DirectObject()
+ d.accept('new event', self.__accept)
+ with self.assertRaises(Exception):
+ Assert.assert_events()
+ d.ignore('new event')
+ Assert.assert_events()
+
+ def __accept(): pass
+
+ def test_tasks(self):
+ t = taskMgr.add(self.__new_task)
+ with self.assertRaises(Exception):
+ Assert.assert_tasks()
+ taskMgr.remove(t)
+ Assert.assert_tasks()
+
+ def __new_task(self, task):
+ return task.again
+
+ def test_threads(self):
+ self.__flag = False
+ t = Thread(target=self.__while_flag)
+ t.start()
+ with self.assertRaises(Exception):
+ Assert.assert_threads()
+ self.__flag = True
+ t.join()
+ Assert.assert_threads()
+
+ def __while_flag(self):
+ while not self.__flag: pass
--- /dev/null
+from panda3d.core import load_prc_file_data
+load_prc_file_data('', 'window-type offscreen')
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from unittest import TestCase
+from panda3d.core import get_model_path, Texture
+from direct.showbase.ShowBase import ShowBase
+from ya2.utils.gfx import GfxTools, Point
+
+
+class TestApp(ShowBase): pass
+
+
+class GraphicsToolsTests(TestCase):
+
+ def setUp(self):
+ self.__app = TestApp()
+ get_model_path().append_directory(str(Path(__file__).parent.parent.parent))
+
+ def tearDown(self):
+ self.__app.destroy()
+
+ def test_srgb(self):
+ model = GfxTools.build_model('assets/models/bam/cube1/cube.bam')
+ srgb_formats = [Texture.F_srgb, Texture.F_srgb_alpha]
+ formats = [t.get_format() for t in model.find_all_textures()]
+ count_before = [f in srgb_formats for f in formats].count(True)
+ model.set_srgb_textures()
+ formats = [t.get_format() for t in model.find_all_textures()]
+ count_after = [f in srgb_formats for f in formats].count(True)
+ self.assertGreater(count_after, count_before)
+
+ def test_positions(self):
+ n = GfxTools.build_empty_node('temporary node')
+ n.reparent_to(render)
+ n.set_pos(1.2, 0, 0)
+ base.camera.set_pos(-8, -10, 5)
+ base.camera.look_at(0, 0, 0)
+ pos = n.pos2d()
+ self.assertAlmostEqual(pos[0], .18, delta=.01)
+ self.assertAlmostEqual(pos[1], .07, delta=.01)
+ pos = n.pos2d_pixel()
+ self.assertEqual(pos[0], 473)
+ self.assertEqual(pos[1], 279)
+ pos = Point(n.get_pos()).screen_coord()
+ self.assertAlmostEqual(pos[0], .24, delta=.01)
+ self.assertAlmostEqual(pos[1], .07, delta=.01)
+ from_, to = pos.from_to_points()
+ self.assertAlmostEqual(from_[0], -7.35, delta=.01)
+ self.assertAlmostEqual(from_[1], -9.32, delta=.01)
+ self.assertAlmostEqual(to[0], 65471.92, delta=.01)
+ self.assertAlmostEqual(to[1], 67972.78, delta=.01)
+ n.remove_node()
--- /dev/null
+from panda3d.core import load_prc_file_data
+load_prc_file_data('', 'window-type offscreen')
+from pathlib import Path
+import sys
+if '' in sys.path: sys.path.remove('')
+sys.path.append(str(Path(__file__).parent.parent.parent))
+from unittest import TestCase
+from unittest.mock import patch
+from panda3d.core import get_model_path
+from direct.showbase.ShowBase import ShowBase
+from ya2.utils.gui import GuiTools
+import ya2
+
+
+class TestApp(ShowBase): pass
+
+
+class GraphicsToolsTests(TestCase):
+
+ def setUp(self):
+ self.__app = TestApp()
+ get_model_path().append_directory(str(Path(__file__).parent.parent.parent))
+
+ def tearDown(self):
+ self.__app.destroy()
+
+ @patch.object(ya2.utils.gui, 'load_prc_file_data')
+ def test_no_window(self, l_mock):
+ GuiTools.no_window()
+ l_mock.assert_called_once()
+ l_args = l_mock.call_args_list[0].args
+ self.assertEqual(l_args[0], '')
+ self.assertEqual(l_args[1], 'window-type none')
+ self.assertEqual(len(l_args), 2)
from functools import reduce
from multiprocessing import Pool
from hashlib import md5
-from shutil import copyfile, rmtree
+from shutil import rmtree
from ya2.build.build import to_be_built
+++ /dev/null
-import threading
-
-
-class Assert:
-
- @staticmethod
- def assert_render3d():
- preserve = ['camera', 'DIRECT']
- unexpected_nodes = [c for c in render.children if c.name not in preserve]
- for node in unexpected_nodes: Assert.__process_render3d_exception(node)
-
- @staticmethod
- def __process_render3d_exception(node):
- render.ls()
- message = f'unexpected render3d node: {node.name}'
- raise Exception(message)
-
- @staticmethod
- def assert_aspect2d():
- preserve = [
- 'a2dBackground', 'a2dTopCenter', 'a2dTopCenterNS',
- 'a2dBottomCenter', 'a2dBottomCenterNS', 'a2dLeftCenter',
- 'a2dLeftCenterNS', 'a2dRightCenter', 'a2dRightCenterNS',
- 'a2dTopLeft', 'a2dTopLeftNS', 'a2dTopRight',
- 'a2dTopRightNS', 'a2dBottomLeft', 'a2dBottomLeftNS',
- 'a2dBottomRight', 'a2dBottomRightNS', 'test_txt']
- unexpected_nodes = [c for c in aspect2d.children
- if c.name not in preserve and not c.has_python_tag('preserve')]
- for node in unexpected_nodes: Assert.__process_aspect2d_exception(node)
-
- @staticmethod
- def __process_aspect2d_exception(node):
- aspect2d.ls()
- message = f'unexpected aspect2d node: {node.name}'
- raise Exception(message)
-
- @staticmethod
- def assert_render2d():
- preserve = ['aspect2d', 'pixel2d', 'camera2d']
- unexpected_nodes = [c for c in render2d.children if c.name not in preserve and not c.has_python_tag('preserve')]
- for node in unexpected_nodes: Assert.__process_render2d_exception(node)
-
- @staticmethod
- def __process_render2d_exception(self, node):
- render2d.ls()
- message = f'unexpected render2d node: {node.name}'
- raise Exception(message)
-
- @staticmethod
- def assert_events():
- preserve = ['window-event', 'window-closed', 'async_loader_0', 'async_loader_1',
- 'render-texture-targets-changed', 'aspectRatioChanged']
- unexpected_events = [e for e in messenger.getEvents() if e not in preserve]
- for e in unexpected_events: Assert.__process_event_exception(e)
-
- @staticmethod
- def __process_event_exception(event):
- if (acc := messenger.who_accepts(event)):
- Assert.__process_event_acceptors(acc, event)
-
- @staticmethod
- def __process_event_acceptors(acceptors, event):
- for key, a in acceptors.items(): Assert.__process_event_acceptor(key, a, event)
-
- @staticmethod
- def __process_event_acceptor(key, acceptor, event):
- #if acceptor[2]:
- # print(f'the event {event} accepted by <{key}, {acceptor[0]}> is persistent')
- #else:
- Assert.__actually_process_event_exception(acceptor, event)
-
- @staticmethod
- def __actually_process_event_exception(acceptor, event):
- message = f'unexpected event: {event}, {str(acceptor)}'
- raise Exception(message)
-
- @staticmethod
- def assert_tasks():
- preserve = [
- 'ivalLoop', 'garbageCollectStates', 'collisionLoop',
- 'igLoop', 'audioLoop', 'resetPrevTransform', 'dataLoop',
- 'eventManager', 'simplepbr update', 'on frame music',
- 'assert_fps', 'DIRECTContextTask']
- unexpected_tasks = [t for t in taskMgr.getTasks() + taskMgr.getDoLaters()
- if t.name not in preserve and not hasattr(t, 'preserve')]
- for t in unexpected_tasks: Assert.__process_task_exception(t)
-
- @staticmethod
- def __process_task_exception(task):
- message = f'unexpected task: {task.name}'
- raise Exception(message)
-
- @staticmethod
- def assert_buffers():
- pass
- #if RenderToTexture.buffers:
- # raise Error()
-
- @staticmethod
- def assert_threads():
- thread_names = [thread.name for thread in threading.enumerate()]
- preserve = ['MainThread', 'rpc_server']
- unexpected_tasks = [t for t in thread_names if t not in preserve]
- for t in unexpected_tasks: Assert.__process_unexpected_thread(t)
-
- @staticmethod
- def __process_unexpected_thread(thread_name):
- message = f'unexpected thread: {thread_name}'
- raise Exception(message)
+++ /dev/null
-import datetime
-from logging import info
-from os import getcwd
-from panda3d.core import AntialiasAttrib, PandaNode, LightRampAttrib, \
- NodePath, Point2, Point3, Texture, load_prc_file_data
-# from ya2.lib.p3d.p3d import LibP3d
-
-
-def set_srgb(model):
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
-
-
-# class RenderToTexture:
-
-# def __init__(self, size=(256, 256)):
-# self.__set_buffer(size)
-# self.__set_display_region()
-# self.__set_camera()
-# self.__set_root()
-# self.display_region.set_camera(self.camera)
-
-# def __set_buffer(self, size):
-# self.buffer = base.win.make_texture_buffer('result buffer', size[0],
-# size[1])
-# self.buffer.set_sort(-100)
-
-# def __set_display_region(self):
-# self.display_region = self.buffer.make_display_region()
-# self.display_region.set_sort(20)
-
-# def __set_camera(self):
-# self.camera = NodePath(Camera('camera 2d'))
-# lens = OrthographicLens()
-# lens.set_film_size(1, 1)
-# lens.set_near_far(-1000, 1000)
-# self.camera.node().set_lens(lens)
-
-# def __set_root(self):
-# self.root = NodePath('root')
-# self.root.set_depth_test(False)
-# self.root.set_depth_write(False)
-# self.camera.reparent_to(self.root)
-
-# @property
-# def texture(self): return self.buffer.get_texture()
-
-# def destroy(self):
-# base.graphicsEngine.remove_window(self.buffer)
-# if base.win: # if you close the window during a race
-# base.win.remove_display_region(self.display_region)
-# list(map(lambda node: node.remove_node(), [self.camera, self.root]))
-
-
-class P3dGfxMgr:
-
- # def __init__(self, model_path, antialiasing, shaders, srgb):
- # self.root = P3dNode(render)
- # self.__srgb = srgb
- # self.callbacks = {}
- # self.filters = None
- # get_model_path().append_directory(model_path)
- # if LibP3d.runtime():
- # root_dir = LibP3d.p3dpath(dirname(__file__))
- # paths = [root_dir + '/' + model_path, root_dir]
- # list(map(get_model_path().append_directory, paths))
- # render.set_shader_auto()
- # # render.set_two_sided(True) # it breaks shadows
- # if antialiasing: render.set_antialias(AntialiasAttrib.MAuto)
- # if shaders and base.win:
- # self.filters = CommonFilters(base.win, base.cam)
-
- # def load_model(self, filename, callback=None, anim=None):
- # ext = '.bam' if exists(filename + '.bam') else ''
- # if anim:
- # anim_dct = {'anim': filename + '-Anim' + ext}
- # node = P3dNode(self.set_srgb(Actor(filename + ext, anim_dct)))
- # elif callback:
- # callb = lambda model: callback(P3dNode(self.set_srgb(model)))
- # node = loader.loadModel(filename + ext, callback=callb)
- # else:
- # node = P3dNode(self.set_srgb(
- # loader.loadModel(LibP3d.p3dpath(filename + ext))))
- # return node
-
- def set_srgb(self, model):
- if self.__srgb:
- for texture in model.find_all_textures():
- if texture.get_format() in [Texture.F_rgba, Texture.F_rgbm]:
- texture.set_format(Texture.F_srgb_alpha)
- elif texture.get_format() in [Texture.F_rgb]:
- texture.set_format(Texture.F_srgb)
- return model
-
- @staticmethod
- def no_window():
- load_prc_file_data('', 'window-type none')
-
- @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, Point3(0, 0, 0))
- p2d = Point2()
- return p2d if base.camLens.project(p3d, p2d) else None
-
- @staticmethod
- def pos2d_p2d(node):
- p3d = base.cam.get_relative_point(node, Point3(0, 0, 0))
- p2d = Point2()
- ret = p2d if base.camLens.project(p3d, p2d) else None
- if ret:
- n = NodePath('tmp')
- rpos = (ret[0], 0, ret[1])
- n.set_pos(rpos)
- pos = n.get_pos(pixel2d)
- return int(round(pos[0])), int(round(-pos[2]))
-
- @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):
-# # crash with texture.set_format
-# self.node.prepare_scene(base.win.get_gsg())
-# 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 direct.gui.DirectGuiGlobals import ENTER, EXIT
-from direct.gui.OnscreenImage import OnscreenImage
-# from ya2.lib.ivals import Seq, Wait, PosIval, Func
-
-
-class CommonBase:
-
- def set_widget(self):
- from ya2.lib.gui import Frame, Slider, Btn, Label, OptionMenu, \
- CheckBtn, Entry, Img, Text, ScrolledFrame
- from ya2.p3d.widget import FrameMixin, SliderMixin, BtnMixin, \
- OptionMenuMixin, CheckBtnMixin, EntryMixin, ImgMixin, \
- ScrolledFrameMixin
- self.__class__ = self.__class__ # for pylint
- libwdg2wdg = {
- FrameMixin: [Frame],
- ScrolledFrameMixin: [ScrolledFrame],
- SliderMixin: [Slider],
- BtnMixin: [Btn, Label],
- OptionMenuMixin: [OptionMenu],
- CheckBtnMixin: [CheckBtn],
- EntryMixin: [Entry],
- ImgMixin: [Img, Text]}
- for libwdg, wdgcls in libwdg2wdg.items():
- if any(cls in getmro(self.__class__) for cls in wdgcls):
- par_cls = libwdg
- clsname = self.__class__.__name__ + 'Widget'
- self.__class__ = type(clsname, (self.__class__, par_cls), {})
- self.init(self)
- if not hasattr(self, 'bind'):
- return
- bind_args = [(ENTER, self.on_wdg_enter), (EXIT, self.on_wdg_exit)]
- list(map(lambda args: self.bind(*args), bind_args))
-
- # def set_enter_transition(self):
- # start_pos = self.get_pos()
- # pos = self.pos - (3.6, 0)
- # self.set_pos((pos.x, 1, pos.y))
- # Seq(
- # Wait(abs(pos.y - 1) / 4),
- # PosIval(self.get_np(), .5, start_pos)
- # ).start()
-
- # def set_exit_transition(self, destroy):
- # start_pos = self.get_pos()
- # end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- # seq = Seq(
- # Wait(abs(self.pos.y - 1) / 4),
- # PosIval(self.get_np(), .5, end_pos),
- # Func(self.destroy if destroy else self.hide))
- # if not destroy: seq += Func(self.set_pos, start_pos)
- # seq.start()
-
- def translate(self):
- if hasattr(self, 'bind_transl'):
- self.wdg['text'] = self.bind_transl
-
-
-class P3dImg(CommonBase):
-
- def __init__(self, filepath, pos=(0, 0), scale=1.0, background=False,
- foreground=False, parent=None):
- self.img = OnscreenImage(
- filepath, pos=(pos[0], 1, pos[1]), scale=scale, parent=parent)
- if background:
- self.img.set_bin('background', 10)
- alpha_formats = [12] # panda3d.core.texture.Frgba
- if self.img.get_texture().get_format() in alpha_formats:
- self.img.set_transparency(True)
- if foreground:
- self.img.set_bin('gui-popup', 50)
-
- def reparent_to(self, node): return self.img.reparent_to(node)
- def show(self): return self.img.show()
- def hide(self): return self.img.hide()
- def set_shader(self, shader): return self.img.set_shader(shader)
-
- def set_shader_input(self, name, val):
- return self.img.set_shader_input(name, val)
-
- def set_texture(self, texturestage, texture):
- return self.img.set_texture(texturestage, texture)
-
- # def set_exit_transition(self, destroy):
- # start_pos = self.get_pos()
- # end_pos = (self.pos.x + 3.6, 1, self.pos.y)
- # seq = Seq(
- # Wait(abs(self.pos.y - 1) / 4),
- # PosIval(self.get_np(), .5, end_pos),
- # Func(self.destroy if destroy else self.hide))
- # if not destroy: seq += Func(self.set_pos, (start_pos[0], start_pos[2]))
- # seq.start()
-
- def set_pos(self, pos): return self.img.set_pos(pos[0], 1, pos[1])
-
- def get_pos(self, pos=None): return self.img.get_pos(*[pos] if pos else [])
-
- @property
- def parent(self): return self.img.get_parent()
-
- @property
- def hidden(self): return self.img.is_hidden()
-
- def set_transparent(self): return self.img.set_transparency(True)
-
- def destroy(self): self.img = self.img.destroy()
-
-
-# class P3dBase(CommonBase):
-
-# def __init__(self, tra_src=None, tra_tra=None):
-# # self.text_src_tra = None # it breaks the gui
-# if tra_src and tra_tra: self.bind_tra(tra_src, tra_tra)
-
-# def set_pos(self, pos): return self.wdg.set_pos(pos)
-# def show(self): return self.wdg.show()
-# def hide(self): return self.wdg.hide()
-
-# def bind_tra(self, text_src, text_transl):
-# # text_transl is not used, anyway we need it since we have this kind of
-# # use: self.bind_transl('example str', _('example str'))
-# # this allows to change translations on the fly keeping the source
-# # text for remapping it later
-# # TODO: try reverse mapping? i.e. retrieve the src string from the
-# # translated one
-# self.text_src_tra = text_src
-# self.text_tra_tra = text_transl
-# tra = lambda self: _(self.text_tra_tra)
-# self.__class__.bind_transl = property(tra)
-# self['text'] = self.bind_transl
-
-# def get_pos(self, pos=None):
-# return self.wdg.get_pos(*[pos] if pos else [])
-
-# def __setitem__(self, key, value): self.wdg[key] = value
-
-# def __getitem__(self, key): return self.wdg[key]
-
-# def get_np(self): return self.wdg
-
-# @property
-# def hidden(self): return self.wdg.is_hidden()
-
-# def destroy(self): self.wdg.destroy()
-
-
-# class P3dAbs(P3dBase):
-
-# def get_value(self): return self.wdg.getValue()
-# def initialiseoptions(self): return self.wdg.initialiseoptions()
-# def set_z(self, val): return self.wdg.set_z(val)
-# def set_shader(self, shader): return self.wdg.set_shader(shader)
-# def set_shader_input(self, name, val):
-# return self.wdg.set_shader_input(name, val)
-# def set_transparency(self, val): return self.wdg.set_transparency(val)
-# def bind(self, evt, mth): return self.wdg.bind(evt, mth)
-
-# def attachNewNode(self, gui_itm, sort_order):
-# # it won't work if we name it attach_node. hopefully this will be
-# # possible when we'll use decorators in place of mixins
-# return self.wdg.attachNewNode(gui_itm, sort_order)
-
-# @property
-# def is_enabled(self): return self.wdg['state'] != DISABLED
-
-
-# class P3dBtn(P3dAbs):
-
-# def __init__(
-# self, text='', parent=None, pos=(0, 0), scale=(1, 1),
-# cmd=None, frame_size=(-1, 1, -1, 1), click_snd=None,
-# text_fg=(1, 1, 1, 1), frame_col=(1, 1, 1, 1), text_font=None,
-# over_snd=None, extra_args=None, frame_texture=None, img=None,
-# tra_src=None, tra_tra=None, text_scale=1.0):
-# str2par = {'bottomcenter': base.a2dBottomCenter}
-# parent = str2par.get(parent, parent)
-# extra_args = extra_args or []
-# self.wdg = DirectButton(
-# text=text, parent=parent, pos=(pos[0], 1, pos[1]),
-# scale=(scale[0], 1, scale[1]), command=cmd,
-# frameSize=frame_size, clickSound=click_snd, text_fg=text_fg,
-# frameColor=frame_col, text_font=text_font,
-# rolloverSound=over_snd,
-# extraArgs=extra_args, frameTexture=frame_texture, image=img,
-# text_scale=text_scale)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-# self['relief'] = FLAT
-# args = [(ENTER, self._on_enter), (EXIT, self._on_exit)]
-# list(map(lambda args: self.bind(*args), args))
-
-# def _on_enter(self, pos): pass # pos comes from mouse
-
-# def _on_exit(self, pos): pass # pos comes from mouse
-
-# # we add these with the mixins
-# # def enable(self): self['state'] = NORMAL
-
-# # def disable(self): self['state'] = DISABLED
-
-
-# class P3dSlider(P3dAbs):
-
-# def __init__(
-# self, parent=None, pos=(0, 0), scale=1, val=0,
-# frame_col=(1, 1, 1, 1), thumb_frame_col=(1, 1, 1, 1),
-# cmd=None, range_=(0, 1), tra_src=None, tra_tra=None):
-# self.wdg = DirectSlider(
-# parent=parent, pos=(pos[0], 1, pos[1]), scale=scale, value=val,
-# frameColor=frame_col, thumb_frameColor=thumb_frame_col,
-# command=cmd, range=range_)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-# class P3dCheckBtn(P3dAbs):
-
-# def __init__(
-# self, pos=(0, 0), text='', indicator_val=False,
-# indicator_frame_col=(1, 1, 1, 1), frame_col=(1, 1, 1, 1),
-# scale=(1, 1, 1), click_snd=None, over_snd=None,
-# text_fg=(1, 1, 1, 1), text_font=None, cmd=None, tra_src=None,
-# tra_tra=None):
-# self.wdg = DirectCheckButton(
-# pos=(pos[0], 1, pos[1]), text=text, indicatorValue=indicator_val,
-# indicator_frameColor=indicator_frame_col,
-# frameColor=frame_col, scale=scale, clickSound=click_snd,
-# rolloverSound=over_snd, text_fg=text_fg, text_font=text_font,
-# command=cmd)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-
-# class P3dOptionMenu(P3dAbs):
-
-# def __init__(
-# self, text='', items=None, pos=(0, 0), scale=(1, 1, 1),
-# initialitem='', cmd=None, frame_size=(-1, 1, -1, 1),
-# click_snd=None, over_snd=None, text_may_change=False,
-# text_fg=(1, 1, 1, 1), item_frame_col=(1, 1, 1, 1),
-# frame_col=(1, 1, 1, 1), highlight_col=(1, 1, 1, 1),
-# text_scale=.05, popup_marker_col=(1, 1, 1, 1),
-# item_relief=None, item_text_font=None, text_font=None,
-# tra_src=None, tra_tra=None):
-# items = items or []
-# self.wdg = DirectOptionMenu(
-# text=text, items=items, pos=(pos[0], 1, pos[1]), scale=scale,
-# initialitem=initialitem, command=cmd, frameSize=frame_size,
-# clickSound=click_snd, rolloverSound=over_snd,
-# textMayChange=text_may_change, text_fg=text_fg,
-# item_frameColor=item_frame_col, frameColor=frame_col,
-# highlightColor=highlight_col, text_scale=text_scale,
-# popupMarker_frameColor=popup_marker_col,
-# item_relief=item_relief, item_text_font=item_text_font,
-# text_font=text_font)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-# def set(self, idx, f_cmd=1): return self.wdg.set(idx, f_cmd)
-
-# @property
-# def curr_val(self): return self.wdg.get()
-
-# @property
-# def curr_idx(self): return self.wdg.selectedIndex
-
-
-# class P3dEntry(P3dAbs, DirectObject, Subject):
-
-# def __init__(
-# self, scale=.05, pos=(0, 0), entry_font=None, width=12,
-# frame_col=(1, 1, 1, 1), initial_text='', obscured=False,
-# cmd=None, focus_in_cmd=None, focus_in_args=None,
-# focus_out_cmd=None, focus_out_args=None, parent=None,
-# tra_src=None, tra_tra=None, text_fg=(1, 1, 1, 1), on_tab=None,
-# on_click=None):
-# self.__focused = False
-# self.__focus_in_cmd = focus_in_cmd
-# self.__focus_out_cmd = focus_out_cmd
-# DirectObject.__init__(self)
-# Subject.__init__(self)
-# focus_in_args = focus_in_args or []
-# focus_out_args = focus_out_args or []
-# self.wdg = DirectEntry(
-# scale=scale, pos=(pos[0], 1, pos[1]), entryFont=entry_font,
-# width=width, frameColor=frame_col, initialText=initial_text,
-# obscured=obscured, command=cmd,
-# focusInCommand=self._focus_in_cmd,
-# focusInExtraArgs=focus_in_args,
-# focusOutCommand=self._focus_out_cmd,
-# focusOutExtraArgs=focus_out_args, parent=parent,
-# text_fg=text_fg)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-# if on_tab:
-# self.on_tab_cb = on_tab
-# self.accept('tab-up', self.on_tab)
-# if on_click: self.wdg.bind(B1PRESS, on_click)
-
-# def set(self, txt): return self.wdg.set(txt)
-
-# def _focus_in_cmd(self, *args):
-# self.__focused = True
-# if self.__focus_in_cmd: self.__focus_in_cmd(*args)
-# self.notify('on_entry_enter')
-
-# def _focus_out_cmd(self, *args):
-# self.__focused = False
-# if self.__focus_out_cmd: self.__focus_out_cmd(*args)
-# self.notify('on_entry_exit')
-
-# def on_tab(self):
-# if self.wdg['focus'] == ENTRY_FOCUS_STATE: self.on_tab_cb()
-
-# @property
-# def focused(self): return self.__focused
-
-# @property
-# def text(self): return self.wdg.get()
-
-# def enter_text(self, txt):
-# return self.wdg.enterText(txt)
-
-# def enable(self): self['state'] = NORMAL
-
-# def disable(self): self['state'] = DISABLED
-
-# def destroy(self):
-# self.ignore('tab-up')
-# self.on_tab_cb = None
-# Subject.destroy(self)
-# P3dAbs.destroy(self)
-
-
-# class P3dLabel(P3dAbs):
-
-# def __init__(
-# self, text='', pos=(0, 0), parent=None, text_wordwrap=12,
-# text_align=None, text_fg=(1, 1, 1, 1), text_font=None, scale=.05,
-# frame_col=(1, 1, 1, 1), tra_src=None, tra_tra=None,
-# hpr=(0, 0, 0)):
-# self.wdg = DirectLabel(
-# text=text, pos=(pos[0], 1, pos[1]), parent=parent,
-# text_wordwrap=text_wordwrap, text_align=text_align,
-# text_fg=text_fg, text_font=text_font, scale=scale,
-# frameColor=frame_col, hpr=hpr)
-# P3dAbs.__init__(self, tra_src, tra_tra)
-
-# def set_bin(self, bin_name, priority):
-# return self.wdg.set_bin(bin_name, priority)
-
-# def set_x(self, x): return self.wdg.set_x(x)
-
-# def set_alpha_scale(self, alpha): return self.wdg.set_alpha_scale(alpha)
-
-
-# class P3dTxt(P3dBase):
-
-# def __init__(
-# self, txt='', pos=(0, 0), scale=.05, wordwrap=12, parent=None,
-# fg=(1, 1, 1, 1), font=None, align=None, tra_src=None,
-# tra_tra=None):
-# str2par = {'bottomleft': base.a2dBottomLeft,
-# 'bottomright': base.a2dBottomRight,
-# 'leftcenter': base.a2dLeftCenter}
-# str2al = {'left': TextNode.A_left, 'right': TextNode.A_right,
-# 'center': TextNode.A_center}
-# if parent and parent in str2par: parent = str2par[parent]
-# if align: align = str2al[align]
-# self.wdg = OnscreenText(
-# text=txt, pos=pos, scale=scale, wordwrap=wordwrap,
-# parent=parent, fg=fg, font=font, align=align)
-# P3dBase.__init__(self, tra_src, tra_tra)
-
-# def set_r(self, r): return self.wdg.set_r(r)
-
-
-# class P3dFrame(P3dAbs):
-
-# def __init__(self, frame_size=(-1, 1, -1, 1), frame_col=(1, 1, 1, 1),
-# pos=(0, 0), parent=None, texture_coord=False):
-# P3dAbs.__init__(self)
-# self.wdg = DirectFrame(frameSize=frame_size, frameColor=frame_col,
-# pos=(pos[0], 1, pos[1]), parent=parent)
-# if texture_coord: self.wdg['frameTexture'] = Texture()
-
-
-# class P3dScrolledFrame(P3dAbs):
-
-# def __init__(
-# self, frame_sz=(-1, 1, -1, 1), canvas_sz=(0, 1, 0, 1),
-# scrollbar_width=.05, frame_col=(1, 1, 1, 1),
-# pos=(0, 0), parent='topleft'):
-# P3dAbs.__init__(self)
-# par2p3d = {'topleft': base.a2dTopLeft}
-# if parent and parent in par2p3d: parent = par2p3d[parent]
-# self.wdg = DirectScrolledFrame(
-# frameSize=frame_sz,
-# canvasSize=canvas_sz,
-# scrollBarWidth=scrollbar_width,
-# frameColor=frame_col,
-# pos=(pos[0], 1, pos[1]),
-# parent=parent)
-
-# @property
-# def canvas(self): return self.wdg.getCanvas()
+++ /dev/null
-import sys
-from logging import info
-from os.path import exists, dirname
-from os import _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.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 = base
- 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 = base
- 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 wdg_pos(wdg):
- pos = wdg.get_pos(pixel2d)
- return int(round(pos[0])), int(round(-pos[2]))
-
- @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')
-
- def is_nm(geom):
- return geom.get_name().startswith(name)
- named_geoms = [geom for geom in geoms if is_nm(geom)]
- return [ng for ng in named_geoms if name in ng.get_name()]
-
- @staticmethod
- def load_sfx(filepath, loop=False):
- sfx = loader.loadSfx(filepath)
- sfx.set_loop(loop)
- return sfx
-
- def remap_code(self, key):
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'code mapping %s to key %s' %
- (key, kmap.get_mapped_button(i)), key,
- kmap.get_mapped_button(i))
- return kmap.get_mapped_button(i)
- self.__log_key('not found a code mapping for %s' %
- key, key, 'not_found')
- return key
-
- def remap_str(self, key):
- if not base.win: # when launched with --version
- return key
- # if isinstance(base.win, GraphicsBuffer):
- # return key
- kmap = base.win.get_keyboard_map()
- for i in range(kmap.get_num_buttons()):
- if str(key).lower() == kmap.get_mapped_button_label(i).lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- for i in range(kmap.get_num_buttons()):
- if key.lower() == kmap.get_mapped_button(i).get_name().lower():
- self.__log_key(
- 'string mapping %s to key %s' %
- (key, kmap.get_mapped_button(i).get_name()), key,
- kmap.get_mapped_button(i).get_name())
- return kmap.get_mapped_button(i).get_name()
- self.__log_key('not found a string mapping for %s' %
- key, key, kmap.get_mapped_button(i).get_name())
- return key
-
- def __log_key(self, msg, key1, key2):
- if key1 in self.__logged_keys and self.__logged_keys[key1] == key2:
- return
- self.__logged_keys[key1] = key2
- print(msg)
-
- def destroy(self): pass
--- /dev/null
+class Decorator:
+
+ def __init__(self, decorated):
+ self.__dict__['_decorated'] = decorated
+
+ def __getattr__(self, attr): return getattr(self._decorated, attr)
+
+ def __setattr__(self, attr, value):
+ return setattr(self._decorated, attr, value)
+
+ def __getitem__(self, key):
+ return self._decorated[key]
--- /dev/null
+import threading
+from re import search
+
+
+class Assert:
+
+ @staticmethod
+ def assert_render3d():
+ preserve = ['camera', 'DIRECT']
+ unexpected_nodes = [c for c in render.children if c.name not in preserve]
+ for node in unexpected_nodes: Assert.__process_render3d_exception(node)
+
+ @staticmethod
+ def __process_render3d_exception(node):
+ render.ls()
+ message = f'unexpected render3d node: {node.name}'
+ raise Exception(message)
+
+ @staticmethod
+ def assert_aspect2d():
+ preserve = [
+ 'a2dBackground', 'a2dTopCenter', 'a2dTopCenterNS',
+ 'a2dBottomCenter', 'a2dBottomCenterNS', 'a2dLeftCenter',
+ 'a2dLeftCenterNS', 'a2dRightCenter', 'a2dRightCenterNS',
+ 'a2dTopLeft', 'a2dTopLeftNS', 'a2dTopRight',
+ 'a2dTopRightNS', 'a2dBottomLeft', 'a2dBottomLeftNS',
+ 'a2dBottomRight', 'a2dBottomRightNS', 'test_txt']
+ unexpected_nodes = [c for c in aspect2d.children
+ if c.name not in preserve and not c.has_python_tag('preserve')]
+ for node in unexpected_nodes: Assert.__process_aspect2d_exception(node)
+
+ @staticmethod
+ def __process_aspect2d_exception(node):
+ aspect2d.ls()
+ message = f'unexpected aspect2d node: {node.name}'
+ raise Exception(message)
+
+ @staticmethod
+ def assert_render2d():
+ preserve = ['aspect2d', 'pixel2d', 'camera2d']
+ unexpected_nodes = [c for c in render2d.children if c.name not in preserve and not c.has_python_tag('preserve')]
+ for node in unexpected_nodes: Assert.__process_render2d_exception(node)
+
+ @staticmethod
+ def __process_render2d_exception(self, node):
+ render2d.ls()
+ message = f'unexpected render2d node: {node.name}'
+ raise Exception(message)
+
+ @staticmethod
+ def assert_events():
+ preserve = ['window-event', 'window-closed', 'async_loader_0', 'async_loader_1',
+ 'render-texture-targets-changed', 'aspectRatioChanged', 'new_scene']
+ preserve_re = ['^async_loader_.*', '^click-mouse1-pg.*']
+ unexpected_events = [e for e in messenger.getEvents()
+ if e not in preserve and not any(search(r, e) for r in preserve_re)]
+ for e in unexpected_events: Assert.__process_event_exception(e)
+
+ @staticmethod
+ def __process_event_exception(event):
+ if (acc := messenger.who_accepts(event)):
+ Assert.__process_event_acceptors(acc, event)
+
+ @staticmethod
+ def __process_event_acceptors(acceptors, event):
+ for key, a in acceptors.items(): Assert.__process_event_acceptor(key, a, event)
+
+ @staticmethod
+ def __process_event_acceptor(key, acceptor, event):
+ #if acceptor[2]:
+ # print(f'the event {event} accepted by <{key}, {acceptor[0]}> is persistent')
+ #else:
+ Assert.__actually_process_event_exception(acceptor, event)
+
+ @staticmethod
+ def __actually_process_event_exception(acceptor, event):
+ message = f'unexpected event: {event}, {str(acceptor)}'
+ raise Exception(message)
+
+ @staticmethod
+ def assert_tasks():
+ preserve = [
+ 'ivalLoop', 'garbageCollectStates', 'collisionLoop',
+ 'igLoop', 'audioLoop', 'resetPrevTransform', 'dataLoop',
+ 'eventManager', 'simplepbr update', 'on frame music',
+ 'assert_fps', 'DIRECTContextTask']
+ unexpected_tasks = [t for t in taskMgr.getTasks() + taskMgr.getDoLaters()
+ if t.name not in preserve and not hasattr(t, 'preserve')]
+ for t in unexpected_tasks: Assert.__process_task_exception(t)
+
+ @staticmethod
+ def __process_task_exception(task):
+ message = f'unexpected task: {task.name}'
+ raise Exception(message)
+
+ @staticmethod
+ def assert_buffers():
+ pass
+ #if RenderToTexture.buffers:
+ # raise Error()
+
+ @staticmethod
+ def assert_threads():
+ thread_names = [thread.name for thread in threading.enumerate()]
+ preserve = ['MainThread', 'rpc_server']
+ unexpected_tasks = [t for t in thread_names if t not in preserve]
+ for t in unexpected_tasks: Assert.__process_unexpected_thread(t)
+
+ @staticmethod
+ def __process_unexpected_thread(thread_name):
+ message = f'unexpected thread: {thread_name}'
+ raise Exception(message)
from panda3d.core import GraphicsWindow, WindowProperties
-from ya2.p3d.gui import P3dImg as Img
+from direct.gui.OnscreenImage import OnscreenImage
class MouseCursorFacade:
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)
+ self.cursor_img = OnscreenImage(filepath, scale=scale)
+ self.cursor_img.set_color(color)
+ self.cursor_img.set_bin('gui-popup', 50)
+ alpha_formats = [12] # panda3d.core.texture.Frgba
+ if self.cursor_img.get_texture().get_format() in alpha_formats:
+ self.cursor_img.set_transparency(True)
# if self.eng.cfg.dev_cfg.functional_test:
# self.cursor_img.hide()
self.hotspot_dx = scale[0] * (1 - 2 * hotspot[0])
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))
+ self.cursor_img.set_pos((h_x, 1, mouse[1] - self.hotspot_dy))
return task.again
# def on_frame(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)
+ self.cursor_img.set_texture(loader.load_texture(img), 1)
def destroy(self):
taskMgr.remove(self._tsk)
from os.path import dirname
from collections.abc import Mapping
from configparser import ConfigParser
-from ya2.p3d.p3d import LibP3d
+from ya2.utils.logics import LogicsTools
class DctFile:
def __init__(self, fpath, default_dct=None, persistent=True):
default_dct = default_dct or {}
- if sys.platform == 'darwin' and LibP3d.runtime():
+ if sys.platform == 'darwin' and LogicsTools.runtime():
fpath = dirname(__file__) + '/' + fpath
self.fpath = fpath
self.persistent = persistent
--- /dev/null
+from panda3d.core import NodePath, Point2, Point3, Texture, LVector3f, LVector2f
+from ya2.patterns.decorator import Decorator
+
+
+class GfxTools:
+
+ @staticmethod
+ def build_model(file_path):
+ m = loader.load_model(file_path)
+ m = NodePathDecorator(m) # we can't use mixins with c++ classes
+ return m
+
+ @staticmethod
+ def build_empty_node(name):
+ return NodePathDecorator(NodePath(name))
+
+ @staticmethod
+ def build_node_from_physics(physics_node):
+ return NodePathDecorator(render.attach_new_node(physics_node))
+
+
+class NodePathDecorator(NodePath, Decorator):
+
+ def set_srgb_textures(self):
+ for t in self.find_all_textures():
+ f = t.get_format()
+ match t.get_format():
+ case Texture.F_rgba | Texture.F_rgbm:
+ f = Texture.F_srgb_alpha
+ case Texture.F_rgb:
+ f = Texture.F_srgb
+ t.set_format(f)
+
+ def pos2d(self):
+ p3d = base.cam.get_relative_point(self, Point3(0, 0, 0))
+ p2d = Point2()
+ return p2d if base.camLens.project(p3d, p2d) else None
+
+ def pos2d_pixel(self):
+ if p2d := self.pos2d():
+ p = _get_pos_relative((p2d[0], 0, p2d[1]), pixel2d)
+ return int(round(p[0])), int(round(-p[2]))
+
+ def pos_as_widget(self):
+ pos = self.get_pos(pixel2d)
+ return int(round(pos[0])), int(round(-pos[2]))
+
+
+class DirectGuiMixin():
+
+ def pos_pixel(self):
+ pos = self.get_pos(pixel2d)
+ return int(round(pos[0])), int(round(-pos[2]))
+
+
+class Point(Decorator):
+
+ def screen_coord(self):
+ pos3d = _get_pos_relative(LVector3f(*self), base.cam)
+ pos2d = Point2()
+ base.camLens.project(pos3d, pos2d)
+ pos_wrt_render2d = Point3(pos2d[0], 0, pos2d[1])
+ pos_wrt_aspect2d = base.aspect2d.get_relative_point(render2d, pos_wrt_render2d)
+ return Point((pos_wrt_aspect2d[0], pos_wrt_aspect2d[2]))
+
+ def from_to_points(self):
+ p_from, p_to = Point3(), Point3() # in camera coordinates
+ base.camLens.extrude(LVector2f(*self), 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
+
+
+def _get_pos_relative(pos, other):
+ n = NodePath('temporary_node')
+ n.set_pos(pos)
+ pos = n.get_pos(other)
+ n.remove_node()
+ return pos
--- /dev/null
+from panda3d.core import load_prc_file_data
+from ya2.utils.gfx import Point
+
+class GuiTools:
+
+ @staticmethod
+ def no_window():
+ load_prc_file_data('', 'window-type none')
+
+ @staticmethod
+ def get_mouse():
+ return Point(base.mouseWatcherNode.get_mouse())
# from multiprocessing import cpu_count
from panda3d.core import Filename, GraphicsWindow, PandaSystem
from panda3d.bullet import get_bullet_version
-from ya2.p3d.p3d import LibP3d
+from ya2.utils.logics import LogicsTools
class LogManagerBase: # headless log manager
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 \
+ opath = LogicsTools.fixpath(opt_path + '/options.ini') if opt_path else \
'options.ini'
return opath
--- /dev/null
+import sys
+from os.path import exists
+from direct.showbase.DirectObject import DirectObject
+
+
+class LogicsTools(DirectObject):
+
+ @staticmethod
+ def runtime(): return not exists('main.py')
+
+ @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