class CLoader(fo.CCompositionBase): """ Base class of collection loader that is to be used to set figures' attributes from some external data source, e.g. file of database """ ######################################## def __init__(self, collection, **args): fo.CCompositionBase.__init__(self, collection, **args) self.srcs = [] self.tmp_draw_attrs = {} self.tmp_layout_attrs = {} ######################################## ## All default values off class' possible attributes should be defined ## These defaults takes precedence over 'CDrawFigure...' defaults attr_defaults = fo.merge_dicts(fo.CCompositionBase.attrDefaults(), {}) ######################################## def HasSource(self, src): return src in self.srcs def AddSource(self, src): if self.HasSource(src): return False self.srcs.append(src) return True ######################################## ## Override this def AcceptFigureAttr(self, attrs, attr_key, attr_val): return attr_val ## No need to override this def SetFigureAttr(self, attrs_key, attr_key, attr_val): attrs = getattr(self, attrs_key) if self.AcceptFigureAttr(attrs, attr_key, attr_val): attrs[attr_key] = fo.merge_dicts( attrs[attr_key], attr_val) if attr_key in attrs else attr_val ######################################## ## Fill collection with figures attributes ## by calling 'AddFigureAttrs'. ## Override this - only dummy usage example def loadFiguresAttrs(self, src, **args): self.SetFigureAttr('tmp_layout_attrs', 'layout_key', 'value') self.SetFigureAttr('tmp_draw_attrs', 'draw_key', 'value') self.AddFigureAttrs() ## Check if this 'src' has not been already loaded. ## If not, call 'loadAttrs'. ## Do not override this def LoadFiguresAttrs(self, src, **args): if not self.AddSource(src): return False self.loadFiguresAttrs(src, **args) return True
class CLayoutMysteriaCardSpell(CLayoutMysteriaCardPlay_): """ Layout class of Mysteria spell cards """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( CLayoutMysteriaCardPlay_.attrDefaults(), { 'spell_class': 1, 'spell_class_width_mm': 20, 'spell_class_height_mm': 20, 'spell_class_xalign': 'center', 'spell_class_yloc': 'below', 'spell_class_add_yoffs_mm': 6, 'spell_class_draw_object_args': { 'effect_fill': { 'type': 'picture' }, 'effect_text': { 'size_pt': 24, 'fg_color': "black" }, }, 'spell_mana': 2, 'spell_mana_draw_object_args': { 'effect_fill': { 'type': 'color', 'color': "blue" }, 'effect_text': { 'size_pt': 12, 'fg_color': "white" }, }, }) local_ranks = [0, 11] ranks_ = None ######################################## def Layout(self, rank=0): CLayoutMysteriaCardPlay_.Layout(self, rank) if rank == 0: spell_class = self.AddObjectToGroup( 'spell_class', parent=self.back.GetObjectByKeyBase('back_artifacts_group'), effect_text={'text': str(self.spell_class)}) elif rank == 11: spell_mana = self.AddObjectToLayout( 'spell_mana', parent=self.front, effect_text={'text': str(self.spell_mana)}) mini = self.front.GetObjectByKeyBase('mini') spell_mana.SetSizeFromObject(mini, set_margin=False) spell_mana.SetPosFromObject(mini, xloc='mirror') return self.ReturnRank(rank)
class CLayoutMysteriaCardPlay_(CLayoutMysteriaCardHold_): """ Incomplete layout class of Mysteria play cards -> all hold cards except units """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( CLayoutMysteriaCardHold_.attrDefaults(), { 'flag': False, 'play_with_yloc': 'below', 'play_with_add_yoffs_mm': 1, 'play_with_scale': 0.7, 'play_with_draw_object_args': { 'effect_fill': { 'color2': "red" }, 'effect_text': { 'text': "" }, }, 'force_play': False, 'back_force_play_width_mm': 9, 'back_force_play_height_mm': 22, 'back_force_play_xalign': 'center', 'back_force_play_yloc': 'below', 'back_force_play_add_yoffs_mm': 3, 'back_force_play_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, }) local_ranks = [0, 1] ranks_ = None ######################################## def Layout(self, rank=0): CLayoutMysteriaCardHold_.Layout(self, rank) if rank == 0: if self.play_with_draw_object_args['effect_text']['text'] != "": play_with = self.AddObjectCopyToLayout( self.front.GetObjectByKeyBase('label'), new_key='play_with') play_with.SetDrawEffectAttrs( 'text', text="+" + play_with.draw.AttrsFromEffects()['effect_text']['text']) elif rank == 1: if self.force_play: back_force_play = self.AddObjectToGroup( 'back_force_play', parent=self.back.GetObjectByKeyBase( 'back_artifacts_group')) return self.ReturnRank(rank)
class CLayoutMysteriaCardClass(CLayoutMysteriaCardPlay_): """ Layout class of Mysteria class cards -> ordinary, special, shared and risc cards """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( CLayoutMysteriaCardPlay_.attrDefaults(), { 'front_class_width_mm': 10.8, 'front_class_height_mm': 10.8, 'front_class_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, 'back_class_width_mm': 18, 'back_class_height_mm': 18, 'back_class_xalign': 'center', 'back_class_yloc': 'below', 'back_class_add_yoffs_mm': 6, 'back_class_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, }) local_ranks = [0, 11] ranks_ = None ######################################## def Layout(self, rank=0): CLayoutMysteriaCardPlay_.Layout(self, rank) if rank == 0: back_class = self.AddObjectToGroup( 'back_class', parent=self.back.GetObjectByKeyBase('back_artifacts_group')) elif rank == 11: front_class = self.AddObjectToLayout('front_class', parent=self.front) front_class.SetPosFromObject(self.front.GetObjectByKeyBase('mini'), xloc='mirror', yloc=None) front_class.SetPosFromObject( self.front.GetObjectByKeyBase('label'), xloc=None, yloc='centerof') return self.ReturnRank(rank)
class CLayoutMysteriaCardBasic(CLayoutMysteriaCardPlay_): """ Layout class of Mysteria basic cards """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts(CLayoutMysteriaCardPlay_.attrDefaults(), {}) local_ranks = [0] ranks_ = None ######################################## def Layout(self, rank=0): CLayoutMysteriaCardPlay_.Layout(self, rank) return self.ReturnRank(rank)
class CLayoutBack(CLayout): """ Layout that adds back root object """ ######################################## attr_defaults = fo.merge_dicts(CLayout.attrDefaults(), {}) local_ranks = [0] ranks_ = None ######################################## ## Creates very common root figure object def Layout(self, rank=0): if rank == 0: self.ptr.ptr.back = self.AddRootObjectToLayout('back') return self.ReturnRank(rank)
class CDrawFigurePrint(CDrawFigureBase): """ Draw figure class that uses terminal printing as draw """ ######################################## default_draw_object_class = fo.CDrawObjectPrint ######################################## ## All default values off class' possible attributes should be defined ## Beware - 'CLayoutFigure...' defaults takes precedence over these ! attr_defaults = fo.merge_dicts(CDrawFigureBase.attrDefaults(), {}) ######################################## def PreDrawFigure(self): print "\n" + "^" * 40 def PostDrawFigure(self): print "+" * 40
class CLoaderDSV(CLoader): """ Collection loader class for files with delimiter-separated values (DSV). Each record has to be delimited with newline. First line is considered as keys. It is also possible to load 'dict's with the same syntax as in Python, but delimiter has to be different from 'dict' symbols [{,:}] and the value must start with '{'. """ ######################################## ## All default values off class' possible attributes should be defined ## These defaults takes precedence over 'CDrawFigure...' defaults attr_defaults = fo.merge_dicts(CLoader.attrDefaults(), { 'delim': '\t', }) ######################################## ## Draw figure attributes should be prefixed with 'd'. ## Layout figure attributes can be prefixed with 'l', ## but don't have to - it acts as default. def loadFiguresAttrs(self, src, delim=None): if not delim: delim = self.delim with open(src) as csvfile: reader = csv.DictReader(csvfile, delimiter=delim) for row in reader: for key in row.keys(): split_ = key.split("_", 1) val = row[key] ## Possibly convert to dict if val and val[0] == '{': val = eval(val) is_default = len(split_) == 1 or split_[0] not in [ 'd', 'l' ] is_layout = split_[0] == 'l' attrs_key = 'tmp_layout_attrs' if is_default or is_layout else 'tmp_draw_attrs' attr_key = key if is_default else split_[1] self.SetFigureAttr(attrs_key, attr_key, val) self.AddFigureAttrs()
class CDrawFigureBase(fo.CCompositionBase): """ Dummy draw figure class that defines interface between 'CFigure' and 'CDrawFigure..' objects. Its purpose is to set draw routines independently on figure layout - i.e. it should set concrete draw tool specific attributes and functions. It should not contain attributes that are under layout responsibility nor those which indeed relates to draw but it is certain that they should be used by all kinds of draw tool (i.e. fill color, pattern or image of background). """ ######################################## default_draw_object_class = fo.CDrawObjectBase ######################################## ## Do not override contructor ## More attributes are possible to set through '**args', ## concrete attributes are set in 'SetAttrs', ## default values should be defined in class variable 'attr_defaults' def __init__(self, figure, draw_object_class, **args): fo.CCompositionBase.__init__(self, figure, **args) self.draw_object_class = draw_object_class ######################################## def __copy__(self): return self.__class__(self.ptr, self.draw_object_class, **self.attrs) ######################################## ## All default values off class' possible attributes should be defined ## Beware - 'CLayoutFigure...' defaults takes precedence over these ! attr_defaults = fo.merge_dicts(fo.CCompositionBase.attrDefaults(), {}) ######################################## ## Override this - things that need to be set up before any drawing done def PreDrawFigure(self): pass ## Override this - things that need to be set up after all drawing done def PostDrawFigure(self): pass
class CLayoutMysteriaCardAddKind(CLayoutMysteriaCardPlay_): """ Additional (it does not inherit behaviour) layout class of Mysteria kind cards -> kind, basic and unit cards """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( CLayoutMysteriaCardPlay_.attrDefaults(), { 'kind_label_add_yoffs_mm': -0.5, 'kind_label_new_width_mm': 15, 'kind_label_scale': 0.75, 'kind_label_draw_object_args': { 'effect_fill': { 'color2': "cyan" }, 'effect_text': { 'text': "Kind name" }, }, 'back_kind_label_xalign': 'center', 'back_kind_label_yloc': 'below', 'back_kind_label_add_yoffs_mm': 5, 'back_kind_label_scale': 1.5, 'no_steal_scale': 0.15, 'no_steal_add_xoffs_mm': 1, 'no_steal_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, 'no_dump': True, 'no_dump_scale': 0.15, 'no_dump_add_xoffs_mm': 1, 'no_dump_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, }) local_ranks = [0] ranks_ = None ######################################## def AddObjectKindLabelToLayout(self, label_obj, add_yoffs_mm=fo.DEFAULT, scale=fo.DEFAULT, **draw_object_args): key = 'kind_label' obj = self.AddObjectCopyToLayout(label_obj, new_key=key, yloc='above', add_yoffs_mm=add_yoffs_mm, scale=scale, **draw_object_args) return obj ######################################## def Layout(self, rank=0): if rank == 0: front_kind_label_obj = self.AddObjectKindLabelToLayout( self.front.GetObjectByKeyBase('label')) back_kind_label_obj = self.AddObjectCopyToLayout( front_kind_label_obj, new_key='back_kind_label', new_parent=self.back, xloc=None, add_xoffs_mm=0, yloc=None, add_yoffs_mm=0, ) self.addObjectToGroup( parent=self.back.GetObjectByKeyBase('back_artifacts_group'), object_=back_kind_label_obj) no_steal_obj = self.AddObjectIconToLayout( 'no_steal', self.back.GetObjectByKeyBase('category_icons_group')) if self.no_dump: no_dump_obj = self.AddObjectIconToLayout( 'no_dump', self.back.GetObjectByKeyBase('category_icons_group')) return self.ReturnRank(rank)
class CLayoutFigureMysteriaCard(fig.CLayoutFigureBase): """ Layout class of all kinds of Mysteria cards """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( fig.CLayoutFigureBase.attrDefaults(), { 'layout_front': { 'front_margin_mm': 3, 'front_draw_object_args': { 'effect_fill': { 'type': 'gradient', 'color1': "black", 'color2': "white", 'angle': 90, 'ratio': 1.2 }, 'effect_border': { 'type': 'color', 'color': "white" }, }, }, 'layout_back': { 'back_margin_mm': 7.5, 'back_draw_object_args': { 'effect_fill': { 'type': 'pattern' }, 'effect_border': { 'type': 'color', 'color': "white" }, }, }, 'layout_mysteria_card_basic': { 'flag': False, 'rank': 5, 'module': __name__, }, 'layout_mysteria_card_class': { 'flag': False, 'rank': 5, 'module': __name__, }, 'layout_mysteria_card_spell': { 'flag': False, 'rank': 5, 'module': __name__, }, 'layout_mysteria_card_mana': { 'flag': False, 'rank': 5, 'module': __name__, }, 'layout_mysteria_card_add_kind': { 'flag': False, 'rank': 7, 'module': __name__, }, })
def AttrsWithLayouts(self): return fo.merge_dicts(self.AttrsFromLayouts(), self.attrs)
class CLayoutFigureBase(fo.CCompositionBase): """ Dummy figure layout class that defines interface between 'CFigure' and 'CLayoutFigure...' objects. It should contain attributes that are common for any used draw tool. """ ######################################## ## Do not override contructor ## More attributes are possible to set through '**args', ## concrete attributes are set in 'SetAttrs', ## default values should be defined in class variable 'attr_defaults' def __init__(self, figure, **args): self.ClearLayouts() fo.CCompositionBase.__init__(self, figure, **args) ######################################## def __copy__(self): layout = self.__class__(self.ptr, **self.attrs) ######################################## def __getattr__(self, attr_key): try: return fo.CCompositionBase.__getattr__(self, attr_key) except AttributeError: if hasattr(self.LastLayout, attr_key): return getattr(self.LastLayout, attr_key) raise ######################################## def ClearLayouts(self): self.layouts = {} self.layouts_ordered = [] self.layouts_pos = -1 self.layouts_rank = 0 self.layouts_next_rank = None ######################################## def CreateLayout(self, layout_class, **layout_args): return layout_class(self, **layout_args) def AddLayoutByClass(self, layout_class, **layout_args): self.AddLayout(self.CreateLayout(layout_class, **layout_args)) def AddLayout(self, layout): self.layouts[layout.LayoutKey] = layout self.layouts_ordered.append(layout) ######################################## def AttrsFromLayouts(self): attrs = {} for layout_key in self.layouts: attrs['layout_' + layout_key] = self.layouts[layout_key].attrs return attrs def AttrsWithLayouts(self): return fo.merge_dicts(self.AttrsFromLayouts(), self.attrs) def AddLayoutsFromAttrs(self): self.attrs = self.AttrsWithLayouts() self.ClearLayouts() layouts = self.DictsFromAttrs('layout', sort_f=lambda l: 0 if not 'rank' in l[1] else l[1]['rank']) for l in layouts: key = l[0] attrs = l[1] if 'module' in attrs: module = __import__(attrs['module']) else: module = sys.modules[__name__] class_ = getattr(module, "CLayout" + fo.str_title(key)) self.AddLayoutByClass(class_, **attrs) ######################################## ## Do not override this def SetAttrs(self, attrs=None): fo.CCompositionBase.SetAttrs(self, attrs) self.AddLayoutsFromAttrs() ######################################## ## All default values off class' possible attributes should be defined ## These defaults takes precedence over 'CDrawFigure...' defaults attr_defaults = fo.merge_dicts(fo.CCompositionBase.attrDefaults(), { 'layout_front': { 'rank': 1 }, 'layout_back': { 'rank': 2 }, }) ######################################## @property def LayoutsPos(self): return self.layouts_pos @property def LayoutsCount(self): return len(self.layouts_ordered) @property def LastLayout(self): return self.layouts_ordered[self.LayoutsPos] ## Executes range of layouts, ## if there are any left, ## which inserts figure objects. ## It is designed to be called multiple times ## and to step either by layout or whole rank. ## Do not override this. ## By default, process all layouts and ranks ## (when step is 'None'). ## Returns whether any layout was processed. def LayoutFigure(self, rank_step=None, layout_step=None): start = self.LayoutsPos + 1 end = self.LayoutsCount if layout_step == None else min( start + layout_step, self.LayoutsCount) layouts = self.layouts_ordered[start:end] if not layouts or (rank_step != None and rank_step <= 0): return False flag = False for layout in layouts: if layout.flag: flag = True next_rank = layout.Layout(self.layouts_rank) if (next_rank != None and next_rank > self.layouts_rank and (self.layouts_next_rank == None or next_rank < self.layouts_next_rank)): self.layouts_next_rank = next_rank self.layouts_pos = end - 1 if (self.LayoutsPos == self.LayoutsCount - 1 and self.layouts_next_rank != None and self.layouts_next_rank > self.layouts_rank): ## All layouts processed, but not all ranks -> next cycle self.layouts_rank = self.layouts_next_rank self.layouts_next_rank = None self.layouts_pos = -1 if rank_step != None: rank_step -= 1 if rank_step <= 0: ## Given step of ranks exceeded return flag flag |= self.LayoutFigure(rank_step, layout_step) return flag
class CLayout(fo.CCompositionBase): """ Class of single layout that is or is not applied to figure layout -> it adds methods to create objects relating to layout and inserts the most common ones automatically. One can inherit layout classes in two ways: 1) Inherit only superclass' default attributes and methods, but do not use superclass' 'Layout'. These classes are treated as 'additional' as their behaviour does not overlay with superclass. One may possibly have included sth. like 'Add' to class' identifier to notify this feature. 2) As 1), but use superclass' 'Layout'. These classes should represent concrete end standalone layouts, that are mutually disjunct, thus one should use only one class 'chain', but additional layouts should be still used at no harm. In both cases, one may want to define an 'incomplete' class that is to be extended. These classes should have set 'flag' to 'False' to avoid multiple calls of 'Layout' from its subclasses and possibly have appended an '_' to its identifier to notify this feature. Each layout can contain multiple branches that will be executed in order according to rank among other layouts - lesser ranks are executed first in all layouts. This is necessary when there are any dependencies between figure objects, e.g. when one wants to deepcopy figure object, it has to be done after insertion of all subobjects into copied object. Also, whole layout can have rank, which defines order of layouts within an branch rank iteration. This is useful only in cases when for some reason multiple layouts has same rank of branch and one wants certain layouts to take precedence, typically root objects at branch rank 0. """ ######################################## ## All default values off class' possible attributes should be defined ## These defaults takes precedence over 'CDrawFigure...' defaults attr_defaults = fo.merge_dicts( fo.CCompositionBase.attrDefaults(), { 'flag': True, 'width_mm': 0, 'height_mm': 0, 'xalign': 'left', 'yalign': 'top', 'xoffs_mm': 0, 'yoffs_mm': 0, 'xloc': 'sameas', 'yloc': 'sameas', 'add_xoffs_mm': 0, 'add_yoffs_mm': 0, 'parent': None, 'margin_mm': 0, 'opacity': 100, 'new_opacity': None, 'new_width_mm': None, 'new_height_mm': None, 'new_margin_mm': None, 'scale': 1, 'draw_object_args': {}, }) ## Branch ranks used only within this class' 'Layout' local_ranks = [0] ## Disable inheritance if 'ranks_' as it will be merged in 'ranks()' ranks_ = None ######################################## @classmethod def ranks(cls): if not cls.ranks_: superclass = cls.__bases__[0] cls.ranks_ = fo.merge_lists( [] if not hasattr(superclass, 'ranks') else superclass.ranks(), cls.local_ranks) cls.local_ranks = None return cls.ranks_ def Ranks(self): return self.__class__.ranks() ######################################## @property def LayoutKey(self): id_ = self.__class__.__name__[len('CLayout'):] key = '' for c in id_: if c.islower(): key += c else: key += "_" + c.lower() return key[1:] if key[-1] != "_" else key[1:-1] ######################################## ## Insert figure object to layout, ## i.e. insert it into its parent ## that may not have been inserted yet, ## or into explicit parent def InsertObject(self, object_, parent=None): if parent == None: parent = object_.parent if parent != None: parent.InsertObject(object_) ######################################## ## Returns newly created figure object, ## which is automatically added into layout ## and will be inserted in next 'DoLayout' call ## 'SetDrawObjectClass' should have beeen called before def AddObjectToLayout(self, key, width_mm=fo.DEFAULT, height_mm=fo.DEFAULT, parent=fo.DEFAULT, xalign=fo.DEFAULT, yalign=fo.DEFAULT, xoffs_mm=fo.DEFAULT, yoffs_mm=fo.DEFAULT, margin_mm=fo.DEFAULT, opacity=fo.DEFAULT, **draw_object_args): self.SetFunctionAttrDefaults(key, 2) parent = self.args.parent root_object = self._dummy_object if parent == None else parent.RootObject if parent == None: parent = root_object obj = fo.CFigObject(key, figure=self.ptr, resolution_ppi=self.Resolution_ppi, width_mm=self.args.width_mm, height_mm=self.args.height_mm, xalign=self.args.xalign, yalign=self.args.yalign, xoffs_mm=self.args.xoffs_mm, yoffs_mm=self.args.yoffs_mm, parent=parent, margin_mm=self.args.margin_mm, opacity=self.args.opacity, draw_class=self.draw.draw_object_class, **self.args.draw_object_args) self.InsertObject(obj) self.CleanFunctionAttrDefaults() return obj def AddRootObjectToLayout(self, key, margin_mm=fo.DEFAULT, opacity=fo.DEFAULT, **draw_object_args): return self.AddObjectToLayout(key, width_mm=self.Width_mm, height_mm=self.Height_mm, margin_mm=margin_mm, opacity=opacity, **draw_object_args) def AddObjectCopyToLayout(self, object_, deepcopy=True, new_key=None, new_parent=None, xloc=fo.DEFAULT, yloc=fo.DEFAULT, add_xoffs_mm=fo.DEFAULT, add_yoffs_mm=fo.DEFAULT, new_opacity=fo.DEFAULT, new_width_mm=fo.DEFAULT, new_height_mm=fo.DEFAULT, new_margin_mm=fo.DEFAULT, scale=fo.DEFAULT, **draw_object_args): obj = cp.copy(object_) if not deepcopy else cp.deepcopy(object_) obj.SetKey(new_key) if new_parent != None: obj.SetParent(new_parent) self.SetFunctionAttrDefaults(obj.key, 2) obj.SetOpacity(self.args.new_opacity) obj.SetSize(scale=self.args.scale, width_mm=self.args.new_width_mm, height_mm=self.args.new_height_mm, margin_mm=self.args.new_margin_mm) obj.SetPosFromObject(object_, xloc=self.args.xloc, yloc=self.args.yloc, add_xoffs_mm=self.args.add_xoffs_mm, add_yoffs_mm=self.args.add_yoffs_mm) obj.SetDrawObjectAttrs(**self.args.draw_object_args) self.InsertObject(obj) self.CleanFunctionAttrDefaults() return obj def AddObjectGroupToLayout(self, key_prefix, parent, xalign=fo.DEFAULT, yalign=fo.DEFAULT, xoffs_mm=fo.DEFAULT, yoffs_mm=fo.DEFAULT, opacity=fo.DEFAULT, **draw_object_args): if key_prefix[-1] == '_': key_prefix = key_prefix[:-1] key = key_prefix + '_group' obj = self.AddObjectToLayout(key, parent=parent, xalign=xalign, yalign=yalign, xoffs_mm=xoffs_mm, yoffs_mm=yoffs_mm, opacity=opacity, **draw_object_args) return obj ## One often wants to use 'None' in 'xloc' and 'yloc' ## (do not discard previous position by default) def addObjectToGroup( self, parent, object_, xloc=fo.DEFAULT, add_xoffs_mm=fo.DEFAULT, yloc=fo.DEFAULT, add_yoffs_mm=fo.DEFAULT, ): self.SetFunctionAttrDefaults(object_.key, 3) object_.SetParent(parent) if parent.ObjectsCount > 1: object_.SetPosFromObject( parent.objects_ordered[-1], xloc=self.args.xloc, add_xoffs_mm=self.args.add_xoffs_mm, yloc=self.args.yloc, add_yoffs_mm=self.args.add_yoffs_mm, ) self.InsertObject(object_) self.CleanFunctionAttrDefaults() return object_ def AddObjectToGroup(self, key, parent, width_mm=fo.DEFAULT, height_mm=fo.DEFAULT, xalign=fo.DEFAULT, xoffs_mm=fo.DEFAULT, yalign=fo.DEFAULT, yoffs_mm=fo.DEFAULT, xloc=fo.DEFAULT, add_xoffs_mm=fo.DEFAULT, yloc=fo.DEFAULT, add_yoffs_mm=fo.DEFAULT, margin_mm=fo.DEFAULT, opacity=fo.DEFAULT, **draw_object_args): obj = self.AddObjectToLayout(key=key, width_mm=width_mm, height_mm=height_mm, xalign=xalign, xoffs_mm=xoffs_mm, yalign=yalign, yoffs_mm=yoffs_mm, margin_mm=margin_mm, opacity=opacity, **draw_object_args) obj = self.addObjectToGroup( parent, obj, xloc=xloc, add_xoffs_mm=add_xoffs_mm, yloc=yloc, add_yoffs_mm=add_yoffs_mm, ) return obj ######################################## def ReturnRank(self, act_rank): for rank in self.Ranks(): if act_rank < rank: return rank return None ## Each rank is called only once. ## Return next rank that is to be called, ## or current rank if there it no one. ## Override this to set and insert all common objects according to layout def Layout(self, rank=0): ##! It would be better to use 'cls.local_ranks' to remove redundancy. ##! But how to access it independently of the object? ##! (Object of some subclass knows only 'local_ranks' of its class, ##! not of its superclasses.) if rank == 0: pass return self.ReturnRank(rank)
def AttrsFromShared(self, idx, attr_key, **args): shared_attrs = getattr(self, 'shared_' + attr_key) figures_attrs_key = 'figures_' + attr_key figs_attrs = getattr(self, figures_attrs_key) fig_attrs = {} if idx >= len(figs_attrs) else figs_attrs[idx] return fo.merge_dicts(shared_attrs, fig_attrs, args)
class CLayoutMysteriaCard_(fig.CLayout): """ Incomplete layout class of all kinds of Mysteria cards. Incomplete within the meaning of that one certainly wants to use some of its subclasses. """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( fig.CLayout.attrDefaults(), { 'flag': False, 'mini_height_mm': 12.5, 'mini_xloc': 'right', 'mini_add_xoffs_mm': -1, 'mini_yloc': 'centerof', 'mini_2': False, 'mini_2_xloc': 'mirror', 'mini_2_scale': 1.2, 'label_width_mm': 28, 'label_height_mm': 5, 'label_margin_mm': 0.4, 'label_xalign': 'center', 'label_xoffs_mm': 1.1, 'label_yoffs_mm': 5, 'label_draw_object_args': { 'effect_fill': { 'type': 'gradient', 'color1': "white", 'color2': "lime", 'angle': 80, 'ratio': 2 }, 'effect_border': { 'type': 'color', 'color': "black" }, 'effect_text': { 'type': '', 'text': "Card name", 'fg_color': "black", 'size_pt': 9.5 }, 'effect_shear': { 'mag_x': -30 }, }, 'picture_width_mm': 30, 'picture_height_mm': 45, 'picture_xalign': 'left', 'picture_xoffs_mm': 1, 'picture_yloc': 'below', 'picture_add_yoffs_mm': 10, 'picture_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, }) local_ranks = [0, 10] ranks_ = None ######################################## def AddObjectBackMiniToLayout( self, xloc=fo.DEFAULT, add_xoffs_mm=fo.DEFAULT, add_yoffs_mm=fo.DEFAULT, ): obj = self.AddObjectCopyToLayout(self.back, new_key='mini', new_parent=self.front, xloc=xloc, add_xoffs_mm=add_xoffs_mm, add_yoffs_mm=add_yoffs_mm, scale=(self.mini_height_mm / self.back.Height_mm)) return obj ######################################## def Layout(self, rank=0): if rank == 0: label = self.AddObjectToLayout('label', parent=self.front) pic = self.AddObjectToLayout('picture', parent=self.front) pic.SetPosFromObject(label, xloc=None, yloc=self.picture_yloc, add_yoffs_mm=self.picture_add_yoffs_mm) elif rank == 10: mini = self.AddObjectBackMiniToLayout() mini.SetPosFromObject(self.front.GetObjectByKeyBase('label'), xloc=None, yloc=self.mini_yloc) if self.mini_2: mini_2 = self.AddObjectCopyToLayout(mini, new_key='mini_2') return self.ReturnRank(rank)
class CLayoutMysteriaCardHold_(CLayoutMysteriaCard_): """ Incomplete layout class of Mysteria hold cards -> all cards that players play with directly (they hold them in hand or have them in packs) """ ######################################## ## All default values off class' possible attributes should be defined attr_defaults = fo.merge_dicts( CLayoutMysteriaCard_.attrDefaults(), { 'flag': False, 'back_artifacts_group_xalign': 'center', 'back_artifacts_group_add_yoffs_mm': 4, 'category_icons_group_xalign': 'center', 'category_icons_group_yalign': 'bottom', 'category_icons_group_yoffs_mm': -3, 'importance_group_xoffs_mm': 1, 'importance_group_yoffs_mm': 1, 'category_importance': 1, 'category_importance_width_mm': 5, 'category_importance_height_mm': 5, 'category_importance_yalign': 'center', 'category_importance_draw_object_args': { 'effect_text': { 'type': '' }, }, 'class_importance': 1, 'class_importance_width_mm': 4.5, 'class_importance_height_mm': 4.5, 'class_importance_yalign': 'center', 'class_importance_xloc': 'rightof', 'class_importance_add_xoffs_mm': 0.2, 'class_importance_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, 'prestige': 0, 'prestige_group_xoffs_mm': 0.5, 'prestige_group_yalign': 'bottom', 'prestige_group_yoffs_mm': -0.5, 'prestige_text_width_mm': 6, 'prestige_text_height_mm': 3, 'prestige_text_draw_object_args': { 'effect_text': { 'type': '' }, }, 'prestige_class_width_mm': 3, 'prestige_class_height_mm': 3, 'prestige_class_draw_object_args': { 'effect_fill': { 'type': 'picture' }, }, }) local_ranks = [0] ranks_ = None ######################################## def AddObjectIconToLayout(self, key, icons_obj, scale=fo.DEFAULT, add_xoffs_mm=fo.DEFAULT, opacity=fo.DEFAULT, **draw_object_args): self.SetFunctionAttrDefaults(key, 3) obj = self.AddObjectToGroup(key, icons_obj, xloc='rightof', add_xoffs_mm=add_xoffs_mm, opacity=opacity, **draw_object_args) obj.SetSizeFromObject(self.back, scale=self.args.scale) obj.AddDrawEffectFromObject(self.back, 'border') self.CleanFunctionAttrDefaults() return obj def AddObjectPrestigeToLayout(self): key = 'prestige' group = self.AddObjectGroupToLayout(key, parent=self.front) if self.prestige != 0: text_obj = self.AddObjectToGroup( parent=group, key=key + '_text', effect_text={ 'text': "%+d" % self.prestige, 'fg_color': "lime" if self.prestige > 0 else "red" }) ##!class_obj ~ prestiz vrstvy return group ######################################## def Layout(self, rank=0): CLayoutMysteriaCard_.Layout(self, rank) if rank == 0: importance_left = self.AddObjectGroupToLayout('importance', parent=self.back) category_importance_left = self.AddObjectToGroup( 'category_importance', parent=importance_left, effect_text={'text': str(self.category_importance)}) class_importance_left = self.AddObjectToGroup( 'class_importance', parent=importance_left) importance_right = self.AddObjectCopyToLayout(importance_left, xloc='mirror') back_artifacts = self.AddObjectGroupToLayout('back_artifacts', parent=self.back) back_artifacts.SetPosFromObject( importance_left, xloc=None, yloc='below', add_yoffs_mm=self.back_artifacts_group_add_yoffs_mm, ) category_icons = self.AddObjectGroupToLayout( 'category_icons', self.back) prestige_group = self.AddObjectPrestigeToLayout() return self.ReturnRank(rank)
def SetFigureAttr(self, attrs_key, attr_key, attr_val): attrs = getattr(self, attrs_key) if self.AcceptFigureAttr(attrs, attr_key, attr_val): attrs[attr_key] = fo.merge_dicts( attrs[attr_key], attr_val) if attr_key in attrs else attr_val