Пример #1
0
class YAMLEditor(FloatDialog, Tempsprites):
    def __init__(self, frontend, template, title):
        self.frontend = frontend
        self.title = title
        self.template = load_yaml('rules', template)
        self.dirname = None
        if self.title == 'Item Editor':
            self.dirname = 'items'
        elif self.title == 'NPC Editor':
            self.dirname = 'characters'
        self.rect = self.frontend.bigwindowrect
        FloatDialog.__init__(self, self.rect, frontend)
        Tempsprites.__init__(self)
        if self.title == 'Item Editor':
            self.item = Item({})
        elif self.title == 'NPC Editor':
            self.item = NPC({},1)
        debug (self.item.animations)
        self.conditional_sprites = []
        self.currentanimation = None
        self.baselayout()
        self.editorlayout()

    def baselayout(self):
        self.lastlayer = 18
        self.image.blit(render_text (self.title, size=32, color=(255,0,0)),(self.rect.w/2 - 20,10))
        split = self.frontend.imagecache['seperator']
        split = pygame.transform.smoothscale(split,(self.frontend.screensize.w -20, 10))
        self.image.blit(split,(10,60))
        save_btn = Button('Save Item', self.save, [], self.frontend.eventstack,self.frontend.imagecache, pos=(self.rect.x +  self.rect.w - 150,self.rect.y + self.rect.h - 50), layer=6)
        load_btn = Button('Load Item', self.load, [], self.frontend.eventstack,self.frontend.imagecache, pos=(self.rect.x +  10,self.rect.y + self.rect.h - 50), layer=6)
        self._addtemp('saveitem', save_btn)
        self._addtemp('loaditem', load_btn)

    def make_event(self, sender, key):
        self.update_yaml()
        if key.startswith('event'):
            default = default_text
        else:
            default = ['']
        data = self.item.get(key, default)
        if not key in data[0]:
            data.insert(0,'#%s' % key)
        data = editsnippet('\n'.join(data))
        self.item.put(key,data.split('\n'))
        self.update_yaml()

    def editorlayout(self):
        debug('Building editor layout')
        self._rmtemp()
        self.baselayout()
        col, row = 0, 0
        for key in [i for i in self.template if '__Y' in i]:
            value = self.item.get(realkey(key),False)
            if value is False:
                self.item.put(realkey(key), self.template[key])            
        list1 = sorted([i for i in self.template if not i.startswith('conditional/') and not i.startswith('events/') and not '__Y' in i and not 'animations' in i and i != 'personal/portrait'])
        list3 = sorted([i for i in self.template if  i.startswith('events/')])
        list2 = sorted([i for i in self.conditional_sprites if not 'animations' in i])
        if [i for i in self.template if 'equiped' in i]:
            list4=['inventory']
        else:
            list4 = []
        allkeys = list1 + list2 + list3 + list4
        for key in allkeys:
            x = col * 450 + self.rect.x + 15
            y = row * 35 + self.rect.y + 75
            if key == 'inventory':
                b = Button('Iventory', 
                    self.showinventory, 
                    [],
                    self.frontend.eventstack,
                    self.frontend.imagecache,
                    pos=(x ,y),
                    layer=6,
                    fontsize=14)
                self._addtemp('%s_button' % key, b)
                row += 1
                continue
            if key.startswith('events/') or key.startswith('__T'):
                b = Button(realkey(key), 
                    self.make_event, 
                    [realkey(key)],
                    self.frontend.eventstack,
                    self.frontend.imagecache,
                    pos=(x ,y),
                    layer=6,
                    sendself=True,
                    fontsize=14)
                self._addtemp('%s_button' % key, b)
            else: 
                sprites = self.handlekey(key, x,y)
                for sprite in sprites:
                    self._addtemp('%s_%s' % (key,sprites.index(sprite)), sprite)
            row += 1
            if row * 35 + self.rect.y + 75 + 128> self.rect.y + self.rect.h -75:
                row = 0
                col += 1
        for key in sorted([i for i in self.conditional_sprites if 'animations' in i])+sorted(i for i in self.template if 'animations' in i and not 'conditional' in i and i != 'personal/portrait'):
            keyname = realkey(key)
            value = self.item.get(keyname,[])
            if not value:
                value = self.template[key]
            self.item.put(keyname, value)
        if self.item.animations:
            x = col * 450 + self.rect.x + 15
            y = row * 35 + self.rect.y + 75
            self.animation_editor(x,y)
        y = y + 75
        for sprite in self.handlekey('personal/portrait', x,y):
            self._addtemp(make_hash(), sprite)

    def animation_editor(self, x, y):
        l = Label('Animations', (x,y))
        y += l.rect.h
        self._addtemp('animations_label', l)
        scale = self.frontend.mapscale
        self.previewsprite = AnimatedSprite(self.frontend.tilemaps, pygame.Rect(x, y, scale, scale), self.item.animations, 8, 5)
        if self.currentanimation is None:
            self.currentanimation = self.previewsprite.animation
            self.previewsprite.pause = True
        else:
            self.previewsprite.setanimation(self.currentanimation)
            self.previewsprite.pause = self.paused.checked
        self._addtemp('previewsprite', self.previewsprite)
        self.animation = Dropdown(self.frontend.eventstack, 
            self.frontend.imagecache, 
            18,
            pygame.Rect(x + scale + 2, y, 200, 20),
            self.previewsprite.animations.keys(),
            choice=self.currentanimation,
            onselect=self.changeanimation,
            layer = self.lastlayer)
        self.lastlayer -= 1
        self._addtemp('selectanimation', self.animation)
        self.paused = checkboxbtn('Paused', 
                    self.togglepause, 
                    [],
                    self.frontend.eventstack,
                    self.frontend.imagecache, 
                    pos=(x + 150,y+22), fontsize=16,
                    layer=6, sendself=True)
        self.paused.checked = self.previewsprite.pause
        self._addtemp('AnimationPauseButton', self.paused)
        if self.paused.checked:
            nextframebtn = ButtonArrow(self.previewsprite.nextframe, 
                [],
                self.frontend.eventstack,
                self.frontend.imagecache,
                'right',
                pos=(x + scale,y+22),
                layer=6)
            self._addtemp('nextframebtn', nextframebtn)
            delframebtn = BlitButton(self.delframe, 
                [],
                self.frontend.eventstack,
                self.frontend.imagecache,
                'minusarrow',
                pos=(nextframebtn.rect.x + nextframebtn.rect.w,y+22),
                layer=6)
            self._addtemp('delete frame button',delframebtn)
            addframebtn = BlitButton(self.addframe,[],
                self.frontend.eventstack,
                self.frontend.imagecache,
                'plusarrow',
                pos=(delframebtn.rect.x + delframebtn.rect.w,y+22),
                layer=6)
            self._addtemp('add frame button',addframebtn)
    
    def togglepause(self,pausbtn, *args):
        self.previewsprite.pause = pausbtn.checked
        self.editorlayout()

    def changeanimation(self,animation):
        self.previewsprite.setanimation(animation)
        self.currentanimation = animation

    def delframe(self):
        key = 'animations/%s' % self.currentanimation
        idx = self.previewsprite.frame
        messages.warning('Deleted frame %s' % (idx))
        try:
            del self.item()[key][idx]
        except IndexError:
            debug('Tried to delete from an already empty list.')

    def addframe(self):
        self.updateconditionals()
        self._rmtemp()
        self.tileselector = TileSelector(self.rect, self.frontend, self.newframe,[])
        self._addtemp('ye_tileselector', self.tileselector)

    def newframe(self, framepath):
        self._rmtemp()
        key = 'animations/%s' % self.currentanimation
        idx = self.previewsprite.frame
        animations = self.item.get(key)
        animations.insert(idx, '%s:0' %framepath)
        self.item.put(key, animations)
        self.editorlayout()

    def listmanager(self,keyname, items):
        self._rmtemp()
        itemlist = []
        for itemfile in file_list('items'):
            itemfile = os.path.basename(itemfile)
            itemlist.append(Item(load_yaml('items',itemfile)))
        c = ContainerDialog(self.rect,
            self.frontend,
            keyname,
            7,
            items=[Item(i) for i in items],
            onclose=self.updatelist,
            onclose_parms=[keyname],
            animation='view',
            can_add=True,
            can_remove=True,
            addfrom=itemlist)
        self._addtemp('%s_listmanager' %keyname, c)

    def showinventory(self, *args):
        #rect, frontend, char, layer=5
        self.update_yaml()
        self._rmtemp()
        inventory = Inventory(
            self.rect, 
            self.frontend,
            self.item,
            7,
            self.editorlayout
            )
        self._addtemp('editor_inventory', inventory)

    def updatelist(self, items, keyname):
        if keyname == 'inventory/pack':
            pack = self.item.get(keyname,[])
            for I  in pack:
                self.item.drop_item(Item(I))
            for I in items:
                self.item.acquire_item(I)
        else:
            items = [i() for i in items]
            self.item.put(keyname, items)
        self.editorlayout()

    def handlekey(self,key, x,y):
        keyname = realkey(key)
        has_label = True
        l = Label(keyname,(x,y))
        lsize = l.rect.w +10
        irect = pygame.Rect(x + lsize, y, 250, 20)
        value = self.item.get(keyname,'')
        if not value:
            if key in self.template:
                value = self.template[key]
            else:
                return ()
            if str(value).startswith('__'):
                value = ''
        if keyname == 'personal/portrait':
            self.item.put('personal/portrait', value)
            self.portrait = value
            d = BlitButton(
                self.nextportrait, 
                [],
                self.frontend.eventstack,
                self.frontend.imagecache,
                self.portrait,
                pos=(irect.x,y),
                scale=128,
                layer=7
                )
        elif isinstance(value, list):
            d = Button('Manage list', 
                self.listmanager,
                [keyname, value],
                self.frontend.eventstack,
                self.frontend.imagecache,
                pos=(irect.x, irect.y),
                layer=self._layer +1)
        elif (key.startswith('conditional') or keyname == key) and not '__[' in str(self.template[key]):
            d = TextInput(
                irect,18, self.frontend.eventstack, prompt=str(value), clearprompt=False, layer=6, name=keyname)
        elif (key.startswith('conditional') or keyname == key) and '__[' in str(self.template[key]):
            liststr = self.template[key]
            items = liststr[3:-1].split(',')
            if sorted([i.upper() for i in items]) == ['FALSE','TRUE']:
                has_label = False
                d = checkboxbtn(keyname, 
                    self.valuechange, 
                    [],
                    self.frontend.eventstack,
                    self.frontend.imagecache, 
                    pos=(x,y), fontsize=16,
                    layer=6, name=key, sendself=True)
                if d.name in self.item():
                    d.checked = self.item.get(d.name)
                else:
                    d.checked = items[0].upper() == 'TRUE'
            else:
                if not value and len(items) == 1:
                    value = items[0]
                d = Dropdown(
                    self.frontend.eventstack, 
                    self.frontend.imagecache, 
                    16,
                    irect, items,layer=self.lastlayer, 
                    choice=value, 
                    onselect=self.valuechange,
                    name=keyname,
                    sendself=True)
                self.lastlayer -= 1
        if has_label:
            return [l, d]
        else:
            return [d]

    def nextportrait(self):
        portraitlist = [i for i in self.frontend.imagecache.keys() if i.startswith('portrait_')]
        idx = portraitlist.index(self.portrait)
        idx += 1
        if idx >= len(portraitlist) -1:
            idx = 0
        self.portrait = portraitlist[idx]
        self.item.put('personal/portrait', self.portrait)
        self.editorlayout()

    def updateconditionals(self):
        self.conditional_sprites = []
        conditional_keys = FlattenedDict(self.template).readsubtree('conditional')
        for key in conditional_keys:
            conditions = [k.replace('.','/') for k in key.split('/') if '=' in k]
            for condition in conditions:
                ckey, cval = condition.split('=')
                if self.item.get(ckey,False) == cval:
                    self.conditional_sprites.append('conditional/%s' % key)
        self.editorlayout()

    def valuechange(self, *args):
        k, v =  args[0].name, args[1]
        self.item.put(k, v)
        self.update_yaml()
        self.updateconditionals()

    def changepreview(self,choice):
        self.previewsprite.setanimation(choice)

    def update_yaml(self):
        for item in self.temp:
            sprite = item[0]
            try:
                k = realkey(sprite.name)
                v = sprite.value
                if k and v:
                    self.item.put(k, v)
            except:
                continue

    def save(self):
        self.update_yaml()
        if self.dirname:
            filename = self.item.save_to_file(self.dirname)
            messages.error('Saved to %s' % os.path.basename(filename))

    def load(self):
        self._rmtemp()
        itemlist = []
        for itemfile in file_list(self.dirname):
            itemfile = os.path.basename(itemfile)
            if self.dirname == 'items':
                itemlist.append(Item(load_yaml(self.dirname,itemfile)))
            else:
                itemlist.append(NPC(load_yaml(self.dirname,itemfile)))
        c = ContainerDialog(self.rect,
            self.frontend,
            'Load %s' %self.dirname,
            7,
            items=itemlist,
            onselect=self.loaditem,
            onselect_parms=[],
            animation='view',
            can_add=False,
            can_remove=False
            )
        self._addtemp(make_hash(), c)

    def loaditem(self, item):
        debug('Loading item', item.displayname())
        self.item = item
        self.updateconditionals()

    def delete(self):
        self._rmtemp()
        self.kill()
        self.restorebg()