+from collections import namedtuple
+from glob import glob
+from importlib import import_module
+from os.path import basename
+from inspect import isclass
+from panda3d.core import Texture, TextNode
+from direct.gui.OnscreenImage import OnscreenImage
+from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, DirectOptionMenu, OkDialog
+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
+
+
+class StartItems(DirectObject):
+
+ def __init__(self, json_items):
+ super().__init__()
+ self.__items = json_items
+ self.__json = self.__items[0]
+ self._font = base.loader.load_font(
+ 'assets/fonts/Hanken-Book.ttf')
+ self._font.clear()
+ self._font.set_pixels_per_unit(60)
+ self._font.set_minfilter(Texture.FTLinearMipmapLinear)
+ self._font.set_outline((0, 0, 0, 1), .8, .2)
+ self._common = {
+ 'scale': .046,
+ 'text_font': self._font,
+ 'text_fg': (.9, .9, .9, 1),
+ 'relief': FLAT,
+ 'frameColor': (.4, .4, .4, .14),
+ 'rolloverSound': loader.load_sfx(
+ 'assets/audio/sfx/rollover.ogg'),
+ 'clickSound': loader.load_sfx(
+ 'assets/audio/sfx/click.ogg')}
+ w, h = .8, 1.04
+ self._frm = DirectFrame(frameColor=(.4, .4, .4, .06),
+ frameSize=(0, w, -h, 0),
+ parent=base.a2dTopRight,
+ pos=(-w, 0, 0))
+ self.__z = -.08
+ item_modules = glob('pmachines/items/*.py')
+ item_modules = [basename(i)[:-3] for i in item_modules]
+ new_items = ['']
+ for item_module in item_modules:
+ mod_name = 'pmachines.items.' + item_module
+ for member in import_module(mod_name).__dict__.values():
+ if isclass(member) and issubclass(member, Item) and \
+ member != Item:
+ new_items = list(set(new_items + [member.__name__]))
+ t, item_class_entry = self.__add_row_option(_('class'), '', new_items, self.on_edit_class)
+ t, count_entry = self.__add_row(_('count'), '', self.on_edit_count)
+ t, scale_entry = self.__add_row(_('scale'), '', self.on_edit_scale)
+ t, mass_entry = self.__add_row(_('mass'), '', self.on_edit_mass)
+ t, restitution_entry = self.__add_row(_('restitution'), '', self.on_edit_restitution)
+ t, friction_entry = self.__add_row(_('friction'), '', self.on_edit_friction)
+ t, id_entry = self.__add_row(_('id'), '', self.on_edit_id)
+ new_items = ['']
+ for item_module in item_modules:
+ mod_name = 'pmachines.items.' + item_module
+ for member in import_module(mod_name).__dict__.values():
+ if isclass(member) and issubclass(member, ItemStrategy) and \
+ member != ItemStrategy:
+ new_items = list(set(new_items + [member.__name__]))
+ t, strategy_entry = self.__add_row_option(_('strategy'), '', new_items, self.on_edit_strategy)
+ t, strategy_args_entry = self.__add_row(_('strategy_args'), '', self.on_edit_strategy_args)
+ fields = ['scale', 'mass', 'restitution', 'friction', 'id', 'strategy', 'strategy_args', 'item_class', 'count']
+ Entries = namedtuple('Entries', fields)
+ self.__entries = Entries(scale_entry, mass_entry, restitution_entry, friction_entry, id_entry, strategy_entry, strategy_args_entry, item_class_entry, count_entry)
+ self.__set(self.__json)
+ def load_images_btn(path, col):
+ colors = {
+ 'gray': [
+ (.6, .6, .6, 1), # ready
+ (1, 1, 1, 1), # press
+ (.8, .8, .8, 1), # rollover
+ (.4, .4, .4, .4)],
+ 'green': [
+ (.1, .68, .1, 1),
+ (.1, 1, .1, 1),
+ (.1, .84, .1, 1),
+ (.4, .1, .1, .4)]}[col]
+ return [self.__load_img_btn(path, col) for col in colors]
+ fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+ DirectButton(
+ image=load_images_btn('exitRight', 'gray'), scale=.05,
+ pos=(.54, 1, -h + .06),
+ parent=self._frm, command=self.destroy, state=NORMAL, relief=FLAT,
+ frameColor=fcols[0],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ DirectButton(
+ image=load_images_btn('save', 'gray'), scale=.05,
+ pos=(.42, 1, -h + .06),
+ parent=self._frm, command=self.__save, state=NORMAL, relief=FLAT,
+ frameColor=fcols[0],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ DirectButton(
+ image=load_images_btn('trashcan', 'gray'), scale=.05,
+ pos=(.3, 1, -h + .06),
+ parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
+ frameColor=fcols[0],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ DirectButton(
+ image=load_images_btn('plus', 'gray'), scale=.05,
+ pos=(.06, 1, -h + .06),
+ parent=self._frm, command=self.__new_item, state=NORMAL, relief=FLAT,
+ frameColor=fcols[0],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ DirectButton(
+ image=load_images_btn('right', 'gray'), scale=.05,
+ pos=(.18, 1, -h + .06),
+ parent=self._frm, command=self.__next_item, state=NORMAL, relief=FLAT,
+ frameColor=fcols[0],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+
+ def __add_row(self, label, text, callback):
+ tw = 10
+ t = OnscreenText(
+ label,
+ pos=(.03, self.__z), parent=self._frm,
+ font=self._common['text_font'],
+ scale=self._common['scale'],
+ fg=self._common['text_fg'],
+ wordwrap=20, align=TextNode.ALeft)
+ e = DirectEntry(
+ scale=self._common['scale'],
+ pos=(.30, 1, self.__z),
+ entryFont=self._font,
+ width=tw,
+ cursorKeys=True,
+ frameColor=self._common['frameColor'],
+ initialText=text,
+ parent=self._frm,
+ text_fg=self._common['text_fg'],
+ command=callback)
+ self.__z -= .1
+ return t, e
+
+ def __add_row_option(self, label, text, items, callback):
+ item_modules = glob('pmachines/items/*.py')
+ item_modules = [basename(i)[:-3] for i in item_modules]
+ t = OnscreenText(
+ label,
+ pos=(.03, self.__z), parent=self._frm,
+ font=self._common['text_font'],
+ scale=self._common['scale'],
+ fg=self._common['text_fg'],
+ wordwrap=20, align=TextNode.ALeft)
+ e = DirectOptionMenu(
+ scale=self._common['scale'],
+ initialitem=text,
+ pos=(.30, 1, self.__z),
+ items=items,
+ parent=self._frm,
+ command=callback,
+ state=NORMAL,
+ relief=FLAT,
+ item_relief=FLAT,
+ frameColor=self._common['frameColor'],
+ item_frameColor=self._common['frameColor'],
+ popupMenu_frameColor=self._common['frameColor'],
+ popupMarker_frameColor=self._common['frameColor'],
+ text_font=self._font,
+ text_fg=self._common['text_fg'],
+ highlightColor=(.9, .9, .9, .9),
+ item_text_font=self._font,
+ item_text_fg=self._common['text_fg'],
+ rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+ clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+ self.__z -= .1
+ return t, e
+
+ def __load_img_btn(self, path, col):
+ img = OnscreenImage('assets/images/buttons/%s.dds' % path)
+ img.set_transparency(True)
+ img.set_color(col)
+ img.detach_node()
+ return img
+
+ def on_edit_scale(self, txt):
+ self.__json['model_scale'] = float(txt)
+
+ def on_edit_mass(self, txt):
+ self.__json['mass'] = float(txt)
+
+ def on_edit_restitution(self, txt):
+ self.__json['restitution'] = float(txt)
+
+ def on_edit_friction(self, txt):
+ self.__json['friction'] = float(txt)
+
+ def on_edit_id(self, txt):
+ self.__json['id'] = txt
+
+ def on_edit_strategy(self, txt):
+ if txt:
+ self.__json['strategy'] = txt
+ self.__entries.strategy_args.set('')
+
+ def on_edit_strategy_args(self, txt):
+ self.__json['strategy_args'] = txt
+
+ def on_edit_class(self, txt):
+ if txt:
+ self.__json['class'] = txt
+
+ def on_edit_count(self, txt):
+ self.__json['count'] = int(txt)
+
+ def __new_item(self):
+ curr_index = self.__items.index(self.__json)
+ self.__json = {}
+ curr_index = (curr_index + 1) % len(self.__items)
+ self.__items.insert(curr_index, self.__json)
+ self.__set(self.__json)
+ import pprint
+ pprint.pprint(self.__items)
+
+ def __next_item(self):
+ curr_index = self.__items.index(self.__json)
+ self.__json = self.__items[(curr_index + 1) % len(self.__items)]
+ self.__set(self.__json)
+ import pprint
+ pprint.pprint(self.__items)
+
+ def __delete_item(self):
+ curr_index = self.__items.index(self.__json)
+ if curr_index == len(self.__items): curr_index = 0
+ self.__items.remove(self.__json)
+ if not self.__items:
+ self.__items = [{}]
+ self.__json = self.__items[curr_index]
+ self.__set(self.__json)
+ import pprint
+ pprint.pprint(self.__items)
+
+ def __set(self, json):
+ if 'model_scale' in json:
+ self.__entries.scale.set(str(json['model_scale']))
+ else:
+ self.__entries.scale.set('')
+ if 'mass' in json:
+ self.__entries.mass.set(str(json['mass']))
+ else:
+ self.__entries.mass.set('')
+ if 'restitution' in json:
+ self.__entries.restitution.set(str(json['restitution']))
+ else:
+ self.__entries.restitution.set('')
+ if 'friction' in json:
+ self.__entries.friction.set(str(json['friction']))
+ else:
+ self.__entries.friction.set('')
+ if 'id' in json:
+ self.__entries.id.set(str(json['id']))
+ else:
+ self.__entries.id.set('')
+ if 'strategy' in json:
+ self.__entries.strategy.set(str(json['strategy']))
+ else:
+ self.__entries.strategy.set('')
+ if 'strategy_args' in json:
+ self.__entries.strategy_args.set(str(json['strategy_args']))
+ else:
+ self.__entries.strategy_args.set('')
+ if 'class' in json:
+ self.__entries.item_class.set(str(json['class']))
+ else:
+ self.__entries.item_class.set('')
+ if 'count' in json:
+ self.__entries.count.set(str(json['count']))
+ else:
+ self.__entries.count.set('')
+ import pprint
+ pprint.pprint(self.__items)
+
+ def __save(self):
+ messenger.send('editor-start-items-save', [self.__items])
+
+ def __show_error_popup(self):
+ self.__dialog = OkDialog(dialogName='Strategy args errors',
+ text=_('There are errors in the strategy args.'),
+ command=self.__actually_close)
+ self.__dialog['frameColor'] = (.4, .4, .4, .14)
+ self.__dialog['relief'] = FLAT
+ self.__dialog.component('text0')['fg'] = (.9, .9, .9, 1)
+ self.__dialog.component('text0')['font'] = self._font
+ for b in self.__dialog.buttonList:
+ b['frameColor'] = (.4, .4, .4, .14)
+ b.component('text0')['fg'] = (.9, .9, .9, 1)
+ b.component('text0')['font'] = self._font
+ b.component('text1')['fg'] = (.9, .1, .1, 1)
+ b.component('text1')['font'] = self._font
+ b.component('text2')['fg'] = (.9, .9, .1, 1)
+ b.component('text2')['font'] = self._font
+
+ def __actually_close(self, arg):
+ self.__entries.strategy.set('')
+ self.__entries.strategy_args.set('')
+ self.__dialog.cleanup()
+
+ def destroy(self):
+ self._frm.destroy()
+ messenger.send('editor-start-items-destroy')