_strategy = self.__item.json['strategy']
_strategy_args = ''
if 'strategy_args' in self.__item.json:
- _strategy_args = ' '.join(self.__item.json['strategy_args'])
+ _strategy_args = ' '.join(map(str, self.__item.json['strategy_args']))
t, pos_entry = self.__add_row(_('position'), f'{round(p.x, 3)}, {round(p.z, 3)}', self.on_edit_position)
t, rot_entry = self.__add_row(_('roll'), f'{round(r, 3)}', self.on_edit_roll)
t, scale_entry = self.__add_row(_('scale'), f'{round(s, 3)}', self.on_edit_scale)
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 = pos.screen_coord()
+ p2d = Point(pos).screen_coord()
ar = base.get_aspect_ratio()
return p2d[1] if ar >= 1 else (p2d[1] * ar)
#+CATEGORY: pmachines
#+TAGS: bug(b) calendar(c) waiting(w)
-* DOING editor
-- [X] edit level (button)
-- [X] global level editor (name, instructions)
- - [X] version is the hash of the json file without the version
- - [X] save button
- - [X] close editor
-- [X] popup if exit with an unsaved scene
-- [X] list of scenes
-- [X] item editor
- - [X] position (default: 0, 0, 0)
- - [X] roll (default: 0)
- - [X] scale (default: 1)
- - [X] mass (default: 1)
- - [X] restitution (default: .5)
- - [X] friction (default: .5)
- - [X] expected number of contacts (default: 1)
- - [X] save modifications in the json file
-- [X] new item
- - [X] create the item
- - [X] refactor: single list of items in the json
- - [X] save the new item in the json
- - [X] delete item
- - [X] id
- - [X] strategy and strategy_args
- - [X] pop up if errors with arguments in strategy_args
-- [X] new scene
-- [X] start items
- - [X] inspector without position and roll
- - [X] optionmenu for class
- - [X] field for quantity
- - [X] new item
- - [X] left/right arrow
- - [X] json
-- [X] editing of test_items in the editor for functional tests
-- [X] draggable frames
-- [ ] collapsable frames
-- [ ] define functional tests
+* BACKLOG bug: only one scene is shown as completed in the scene menu
* BACKLOG test for wdg_pos
* BACKLOG tooltips for buttons
+* BACKLOG define functional tests for the editor
+* BACKLOG second background
* BACKLOG teeter-tooter with constraints (real teeter tooter)
* BACKLOG magnet, road cone, bucket
* BACKLOG actions: rewind, prev, next
-* BACKLOG (when python 3.11) use toml in place of ini
* BACKLOG (when panda3d provides it) android build (test with the emulator of android studio)
* BACKLOG (when itch.io's client waiting works with wine) functional tests for windows-itch.io
* calendar :calendar:
+++ /dev/null
-from pathlib import Path
-import sys
-if '' in sys.path: sys.path.remove('')
-sys.path.append(str(Path(__file__).parent.parent.parent))
-from unittest import TestCase
-from unittest.mock import MagicMock
-from ya2.patterns.observer import Subject
-
-
-class Observed(Subject): pass
-
-
-class Observer:
-
- def __init__(self, observed): self.__observed = observed
-
- def callback(self): pass
-
-
-class ObserverTests(TestCase):
-
- def test_all(self):
- observed = Observed()
- observer = Observer(observed)
- observer.callback = MagicMock(side_effect=observer.callback)
- observer.callback.__name__ = 'callback'
- self.assertFalse(observed.observing(observer.callback))
- observed.attach(observer.callback)
- self.assertTrue(observed.observing(observer.callback))
- observer.callback.assert_not_called()
- observed.notify('callback')
- observer.callback.assert_called()
- observed.detach(observer.callback)
- self.assertFalse(observed.observing(observer.callback))
+++ /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