class Exporter(object): def __init__(self): # rest self.gridinfo = GridInfo() self.sim = SimConnection() self.ogre = OgreExporter() def connect(self, base_url, username="", password=""): """ Connect to an opensim instance """ self.gridinfo.connect(base_url, username, password) self.sim.connect(base_url) def test(self): """ Api tests """ print self.gridinfo.getGridInfo()["gridnick"] regions = self.gridinfo.getRegions() for id in regions: region = regions[id] print " *", region["name"], region["x"], region["y"], id # xmlrpc print self.sim.login("caedes", "caedes", "pass") print self.sim.sceneClear("d9d1b302-5049-452d-b176-3a9561189ca4", "cube") print self.sim.sceneUpload("d9d1b302-5049-452d-b176-3a9561189ca4", "cube", "/home/caedes/groupmembers.zip") def export(self, path, pack_name, offset, exportSettings): """ Export the scene to a zipfile. """ b2rexpkg.start() if exportSettings.regenMaterials: reset_uuids(Blender.Material.Get()) if exportSettings.regenObjects: reset_uuids(Blender.Object.Get()) if exportSettings.regenTextures: reset_uuids(Blender.Texture.Get()) if exportSettings.regenMeshes: reset_uuids(Blender.Mesh.Get()) self.ogre.export(path, pack_name, offset) f = open(os.path.join(path, pack_name + ".uuids"), 'w') b2rexpkg.write(f) f.close()
class BaseApplication(object): def __init__(self, title="RealXtend"): self.screen = Screen() self.gridinfo = GridInfo() self.buttons = {} self.settings_visible = False self.exportSettings = ExportSettings() self.initGui(title) self.addStatus("b2rex started") def connect(self, base_url, username="", password=""): """ Connect to an opensim instance """ self.gridinfo.connect(base_url, username, password) #self.sim.connect(base_url) def initGui(self, title): """ Initialize the interface system. """ self.vLayout = VerticalLayout() self.buttonLayout = HorizontalLayout() self.addCallbackButton('Connect', self.buttonLayout, 'Connect to opensim server. Needed if you want to upload worlds directly.') #self.addButton('Export', self.buttonLayout, 'Export to disk') self.addButton('Quit', self.buttonLayout, 'Quit the exporter') self.vLayout.addWidget(self.buttonLayout, 'buttonPanel') self.screen.addWidget(Box(self.vLayout, title), "layout") settingsButton = CheckBox(self.ToggleSettingsAction(self), self.settings_visible, 'Settings', [100, 20], tooltip='Show Settings') self.buttonLayout.addWidget(settingsButton, 'SettingsButton') def addSettingsButton(self, button_name, layout, tooltip=""): """ Create a settings string button. """ val = getattr(self.exportSettings, button_name) self.buttons[button_name] = StringButton(val, self.ChangeSettingAction(self, button_name), button_name+": ", [200, 20], tooltip) layout.addWidget(self.buttons[button_name], 'buttonPanelButton' + button_name) def showSettings(self): """ Create the settings widgets. """ self.settingsLayout = VerticalLayout() self.vLayout.addWidget(self.settingsLayout, 'settingsLayout') self.addSettingsButton('pack', self.settingsLayout, 'name for the main world files') self.addSettingsButton('path', self.settingsLayout, 'path to export to') self.addSettingsButton('server_url', self.settingsLayout, 'server login url') self.addSettingsButton('username', self.settingsLayout, 'server login username') self.addSettingsButton('password', self.settingsLayout, 'server login password') posControls = HorizontalLayout() uuidControls = HorizontalLayout() self.settingsLayout.addWidget(posControls, 'posControls') self.settingsLayout.addWidget(uuidControls, 'uuidControls') posControls.addWidget(NumberView('OffsetX:', self.exportSettings.locX, [100, 20], [Widget.INFINITY, 20], tooltip='Additional offset on the x axis.'), 'locX') posControls.addWidget(NumberView('OffsetY:', self.exportSettings.locY, [100, 20], [Widget.INFINITY, 20], tooltip='Additional offset on the y axis.'), 'locY') posControls.addWidget(NumberView('OffsetZ:', self.exportSettings.locZ, [100, 20], [Widget.INFINITY, 20], tooltip='Additional offset on the z axis.'), 'locZ') for objtype in ['Objects', 'Meshes', 'Materials', 'Textures']: keyName = 'regen' + objtype settingToggle = CheckBox(self.ToggleSettingAction(self, objtype), getattr(self.exportSettings, keyName), 'Regen ' + objtype, [100, 20], tooltip='Regenerate uuids for ' + objtype) uuidControls.addWidget(settingToggle, keyName) def addRegionsPanel(self, regions, griddata): """ Show available regions """ vLayout = VerticalLayout() self.regionLayout = vLayout title = griddata['gridname'] + ' (' + griddata['mode'] + ')' vLayout.addWidget(Label(title), 'scene_key_title') self.screen.addWidget(Box(vLayout, griddata['gridnick']), "layout2") pack = SelectablePack() for key, region in regions.iteritems(): selectable = SelectableRegion(0, region["id"], self, pack) label_text = region["name"] + " (" + str(region["x"]) + "," + str(region["y"]) + ")" vLayout.addWidget(SelectableLabel(selectable, region['name']),'region_'+key) return griddata def onConnectAction(self): """ Connect Action """ base_url = self.exportSettings.server_url self.addStatus("Connecting to " + base_url, IMMEDIATE) self.connect(base_url, self.exportSettings.username, self.exportSettings.password) self.region_uuid = '' self.regionLayout = None try: regions = self.gridinfo.getRegions() griddata = self.gridinfo.getGridInfo() except: self.addStatus("Error: couldnt connect to " + base_url, ERROR) traceback.print_exc() return self.addRegionsPanel(regions, griddata) # create the regions panel self.addStatus("Connected to " + griddata['gridnick']) def toggleSettings(self): """ Toggle the settings widget. """ if self.settings_visible: self.vLayout.removeWidget('settingsLayout') self.settings_visible = False else: self.showSettings() self.settings_visible = True def addCallbackButton(self, button_name, layout, tooltip=""): """ Add a button to the interface. This function prelinks the button to a function in the class, called like "on" + button_name + "Action" """ cb = getattr(self, 'on' + button_name.replace(" ", "") + 'Action') return layout.addWidget(Button(self.CallbackAction(cb), button_name, [100, 20], tooltip), button_name + 'Button') def addButton(self, button_name, layout, tooltip=""): """ Add a button to the interface. This function prelinks the button to an action on this clss. """ action = getattr(self, button_name + 'Action') return layout.addWidget(Button(action(self), button_name, [100, 20], tooltip), button_name + 'Button') def addStatus(self, text, level = OK): """ Add status information. """ self.screen.addWidget(Box(Label(text), 'status'), 'b2rex initialized') if level in [ERROR, IMMEDIATE]: # Force a redraw Blender.Draw.Draw() else: Blender.Draw.Redraw(1) def go(self): """ Start the ogre interface system """ self.screen.activate() class ToggleSettingAction(Action): """ Toggle a boolean setting. """ def __init__(self, app, objtype): self.app = app self.objtype = objtype def execute(self): keyName = 'regen' + self.objtype setattr(self.app.exportSettings, keyName, not getattr(self.app.exportSettings, keyName)) class ChangeSettingAction(Action): """ Change a setting from the application. """ def __init__(self, app, name): self.app = app self.name = name def execute(self): setattr(self.app.exportSettings, self.name, self.app.buttons[self.name].string.val) self.app.exportSettings.save() class ToggleSettingsAction(Action): """ Toggle the settings panel. """ def __init__(self, app): self.app = app def execute(self): self.app.toggleSettings() class CallbackAction(Action): """ Connect to the opensim server. """ def __init__(self, cb): self.cb = cb def execute(self): try: self.cb() except: traceback.print_exc() self.app.addStatus("Error: couldnt rum. Check your settings to see they are ok", ERROR) return False class QuitAction(Action): """ Quit the application. """ def __init__(self, app): self.settings = app.exportSettings def execute(self): import Blender self.settings.save() Blender.Draw.Exit()
class CharacterExporter(object): action_uuids = {'Walk': '6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0', 'CrouchWalk': "47f5f6fb-22e5-ae44-f871-73aaaf4a6022", 'Fly': "aec4610c-757f-bc4e-c092-c6e9caf18daf", "HoverDown": "20f063ea-8306-2562-0b07-5c853b37b31e", "HoverUp": "62c5de58-cb33-5743-3d07-9e4cd4352864", "Hover": "4ae8016b-31b9-03bb-c401-b1ea941db41d", "Run": "05ddbff8-aaa9-92a1-2b74-8fe77a29b445", "Sit": "1a5fe8ac-a804-8a5d-7cbd-56bd83184568", "SitGround": "1c7600d6-661f-b87b-efe2-d7421eb93c86", "Stand": "2408fe9e-df1d-1d7d-f4ff-1384fa7b350f"} def __init__(self): # rest self.gridinfo = GridInfo() self.sim = SimConnection() self.ogre = OgreExporter() self.settings = {} self.actions_map = {} for name in self.action_uuids: self.actions_map[name.lower()] = name def connect(self, base_url): """ Connect to an opensim instance """ self.gridinfo.connect(base_url) print self.sim.connect(base_url) def test(self): """ Api tests """ print self.gridinfo.getGridInfo()["gridnick"] regions = self.gridinfo.getRegions() for id in regions: region = regions[id] print " *", region["name"], region["x"], region["y"], id # xmlrpc print self.sim.login("caedes", "caedes", "pass") print self.sim.sceneClear("d9d1b302-5049-452d-b176-3a9561189ca4", "cube") print self.sim.sceneUpload("d9d1b302-5049-452d-b176-3a9561189ca4", "cube", "/home/caedes/groupmembers.zip") def writeAnimation(self, f, id, name, internal_name): """ Write an animation to the avatar file """ f.write(indent(1)+'<animation name="'+name+'" ') f.write('id="'+id+'" internal_name="'+internal_name+'" ') f.write('looped="1" speedfactor="1.0" ') if 'walk' in name.lower() or 'run' in name.lower(): f.write('usevelocity="1" ') f.write('fadein="0.25" ') f.write('fadeout="0.25" />\n') def writeAnimations(self, f): """ Write all animations to the avatar file """ actions = Blender.Armature.NLA.GetActions() for name, action in actions.items(): if action.name.lower() in self.actions_map: action_name = self.actions_map[action.name.lower()] action_uuid = self.action_uuids[action_name] else: action_name = action.name action_uuid = 'not-needed' # has to exist according to manual self.writeAnimation(f, action_uuid, action_name, action.name) def writeProperty(self, f, name, value): """ Write an avatar property """ f.write(indent(1) + '<property name="'+name+'" value="'+value+'" />') def writeProperties(self, f): """ Write all properties """ if self.settings['MovementSpeed']: self.writeProperty(f, 'MovementSpeed', self.settings['MovementSpeed']) # needed?? # automatic ground offset: # bone which should be adjusted to align with the ground if self.settings['basebone']: self.writeProperty(f, 'basebone', self.settings['basebone']) # avatar skeleton's hierarchy root if self.settings['rootbone']: self.writeProperty(f, 'rootbone', self.settings['rootbone']) # finetuning if self.settings['baseoffset']: self.writeProperty(f, 'baseoffset', self.settings['baseoffset']) return # parametrized head turning: if self.settings['headbone']: self.writeProperty(f, 'headbone', '') if self.settings['neckbone']: self.writeProperty(f, 'neckbone', '') if self.settings['torsobone']: self.writeProperty(f, 'torsobone', '') if self.settings['headboneaxis']: self.writeProperty(f, 'headboneaxis', '') # optional if self.settings['neckboneaxis']: self.writeProperty(f, 'neckboneaxis', '') # optional if self.settings['torsoboneaxis']: self.writeProperty(f, 'torsoboneaxis', '') # optional def writeAvatarFile(self, f): """ Write an avatar file for the selected mesh. """ f.write('<?xml version="1.0" encoding="utf-8" ?>\n') f.write('<avatar>\n') f.write(indent(1)+'<version>0.2</version>\n') f.write(indent(1)+'<base name="default_female" mesh="'+self.settings['mesh_file']+'" />\n') f.write(indent(1)+'<skeleton name="'+self.settings['skeleton_file']+'" />\n') #f.write(indent(1)+'<material name="male/Body" />\n') #f.write(indent(1)+'<material name="male/Face" />\n') first_face_image = self.getMesh().getData(0, True).faces[0].image if first_face_image: texture_name = os.path.basename(first_face_image.getFilename()) else: texture_name = '' f.write(indent(1)+'<texture_body name="'+texture_name+'" />\n') #f.write(indent(1)+'<texture_face name="" />\n') f.write(indent(1)+'<appearance height="1.800000" weight="1" />\n') f.write(indent(1)+'<transformation position="%s" rotation="%s" \ scale="%s" />\n' % (self.settings['translation'], self.settings['rotation'], self.settings['scale'])) self.writeProperties(f) self.writeAnimations(f) f.write('</avatar>') def createAvatarFile(self, path): """ Create the avatar file at the specified location. """ character_name = self.settings['character_name'] f = open(os.path.join(path, character_name + '.xml'), 'w') self.writeAvatarFile(f) f.close() def getMesh(self): """ Get the selected mesh """ selected = Blender.Object.GetSelected() for sel in selected: if sel.getType() == 'Mesh': return sel def getArmature(self): """ Get the selected object's armature """ bObject = self.getMesh() return GetArmatureObject(bObject) def parseSettings(self, exportSettings): """ Decide settings for export """ mesh = self.getMesh() name = mesh.getData(0, True).name armature_name = self.getArmature().name self.settings['character_name'] = mesh.name self.settings['mesh_file'] = name + '.mesh' self.settings['skeleton_file'] = armature_name + '.skeleton' self.settings.update(exportSettings.getDict()) def setupAnimations(self): """ Setup animations on the ogre exporter. """ ogreSelection = self.ogre.meshapp.selectedObjectManager ogreSelection.updateSelection() armatureManager = ogreSelection.getArmatureAnimationProxyManager(self.getMesh().getData(True)) armatureManager.removeProxies() # cleanup armatureManager.animationProxyKeyList = [] # shouldnt be needed armatureManager.update() actionList = armatureManager.getActions() for action in actionList: bAction = action.bAction anim = ArmatureAnimationProxy(armatureManager, action, action.getName(), action.getFirstFrame(), action.getLastFrame()) armatureManager.addProxy(anim) armatureManager.savePackageSettings() def export(self, path, pack_name, offset, exportSettings): """ Export the character and its avatar file. """ b2rexpkg.start() self.setupAnimations() self.ogre.export(path, pack_name, offset) self.parseSettings(exportSettings) self.createAvatarFile(path)