source: OGRE/trunk/ogrenew/Tools/XSIExport/src/OgreXSIExport.cpp @ 657

Revision 657, 31.2 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include <xsi_value.h>
26#include <xsi_status.h>
27#include <xsi_application.h>
28#include <xsi_plugin.h>
29#include <xsi_pluginitem.h>
30#include <xsi_pluginregistrar.h>
31#include <xsi_pluginitem.h>
32#include <xsi_command.h>
33#include <xsi_argument.h>
34#include <xsi_context.h>
35#include <xsi_menuitem.h>
36#include <xsi_menu.h>
37#include <xsi_model.h>
38#include <xsi_customproperty.h>
39#include <xsi_ppglayout.h>
40#include <xsi_ppgeventcontext.h>
41#include <xsi_selection.h>
42#include <xsi_comapihandler.h>
43#include <xsi_uitoolkit.h>
44#include <xsi_time.h>
45#include <xsi_griddata.h>
46#include <xsi_gridwidget.h>
47#include <xsi_mixer.h>
48#include <xsi_source.h>
49
50#include "OgreXSIMeshExporter.h"
51#include "OgreXSISkeletonExporter.h"
52#include "OgreXSIMaterialExporter.h"
53#include "OgreLogManager.h"
54#include "OgreException.h"
55#include "OgreXSIHelper.h"
56#include "OgreProgressiveMesh.h"
57#include "OgreString.h"
58#include "OgreLogManager.h"
59#include "OgreMeshManager.h"
60#include "OgreSkeletonManager.h"
61#include "OgreDefaultHardwareBufferManager.h"
62#include "OgreMaterialManager.h"
63
64using namespace XSI;
65
66#define OGRE_XSI_EXPORTER_VERSION L"1.0.7"
67
68/** This is the main file for the OGRE XSI plugin.
69The purpose of the methods in this file are as follows:
70
71XSILoadPlugin
72  registers the export command, the menu item, and the option dialog
73
74XSIUnloadPlugin
75  cleans up
76
77OgreMeshExportCommand_Init
78  Defines the arguments to the export command
79
80OgreMeshExportCommand_Execute
81  Runs the exporter using arguments obtained from a context object
82  (I assume this is to allow general access to this export rather than using
83   the property dialog)
84
85OgreMeshExportMenu_Init
86  Defines the menu text and the event callback to execute (OnOgreMeshExportMenu)
87
88OnOgreMeshExportMenu
89  Callback event when clicking the export menu option. Adds an instance of the
90  options dialog as a property, then uses the InspectObj XSI command to pop it up
91  in a modal dialog. If it wasn't cancelled, performs an export.
92
93OgreMeshExportOptions_Define
94  Defines the persistable parameters on the options dialog
95
96OgreMeshExportOptions_DefineLayout
97  Defines the visual layout of the options dialog
98
99OgreMeshExportOptions_PPGEvent
100  Event handler for when the options dialog is interacted with
101*/
102
103CString GetUserSelectedObject();
104CStatus Popup( const CString& in_inputobjs, const CString& in_keywords, const CString& in_title, const CValue& in_mode, bool in_throw );
105void DeleteObj( const CValue& in_inputobj );
106
107Ogre::AnimationList animList;
108
109
110#ifdef unix
111extern "C"
112#endif
113/** Registers the export command, the menu item, and the option dialog */
114CStatus XSILoadPlugin( XSI::PluginRegistrar& registrar )
115{
116        registrar.PutAuthor( L"Steve Streeting" );
117        registrar.PutName( L"OGRE Exporter Plugin" );   
118    registrar.PutVersion( 1, 0 );
119    registrar.PutURL(L"http://www.ogre3d.org");
120   
121
122        // register the mesh export command
123        registrar.RegisterCommand( L"OgreMeshExportCommand", L"OgreMeshExportCommand" );
124
125    // register the menu under File > Export
126        registrar.RegisterMenu(siMenuMainFileExportID, L"OgreMeshExportMenu", false, false);
127
128        // register the export dialog properties factory
129        registrar.RegisterProperty( L"OgreMeshExportOptions" );
130
131#ifdef _DEBUG
132    Application app;
133    app.LogMessage( registrar.GetName() + L" has been loaded.");
134#endif
135
136    return XSI::CStatus::OK;   
137}
138
139#ifdef unix
140extern "C"
141#endif
142/** Cleans up */
143XSI::CStatus XSIUnloadPlugin( const XSI::PluginRegistrar& registrar )
144{
145#ifdef _DEBUG
146    Application app;
147        app.LogMessage(registrar.GetName() + L" has been unloaded.");
148#endif
149
150        return XSI::CStatus::OK;
151}
152
153#ifdef unix
154extern "C"
155#endif
156/** Defines the arguments to the export command */
157XSI::CStatus OgreMeshExportCommand_Init( const XSI::CRef& context )
158{
159        Context ctx(context);
160        Command cmd(ctx.GetSource());
161
162        Application app;
163        app.LogMessage( L"Defining: " + cmd.GetName() );
164
165        ArgumentArray args = cmd.GetArguments();
166
167    args.Add( L"objectName", L"" );
168        args.Add( L"targetMeshFileName", L"c:/default.mesh" );
169        args.Add( L"calculateEdgeLists", L"true" );
170    args.Add( L"calculateTangents", L"false" );
171    args.Add( L"exportSkeleton", L"true" );
172    args.Add( L"targetSkeletonFileName", L"c:/default.skeleton" );
173    args.Add( L"fps", L"24" );
174    args.Add( L"animationList", L"" );
175        return XSI::CStatus::OK;
176
177}
178
179#ifdef unix
180extern "C"
181#endif
182/** Runs the exporter using arguments obtained from a context object
183  (I assume this is to allow general access to this export rather than using
184   the property dialog)
185*/
186XSI::CStatus OgreMeshExportCommand_Execute( XSI::CRef& in_context )
187{
188        Application app;
189        Context ctxt(in_context);
190        CValueArray args = ctxt.GetAttribute( L"Arguments" );
191
192#ifdef _DEBUG
193        for (long i=0; i<args.GetCount(); i++)
194        {
195                app.LogMessage( L"Arg" + CValue(i).GetAsText() + L": " +
196                        args[i].GetAsText() );                 
197        }
198#endif
199
200        if ( args.GetCount() != 9 )
201        {
202                // Arguments of the command might not be properly registered
203                return CStatus::InvalidArgument ;
204        }
205
206    // TODO - perform the export!
207
208    return XSI::CStatus::OK;
209}
210
211
212#ifdef unix
213extern "C"
214#endif
215/** Defines the menu text and the event callback to execute (OnOgreMeshExportMenu) */
216XSI::CStatus OgreMeshExportMenu_Init( XSI::CRef& in_ref )
217{
218        Context ctxt = in_ref;
219        Menu menu = ctxt.GetSource();
220
221        CStatus st;
222        MenuItem item;
223        menu.AddCallbackItem(L"OGRE Mesh / Skeleton...", L"OnOgreMeshExportMenu", item);
224
225        return CStatus::OK;     
226}
227
228CString exportPropertyDialogName = L"OgreMeshExportOptions";
229
230#ifdef unix
231extern "C"
232#endif
233/** Callback event when clicking the export menu option. Adds an instance of the
234    options dialog as a property, then uses the InspectObj XSI command to pop it up
235    in a modal dialog. If it wasn't cancelled, performs an export.
236*/
237XSI::CStatus OnOgreMeshExportMenu( XSI::CRef& in_ref )
238{       
239        Ogre::LogManager logMgr;
240        logMgr.createLog("OgreXSIExporter.log", true);
241        CString msg(L"OGRE Exporter Version ");
242        msg += OGRE_XSI_EXPORTER_VERSION;
243        LogOgreAndXSI(msg);
244
245        Application app;
246        CStatus st(CStatus::OK);
247        Property prop = app.GetActiveSceneRoot().GetProperties().GetItem(exportPropertyDialogName);
248        if (prop.IsValid())
249        {
250                // Check version number
251                CString currVersion(prop.GetParameterValue(L"version"));
252                if (!currVersion.IsEqualNoCase(OGRE_XSI_EXPORTER_VERSION))
253                {
254                        DeleteObj(exportPropertyDialogName);
255                        prop.ResetObject();
256                }
257        }
258        if (!prop.IsValid())
259        {
260                prop = app.GetActiveSceneRoot().AddProperty(exportPropertyDialogName);
261                prop.PutParameterValue(L"version", CString(OGRE_XSI_EXPORTER_VERSION));
262        }
263       
264        try
265        {
266                // Popup Returns true if the command was cancelled otherwise it returns false.
267                CStatus ret = Popup(exportPropertyDialogName,CValue(),L"OGRE Mesh / Skeleton Export",(long)siModal,true);
268                if (ret == CStatus::OK)
269                {
270                        Ogre::XsiMeshExporter meshExporter;
271                        Ogre::XsiSkeletonExporter skelExporter;
272
273                        // retrieve the parameters
274                        Parameter param = prop.GetParameters().GetItem(L"objectName");
275                        CString objectName = param.GetValue();
276                        param = prop.GetParameters().GetItem( L"targetMeshFileName" );
277                        Ogre::String meshFileName = XSItoOgre(param.GetValue());
278                        if (meshFileName.empty())
279                        {
280                                OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
281                                        "You must supply a mesh file name",
282                                        "OGRE Exporter");
283                        }
284                        param = prop.GetParameters().GetItem( L"mergeSubmeshes" );
285                        bool mergeSubmeshes = param.GetValue();
286                        param = prop.GetParameters().GetItem( L"exportChildren" );
287                        bool exportChildren = param.GetValue();
288                        param = prop.GetParameters().GetItem( L"calculateEdgeLists" );
289                        bool edgeLists = param.GetValue();
290                        param = prop.GetParameters().GetItem( L"calculateTangents" );
291                        bool tangents = param.GetValue();
292                        param = prop.GetParameters().GetItem( L"numLodLevels" );
293                        long numlods = param.GetValue();
294                        Ogre::XsiMeshExporter::LodData* lodData = 0;
295                        if (numlods > 0)
296                        {
297                                param = prop.GetParameters().GetItem( L"lodDistanceIncrement" );
298                                float distanceInc = param.GetValue();
299
300                                param = prop.GetParameters().GetItem(L"lodQuota");
301                                CString quota = param.GetValue();
302
303                                param = prop.GetParameters().GetItem(L"lodReduction");
304                                float reduction = param.GetValue();
305
306                                lodData = new Ogre::XsiMeshExporter::LodData;
307                                float currentInc = distanceInc;
308                                for (int l = 0; l < numlods; ++l)
309                                {
310                                        lodData->distances.push_back(currentInc);
311                                        currentInc += distanceInc;
312                                }
313                                lodData->quota = (quota == L"p") ?
314                                        Ogre::ProgressiveMesh::VRQ_PROPORTIONAL : Ogre::ProgressiveMesh::VRQ_CONSTANT;
315                                if (lodData->quota == Ogre::ProgressiveMesh::VRQ_PROPORTIONAL)
316                                        lodData->reductionValue = reduction * 0.01;
317                                else
318                                        lodData->reductionValue = reduction;
319
320                        }
321
322                        param = prop.GetParameters().GetItem( L"exportSkeleton" );
323                        bool exportSkeleton = param.GetValue();
324                        param = prop.GetParameters().GetItem( L"exportMaterials" );
325                        bool exportMaterials = param.GetValue();
326                        param = prop.GetParameters().GetItem( L"copyTextures" );
327                        bool copyTextures = param.GetValue();
328
329                        // create singletons
330                        Ogre::ResourceGroupManager rgm;
331                        Ogre::MeshManager meshMgr;
332                        Ogre::SkeletonManager skelMgr;
333                        Ogre::MaterialManager matMgr;
334                        Ogre::DefaultHardwareBufferManager hardwareBufMgr;
335
336                       
337                        // determine number of exportsteps
338                        size_t numSteps = 3 + OGRE_XSI_NUM_MESH_STEPS;
339                        if (numlods > 0)
340                                numSteps++;
341                        if (edgeLists)
342                                numSteps++;
343                        if (tangents)
344                                numSteps++;
345                        if (exportSkeleton)
346                                numSteps += 3;
347
348                        Ogre::ProgressManager progressMgr(numSteps);
349                       
350                        // Any material prefix? We need that for mesh linking too
351                        param = prop.GetParameters().GetItem( L"materialPrefix" );
352                        Ogre::String materialPrefix = XSItoOgre(param.GetValue());
353
354                        if (exportSkeleton)
355                        {
356                                param = prop.GetParameters().GetItem( L"targetSkeletonFileName" );
357                                Ogre::String skeletonFileName = XSItoOgre(param.GetValue());
358                                if (skeletonFileName.empty())
359                                {
360                                        OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
361                                                "You must supply a skeleton file name",
362                                                "OGRE Exporter");
363                                }
364                                param = prop.GetParameters().GetItem( L"fps" );
365                                float fps = param.GetValue();
366                                if (fps == 0.0f)
367                                {
368                                        OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
369                                                "You must supply a valid value for 'FPS'",
370                                                "OGRE Export");
371                                }
372
373                                param = prop.GetParameters().GetItem( L"animationList" );
374                                GridData gd(param.GetValue());
375                                Ogre::AnimationList selAnimList;
376                                bool anyIKSample = false;
377                                for (int a = 0; a < gd.GetRowCount(); ++a)
378                                {
379                                        if (gd.GetCell(1, a) == true)
380                                        {
381                                                Ogre::String name = XSItoOgre(gd.GetCell(0, a));
382
383                                                for (Ogre::AnimationList::iterator ai = animList.begin(); ai != animList.end(); ++ai)
384                                                {
385                                                        if (ai->animationName == name)
386                                                        {
387                                                                if (gd.GetCell(2, a))
388                                                                {
389                                                                        // IK sample
390                                                                        ai->ikSample = true;
391                                                                        ai->ikSampleInterval = gd.GetCell(3, a);
392                                                                        anyIKSample = true;
393
394                                                                }
395                                                                else
396                                                                {
397                                                                        ai->ikSample = false;
398                                                                }
399                                                                selAnimList.push_back(*ai);
400                                                                break;
401                                                        }
402                                                }
403                                        }
404                                }
405
406                                // Warn about effect of IK sampling
407                                if (anyIKSample)
408                                {
409                                        long btn;
410                                        CStatus ret = app.GetUIToolkit().MsgBox(
411                                                L"You have chosen to sample one or more of your "
412                                                L"animations (in order to convert IK or other "
413                                                L"constraint-based animation). \n\n This will require "
414                                                L"all animation which has not yet been stored in an "
415                                                L"action to be removed, and the mixer to be cleared. "
416                                                L"Is this OK?",
417                                                siMsgYesNo,
418                                                L"Animation sampling required",
419                                                btn);
420                                        if (btn != 6)
421                                                return CStatus::Fail;
422                                       
423                                }
424
425                                // Truncate the skeleton filename to just the name (no path)
426                                Ogre::String skelName = skeletonFileName;
427                                int pos = skeletonFileName.find_last_of("\\");
428                                if (pos == Ogre::String::npos)
429                                {
430                                        pos = skeletonFileName.find_last_of("/");
431                                }
432                                if (pos != Ogre::String::npos)
433                                {
434                                        skelName = skelName.substr(pos+1, skelName.size() - pos - 1);
435                                }
436
437
438                                // Do the mesh
439                                Ogre::DeformerMap& deformers =
440                                        meshExporter.exportMesh(meshFileName, mergeSubmeshes,
441                                                exportChildren, edgeLists, tangents, materialPrefix,
442                                                lodData, skelName);
443                                // do the skeleton
444                                skelExporter.exportSkeleton(skeletonFileName, deformers, fps, selAnimList);
445
446
447
448                        }
449                        else
450                        {
451                                // Just mesh
452                                meshExporter.exportMesh(meshFileName, mergeSubmeshes,
453                                        exportChildren, edgeLists, tangents, materialPrefix, lodData);
454                        }
455
456                       
457                        delete lodData;
458
459                        // Do we want to export materials too?
460                        if (exportMaterials)
461                        {
462                                param = prop.GetParameters().GetItem( L"targetMaterialFileName" );
463                                Ogre::String materialFileName = XSItoOgre(param.GetValue());
464                               
465                                Ogre::XsiMaterialExporter matExporter;
466                                try
467                                {
468                                        matExporter.exportMaterials(meshExporter.getMaterials(),
469                                                meshExporter.getTextureProjectionMap(),
470                                                materialFileName, copyTextures, materialPrefix);
471                                }
472                                catch (Ogre::Exception& e)
473                                {
474                                        // ignore, non-fatal and will be in log
475                                }
476                        }
477
478                }
479
480        }
481        catch (Ogre::Exception& e)
482        {
483                // Will already have been logged to the Ogre log manager
484                // Tell XSI
485                app.LogMessage(OgretoXSI(e.getDescription()), XSI::siFatalMsg);
486                app.LogMessage(OgretoXSI(e.getFullDescription()), XSI::siInfoMsg);
487        }
488
489        //DeleteObj( L"OgreMeshExportOptions" );
490        return st;     
491}
492
493
494#ifdef unix
495extern "C"
496#endif
497/** Defines the persistable parameters on the options dialog */
498CStatus OgreMeshExportOptions_Define( const CRef & in_Ctx )
499{
500        // Here is where we add all the parameters to the
501        // Custom Property.  This will be called each time
502        // an new instance of the Custom Property is called.
503        // It is not called when an persisted Custom Property is loaded.
504
505    Application app ;
506        CustomProperty prop = Context(in_Ctx).GetSource();
507        Parameter param ;
508
509        // Default capabilities for most of these parameters
510        int caps = siPersistable  ;
511        CValue nullValue;       // Used for arguments we don't want to set
512
513        prop.AddParameter(     
514                L"version",CValue::siString, caps,
515                L"Version", L"",
516                nullValue, param) ;     
517    prop.AddParameter( 
518        L"objectName",CValue::siString, caps,
519        L"Object Name", L"",
520        nullValue, param) ;     
521        prop.AddParameter(     
522                L"objects",CValue::siRefArray, caps,
523                L"Collection of selected objects", L"",
524                nullValue, param) ;     
525        prop.AddParameter(     
526        L"targetMeshFileName",CValue::siString, caps,
527                L"Mesh Filename", L"",
528                nullValue, param) ;     
529        prop.AddParameter(
530                L"mergeSubmeshes",CValue::siBool, caps,
531                L"Merge objects with same material?",
532                L"If false, a separate named SubMesh will be created for every PolygonMesh "
533                L"preserving your model divisions. If true, the exporter will merge all "
534                L"PolygonMesh objects with the same material, which is more efficient, but "
535                L"does not preserve your modelling divisions.",
536                CValue(true), param) ; 
537        prop.AddParameter(
538                L"exportChildren",CValue::siBool, caps,
539                L"Export Children",
540                L"If true, children of all selected objects will be exported.",
541                CValue(true), param) ; 
542    prop.AddParameter( 
543        L"calculateEdgeLists",CValue::siBool, caps,
544        L"Calculate Edge Lists (stencil shadows)", L"",
545        CValue(true), param) ; 
546    prop.AddParameter( 
547        L"calculateTangents",CValue::siBool, caps,
548        L"Calculate Tangents (normal mapping)", L"",
549        CValue(false), param) ;
550        prop.AddParameter(     
551                L"numLodLevels",CValue::siInt2, caps,
552                L"Levels of Detail", L"",
553                CValue(0L), param) ;   
554        prop.AddParameter(     
555                L"lodDistanceIncrement",CValue::siFloat, caps,
556                L"Distance Increment", L"",
557                CValue(2000L), //default
558                CValue(1L), // hard min
559                CValue(1000000L), // hard max
560                CValue(50L), // suggested min
561                CValue(10000L), // suggested max
562                param) ;       
563        prop.AddParameter(     
564                L"lodQuota",CValue::siString, caps,
565                L"Reduction Style", L"",
566                L"p", param) ; 
567        prop.AddParameter(     
568                L"lodReduction",CValue::siFloat, caps,
569                L"Reduction Value", L"",
570                CValue(50.0f), param) ;
571    prop.AddParameter( 
572        L"exportSkeleton",CValue::siBool, caps,
573        L"Export Skeleton", L"",
574        CValue(true), param) ; 
575    prop.AddParameter( 
576        L"targetSkeletonFileName",CValue::siString, caps,
577        L"Skeleton Filename", L"",
578        nullValue, param) ;     
579    prop.AddParameter(
580        L"fps",CValue::siInt2, caps,
581        L"Frames per second", L"",
582        CValue(24l), param) ;   
583        prop.AddGridParameter(L"animationList");       
584        prop.AddParameter(
585                L"exportMaterials", CValue::siBool, caps,
586                L"Export Materials", L"",
587                CValue(true), param);
588        prop.AddParameter(
589                L"copyTextures", CValue::siBool, caps,
590                L"Copy Textures To Folder", L"",
591                CValue(true), param);
592    prop.AddParameter( 
593        L"targetMaterialFileName",CValue::siString, caps,
594        L"Material Filename", L"",
595        nullValue, param) ;     
596        prop.AddParameter(     
597                L"materialPrefix",CValue::siString, caps,
598                L"Material Prefix", L"",
599                nullValue, param) ;     
600               
601
602
603        return CStatus::OK;     
604}
605
606#ifdef unix
607extern "C"
608#endif
609/** Defines the visual layout of the options dialog */
610CStatus OgreMeshExportOptions_DefineLayout( const CRef & in_Ctx )
611{
612        // XSI will call this to define the visual appearance of the CustomProperty
613        // The layout is shared between all instances of the CustomProperty
614        // and is cached.  You can force the code to re-execute by using the
615        // XSIUtils.Refresh feature.
616
617        PPGLayout oLayout = Context( in_Ctx ).GetSource() ;
618        PPGItem item ;
619
620        oLayout.Clear() ;
621
622        // Mesh tab
623        oLayout.AddTab(L"Basic");
624    // Object
625
626        oLayout.AddGroup(L"Object(s) to export");
627        item = oLayout.AddItem(L"objectName");
628    item.PutAttribute( siUINoLabel, true );
629        oLayout.EndGroup();
630       
631        /*
632    item.PutWidthPercentage(80);
633    item = oLayout.AddButton(L"Refresh", L"Refresh");
634    item.PutWidthPercentage(1) ;
635        */
636
637        oLayout.AddGroup(L"Mesh");
638    item = oLayout.AddItem(L"targetMeshFileName", L"Target", siControlFilePath);
639        item.PutAttribute( siUINoLabel, true );
640        item.PutAttribute( siUIFileFilter, L"OGRE Mesh format (*.mesh)|*.mesh|All Files (*.*)|*.*||" );
641        item = oLayout.AddItem(L"mergeSubmeshes") ;
642        item = oLayout.AddItem(L"exportChildren") ;
643
644
645    item = oLayout.AddItem(L"calculateEdgeLists");
646    item = oLayout.AddItem(L"calculateTangents");
647        oLayout.AddGroup(L"Level of Detail Reduction");
648    item = oLayout.AddItem(L"numLodLevels");
649        item = oLayout.AddItem(L"lodDistanceIncrement");
650        CValueArray vals;
651        vals.Add(L"Percentage");
652        vals.Add(L"p");
653        vals.Add(L"Constant");
654        vals.Add(L"c");
655        item = oLayout.AddEnumControl(L"lodQuota", vals, L"Quota", XSI::siControlCombo);
656        item = oLayout.AddItem(L"lodReduction");
657        oLayout.EndGroup();
658        oLayout.EndGroup();
659
660        oLayout.AddTab(L"Materials");
661        // Material Tab
662    item = oLayout.AddItem(L"exportMaterials") ;
663    item = oLayout.AddItem(L"targetMaterialFileName", L"Target", siControlFilePath) ;
664        item.PutAttribute( siUINoLabel, true );
665        item.PutAttribute( siUIFileFilter, L"OGRE Material script (*.material)|*.material|All Files (*.*)|*.*||" );
666        item = oLayout.AddItem(L"materialPrefix");
667    item = oLayout.AddItem(L"copyTextures");
668       
669       
670        // Skeleton Tab
671        oLayout.AddTab(L"Animation");
672
673        item = oLayout.AddItem(L"exportSkeleton");
674        item = oLayout.AddItem(L"targetSkeletonFileName", L"Target", siControlFilePath);
675        item.PutAttribute( siUINoLabel, true );
676        item.PutAttribute( siUIFileFilter, L"OGRE Skeleton format (*.skeleton)|*.skeleton|All Files (*.*)|*.*||" );
677        item = oLayout.AddItem(L"fps");
678        item = oLayout.AddItem(L"animationList", L"Animations", siControlGrid);
679        item.PutAttribute(siUIGridColumnWidths, L"0:120:60:90:130");
680        item.PutAttribute(siUIGridHideRowHeader, true);
681        // Make animatino name read-only
682        item.PutAttribute(siUIGridReadOnlyColumns, L"1:0:0:0");
683
684
685
686
687
688
689
690        return CStatus::OK;     
691}
692
693
694bool hasSkeleton(X3DObject& si, bool recurse)
695{
696        if (si.GetEnvelopes().GetCount() > 0)
697        {
698                return true;
699        }
700
701        if (recurse)
702        {
703
704                CRefArray children = si.GetChildren();
705
706                for(long i = 0; i < children.GetCount(); i++)
707                {
708                        X3DObject child(children[i]);
709                        bool ret = hasSkeleton(child, recurse);
710                        if (ret)
711                                return ret;
712                }
713        }
714
715        return false;
716       
717}
718
719bool hasSkeleton(Selection& sel, bool recurse)
720{
721        // iterate over selection
722        for (int i = 0; i < sel.GetCount(); ++i)
723        {
724                X3DObject obj(sel[i]);
725                bool ret = hasSkeleton(obj, recurse);
726                if (ret)
727                        return ret;
728        }
729
730        return false;
731}
732
733bool isAnimationIK(XSI::ActionSource& source)
734{
735        // Iterate over the animation items, and return true if any of them
736        // are effectors.
737        Application app;
738        CRefArray items = source.GetItems();
739        for (int i = 0; i < items.GetCount(); ++i)
740        {
741                XSI::AnimationSourceItem item = items[i];
742
743                // Check the target
744                Ogre::String target = XSItoOgre(item.GetTarget());
745                size_t firstDotPos = target.find_first_of(".");
746                if (firstDotPos != Ogre::String::npos)
747                {
748                        Ogre::String targetName = target.substr(0, firstDotPos);
749                        // Find object
750                        X3DObject targObj = app.GetActiveSceneRoot().FindChild(
751                                OgretoXSI(targetName), L"", CStringArray());
752                        if (targObj.IsValid())
753                        {
754                                if (targObj.IsA(siChainEffectorID))
755                                        return true;
756                        }
757                }
758        }
759
760        return false;
761
762
763}
764
765void findAnimations(XSI::Model& model, Ogre::AnimationList& animList)
766{
767        XSI::CRefArray sources = model.GetSources();
768        for (int s = 0; s < sources.GetCount(); ++s)
769        {
770                XSI::Source src(sources[s]);
771                if (src.IsA(siActionSourceID))
772                {
773                        bool add = true;
774                        Ogre::String name = XSItoOgre(src.GetName());
775                        for (Ogre::AnimationList::iterator e = animList.begin(); e != animList.end(); ++e)
776                        {
777                                if (e->animationName == name)
778                                {
779                                        add = false;
780                                        break;
781                                }
782                        }
783                        if (add)
784                        {
785                                Ogre::AnimationEntry anim;
786                                anim.animationName = name;
787                                anim.startFrame = -1;
788                                anim.endFrame = -1;
789                                anim.source = ActionSource(src);
790                                // default to sampling
791                                anim.ikSample = true;
792                                anim.ikSampleInterval = 5.0f;
793                                animList.push_back(anim);
794                        }
795                }
796
797        }
798
799}
800
801void getAnimations(XSI::Model& root, Ogre::AnimationList& animList)
802{
803        animList.clear();
804
805        findAnimations(root, animList);
806
807        // Find all children (recursively)
808        XSI::CRefArray children = root.FindChildren(L"", siModelType, XSI::CStringArray());
809        for (int c = 0; c < children.GetCount(); ++c)
810        {
811                XSI::Model child(children[c]);
812                findAnimations(child, animList);
813        }
814
815}
816
817
818struct AnimSetting
819{
820        bool toexport;
821        bool ik;
822        double ikSampleInterval;
823};
824
825#ifdef unix
826extern "C"
827#endif
828/** Event handler for when the options dialog is interacted with */
829CStatus OgreMeshExportOptions_PPGEvent( const CRef& io_Ctx )
830{
831        // This callback is called when events happen in the user interface
832        // This is where you implement the "logic" code.
833
834        Application app ;
835        static bool hasSkel = false;
836
837        PPGEventContext ctx( io_Ctx ) ;
838
839        PPGEventContext::PPGEvent eventID = ctx.GetEventID() ;
840
841        CustomProperty prop = ctx.GetSource() ;
842        Parameter objectNameParam = prop.GetParameters().GetItem( L"objectName" ) ;
843    // On open dialog
844    if ( eventID == PPGEventContext::siOnInit )
845        {
846        // Pre-populate object with currently selected item(s)
847                Selection sel(app.GetSelection());
848                if (sel.GetCount() > 0)
849                {
850                        CString val;
851                        for (int i = 0; i < sel.GetCount(); ++i)
852                        {
853                                val += SIObject(sel[i]).GetName();
854                                if (i < sel.GetCount() - 1)
855                                        val += L", ";
856                        }
857                        prop.PutParameterValue(L"objectName", val);
858                }
859                else
860                {
861                        // no selection, assume entire scene
862                        prop.PutParameterValue(L"objectName", CString(L"[Entire Scene]"));
863                }
864        // Make the selection read-only
865                objectNameParam.PutCapabilityFlag( siReadOnly, true );
866
867        // enable / disable the skeleton export based on envelopes
868                if (!hasSkeleton(sel, true))
869                {
870                        prop.PutParameterValue(L"exportSkeleton", false);
871                        Parameter param = prop.GetParameters().GetItem(L"exportSkeleton");
872                        param.PutCapabilityFlag(siReadOnly, true);
873                        param = prop.GetParameters().GetItem(L"targetSkeletonFileName");
874                        param.PutCapabilityFlag(siReadOnly, true);
875                        param = prop.GetParameters().GetItem(L"fps");
876                        param.PutCapabilityFlag(siReadOnly, true);
877                        param = prop.GetParameters().GetItem(L"animationList");
878                        param.PutCapabilityFlag(siReadOnly, true);
879                        hasSkel = false;
880                }
881                else
882                {
883                        prop.PutParameterValue(L"exportSkeleton", true);
884                        Parameter param = prop.GetParameters().GetItem(L"exportSkeleton");
885                        param.PutCapabilityFlag(siReadOnly, false);
886                        param = prop.GetParameters().GetItem(L"targetSkeletonFileName");
887                        param.PutCapabilityFlag(siReadOnly, false);
888                        param = prop.GetParameters().GetItem(L"fps");
889                        param.PutCapabilityFlag(siReadOnly, false);
890                        // default the frame rate to that selected in animation panel
891                        prop.PutParameterValue(L"fps", CTime().GetFrameRate());
892                        param = prop.GetParameters().GetItem(L"animationList");
893                        param.PutCapabilityFlag(siReadOnly, false);
894                        // value of param is a griddata object
895                        // initialise it with all animations but try to remember previous values
896                        GridData gd(param.GetValue());
897                        // Store the existing settings
898                        std::map<Ogre::String,AnimSetting> rememberedAnimations;
899                        int row;
900                        for (row = 0; row < gd.GetRowCount(); ++row)
901                        {
902                                AnimSetting s;
903                                s.toexport = gd.GetCell(1, row);
904                                s.ik = gd.GetCell(2, row);
905                                s.ikSampleInterval = gd.GetCell(3, row);
906                                Ogre::String animName = XSItoOgre(gd.GetCell(0, row));
907                                rememberedAnimations[animName] = s;
908                        }
909
910                        // Second & third column is check box                   
911                        gd.PutColumnType(1, siColumnBool);
912                        gd.PutColumnType(2, siColumnBool);
913                        // Name is not adjustable
914
915
916                        gd.PutColumnCount(4);
917                        gd.PutColumnLabel(0, L"Name");
918                        gd.PutColumnLabel(1, L"Export?");
919                        gd.PutColumnLabel(2, L"Sample?");
920                        gd.PutColumnLabel(3, L"Sample Interval");
921
922
923                        XSI::Model appRoot(app.GetActiveSceneRoot());
924                        getAnimations(appRoot, animList);
925                        gd.PutRowCount(animList.size());
926                        row = 0;
927                        for (Ogre::AnimationList::iterator a = animList.begin(); a != animList.end(); ++a, ++row)
928                        {
929                                gd.PutCell(0, row, OgretoXSI(a->animationName));
930                                // do we have a setting for this already?
931                                std::map<Ogre::String, AnimSetting>::iterator ra =
932                                        rememberedAnimations.find(a->animationName);
933
934                                if (ra != rememberedAnimations.end())
935                                {
936                                        AnimSetting& s = ra->second;
937
938                                        gd.PutCell(1, row, s.toexport);
939                                        gd.PutCell(2, row, s.ik);
940                                        gd.PutCell(3, row, s.ikSampleInterval);
941                                }
942                                else
943                                {
944                                        // default to true
945                                        gd.PutCell(1, row, true);
946                                        gd.PutCell(2, row, a->ikSample);
947                                        gd.PutCell(3, row, a->ikSampleInterval);
948                                }
949                        }
950                       
951                        hasSkel = true;
952                }
953        }
954    // On clicking a button
955        else if ( eventID == PPGEventContext::siButtonClicked )
956        {
957                CValue buttonPressed = ctx.GetAttribute( L"Button" );   
958        // Clicked the refresh button
959                /*
960                if ( buttonPressed.GetAsText() == L"Refresh" )
961                {
962                        objectNameParam.PutCapabilityFlag( siReadOnly, false );
963                        // Pre-populate object with currently selected item
964                        Selection sel(app.GetSelection());
965                        CString val;
966                        for (int i = 0; i < sel.GetCount(); ++i)
967                        {
968                                val += SIObject(sel[0]).GetName();
969                                if (i < sel.GetCount() - 1)
970                                        val += L", ";
971                        }
972                        prop.PutParameterValue(L"objectName", val);
973                        prop.PutParameterValue(L"objects", CValue(CRefArray(sel.GetArray())));
974                        // Make the selection read-only
975                        objectNameParam.PutCapabilityFlag( siReadOnly, true );
976                }
977                */
978        }
979    // Changed a parameter
980        else if ( eventID == PPGEventContext::siParameterChange )
981        {
982                Parameter changed = ctx.GetSource() ;   
983                CustomProperty prop = changed.GetParent() ;     
984                CString   paramName = changed.GetScriptName() ;
985
986        // Check paramName against parameter names, perform custom onChanged event
987                if (paramName == L"targetMeshFileName")
988                {
989                        // Default skeleton name if blank
990                        Ogre::String meshName = XSItoOgre(changed.GetValue());
991                        if (hasSkel && Ogre::StringUtil::endsWith(meshName, "mesh") &&
992                                prop.GetParameterValue(L"targetSkeletonFileName") == L"")
993                        {
994                                Ogre::String skelName = meshName.substr(0, meshName.size() - 4) + "skeleton";
995                                CString xsiSkelName = OgretoXSI(skelName);
996                                prop.PutParameterValue(L"targetSkeletonFileName", xsiSkelName);
997                        }
998                        if (Ogre::StringUtil::endsWith(meshName, "mesh") &&
999                                prop.GetParameterValue(L"targetMaterialFileName") == L"")
1000                        {
1001                                // default material script name if blank
1002                                Ogre::String matName = meshName.substr(0, meshName.size() - 4) + "material";
1003                                CString xsiMatName = OgretoXSI(matName);
1004                                prop.PutParameterValue(L"targetMaterialFileName", xsiMatName);
1005                        }
1006
1007                       
1008                }
1009        }
1010
1011
1012        return CStatus::OK;     
1013
1014}
1015
1016CString GetUserSelectedObject()
1017{
1018        Application app;
1019        Model root(app.GetActiveSceneRoot());
1020        CStringArray emptyArray;
1021        CRefArray cRefArray = root.FindChildren( L"", L"", emptyArray, true );
1022
1023        CStringArray nameArray(cRefArray.GetCount());
1024        for ( long i=0; i < cRefArray.GetCount(); i++ )
1025        {
1026                nameArray[i] = SIObject(cRefArray[i]).GetName();
1027        }
1028        //todo qsort the nameArray
1029
1030        // Using the COMAPIHandler for creating a "XSIDial.XSIDialog"
1031        CComAPIHandler xsidialog;
1032        xsidialog.CreateInstance( L"XSIDial.XSIDialog");
1033        CValue index;
1034        CValueArray args(cRefArray.GetCount());
1035        for (long y=0; y < cRefArray.GetCount(); y++)
1036                args[y]=nameArray[y];
1037
1038        xsidialog.Call(L"Combo",index,L"Select Item",args );
1039
1040        long ind = (long)index;
1041        return args[ind];
1042}
1043
1044
1045CStatus Popup( const CString& in_inputobjs, const CString& in_keywords, const CString& in_title, const CValue& /*number*/ in_mode, bool in_throw )
1046{
1047        Application app;
1048        CValueArray args(5);
1049        CValue retval;
1050        long i(0);
1051
1052        args[i++]= in_inputobjs;
1053        args[i++]= in_keywords;
1054        args[i++]= in_title;
1055        args[i++]= in_mode;
1056        args[i++]= in_throw;
1057
1058        return app.ExecuteCommand( L"InspectObj", args, retval );
1059
1060}
1061
1062void DeleteObj( const CValue& in_inputobj )
1063{
1064        Application app;
1065        CValueArray args(1);
1066        CValue retval;
1067        long i(0);
1068
1069        args[i++]= in_inputobj;
1070
1071        CStatus st = app.ExecuteCommand( L"DeleteObj", args, retval );
1072
1073        return;
1074}
Note: See TracBrowser for help on using the repository browser.