# -*- test-case-name: mv3d.test.util.test_modifier -*- # Copyright (C) 2008-2012 Mortal Coil Games # See LICENSE for details. """ """ from zope.interface import Interface, implements from twisted.internet import defer from twisted.internet.defer import inlineCallbacks from twisted.spread import pb from mv3d.net.security import requirePermissions from mv3d.util.classgen import ClassGenerator from mv3d.util.persist import Text, Stringable, List, MapAttribute class IModifiable(Interface): """ Specifies a means of getting modifier interfaces """ def getModifiers(type=None, conductor=None): #@NoSelf """ Return the modifiers for a given type, or the default type if not specified. """ def addModifier(type, assetid): #@NoSelf """ Add a modifier to the list for the given type of modification interface """ class Modifiable(object): """ A simple implementation of an IModifiable. ** note ** classModifiers should be defined when defining the class and should not change. They will not be persisted and are assumed to be integral to the class. """ implements(IModifiable) modifiers = MapAttribute(Text(), List(Stringable(ClassGenerator))) classModifiers = {} defaultModifierType = Text(default="", autoSave=True, partialSave=True) allowedState = ["modifiers", "defaultModifierType"] def __init__(self): self.modifiers = {} def getModifiers(self, type=None, conductor=None): """ Return the modifiers for a given type, or the default type if not specified """ if self.modifiers is None: self.modifiers = dict() type = type or self.defaultModifierType mods = self.modifiers.get(type, []) + self.classModifiers.get( type, []) d = [] from mv3d.util.conductor import IConductor, findParent from mv3d.util.iservice import IAssetClient conductor = conductor or findParent(self, IConductor) assetService = conductor.getLocalService( IAssetClient) for mod in mods: mod.assetService = assetService d.append(defer.maybeDeferred(mod.construct, self)) return defer.gatherResults(d) @requirePermissions("modify") def view_getModifiers(self, type=None): """ Return the modifiers for a given type, or the default type if not specified """ return self.getModifiers(type) def addModifier(self, type, modifier): """ Add a modifier to the list for the given type of modification interface Modifier should be a ClassGenerator """ if self.modifiers is None: self.modifiers = dict() if not self.modifiers.has_key(type): self.modifiers[type] = [modifier] if hasattr(self, "save"): self.queueSave(selectAttributes=["modifiers"]) return self.modifiers[type].append(modifier) if hasattr(self, "save"): self.queueSave(selectAttributes=["modifiers"]) class IModifier(Interface): """ A method of modifying another class """ def getMinimumPermissions(self): """ Returns a set of minimum permissions to access this modifier. This should be a list of permission names and if any one of them is valid for the connecting user, the modifier will be accessible. """ class BoxCreator(pb.Viewable): """ A sample modifier that creates boxes """ implements(IModifier) name = "Create Box" def __init__(self, parent): self.parent = parent @inlineCallbacks def view_createBox(self, client, position): """ Just create a box """ a = yield self.parent.getItem((0, 0)) r = a.realm o = yield a.newObject(ClassGenerator( "mv3d.server.model.physical.PhysicalBox")) o.create(r) o.setName(u"Box%s" % str(position)) o.setPosition(position) o.addVisualAsset((0, 6)) o.body.vobs[0].setScale((0.05, 0.05, 0.05)) a.takeOut(o.getID()) a.contain(o.getID()) def view_getUI(self, client): """ Return the class generator for the UI component to this. """ return ClassGenerator( "mv3d.client.ui.editor.BoxCreatorView")