Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/BlenderExport/ogremeshesexporter.py @ 45

Last change on this file since 45 was 6, checked in by anonymous, 17 years ago

=…

File size: 66.7 KB
Line 
1#!BPY
2
3# """
4# Name: 'OGRE Meshes'
5# Blender: 242
6# Group: 'Export'
7# Tooltip: 'Export meshes and animations to OGRE'
8# """
9
10# Copyright (C) 2005  Michael Reimpell
11#
12# This library is free software; you can redistribute it and/or
13# modify it under the terms of the GNU Lesser General Public
14# License as published by the Free Software Foundation; either
15# version 2.1 of the License, or (at your option) any later version.
16#
17# This library is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20# Lesser General Public License for more details.
21#
22# You should have received a copy of the GNU Lesser General Public
23# License along with this library; if not, write to the Free Software
24# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25
26__author__ = 'Michael Reimpell'
27__version__ = 'n/a'
28__url__ = ["Help, http://www.ogre3d.org/phpBB2/search.php", "Ogre3D, http://www.ogre3d.org"]
29__bpydoc__ = "Please see the external documentation that comes with the script."
30
31# epydoc doc format
32__docformat__ = "javadoc en"
33
34import sys
35
36try:
37        import Blender
38except ImportError:
39        sys.exit("Please run this script from within Blender!\nSee the script's manual for more information.")
40
41class OgrePackageImporter:
42                """Imports ogrepkg.
43               
44                   If ogrepkg fails to load, the user can be requested to
45                   point to the parent directory of the 'ogrepkg' directory.
46                   The PYTHONPATH is then set accordingly and the package
47                   location is stored in Blender's registry.
48                   
49                   Requires modules sys and Blender.
50                """
51                def __init__(self, packagePath=None):
52                        """Constructor.
53                       
54                           @param packagePath Optional packagePath to include into PYTHONPATH.
55                        """
56                        # import sys
57                        self.packagePath = packagePath
58                        return
59                def importPackage(self):
60                        """Tries to import ogrepkg.
61                       
62                           Tries to import ogrepkg with the PYTHONPATH based
63                           on the optional constructor argument and the contents
64                           of Blender's registry entry for "OgrePackage".
65                           Raises an ImportError on failure.
66                        """
67                        if not self.packagePath:
68                                # load registry if packagePath is not given to constructor.
69                                self._loadRegistry()
70                        if self.packagePath:
71                                # append patckagePath to PYTHONPATH
72                                sys.path.append(self.packagePath)
73                        # try importing ogrepkg
74                        import ogrepkg #raises ImportError on failure
75                        return
76                def requestPackagePath(self):
77                        """Requests path to the ogrepkg package from the user.
78                        """
79                        # gui
80                        path = Blender.Get('uscriptsdir')
81                        if not path:
82                                path = Blender.Get('scriptsdir')
83                        if not path:
84                                path = Blender.Get('filename')
85                        if not path:
86                                path = ''
87                        self.pathButton = Blender.Draw.Create(path)
88                        self.importSuccess = False
89                        Blender.Draw.Register(self._draw, self._eventHandler, self._buttonHandler)
90                        return
91                def _loadRegistry(self):
92                        registryDict = Blender.Registry.GetKey('OgrePackage', True)
93                        if registryDict:
94                                if registryDict.has_key('packagePath'):
95                                        if registryDict['packagePath']:
96                                                self.packagePath = registryDict['packagePath']
97                        return
98                def _saveRegistry(self):
99                        if self.packagePath:
100                                registryDict = Blender.Registry.GetKey('OgrePackage', True)
101                                if registryDict is None:
102                                        registryDict =  {}
103                                registryDict['packagePath'] = self.packagePath
104                                Blender.Registry.SetKey('OgrePackage', registryDict, True)
105                        return
106                def _checkPath(self, path):
107                        # Sets self.pathButton, self.importSuccess
108                        dirName = Blender.sys.dirname(path)
109                        if Blender.sys.exists(dirName):
110                                self.pathButton = Blender.Draw.Create(dirName)
111                                sys.path.append(dirName)
112                                try:
113                                        import ogrepkg
114                                except ImportError:
115                                        self.importSuccess = False
116                                else:
117                                        self.importSuccess = True
118                                sys.path.remove(dirName)
119                                Blender.Draw.Redraw(1)
120                        return
121                def _pathSelector(self, filename):
122                        self._checkPath(filename)
123                        return
124                def _draw(self):
125                        # clear background
126                        theme = Blender.Window.Theme.Get()[0]
127                        bgColor = [color/255.0 for color in theme.get('buts').back]
128                        Blender.BGL.glClearColor(*bgColor)
129                        Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
130                        size = list(Blender.Window.GetAreaSize())
131                        if size[0] < 350:
132                                size[0] = 350
133                        if size[1] < 165:
134                                size[1] = 165
135                        # 10 px border
136                        rect = [10, 10, size[0]-11, size[1]-11]
137                        # text color
138                        Blender.BGL.glColor4ub(*theme.get('text').text)
139                        # title "Settings", large, bold, underlined
140                        Blender.BGL.glRasterPos2i(rect[0], rect[3] - 9)
141                        Blender.Draw.Text("Settings", 'large')
142                        Blender.BGL.glRasterPos2i(rect[0] + 1, rect[3] - 9)
143                        Blender.Draw.Text("Settings", 'large')
144                        # 14 px font size, 2 px line spacing, 5 px shift to baseline
145                        rect[3] -= 16
146                        # 2 px underline
147                        Blender.BGL.glRecti(rect[0], \
148                                rect[3]-2, \
149                                rect[0] + Blender.Draw.GetStringWidth("Settings", 'large') + 1, \
150                                rect[3])
151                        # 10 px skip
152                        rect[3] -= 12
153                        # message 12 px font size, 2 px line spacing, 4 px shift to baseline
154                        if not self.importSuccess:
155                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 8)
156                                Blender.Draw.Text("The script can't find the 'ogrepkg' package!")
157                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 22)
158                                Blender.Draw.Text("In order to run the script, please provide the path to the")
159                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 36)
160                                Blender.Draw.Text("directory that contains the 'ogrepkg' directory.")
161                        else:
162                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 8)
163                                Blender.Draw.Text("Package 'ogrepkg' found!")
164                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 22)
165                                Blender.Draw.Text("Click 'Ok' to store the package location permanently")
166                                Blender.BGL.glRasterPos2i(rect[0], rect[3] - 36)
167                                Blender.Draw.Text("and run the script again.")
168                                # You can cange the location any time using Blender's script registry editor.
169                        # 10 px skip
170                        rect[3] -= 52
171                        # path string
172                        self.pathButton = Blender.Draw.String("Path: ", 101, rect[0], rect[3] - 21, rect[2] - rect[1] - 71, 20, self.pathButton.val, 255, "Package location")
173                        # select button
174                        Blender.Draw.Button("Select", 102, rect[2] - 70, rect[3] - 21, 70, 20, "Select package location")
175                        rect[3] -= 31
176                        # Ok button
177                        if self.importSuccess:
178                                Blender.Draw.Button("Ok", 103, rect[0], rect[1], 100, 30, "Quit, accepting package location")
179                        # Abort button
180                        Blender.Draw.Button("Abort", 104, rect[2] - 101, rect[1], 100, 30, "Quit, discarding package location")
181                        return
182                def _eventHandler(self, event, value):
183                        return
184                def _buttonHandler(self, event):
185                        # 101: PathString
186                        # 102: Select
187                        # 103: Ok
188                        # 104: Abort
189                        if (event == 101): # PathString
190                                self._checkPath(self.pathButton.val)
191                        elif (event == 102): # Select
192                                Blender.Window.FileSelector(self._pathSelector, "Select Package Location", self.pathButton.val)
193                        elif (event ==  103): # Ok
194                                # assign packagePath
195                                self.packagePath = self.pathButton.val
196                                self._saveRegistry()
197                                Blender.Draw.Exit()
198                        elif(event == 104): # Abort
199                                Blender.Draw.Exit()
200                        return
201
202try:
203        import pickle
204except ImportError:
205        choice = Blender.Draw.PupMenu("Error: Python installation not found!%t" \
206                + "|This script needs a full Python %d.%d installation." % tuple(sys.version_info[0:2]) \
207                + "|Please refer to the Blender website how to install Python for Blender.|%l" \
208                + "|www.blender.org" \
209                + "|www.python.org")
210        try:
211                import webbrowser
212        except ImportError:
213                pass
214        else:
215                if (choice == 4):
216                        webbrowser.open("www.blender.org", 1, 1)
217                elif (choice == 5):
218                        webbrowser.open("www.python.org", 1 , 1)
219else:
220        # force reload of modules
221        for name in sys.modules.keys()[:]:
222                if name[0:7] == 'ogrepkg':
223                        del sys.modules[name]
224        opi = OgrePackageImporter()
225        try:
226                opi.importPackage() # import ogrepkg
227        except ImportError:
228                opi.requestPackagePath()
229        else:
230                import webbrowser
231                # ogrepkg successfully imported
232                from ogrepkg import *
233                from ogrepkg.base import *
234                from ogrepkg.gui import *
235                from ogrepkg.meshexport import *
236                from ogrepkg.materialexport import *
237               
238                PackageSettings.getSingleton().load()
239                # modules stay in memory, therefore update settings and clear log manually
240                ##Log.getSingleton().clear()
241               
242                class PreferencesScreen(Screen):
243                        def __init__(self):
244                                Screen.__init__(self)
245                                # none or converter
246                                self.converter = ValueModel(OgreXMLConverter.getSingleton().getConverter())
247                                # always valid string '' if no additional arguments
248                                self.converterArgs = ValueModel(OgreXMLConverter.getSingleton().getAdditionalArguments())
249                                frame = OgreFrame(self, "Preferences")
250                                layout = VerticalLayout(frame)
251                                cbox = Box(layout, L("OgreXMLConverter"), 0 , 10)
252                                cbLayout = VerticalLayout(cbox)
253                                # converter location
254                                self.locationView = PreferencesScreen.ConverterLocationView(cbLayout, self.converter)
255                                # additional arguments
256                                Spacer(cbLayout, Size([0, 20]))
257                                LabelView(cbLayout, L("Additional arguments:"))
258                                StringView(cbLayout, Size([Size.INFINITY, 20], [200, 20]), self.converterArgs, T("Arguments: "), \
259                                                T("Additional arguments in call to OgreXMLConverter."))
260                                Spacer(layout, Size([0, Size.INFINITY], [0, 0]))
261                                # button row
262                                Spacer(layout, Size([0, 10]))
263                                bhLayout = HorizontalLayout(layout)
264                                bSize = Size([Size.INFINITY, 30], [Blender.Draw.GetStringWidth('Preferences')+10, 30])
265                                Button(bhLayout, bSize, PreferencesScreen.OkAction(self), T("Ok"), \
266                                        T("Apply and save settings."))
267                                Spacer(bhLayout, bSize)
268                                Spacer(bhLayout, bSize)
269                                Button(bhLayout, bSize, PreferencesScreen.CancelAction(self), T("Cancel"), \
270                                        T("Restore old settings."))
271                                return
272                        def activate(self):
273                                self.converter.setValue(OgreXMLConverter.getSingleton().getConverter())
274                                self.converterArgs.setValue(OgreXMLConverter.getSingleton().getAdditionalArguments())
275                                self.locationView.activate()
276                                Screen.activate(self)
277                                return
278                        def applySettings(self):
279                                """Apply settings.
280                                """
281                                OgreXMLConverter.getSingleton().setConverter(self.converter.getValue())
282                                OgreXMLConverter.getSingleton().setAdditionalArguments(self.converterArgs.getValue())
283                                return
284                        def discardSettings(self):
285                                self.locationView.discardSettings()
286                                return
287                        class ConverterLocationView(View):
288                                def __init__(self, layout, converterModel):
289                                        self.converter = converterModel
290                                        # "Location:"
291                                        LabelView(layout, L("Location:"))
292                                        # [  Auto  ] [ Manual ]
293                                        ctg = ToggleGroup()
294                                        self.cAutoToggle = ToggleModel(True)
295                                        self.cManualToggle = ToggleModel(False)
296                                        ctg.addToggle(self.cAutoToggle)
297                                        ctg.addToggle(self.cManualToggle)
298                                        cthLayout = HorizontalLayout(layout)
299                                        ToggleView(cthLayout, Size([Size.INFINITY, 20], [100, 20]), self.cAutoToggle, T("Auto"), \
300                                                T("Use OgreXMLConverter in Path."))
301                                        ToggleView(cthLayout, Size([Size.INFINITY, 20], [100, 20]), self.cManualToggle, T("Manual"), \
302                                                T("Specifiy OgreXMLConverter location manually."))
303                                        # save choosen path temporarily,
304                                        # so clicking on Auto and back on Manual does not clear it
305                                        self.lastPath = ValueModel('')
306                                        # Nothing or [Converter: ............ ][select]
307                                        self.alternatives = AlternativesLayout(layout)
308                                        self.altAuto = Spacer(self.alternatives, Size([0, 20]))
309                                        self.altManual = HorizontalLayout(self.alternatives)
310                                        StringView(self.altManual, Size([Size.INFINITY, 20], [200, 20]), \
311                                                PreferencesScreen.ConverterLocationView.ConverterAdapter(self.converter), T("Converter: "), \
312                                                T("OgreXMLConverter executable."))
313                                        Button(self.altManual, Size([70, 20]), PreferencesScreen.ConverterLocationView.SelectAction(self.converter), \
314                                                T("Select"), T("Select the converter location."))
315                                        self.cAutoToggle.addView(self)
316                                        self.activate()                                 
317                                        return
318                                def activate(self):
319                                        """Reset to saved configuration.
320                                        """
321                                        if (self.converter.getValue() == None):
322                                                # restore last path
323                                                self.converter.setValue(self.lastPath.getValue())
324                                                # select auto (sets converter back to "None")
325                                                self.cAutoToggle.setValue(True)
326                                                self.alternatives.setCurrent(self.altAuto)
327                                        else:
328                                                self.cManualToggle.setValue(True)
329                                                self.alternatives.setCurrent(self.altManual)                                           
330                                        return
331                                def update(self):
332                                        """Called by cAutoToggle.
333                                        """
334                                        if self.cAutoToggle.getValue():
335                                                self.alternatives.setCurrent(self.altAuto)
336                                                self.lastPath.setValue(self.converter.getValue())
337                                                self.converter.setValue(None)
338                                        else:
339                                                self.converter.setValue(self.lastPath.getValue())
340                                                self.alternatives.setCurrent(self.altManual)
341                                        return
342                                def discardSettings(self):
343                                        self.lastPath.setValue(self.converter.getValue())
344                                        return
345                                class ConverterAdapter(ValueModel):
346                                        def __init__(self, model):
347                                                Model.__init__(self)
348                                                self.model = model
349                                                return
350                                        def setValue(self, value):
351                                                self.model.setValue(value)
352                                                self._notify()
353                                                return
354                                        def getValue(self):
355                                                value = self.model.getValue()
356                                                if value is None:
357                                                        value = ''
358                                                return value
359                                class SelectAction(Action):
360                                        def __init__(self, converterModel):
361                                                self.converter = converterModel
362                                                return
363                                        def execute(self):
364                                                if( self.converter.getValue() == None):
365                                                        self.converter.setValue('')
366                                                Blender.Window.FileSelector(self.converter.setValue, "Select Converter", self.converter.getValue())
367                                                return
368                        class OkAction(Action):
369                                def __init__(self, screen):
370                                        self.screen = screen
371                                        return
372                                def execute(self):
373                                        self.screen.applySettings()
374                                        self.screen.deactivate()
375                                        return
376                        class CancelAction(Action):
377                                def __init__(self, screen):
378                                        self.screen = screen
379                                        return
380                                def execute(self):
381                                        self.screen.discardSettings()
382                                        self.screen.deactivate()
383                                        return
384               
385                class ArmatureAction:
386                        """Wrapper for Blender actions.
387                        """
388                        def __init__(self, bAction):
389                                self.bAction = bAction
390                                self.firstFrame = None
391                                self.lastFrame = None
392                                self.animationProxyList = []
393                                self.update()
394                        def invalidate(self):
395                                """Invalidate all ArmatureAnimationProxys as Blender actions does no longer exist or affect the mesh.
396                               
397                                   Called by ActionManager. Calls ArmatureAnimationProxy.invalidate() on all attached
398                                   ArmatureAnimationProxies.
399                                """
400                                # copy list as proxy.invalidate() calls detachAnimationProxy(proxy)
401                                for proxy in self.animationProxyList[:]:
402                                        proxy.invalidate()
403                                return
404                        def attachAnimationProxy(self, proxy):
405                                """Attaches ArmatureAnimationProxy to this action.
406                               
407                                   All attached actions are notified to invalidate themselves if this
408                                   ArmatureAction gets invalidated.
409                                   
410                                   This method is called by the ArmatureAnimationProxy constructor.
411                                   @see ArmatureAnimationProxy
412                                """
413                                self.animationProxyList.append(proxy)
414                                return
415                        def detachAnimationProxy(self, proxy):
416                                """Detaches ArmatureAnimationProxy from this action.
417                               
418                                   The proxy is removed from the list of attached animations and thus no
419                                   longer invalidated if this ArmatureAction gets invalidated.
420                                   
421                                   This method is called by the ArmatureAnimationProxyManager.removeProxy() method.
422                               
423                                   @see attachAnimationProxy()
424                                   @see ArmatureAnimationProxyManager
425                                """
426                                if proxy in self.animationProxyList:
427                                        self.animationProxyList.remove(proxy)
428                                return
429                        def getName(self):
430                                return self.bAction.getName()
431                        def getFirstFrame(self):
432                                return self.firstFrame
433                        def getLastFrame(self):
434                                return self.lastFrame
435                        def getBlenderAction(self):
436                                return self.bAction
437                        def hasEffectOn(self, bArmature):
438                                hasEffect = False
439                                actionIpoDict = self.bAction.getAllChannelIpos()
440                                armatureBoneIter = iter(bArmature.bones.keys())
441                                try:
442                                        while not hasEffect:
443                                                boneName = armatureBoneIter.next()
444                                                if actionIpoDict.has_key(boneName):
445                                                        # TODO: check for curves
446                                                        hasEffect = True
447                                except StopIteration:
448                                        pass
449                                return hasEffect
450                        def update(self):
451                                """Updates firstKeyFrame and lastKeyFrame considering the current IpoCurves.
452                                """
453                                firstKeyFrame = None
454                                lastKeyFrame = None
455                                ipoDict = self.bAction.getAllChannelIpos()
456                                if ipoDict is not None:
457                                        # check all bone Ipos
458                                        # ipoDict[boneName] = Blender.Ipo
459                                        for ipo in ipoDict.values():
460                                                if ipo is not None:
461                                                        # check all IpoCurves
462                                                        for ipoCurve in ipo.getCurves():
463                                                                # check first and last keyframe
464                                                                for bezTriple in ipoCurve.getPoints():
465                                                                        iFrame = bezTriple.getPoints()[0]
466                                                                        if ((iFrame < firstKeyFrame) or (firstKeyFrame is None)):
467                                                                                firstKeyFrame = iFrame
468                                                                        if ((iFrame > lastKeyFrame) or (lastKeyFrame is None)):
469                                                                                lastKeyFrame = iFrame
470                                if firstKeyFrame == None:
471                                        firstKeyFrame = 1
472                                if lastKeyFrame == None:
473                                        lastKeyFrame = 1
474                                self.firstFrame = firstKeyFrame
475                                self.lastFrame = lastKeyFrame
476                                return
477               
478                class ActionManager:
479                        """Manages Blender actions.
480                        """
481                        def __init__(self):
482                                # key: name, value: ArmatureAction
483                                self.armatureActionDict = {}
484                                self.update()
485                                return
486                        def update(self):
487                                """Synchronizes with Blender.
488                               
489                                   Updates available actions and default keyframe ranges.
490                                   Invalidates actions that are no longer available.
491                                   
492                                   update() calls Armature.Action.invalidate(), which in turn calls
493                                   ArmatureAnimationProxy.invalidate(), which in turn calls
494                                   ArmatureAnimationProxyMangaer.removeProxy().
495                                """
496                                # popultate armatureActionDict
497                                # get dictionary (name, Blender Action) of valid blender actions
498                                bActionDict = Blender.Armature.NLA.GetActions()
499                                #TODO: ?Check for curve and beztriple?
500                                # invalidate and remove deleted actions
501                                for actionName in [name for name in self.armatureActionDict.keys() if name not in bActionDict.keys()]:
502                                        self.armatureActionDict[actionName].invalidate()
503                                        del self.armatureActionDict[actionName]
504                                # update remaining actions
505                                for action in self.armatureActionDict.values():
506                                        action.update()
507                                # create new actions
508                                for bAction in [action for (name, action) in bActionDict.iteritems() if name not in self.armatureActionDict.keys()]:
509                                        self.armatureActionDict[bAction.getName()] = ArmatureAction(bAction)
510                                return
511                        def getAction(self, name):
512                                """Returns ArmatureAction for Blender action with given name.
513                                """
514                                action = None
515                                if name in self.armatureActionDict.keys():
516                                        action = self.armatureActionDict[name]
517                                return action
518                        def getActions(self, bObject):
519                                """Returns list of actions that have effect on the given Blender mesh object.
520                               
521                                   If the mesh is linked to an action that has an effect on the meshes armature,
522                                   this action is the first element of the returned action list.
523                                   
524                                   @param bObject Blender mesh object.
525                                   @return list of ArmatureActions that have an effect on the given mesh object.
526                                """
527                                actionList = []
528                                # get available actions
529                                parent = GetArmatureObject(bObject)
530                                if (parent is not None):
531                                        actionList = [action for action in self.armatureActionDict.values() if action.hasEffectOn(parent.getData())]
532                                # move linked action to first position in returned list
533                                bAction = bObject.getAction()
534                                if bAction is not None:
535                                        # linked
536                                        if self.armatureActionDict.has_key(bAction.getName()):
537                                                # valid
538                                                linkedAction = self.armatureActionDict[bAction.getName()]
539                                                if linkedAction in actionList:
540                                                        # has effect on mesh, move to first position in list
541                                                        actionList.remove(linkedAction)
542                                                        actionList.insert(0, linkedAction)
543                                return actionList
544               
545                class AnimationProxy(Model, View):
546                        """Base class that represents an animation.
547                        """
548                        def __init__(self, name='', startFrame=1, endFrame=1):
549                                Model.__init__(self)
550                                # Model
551                                self.nameModel = ValueModel(name)
552                                self.nameModel.addView(self)
553                                self.startFrameModel = BoundedValueModel(1, 30000, startFrame)
554                                self.startFrameModel.addView(self)
555                                self.endFrameModel = BoundedValueModel(1, 30000, endFrame)
556                                self.endFrameModel.addView(self)
557                                return 
558                        def getName(self):
559                                return self.nameModel.getValue()
560                        def getStartFrame(self):
561                                return self.startFrameModel.getValue()
562                        def getEndFrame(self):
563                                return self.endFrameModel.getValue()
564                        def update(self):
565                                self._notify()
566                                return
567                        def toAnimation(self):
568                                """Returns a corresponding animation.
569                                """
570                                raise NotImplementedError
571                                return         
572               
573                class PoseAnimationProxy(AnimationProxy):
574                        def toAnimation(self):
575                                return PoseAnimation(self.nameModel.getValue(), self.startFrameModel.getValue(), self.endFrameModel.getValue())
576                       
577                class MorphAnimationProxy(AnimationProxy):
578                        def toAnimation(self):
579                                return MorphAnimation(self.nameModel.getValue(), self.startFrameModel.getValue(), self.endFrameModel.getValue())
580               
581                class AnimationProxyView(HorizontalLayout, View):
582                        def __init__(self, parent, model, deleteAction):
583                                HorizontalLayout.__init__(self, parent)
584                                View.__init__(self, model)
585                                NumberView(self, Size([100, 20]), self.model.startFrameModel, T("Start: "), T("Start frame"))
586                                NumberView(self, Size([100, 20]), self.model.endFrameModel, T("End: "), T("End frame"))
587                                StringView(self, Size([Size.INFINITY, 20], [80, 20]), self.model.nameModel, tooltip=T("Animation name in Ogre3D"))
588                                Button(self, Size([60, 20]), deleteAction, T("Delete"), T("Delete animation from export"))
589                                return
590               
591                class ArmatureAnimationProxy(AnimationProxy):
592                        """Represents an ArmatureAnimation.
593                        """
594                        def __init__(self, manager, action=None, name='', startFrame=-1, endFrame=-1):
595                                """Constructor.
596                               
597                                   @param manager ArmatureAnimationProxyManager
598                                   @param action Armature action. If <code>None</code> the default action is used.
599                                                 In this case, the manager must provide at least one action.
600                                   @param name Animation name. If an empty string is passed, the name is set to
601                                               the name of the action.
602                                   @param startFrame Start frame of animation. If set to -1, it is set to the
603                                                     first keyframe for the action .
604                                   @param endFrame End frame of animation. If set to -1, it is set to the last
605                                                   keyframe for the action.
606                                """
607                                self.manager = manager
608                                # action
609                                if action is None:
610                                        self.actionModel = ArmatureAnimationProxy.ActionValueModel(self, self.manager.getActions()[0])
611                                else:
612                                        self.actionModel = ArmatureAnimationProxy.ActionValueModel(self, action)
613                                self.actionModel.addView(self)
614                                if (name == ''):
615                                        name = self.actionModel.getValue().getName()
616                                if (startFrame == -1):
617                                        startFrame = self.actionModel.getValue().getFirstFrame()
618                                if (endFrame == -1):
619                                        endFrame = self.actionModel.getValue().getLastFrame()
620                                AnimationProxy.__init__(self, name, startFrame, endFrame)
621                                return
622                        def invalidate(self):
623                                """Invalidate animation as action does no longer exist or affect the mesh.
624                               
625                                   Called by ArmatureAction. It invalidates itself by calling
626                                   ArmatureAnimationProxyManager.removeProxy().
627                                """
628                                self.manager.removeProxy(self.manager.getKey(proxy))
629                                return
630                        def getAction(self):
631                                return self.actionModel.getValue()
632                        def setAction(self, action):
633                                self.actionModel.setValue(action)
634                                return
635                        def getActionChoices(self):
636                                return self.manager.getActions()
637                        def toAnimation(self):
638                                """Returns the corresponding armature animation.
639                                """
640                                return ArmatureAnimation(self.actionModel.getValue().getBlenderAction(), \
641                                        self.nameModel.getValue(), self.startFrameModel.getValue(), self.endFrameModel.getValue())
642                        class ActionValueModel(ValueModel):
643                                def __init__(self, armatureAnimationProxy, armatureAction):
644                                        """Constructor.
645                                       
646                                           Attaches ArmatureAnimationProxy to ArmatureAction.
647                                        """
648                                        Model.__init__(self)
649                                        self.proxy = armatureAnimationProxy
650                                        # do not call setValue() in constructor as it relies on other proxy models
651                                        # and it doesn't have a view yet.
652                                        self.value = armatureAction
653                                        self.value.attachAnimationProxy(self.proxy)
654                                        return
655                                def setValue(self, value):
656                                        """Set to new action.
657                                       
658                                           Detaches proxy on old action and attaches proxy on new action.
659                                        """
660                                        if (value != self.value):
661                                                self.value.detachAnimationProxy(self.proxy)
662                                                value.attachAnimationProxy(self.proxy)
663                                                ValueModel.setValue(self, value)
664                                                # reset animation properties to action's default.
665                                                self.proxy.nameModel.setValue(value.getName())
666                                                self.proxy.startFrameModel.setValue(value.getFirstFrame())
667                                                self.proxy.endFrameModel.setValue(value.getLastFrame())
668                                        return
669               
670                class ArmatureAnimationProxyView(HorizontalLayout, View):
671                        def __init__(self, parent, model, deleteAction):
672                                HorizontalLayout.__init__(self, parent)
673                                View.__init__(self, model)
674                                # action menu
675                                self.menu = Menu(self, Size([100, 20]), T("Blender Action"))
676                                NumberView(self, Size([100, 20]), self.model.startFrameModel, T("Start: "), T("Start frame"))
677                                NumberView(self, Size([100, 20]), self.model.endFrameModel, T("End: "), T("End frame"))
678                                StringView(self, Size([Size.INFINITY, 20], [80, 20]), self.model.nameModel, tooltip=T("Animation name in Ogre3D"))
679                                Button(self, Size([60, 20]), deleteAction, T("Delete"), T("Delete animation from export"))
680                                self.update()
681                                return
682                        def update(self):
683                                # rebuild action menu
684                                self.menu.removeAll()
685                                self.menu.appendItem(MenuTitle("Action"))
686                                # current available actions
687                                choices = self.model.getActionChoices()
688                                current = self.model.getAction()
689                                for action in choices:
690                                        if action == current:
691                                                isSelected = True
692                                        else:
693                                                isSelected = False
694                                        self.menu.appendItem(MenuItem(action.getName(), \
695                                                ArmatureAnimationProxyView.SelectAction(self, action)), isSelected)
696                                return
697                        class SelectAction(Action):
698                                def __init__(self, view, action):
699                                        self.view = view
700                                        self.action = action
701                                        return
702                                def execute(self):
703                                        self.view.model.setAction(self.action)
704                                        return
705                       
706                class AnimationProxyManager(Model):
707                        """Base class for managing animations of a given Blender mesh object.
708                        """
709                        def __init__(self, bObject):
710                                Model.__init__(self)
711                                self.bObject = bObject
712                                # list of keys determines ordering
713                                self.animationProxyKeyList = []
714                                # all keys < maxKey
715                                self.maxKey = 0
716                                # key: key, value: xAnimationProxy
717                                self.animationProxyDict = {}
718                                return
719                        def addProxy(self, proxy):
720                                """Adds an AnimationProxy to the manager.
721                               
722                                   @param proxy AnimationProxy.
723                                   @return Key.
724                                """
725                                if (len(self.animationProxyKeyList) == self.maxKey):
726                                        self.maxKey += 1
727                                        key = self.maxKey
728                                else:
729                                        # first unused
730                                        key = [(x + 1) for x in range(self.maxKey) if (x + 1) not in self.animationProxyDict.keys()][0]
731                                self.animationProxyDict[key] = proxy
732                                self.animationProxyKeyList.append(key)
733                                for view in self.viewList:
734                                        view.notifyAdded(key)
735                                return key
736                        def removeProxy(self, key):
737                                if self.animationProxyDict.has_key(key):
738                                        del self.animationProxyDict[key]
739                                        self.animationProxyKeyList.remove(key)
740                                        for view in self.viewList:
741                                                view.notifyRemoved(key)
742                                return
743                        def getBlenderObject(self):
744                                return self.bObject
745                        def getKey(self, proxy):
746                               
747                                return
748                        def getKeyList(self):
749                                return self.animationProxyKeyList
750                        def getProxy(self, key):
751                                proxy = None
752                                if key in self.animationProxyDict.keys():
753                                        proxy = self.animationProxyDict[key]
754                                return proxy
755                        def toAnimations(self, animationExporter):
756                                for key in self.animationProxyKeyList:
757                                        animationExporter.addAnimation(self.animationProxyDict[key].toAnimation())
758                                return
759                        def update(self):
760                                """Synchronize with Blender.
761                               
762                                   @param <code>True</code> if animations can still be exported, else <code>False</code>.
763                                """
764                                return
765                        def loadPackageSettings(self):
766                                return
767                        def savePackageSettings(self):
768                                return
769                        # @staticmethod
770                        # def create( ... ):
771                        #       """Factory method.
772                        #       """
773               
774                class PoseAnimationProxyManager(AnimationProxyManager):
775                        """Manages pose animations of a given Blender mesh object.
776                        """
777                        def __init__(self, bMeshObject):
778                                AnimationProxyManager.__init__(self, bMeshObject)
779                                # load package settings if available
780                                self.loadPackageSettings()
781                                return
782                        def toAnimations(self, animationExporter):
783                                for key in self.animationProxyKeyList:
784                                        animationExporter.addPoseAnimation(self.animationProxyDict[key].toAnimation())
785                                return
786                        def loadPackageSettings(self):
787                                # clear old
788                                self.animationProxyKeyList = []
789                                self.maxKey = 0
790                                self.animationProxyDict = {}
791                                # get package settings
792                                poseAnimationList = PackageSettings.getSingleton().getObjectSetting(self.bObject.getName(), 'PoseAnimationList')
793                                # old naming convention
794                                if not poseAnimationList:
795                                        poseAnimationList = PackageSettings.getSingleton().getObjectSetting(self.bObject.getName(), 'poseAnimationList')
796                                if poseAnimationList:
797                                        for poseAnimation in poseAnimationList:
798                                                # skip old single frame pose animations
799                                                if (len(poseAnimation) == 3):
800                                                        self.addProxy(PoseAnimationProxy(poseAnimation[0], poseAnimation[1], poseAnimation[2]))
801                                self._notify()
802                                return
803                        def savePackageSettings(self):
804                                poseAnimationList = []
805                                for key in self.animationProxyKeyList:
806                                        proxy = self.animationProxyDict[key]
807                                        poseAnimationList.append([proxy.getName(), proxy.getStartFrame(), proxy.getEndFrame()])
808                                PackageSettings.getSingleton().setObjectSetting(self.bObject.getName(), 'PoseAnimationList', poseAnimationList)
809                                return
810                        def update(self):
811                                """Checks if Blender object has still shape keys.
812                               
813                                   @return <code>True</code> if shape keys still present, else <code>False</code>.
814                                """
815                                isValid = False
816                                bKey = self.bObject.getData().getKey()
817                                if bKey is not None:
818                                        if (len(bKey.blocks) > 0):
819                                                isValid = True
820                                return isValid
821                        # @staticmethod
822                        def create(bMeshObject):
823                                """Factory method:
824                                       
825                                   @return instance or <code>None</code> if object has no shape key.
826                                """
827                                manager = None
828                                bKey =  bMeshObject.getData().getKey()
829                                if bKey is not None:
830                                        if (len(bKey.blocks) > 0):
831                                                manager = PoseAnimationProxyManager(bMeshObject)
832                                return manager
833                        create = staticmethod(create)
834                               
835                class MorphAnimationProxyManager(AnimationProxyManager):
836                        """Manages morph animations of a given Blender mesh object.
837                        """
838                        def __init__(self, bMeshObject):
839                                AnimationProxyManager.__init__(self, bMeshObject)
840                                # load package settings if available
841                                self.loadPackageSettings()
842                                return
843                        def toAnimations(self, animationExporter):
844                                for key in self.animationProxyKeyList:
845                                        animationExporter.addMorphAnimation(self.animationProxyDict[key].toAnimation())
846                                return
847                        def loadPackageSettings(self):
848                                # clear old
849                                self.animationProxyKeyList = []
850                                self.maxKey = 0
851                                self.animationProxyDict = {}
852                                # get package settings
853                                morphAnimationList = PackageSettings.getSingleton().getObjectSetting(self.bObject.getName(), 'MorphAnimationList')
854                                # old naming convention
855                                if not morphAnimationList:
856                                        morphAnimationList = PackageSettings.getSingleton().getObjectSetting(self.bObject.getName(), 'morphAnimationList')
857                                if morphAnimationList:
858                                        for morphAnimation in morphAnimationList:
859                                                self.addProxy(MorphAnimationProxy(morphAnimation[0], morphAnimation[1], morphAnimation[2]))
860                                self._notify()
861                                return
862                        def savePackageSettings(self):
863                                morphAnimationList = []
864                                for key in self.animationProxyKeyList:
865                                        proxy = self.animationProxyDict[key]
866                                        morphAnimationList.append([proxy.getName(), proxy.getStartFrame(), proxy.getEndFrame()])
867                                PackageSettings.getSingleton().setObjectSetting(self.bObject.getName(), 'MorphAnimationList', morphAnimationList)
868                                return
869                        def update(self):
870                                """Checks if Blender object has still shape keys.
871                               
872                                   @return <code>True</code> if shape keys still present, else <code>False</code>.
873                                """
874                                isValid = False
875                                bKey = self.bObject.getData().getKey()
876                                if bKey is not None:
877                                        if (len(bKey.blocks) > 0):
878                                                isValid = True
879                                return isValid
880                        # @staticmethod
881                        def create(bMeshObject):
882                                """Factory method:
883                                       
884                                   @return instance or <code>None</code> if object has no shape key.
885                                """
886                                manager = None
887                                bKey =  bMeshObject.getData().getKey()
888                                if bKey is not None:
889                                        if (len(bKey.blocks) > 0):
890                                                manager = MorphAnimationProxyManager(bMeshObject)
891                                return manager
892                        create = staticmethod(create)
893               
894                class AnimationProxyManagerView(AddWidgetListLayout, View):
895                        """Base class for view for AnimationProxyMangager.
896                        """
897                        def __init__(self, parent, size, model, addAction, addTooltip):
898                                # Model
899                                View.__init__(self, model)
900                                # View
901                                AddWidgetListLayout.__init__(self, parent, size)
902                                Button(self, Size([60, 20]), addAction, T("Add"), addTooltip)
903                                # list of displayed keys
904                                self.displayedKeyList = []
905                                # key: key, value: AnimationProxyView
906                                self.proxyViewDict = {}
907                                self.update()
908                                self.setAutoScroll(True)
909                                return
910                        def notifyAdded(self, key):
911                                proxyView = AnimationProxyView(self, self.model.getProxy(key), AnimationProxyManagerView.DeleteAction(self.model, key))
912                                self.proxyViewDict[key] = proxyView
913                                self.displayedKeyList.append(key)
914                                Blender.Draw.Redraw(1)
915                                return
916                        def update(self):
917                                self.removeAll()
918                                self.displayedKeyList = []
919                                for key in self.model.getKeyList():
920                                        self.notifyAdded(key)
921                                Blender.Draw.Redraw(1)
922                                return
923                        def notifyRemoved(self, key):
924                                self.displayedKeyList.remove(key)
925                                self.proxyViewDict[key].removeFromParent()
926                                del self.proxyViewDict[key]
927                                Blender.Draw.Redraw(1)
928                                return
929                        class DeleteAction(Action):
930                                def __init__(self, model, key):
931                                        self.model = model
932                                        self.key = key
933                                        return
934                                def execute(self):
935                                        self.model.removeProxy(self.key)
936                                        return
937               
938                class PoseAnimationProxyManagerView(AnimationProxyManagerView):
939                        """View for PoseAnimationProxyManager.
940                       
941                           Set size greater than <code>Size([350,100])</code>.
942                        """
943                        def __init__(self, parent, size, model):
944                                AnimationProxyManagerView.__init__(self, parent, size, model, \
945                                        PoseAnimationProxyManagerView.AddAction(model), \
946                                        T("Add new pose animation."))
947                                return
948                        class AddAction(Action):
949                                def __init__(self, model):
950                                        self.model = model
951                                        return
952                                def execute(self):
953                                        key = self.model.addProxy(PoseAnimationProxy('name', 1, 1))
954                                        return
955                       
956                class MorphAnimationProxyManagerView(AnimationProxyManagerView):
957                        """View for MorphAnimationProxyManager.
958                       
959                           Set size greater than <code>Size([350,100])</code>.
960                        """
961                        def __init__(self, parent, size, model):
962                                AnimationProxyManagerView.__init__(self, parent, size, model, \
963                                        MorphAnimationProxyManagerView.AddAction(model), \
964                                        T("Add new morph animation."))
965                                return
966                        class AddAction(Action):
967                                def __init__(self, model):
968                                        self.model = model
969                                        return
970                                def execute(self):
971                                        key = self.model.addProxy(MorphAnimationProxy('name', 1, 1))
972                                        return
973               
974                class ArmatureAnimationProxyManager(AnimationProxyManager):
975                        """Manages armature animations of a given Blender mesh object.
976                        """
977                        def __init__(self, bMeshObject, actionManager):
978                                AnimationProxyManager.__init__(self, bMeshObject)
979                                # actions
980                                self.actionManager = actionManager
981                                self.actionList = []
982                                self.update()
983                                # load package settings if available
984                                self.loadPackageSettings()
985                                return
986                        def removeProxy(self, key):
987                                """Removes proxy from ProxyManager as well as detaches it from ActionManager.
988                                """
989                                if self.animationProxyDict.has_key(key):
990                                        proxy = self.animationProxyDict[key]
991                                        proxy.getAction().detachAnimationProxy(proxy)
992                                        del self.animationProxyDict[key]
993                                        self.animationProxyKeyList.remove(key)
994                                        for view in self.viewList:
995                                                view.notifyRemoved(key)
996                                return
997                        def removeProxies(self):
998                                """Removes all animation proxies.
999                                """
1000                                for proxy in self.animationProxyDict.values():
1001                                        proxy.getAction().detachAnimationProxy(proxy)
1002                                self.animationProxyDict = {}
1003                                return
1004                        def update(self):
1005                                """Updates available actions and default action keyframe ranges.
1006                               
1007                                   Only notifies views if it is still a valid manager.
1008                                   @return <code>True</code> if armature and actions are still present,
1009                                           else <code>False</code>.
1010                                """
1011                                isValid = False
1012                                self.actionList = []
1013                                # check if mesh object has (still) an armature is done by getActions
1014                                self.actionList = self.actionManager.getActions(self.bObject)
1015                                if (len(self.actionList) > 0):
1016                                        isValid = True
1017                                return isValid
1018                        def loadPackageSettings(self):
1019                                # clear old
1020                                for proxy in self.animationProxyDict.values():
1021                                        proxy.invalidate()             
1022                                self.animationProxyKeyList = []
1023                                self.maxKey = 0
1024                                self.animationProxyDict = {}
1025                                # get package settings
1026                                animationList = PackageSettings.getSingleton().getObjectSetting(self.bObject.getName(), 'ArmatureAnimationList')
1027                                if not animationList:
1028                                        # load old configuration text
1029                                        animationList = self._loadOldSettings()
1030                                if animationList and len(animationList):
1031                                        validActionNames = [action.getName() for action in self.actionList]
1032                                        for animation in animationList:
1033                                                # animation = [action name, animation name, start frame, end frame]
1034                                                # check if action is still available
1035                                                if animation[0] in validActionNames:
1036                                                        # add animiation
1037                                                        action = self.actionManager.getAction(animation[0])
1038                                                        if action:
1039                                                                self.addProxy(ArmatureAnimationProxy(self, action, animation[1], animation[2], animation[3]))                                   
1040                                self._notify()
1041                                return
1042                        def savePackageSettings(self):
1043                                animationList = []
1044                                for key in self.animationProxyKeyList:
1045                                        proxy = self.animationProxyDict[key]
1046                                        animationList.append([proxy.getAction().getName(), proxy.getName(), proxy.getStartFrame(), proxy.getEndFrame()])
1047                                PackageSettings.getSingleton().setObjectSetting(self.bObject.getName(), 'ArmatureAnimationList', animationList)
1048                                return
1049                        def toAnimations(self, animationExporter):
1050                                for key in self.animationProxyKeyList:
1051                                        animationExporter.addAnimation(self.animationProxyDict[key].toAnimation())
1052                                return
1053                        def getActions(self):
1054                                return self.actionList
1055                        def _loadOldSettings(self):
1056                                """Load animation settings from the old exporter.
1057                               
1058                                   @return list of animations in the new format or <code>None</code>.
1059                                """
1060                                animationList = None
1061                                # try open 'ogreexport.cfg' text
1062                                configTextName = 'ogreexport.cfg'
1063                                if configTextName in [text.getName() for text in Blender.Text.Get()]:
1064                                        configText = Blender.Text.Get(configTextName)
1065                                        # compose string from text and unpickle
1066                                        try:
1067                                                # unpickle
1068                                                settingsDict = pickle.loads(string.join(configText.asLines()[4:],'\n'))
1069                                        except (PickleError):
1070                                                pass
1071                                        else:
1072                                                # read configuration
1073                                                if settingsDict.has_key('armatureAnimationDictListDict'):
1074                                                        armatureAnimationDictListDict = settingsDict['armatureAnimationDictListDict']
1075                                                        parent = GetArmatureObject(self.bObject)
1076                                                        if (parent is not None):
1077                                                                if armatureAnimationDictListDict.has_key(parent.getName()):
1078                                                                        armatureAnimationDictList = armatureAnimationDictListDict[parent.getName()]
1079                                                                        animationList = []
1080                                                                        for animationDict in armatureAnimationDictList:
1081                                                                                actionName = animationDict['actionKey']
1082                                                                                name = animationDict['name']
1083                                                                                startFrame = animationDict['startFrame']
1084                                                                                endFrame = animationDict['endFrame']
1085                                                                                animationList.append([actionName, name, startFrame, endFrame])
1086                                return animationList
1087                        # @staticmethod
1088                        def create(bMeshObject, actionManager):
1089                                """Factory method:
1090                                       
1091                                   @return instance or <code>None</code> if object has no shape key.
1092                                """
1093                                manager = None
1094                                if (len(actionManager.getActions(bMeshObject)) > 0):
1095                                        manager = ArmatureAnimationProxyManager(bMeshObject, actionManager)
1096                                return manager
1097                        create = staticmethod(create)
1098                       
1099                class ArmatureAnimationProxyManagerView(AnimationProxyManagerView):
1100                        """View for MorphAnimationProxyManager.
1101                       
1102                           Set size greater than <code>Size([350,100])</code>.
1103                        """
1104                        def __init__(self, parent, size, model):
1105                                AnimationProxyManagerView.__init__(self, parent, size, model, \
1106                                        ArmatureAnimationProxyManagerView.AddAction(model), \
1107                                        T("Add new skeleton animation."))
1108                                return
1109                        def notifyAdded(self, key):
1110                                proxyView = ArmatureAnimationProxyView(self, self.model.getProxy(key), AnimationProxyManagerView.DeleteAction(self.model, key))
1111                                self.proxyViewDict[key] = proxyView
1112                                self.displayedKeyList.append(key)
1113                                Blender.Draw.Redraw(1)
1114                                return
1115                        class AddAction(Action):
1116                                def __init__(self, model):
1117                                        self.model = model
1118                                        return
1119                                def execute(self):
1120                                        key = self.model.addProxy(ArmatureAnimationProxy(self.model))
1121                                        return
1122               
1123                class SelectedObjectManager(Model):
1124                        """Manages mesh objects selected for export.
1125                       
1126                           Views have to provide an updateSelection() method.
1127                        """
1128                        def __init__(self):
1129                                Model.__init__(self)
1130                                # ActionManager takes care of actions for all objects
1131                                self.actionManager = ActionManager()
1132                                # object names
1133                                self.selectedList = []
1134                                # key: name, value: Blender Object of type Mesh
1135                                self.selectedDict = {}
1136                                # name of current selected object
1137                                self.current = None
1138                                # key: name; value: MorphAnimationProxyManager
1139                                self.morphAnimationProxyManagerDict = {}
1140                                # key: name; value: PoseAnimationProxyMangager
1141                                self.poseAnimationProxyManagerDict = {}
1142                                # key: name; value: ArmatureAnimationProxyManager
1143                                self.armatureAnimationProxyManagerDict = {}
1144                                self.updateSelection()
1145                                return
1146                        def updateSelection(self):
1147                                """Update the list of objects selected for export and the available actions for these objects.
1148                                """
1149                                # update available actions
1150                                self.actionManager.update()
1151                                self.selectedList = []
1152                                self.selectedDict = {}
1153                                # for every currently selected mesh object
1154                                for bMeshObject in [bObject for bObject in Blender.Object.GetSelected() if (bObject.getType() == 'Mesh')]:
1155                                        name = bMeshObject.getName()
1156                                        self.selectedList.append(name)
1157                                        self.selectedDict[name] = bMeshObject
1158                                        # morph animation
1159                                        if self.morphAnimationProxyManagerDict.has_key(name):
1160                                                # update
1161                                                if not self.morphAnimationProxyManagerDict[name].update():
1162                                                        # manager no longer valid
1163                                                        del self.morphAnimationProxyManagerDict[name]
1164                                        else:
1165                                                # create new manager
1166                                                manager = MorphAnimationProxyManager.create(bMeshObject)
1167                                                if manager:
1168                                                        self.morphAnimationProxyManagerDict[name] = manager
1169                                        # pose animation
1170                                        if self.poseAnimationProxyManagerDict.has_key(name):
1171                                                # update
1172                                                if not self.poseAnimationProxyManagerDict[name].update():
1173                                                        # manager no longer valid
1174                                                        del self.poseAnimationProxyManagerDict[name]
1175                                        else:
1176                                                # create new manager
1177                                                manager = PoseAnimationProxyManager.create(bMeshObject)
1178                                                if manager:
1179                                                        self.poseAnimationProxyManagerDict[name] = manager
1180                                        # armature animation
1181                                        if self.armatureAnimationProxyManagerDict.has_key(name):
1182                                                # update
1183                                                if not self.armatureAnimationProxyManagerDict[name].update():
1184                                                        # manager no longer valid
1185                                                        self.armatureAnimationProxyManagerDict[name].removeProxies()
1186                                                        del self.armatureAnimationProxyManagerDict[name]
1187                                        else:
1188                                                # create new manager
1189                                                manager = ArmatureAnimationProxyManager.create(bMeshObject, self.actionManager)
1190                                                if manager:
1191                                                        self.armatureAnimationProxyManagerDict[name] = manager
1192                                # == remove AnimationProxyManagers of unselected objects ==
1193                                # save animations of unselected objects
1194                                # remove MorphAnimationProxyManagers of unselected objects
1195                                for (bObjectName, proxyManager) in [(name, self.morphAnimationProxyManagerDict[name]) \
1196                                        for name in self.morphAnimationProxyManagerDict.keys()[:] if name not in self.selectedList]:
1197                                        proxyManager.savePackageSettings()
1198                                        del self.morphAnimationProxyManagerDict[bObjectName]
1199                                # remove PoseAnimationProxyManagers of unselected objects
1200                                for (bObjectName, proxyManager) in [(name, self.poseAnimationProxyManagerDict[name]) \
1201                                        for name in self.poseAnimationProxyManagerDict.keys()[:] if name not in self.selectedList]:
1202                                        proxyManager.savePackageSettings()
1203                                        del self.poseAnimationProxyManagerDict[bObjectName]
1204                                # remove ArmatureAnimationProxyMangers of unselected objects
1205                                for (bObjectName, proxyManager) in [(name, self.armatureAnimationProxyManagerDict[name]) \
1206                                        for name in self.armatureAnimationProxyManagerDict.keys()[:] if name not in self.selectedList]:
1207                                        proxyManager.savePackageSettings()
1208                                        # detach animations from actions
1209                                        proxyManager.removeProxies()
1210                                        del self.armatureAnimationProxyManagerDict[bObjectName]
1211                                # update current selected
1212                                if len(self.selectedList):
1213                                        self.current = self.selectedList[0]
1214                                else:
1215                                        self.current = None
1216                                # notify views
1217                                for view in self.viewList:
1218                                        view.updateSelection()
1219                                return
1220                        def setCurrentObjectName(self, name):
1221                                if name in self.selectedDict.keys():
1222                                        self.current = name
1223                                        self._notify()
1224                                return
1225                        def getCurrentObjectName(self):
1226                                return self.current
1227                        def getObject(self, name):
1228                                bObject = None
1229                                if name in self.selectedDict.keys():
1230                                        bObject = self.selectedDict[name]
1231                                return bObject
1232                        def getMorphAnimationProxyManager(self, name):
1233                                proxyManager = None
1234                                if name in self.morphAnimationProxyManagerDict.keys():
1235                                        proxyManager = self.morphAnimationProxyManagerDict[name]
1236                                return proxyManager
1237                        def getPoseAnimationProxyManager(self, name):
1238                                proxyManager = None
1239                                if name in self.poseAnimationProxyManagerDict.keys():
1240                                        proxyManager = self.poseAnimationProxyManagerDict[name]
1241                                return proxyManager
1242                        def getArmatureAnimationProxyManager(self, name):
1243                                proxyManger = None
1244                                if name in self.armatureAnimationProxyManagerDict.keys():
1245                                        proxyManger = self.armatureAnimationProxyManagerDict[name]
1246                                return proxyManger
1247                        def getObjectNameList(self):
1248                                return self.selectedList
1249                        def savePackageSettings(self):
1250                                for proxyManager in self.morphAnimationProxyManagerDict.values():
1251                                        proxyManager.savePackageSettings()
1252                                for proxyManager in self.poseAnimationProxyManagerDict.values():
1253                                        proxyManager.savePackageSettings()
1254                                for proxyManager in self.armatureAnimationProxyManagerDict.values():
1255                                        proxyManager.savePackageSettings()
1256                                return
1257                        def export(self, exportPath, materialScriptName, colouredAmbient, gameEngineMaterials, convertXML, copyTextures):
1258                                # create MaterialManager
1259                                if len(self.selectedList):
1260                                        materialManager = MaterialManager(exportPath, materialScriptName)
1261                                        Log.getSingleton().logInfo("Output to directory \"%s\"" % exportPath)
1262                                        for name in self.selectedList:
1263                                                Log.getSingleton().logInfo("Processing Object \"%s\"" % name)
1264                                                # create MeshExporter
1265                                                meshExporter = MeshExporter(self.selectedDict[name])
1266                                                if self.morphAnimationProxyManagerDict.has_key(name):
1267                                                        self.morphAnimationProxyManagerDict[name].toAnimations(meshExporter.getVertexAnimationExporter())
1268                                                if self.poseAnimationProxyManagerDict.has_key(name):
1269                                                        self.poseAnimationProxyManagerDict[name].toAnimations(meshExporter.getVertexAnimationExporter())
1270                                                if self.armatureAnimationProxyManagerDict.has_key(name):
1271                                                        self.armatureAnimationProxyManagerDict[name].toAnimations(meshExporter.getArmatureExporter())
1272                                                # export
1273                                                meshExporter.export(exportPath, materialManager, Matrix(*matrixOne), colouredAmbient, gameEngineMaterials, convertXML)
1274                                        # export materials
1275                                        materialManager.export(exportPath, materialScriptName, copyTextures)
1276                                else:
1277                                        Log.getSingleton().logWarning("No mesh object selected for export!")
1278                                return
1279
1280                class SelectedObjectManagerView(VerticalLayout, View):
1281                        def __init__(self, parent, model):
1282                                VerticalLayout.__init__(self, parent)
1283                                View.__init__(self, model)
1284                                hLayout = HorizontalLayout(self)
1285                                LabelView(hLayout, L("Selected: "))
1286                                self.menu = Menu(hLayout, Size([Size.INFINITY, 20], [150, 20]), T("Objects selected for export."))
1287                                Button(hLayout, Size([70, 20]), SelectedObjectManagerView.UpdateAction(self.model), T("Update"), \
1288                                        T("Update list of objects selected for export."))
1289                                Spacer(self, Size([0, 10]))
1290                                self.alternatives = AlternativesLayout(self)
1291                                self.noneSelectedWidget = Spacer(self.alternatives, Size([0, Size.INFINITY], [0, 0]))
1292                                self.alternatives.setCurrent(self.noneSelectedWidget)
1293                                # key: object name, value: AnimationProxyManagersView
1294                                self.animationProxyManagersViewDict = {}
1295                                self.updateSelection()
1296                                return
1297                        def updateSelection(self):
1298                                """Called from model if list of selected mesh objects changes.
1299                                """
1300                                self.menu.removeAll()
1301                                self.alternatives.setCurrent(self.noneSelectedWidget)
1302                                for name in self.model.getObjectNameList():
1303                                        # set current object to first in list
1304                                        setCurrent = False
1305                                        if (name == self.model.getObjectNameList()[0]):
1306                                                setCurrent = True
1307                                        self.menu.appendItem(MenuItem(name, SelectedObjectManagerView.SelectAction(self.model, name)), setCurrent)
1308                                        if not self.animationProxyManagersViewDict.has_key(name):
1309                                                poseManager = self.model.getPoseAnimationProxyManager(name)
1310                                                morphManager = self.model.getMorphAnimationProxyManager(name)
1311                                                armatureManager = self.model.getArmatureAnimationProxyManager(name)
1312                                                self.animationProxyManagersViewDict[name] = SelectedObjectManagerView.AnimationProxyManagersView( \
1313                                                        self.alternatives, self.model, name)
1314                                        else:
1315                                                # udpate existing
1316                                                self.animationProxyManagersViewDict[name].updateSelection()
1317                                        # set current object to first in list
1318                                        if (name == self.model.getObjectNameList()[0]):
1319                                                self.alternatives.setCurrent(self.animationProxyManagersViewDict[name])
1320                                Blender.Draw.Redraw(1)
1321                                return
1322                        def update(self):
1323                                """Update current selected.
1324                                """
1325                                self.alternatives.setCurrent(self.animationProxyManagersViewDict[self.model.getCurrentObjectName()])
1326                                Blender.Draw.Redraw(1)
1327                                return
1328                        class SelectAction(Action):
1329                                def __init__(self, model, name):
1330                                        self.model = model
1331                                        self.name = name
1332                                        return
1333                                def execute(self):
1334                                        self.model.setCurrentObjectName(self.name)
1335                                        return
1336                        class UpdateAction(Action):
1337                                def __init__(self, model):
1338                                        self.model = model
1339                                        return
1340                                def execute(self):
1341                                        self.model.updateSelection()
1342                                        return
1343                        class AnimationProxyManagersView(Box, View):
1344                                """View for the different animation proxy managers.
1345                               
1346                                   Provides toggles to switch between morph, pose and armature animation proxy managers.
1347                                """
1348                                def __init__(self, parent, manager, name):
1349                                        """Constructor.
1350                                       
1351                                           @manager SelectedObjectManager.
1352                                           @name Blender mesh object name.
1353                                        """
1354                                        Box.__init__(self, parent, L("Animation Settings of \"%s\"" % name), 0, 10)
1355                                        # mesh object name
1356                                        self.name = name
1357                                        # SelectedObjectManager
1358                                        self.manager = manager
1359                                        # AnimationProxyManagers
1360                                        # [Armature, Pose, Morph]
1361                                        self.managerList = [None, None, None]
1362                                        # Toggle Bar [Skeleton] [  Pose  ] [  Morph ]
1363                                        # If corresponding manager does not exist
1364                                        # the toggle is replaced with a Spacer that has size [0, 0].
1365                                        # Therefore ToggleView and Spacer are alternatives
1366                                        #
1367                                        # Only active toggles, i.e. toggles that correspond to an existing
1368                                        # AnimationProxyManager are currently in the group
1369                                        self.toggleList = [None, None, None] # models
1370                                        self.toggleList[0] = ToggleModel(False)
1371                                        self.toggleList[1] = ToggleModel(False)
1372                                        self.toggleList[2] = ToggleModel(False)                         
1373                                        # self.model = ToggleGroup()
1374                                        View.__init__(self, ToggleGroup())     
1375                                        vLayout = VerticalLayout(self)
1376                                        hLayout = HorizontalLayout(vLayout)
1377                                        self.alternativesList = [None, None, None]
1378                                        self.alternativesList[0] = AlternativesLayout(hLayout)
1379                                        self.alternativesList[1] = AlternativesLayout(hLayout)
1380                                        self.alternativesList[2] = AlternativesLayout(hLayout)
1381                                        self.toggleViewList = [None, None, None]
1382                                        self.toggleViewList[0] = ToggleView(self.alternativesList[0], \
1383                                                Size([Size.INFINITY, 20], [150, 20]), \
1384                                                self.toggleList[0], \
1385                                                T("Skeleton"), T("Armature animation to Ogre skeleton animation."))
1386                                        self.toggleViewList[1] = ToggleView(self.alternativesList[1], \
1387                                                Size([Size.INFINITY, 20], [150, 20]), \
1388                                                self.toggleList[1], \
1389                                                T("Pose"),T("Shape animation to Ogre pose animation."))
1390                                        self.toggleViewList[2] = ToggleView(self.alternativesList[2], \
1391                                                Size([Size.INFINITY, 20], [150, 20]), \
1392                                                self.toggleList[2], \
1393                                                T("Morph"),T("Shape animation to Ogre morph animation."))
1394                                        self.spacerList = [None, None, None]
1395                                        self.spacerList[0] = Spacer(self.alternativesList[0], Size([0,0]))
1396                                        self.alternativesList[0].setCurrent(self.spacerList[0])
1397                                        self.spacerList[1] = Spacer(self.alternativesList[1], Size([0,0]))
1398                                        self.alternativesList[1].setCurrent(self.spacerList[1])
1399                                        self.spacerList[2] = Spacer(self.alternativesList[2], Size([0,0]))
1400                                        self.alternativesList[2].setCurrent(self.spacerList[2])
1401                                        # lower part of screen shows either the selected AnimationProxyManagerView
1402                                        # or a spacer
1403                                        self.alternatives = AlternativesLayout(vLayout)
1404                                        # AnimationProxyManagerViews
1405                                        self.managerViewList = [None, None, None]
1406                                        self.spacer = Spacer(self.alternatives, Size([Size.INFINITY, Size.INFINITY], [350, 120]))
1407                                        self.alternatives.setCurrent(self.spacer)
1408                                        # update managers
1409                                        self.updateSelection()
1410                                        return
1411                                def update(self):
1412                                        """Updates togglegroup status.
1413                                        """
1414                                        if (self.managerList.count(None) != 3):
1415                                                toggleModel = self.model.getValue()
1416                                                # TODO: test if toggle is enabled should be unnecessary
1417                                                if toggleModel and toggleModel.getValue():
1418                                                        # raises ValueError if model is not in list
1419                                                        index = self.toggleList.index(toggleModel)
1420                                                        if self.managerViewList[index] is not None:
1421                                                                # display current selected AnimationProxyMana
1422                                                                self.alternatives.setCurrent(self.managerViewList[index])
1423                                                        else:
1424                                                                # forgot to remove toggle from ToggleGroup
1425                                                                # as manager is no longer present
1426                                                                raise RuntimeError
1427                                        return
1428                                def updateSelection(self):
1429                                        """Checks if action managers are still or newly available.
1430                                        """
1431                                        newManager = self.manager.getArmatureAnimationProxyManager(self.name)
1432                                        if not (self.managerList[0] == newManager):
1433                                                # armature manager changed
1434                                                if self.managerList[0] is None:
1435                                                        # create new
1436                                                        # add manager
1437                                                        self.managerList[0] = newManager
1438                                                        # add manager view
1439                                                        self.managerViewList[0] = ArmatureAnimationProxyManagerView( \
1440                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1441                                                                self.managerList[0])
1442                                                        # add toggle to toggleGroup, calls update() if selected
1443                                                        self.model.addToggle(self.toggleList[0])
1444                                                        # show ToggleView
1445                                                        self.alternativesList[0].setCurrent(self.toggleViewList[0])
1446                                                elif newManager is None:
1447                                                        # remove old
1448                                                        # hide ToggleView
1449                                                        self.alternativesList[0].setCurrent(self.spacerList[0])
1450                                                        # remove toggle from ToggleGroup
1451                                                        self.model.removeToggle(self.toggleList[0])
1452                                                        # set spacer in lower part of the window if no manager left
1453                                                        if (self.managerList.count(None) >= 2):
1454                                                                self.alternatives.setCurrent(self.spacer)
1455                                                        # remove old manager in list
1456                                                        self.managerList[0] = None
1457                                                        # remove old managerView
1458                                                        self.managerViewList[0].removeFromParent()
1459                                                        self.managerViewList[0] = None
1460                                                else:
1461                                                        # swap
1462                                                        # manager
1463                                                        self.managerList[0] = newManager
1464                                                        # view
1465                                                        oldView = self.managerViewList[0]
1466                                                        # add new to alternatives layout
1467                                                        self.managerViewList[0] = ArmatureAnimationProxyanagerView( \
1468                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1469                                                                self.managerList[0])
1470                                                        # remove old from alternatives layout
1471                                                        if (self.alternatives.getCurrent() == oldView):
1472                                                                # show view
1473                                                                self.alternatives.setCurrent(self.managerViewList[0])
1474                                                        oldView.removeFromParent()
1475                                        newManager = self.manager.getPoseAnimationProxyManager(self.name)
1476                                        if not (self.managerList[1] == newManager):
1477                                                # pose manager changed
1478                                                if self.managerList[1] is None:
1479                                                        # create new
1480                                                        # add manager
1481                                                        self.managerList[1] = newManager
1482                                                        # add manager view
1483                                                        self.managerViewList[1] = PoseAnimationProxyManagerView( \
1484                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1485                                                                self.managerList[1])
1486                                                        # add toggle to toggleGroup, calls update() if selected
1487                                                        self.model.addToggle(self.toggleList[1])
1488                                                        # show ToggleView
1489                                                        self.alternativesList[1].setCurrent(self.toggleViewList[1])
1490                                                elif newManager is None:
1491                                                        # remove old
1492                                                        # hide ToggleView
1493                                                        self.alternativesList[1].setCurrent(self.spacerList[1])
1494                                                        # remove toggle from ToggleGroup
1495                                                        self.model.removeToggle(self.toggleList[1])
1496                                                        # set spacer in lower part of the window if no manager left
1497                                                        if (self.managerList.count(None) >= 2):
1498                                                                self.alternatives.setCurrent(self.spacer)
1499                                                        # remove old manager in list
1500                                                        self.managerList[1] = None
1501                                                        # remove old managerView
1502                                                        self.managerViewList[1].removeFromParent()
1503                                                        self.managerViewList[1] = None
1504                                                else:
1505                                                        # swap
1506                                                        # manager
1507                                                        self.managerList[0] = newManager
1508                                                        # view
1509                                                        oldView = self.managerViewList[1]
1510                                                        # add new to alternatives layout
1511                                                        self.managerViewList[1] = PoseAnimationProxyanagerView( \
1512                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1513                                                                self.managerList[1])
1514                                                        # remove old from alternatives layout
1515                                                        if (self.alternatives.getCurrent() == oldView):
1516                                                                # show view
1517                                                                self.alternatives.setCurrent(self.managerViewList[1])
1518                                                        oldView.removeFromParent()
1519                                        newManager = self.manager.getMorphAnimationProxyManager(self.name)
1520                                        if not (self.managerList[2] == newManager):
1521                                                # morph manager changed
1522                                                if self.managerList[2] is None:
1523                                                        # create new
1524                                                        # add manager
1525                                                        self.managerList[2] = newManager
1526                                                        # add manager view
1527                                                        self.managerViewList[2] = MorphAnimationProxyManagerView( \
1528                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1529                                                                self.managerList[2])
1530                                                        # add toggle to toggleGroup, calls update() if selected
1531                                                        self.model.addToggle(self.toggleList[2])
1532                                                        # show ToggleView
1533                                                        self.alternativesList[2].setCurrent(self.toggleViewList[2])
1534                                                elif newManager is None:
1535                                                        # remove old
1536                                                        # hide ToggleView
1537                                                        self.alternativesList[2].setCurrent(self.spacerList[2])
1538                                                        # remove toggle from ToggleGroup
1539                                                        self.model.removeToggle(self.toggleList[2])
1540                                                        # set spacer in lower part of the window if no manager left
1541                                                        if (self.managerList.count(None) >= 2):
1542                                                                self.alternatives.setCurrent(self.spacer)
1543                                                        # remove old manager in list
1544                                                        self.managerList[2] = None
1545                                                        # remove old managerView
1546                                                        self.managerViewList[2].removeFromParent()
1547                                                        self.managerViewList[2] = None
1548                                                else:
1549                                                        # swap
1550                                                        # manager
1551                                                        self.managerList[2] = newManager
1552                                                        # view
1553                                                        oldView = self.managerViewList[2]
1554                                                        # add new to alternatives layout
1555                                                        self.managerViewList[2] = PoseAnimationProxyanagerView( \
1556                                                                self.alternatives,  Size([Size.INFINITY, Size.INFINITY], [350, 120]), \
1557                                                                self.managerList[2])
1558                                                        # remove old from alternatives layout
1559                                                        if (self.alternatives.getCurrent() == oldView):
1560                                                                # show view
1561                                                                self.alternatives.setCurrent(self.managerViewList[2])
1562                                                        oldView.removeFromParent()
1563                                        return
1564               
1565                class MeshExporterApplication:
1566                        def __init__(self):
1567                                # initialize global settings to default value
1568                                self.materalScriptName = BasenameModel(Blender.Scene.GetCurrent().getName() + '.material')
1569                                self.exportPath = DirnameModel(Blender.Get('filename'))
1570                                self.colouredAmbient = ToggleModel(0)
1571                                self.gameEngineMaterials = ToggleModel(0)
1572                                self.convertXML = ToggleModel(0)
1573                                self.copyTextures = ToggleModel(0)
1574                                # load package settings if applicable
1575                                self._loadPackageSettings()
1576                                # manager for selected objects
1577                                self.selectedObjectManager = SelectedObjectManager()
1578                                self.preferencesScreen = PreferencesScreen()
1579                                # create main screen
1580                                #  material settings
1581                                self.mainScreen = Screen()
1582                                frame = OgreFrame(self.mainScreen, "Meshes Exporter")
1583                                vLayout = VerticalLayout(frame)
1584                                # SelectedObjectManagerView
1585                                SelectedObjectManagerView(vLayout, self.selectedObjectManager)
1586                                ## material settings
1587                                Spacer(vLayout, Size([0, 10]))
1588                                mbox = Box(vLayout, L("Material Settings"), 0 , 10)
1589                                mvLayout = VerticalLayout(mbox)
1590                                StringView(mvLayout, Size([200, 20]), self.materalScriptName, T("Material File: "), \
1591                                        T("All material definitions go in this file (relative to the export path)."))
1592                                mvhLayout = HorizontalLayout(mvLayout)
1593                                ToggleView(mvhLayout, Size([Size.INFINITY, 20], [150, 20]), self.colouredAmbient, \
1594                                        T("Coloured Ambient"), \
1595                                        T("Use Amb factor times diffuse colour as ambient instead of Amb factor times white."))
1596                                ToggleView(mvhLayout, Size([Size.INFINITY, 20], [150, 20]), self.gameEngineMaterials, \
1597                                        T("Game Engine Materials"), \
1598                                        T("Export game engine materials instead of rendering materials."))
1599                                ToggleView(mvLayout, Size([Size.INFINITY, 20], [150, 20]), self.copyTextures, \
1600                                        T("Copy Textures"), \
1601                                        T("Copy texture files into export path."))
1602                                ## global settings
1603                                Spacer(vLayout, Size([0, 10]))
1604                                ToggleView(vLayout, Size([Size.INFINITY, 20], [150, 20]), self.convertXML, T("OgreXMLConverter"), \
1605                                        T("Run OgreXMLConverter on the exported XML files."))
1606                                # path panel
1607                                phLayout = HorizontalLayout(vLayout)
1608                                StringView(phLayout, Size([Size.INFINITY, 20], [200, 20]), self.exportPath, T("Path: "), \
1609                                        T("The directory where the exported files are saved."))
1610                                Button(phLayout, Size([70, 20]), MeshExporterApplication.SelectAction(self), T("Select"), \
1611                                        T("Select the export directory."))                             
1612                                ## buttons
1613                                Spacer(vLayout, Size([0, 10]))
1614                                bhLayout = HorizontalLayout(vLayout)
1615                                bSize = Size([Size.INFINITY, 30], [Blender.Draw.GetStringWidth('Preferences')+10, 30])
1616                                Button(bhLayout, bSize, MeshExporterApplication.ExportAction(self), T("Export"), \
1617                                        T("Export selected mesh objects."))
1618                                Button(bhLayout, bSize, MeshExporterApplication.PreferencesAction(self), T("Preferences"), \
1619                                        T("Exporter preferences."))
1620                                Button(bhLayout, bSize, MeshExporterApplication.HelpAction(), T("Help"), \
1621                                        T("Get help."))
1622                                Button(bhLayout, bSize, MeshExporterApplication.QuitAction(self), T("Quit"), \
1623                                        T("Quit without exporting."))
1624                                return
1625                        def go(self):
1626                                self.mainScreen.activate()
1627                                return
1628                        def _loadPackageSettings(self):
1629                                materalScriptName = PackageSettings.getSingleton().getSetting('materalScriptName')
1630                                if materalScriptName is not None:
1631                                        self.materalScriptName.setValue(materalScriptName)
1632                                colouredAmbient = PackageSettings.getSingleton().getSetting('colouredAmbient')
1633                                if colouredAmbient is not None:
1634                                        self.colouredAmbient.setValue(colouredAmbient)
1635                                gameEngineMaterials = PackageSettings.getSingleton().getSetting('gameEngineMaterials')
1636                                if gameEngineMaterials is not None:
1637                                        self.gameEngineMaterials.setValue(gameEngineMaterials)
1638                                copyTextures = PackageSettings.getSingleton().getSetting('copyTextures')
1639                                if copyTextures is not None:
1640                                        self.copyTextures.setValue(copyTextures)
1641                                convertXML = PackageSettings.getSingleton().getSetting('convertXML')
1642                                if convertXML is not None:
1643                                        self.convertXML.setValue(convertXML)
1644                                exportPath = PackageSettings.getSingleton().getSetting('exportPath')
1645                                if exportPath is not None:
1646                                        self.exportPath.setValue(exportPath)
1647                                return
1648                        def _savePackageSettings(self):
1649                                self.selectedObjectManager.savePackageSettings()
1650                                PackageSettings.getSingleton().setSetting('materalScriptName', self.materalScriptName.getValue())
1651                                PackageSettings.getSingleton().setSetting('colouredAmbient', self.colouredAmbient.getValue())
1652                                PackageSettings.getSingleton().setSetting('gameEngineMaterials', self.gameEngineMaterials.getValue())
1653                                PackageSettings.getSingleton().setSetting('copyTextures', self.copyTextures.getValue())
1654                                PackageSettings.getSingleton().setSetting('convertXML', self.convertXML.getValue())
1655                                PackageSettings.getSingleton().setSetting('exportPath', self.exportPath.getValue())
1656                                PackageSettings.getSingleton().save()
1657                                return
1658                        class PreferencesAction(Action):
1659                                def __init__(self, app):
1660                                        self.app = app
1661                                        return
1662                                def execute(self):
1663                                        self.app.preferencesScreen.activate()
1664                                        return
1665                        class HelpAction(Action):
1666                                def execute(self):
1667                                        dirList = [Blender.Get('datadir'), Blender.Get('udatadir'), Blender.Get('scriptsdir'), Blender.Get('uscriptsdir')]
1668                                        stack = [dir for dir in dirList if dir is not None]
1669                                        found = False
1670                                        helpFile = ''
1671                                        while not(found) and (len(stack) > 0):
1672                                                dir = stack.pop(0)
1673                                                helpFile = Blender.sys.join(dir, Blender.sys.join('ogrehelp','ogremeshesexporter.html'))
1674                                                if Blender.sys.exists(helpFile):
1675                                                        found = True
1676                                        if found:
1677                                                webbrowser.open(helpFile, 1, 1)
1678                                        else:
1679                                                webbrowser.open("http://www.ogre3d.org/phpBB2/search.php", 1, 1)
1680                                        return
1681                        class UpdateAction(Action):
1682                                def __init__(self, app):
1683                                        self.app = app
1684                                        return
1685                        class SelectAction(Action):
1686                                def __init__(self, app):
1687                                        self.app = app
1688                                        return
1689                                def execute(self):
1690                                        Blender.Window.FileSelector(self.app.exportPath.setValue, "Export Directory", self.app.exportPath.getValue())
1691                                        return
1692                        class ExportAction(Action):
1693                                def __init__(self, app):
1694                                        self.app = app
1695                                        self.exportScreen = None
1696                                        self.logView = None
1697                                        return
1698                                def execute(self):
1699                                        # create export screen
1700                                        self.exportScreen = Screen()
1701                                        frame = OgreFrame(self.exportScreen, "Meshes Exporter")
1702                                        vLayout = VerticalLayout(frame)
1703                                        LabelView(vLayout, L('Export Log:', 'large'))
1704                                        self.logView = LogView(vLayout, Size([Size.INFINITY, Size.INFINITY], [300, 200]), 20, False)
1705                                        Spacer(vLayout, Size([0, 10]))
1706                                        activator = Activator(vLayout, False)
1707                                        bhLayout = HorizontalLayout(activator)
1708                                        Button(bhLayout, Size([Size.INFINITY, 30], [120, 30]), MeshExporterApplication.ExportAction.OkAction(self), \
1709                                                T("Ok"), T("Close export log."))
1710                                        Spacer(bhLayout, Size([Size.INFINITY, 30], [120, 30]))
1711                                        Spacer(bhLayout, Size([Size.INFINITY, 30], [120, 30]))
1712                                        Button(bhLayout, Size([Size.INFINITY, 30], [120, 30]), MeshExporterApplication.QuitAction(self.app), \
1713                                                T("Quit"), T("Quit exporter."))
1714                                        self.exportScreen.activate()
1715                                        # save package settings on every export
1716                                        self.app._savePackageSettings()
1717                                        Log.getSingleton().logInfo("Exporting...")
1718                                        self.app.selectedObjectManager.export(self.app.exportPath.getValue(), \
1719                                                self.app.materalScriptName.getValue(), \
1720                                                self.app.colouredAmbient.getValue(), \
1721                                                self.app.gameEngineMaterials.getValue(), \
1722                                                self.app.convertXML.getValue(), \
1723                                                self.app.copyTextures.getValue())
1724                                        Log.getSingleton().logInfo("Done.")
1725                                        activator.setEnabled(True)
1726                                        Blender.Draw.Redraw(1)
1727                                        return
1728                                class OkAction(Action):
1729                                        def __init__(self, exportAction):
1730                                                self.action = exportAction
1731                                                return
1732                                        def execute(self):
1733                                                self.action.exportScreen.deactivate()
1734                                                # remove view from model
1735                                                self.action.logView.detachModel()
1736                                                return
1737                        class QuitAction(QuitAction):
1738                                def __init__(self, app):
1739                                        self.app = app
1740                                        return
1741                                def execute(self):
1742                                        self.app._savePackageSettings()
1743                                        QuitAction.execute(self)
1744                                        return
1745
1746                application = MeshExporterApplication()
1747                application.go()
Note: See TracBrowser for help on using the repository browser.