1106 lines
40 KiB
C++
1106 lines
40 KiB
C++
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef NL_EXPORT_NEL_H
|
|
#define NL_EXPORT_NEL_H
|
|
|
|
#include "nel/misc/types_nl.h"
|
|
#include "nel/3d/mesh.h"
|
|
#include "nel/3d/material.h"
|
|
#include "nel/3d/mesh_vertex_program.h"
|
|
#include "nel/3d/camera.h"
|
|
#include "nel/3d/key.h"
|
|
#include "nel/3d/track_keyframer.h"
|
|
#include "nel/3d/bone.h"
|
|
#include "nel/3d/animation_time.h"
|
|
#include "nel/3d/animation_time.h"
|
|
#include "nel/../../src/pacs/collision_mesh_build.h"
|
|
|
|
#define UVGEN_MISSING (-1)
|
|
#define UVGEN_REFLEXION (-2)
|
|
#define FLOAT_EPSILON 0.001
|
|
|
|
#define NEL_MTL_A 0x64c75fec
|
|
#define NEL_MTL_B 0x222b9eb9
|
|
#define NEL_LIGHT_CLASS_ID_A 0x36e3181f
|
|
#define NEL_LIGHT_CLASS_ID_B 0x3ac24049
|
|
#define NEL_PACS_BOX_CLASS_ID_A 0x7f374277
|
|
#define NEL_PACS_BOX_CLASS_ID_B 0x5d3971df
|
|
#define NEL_PACS_CYL_CLASS_ID_A 0x62a56810
|
|
#define NEL_PACS_CYL_CLASS_ID_B 0x4b3d601c
|
|
#define NEL_PARTICLE_SYSTEM_CLASS_ID 0x58ce2893
|
|
#define NEL_FLARE_CLASS_ID_A 0x4e913532
|
|
#define NEL_FLARE_CLASS_ID_B 0x3c2f2307
|
|
#define NEL_WAVE_MAKER_CLASS_ID_A 0x77e24828
|
|
#define NEL_WAVE_MAKER_CLASS_ID_B 0x329a1de5
|
|
#define NEL_REMANENT_SEGMENT_CLASS_ID_A 0x72f3588b
|
|
#define NEL_REMANENT_SEGMENT_CLASS_ID_B 0x6eda0a52
|
|
|
|
#define MAX_MAX_TEXTURE 8
|
|
|
|
#define MAX_MORPHER_CLASS_ID Class_ID(0x17bb6854, 0xa5cba2a3)
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
enum TNelValueType
|
|
{
|
|
typeFloat,
|
|
typePos,
|
|
typeScale,
|
|
typeRotation,
|
|
typeColor,
|
|
typeInt,
|
|
typeBoolean,
|
|
typeString,
|
|
typeMatrix,
|
|
};
|
|
|
|
// ***************************************************************************
|
|
|
|
enum TNelScriptValueType
|
|
{
|
|
scriptNothing,
|
|
scriptFloat,
|
|
scriptBool,
|
|
scriptNode,
|
|
};
|
|
|
|
// ***************************************************************************
|
|
|
|
namespace NL3D
|
|
{
|
|
class CAnimation;
|
|
class ITrack;
|
|
class CTrackKeyFramerConstBool;
|
|
class CSkeletonShape;
|
|
class CMRMParameters;
|
|
class IMeshGeom;
|
|
class CInstanceGroup;
|
|
class CVegetableShape;
|
|
class CLodCharacterShapeBuild;
|
|
class CShapeBank;
|
|
class IDriver;
|
|
class CLandscape;
|
|
class CTextureCube;
|
|
};
|
|
|
|
|
|
namespace NLPACS
|
|
{
|
|
class CRetrieverBank;
|
|
class CGlobalRetriever;
|
|
class CPrimitiveBlock;
|
|
};
|
|
|
|
namespace NLMISC
|
|
{
|
|
class CAABBox;
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
// Interface for feed back during calculation
|
|
class IProgress
|
|
{
|
|
public:
|
|
virtual void setLine (uint32 LineNumber, std::string &LineText)=0;
|
|
virtual void update()=0;
|
|
};
|
|
|
|
// ***************************************************************************
|
|
struct CExportNelOptions
|
|
{
|
|
bool bShadow;
|
|
bool bExportLighting;
|
|
bool bExportBgColor;
|
|
bool OutputLightmapLog;
|
|
std::string sExportLighting;
|
|
sint32 nExportLighting;
|
|
float rLumelSize;
|
|
sint32 nOverSampling;
|
|
bool bExcludeNonSelected;
|
|
IProgress *FeedBack;
|
|
bool bShowLumel;
|
|
bool bTestSurfaceLighting;
|
|
float SurfaceLightingCellSize;
|
|
float SurfaceLightingDeltaZ;
|
|
|
|
|
|
CExportNelOptions::CExportNelOptions()
|
|
{
|
|
// If no configuration file
|
|
bShadow = false;
|
|
bExportLighting = false;
|
|
bExportBgColor = true;
|
|
OutputLightmapLog = false;
|
|
sExportLighting = "c:\\temp";
|
|
nExportLighting = 0; // Normal lighting
|
|
rLumelSize = 0.25f;
|
|
nOverSampling = 1;
|
|
bExcludeNonSelected = false;
|
|
FeedBack = NULL;
|
|
bShowLumel = false;
|
|
bTestSurfaceLighting= true;
|
|
SurfaceLightingCellSize= 1.5f;
|
|
SurfaceLightingDeltaZ= 0.8f;
|
|
}
|
|
|
|
void serial(NLMISC::IStream& stream)
|
|
{
|
|
sint version = stream.serialVersion (6);
|
|
|
|
// Check version
|
|
switch (version)
|
|
{
|
|
case 6:
|
|
stream.serial (OutputLightmapLog);
|
|
case 5:
|
|
{
|
|
bool fake= false;
|
|
stream.serial (fake);
|
|
}
|
|
case 4:
|
|
stream.serial (SurfaceLightingDeltaZ);
|
|
case 3:
|
|
stream.serial (bTestSurfaceLighting);
|
|
stream.serial (SurfaceLightingCellSize);
|
|
case 2:
|
|
stream.serial (bExportBgColor);
|
|
case 1:
|
|
stream.serial (bShowLumel);
|
|
stream.serial (bShadow);
|
|
stream.serial (bExportLighting);
|
|
stream.serial (sExportLighting);
|
|
stream.serial (nExportLighting);
|
|
stream.serial (rLumelSize);
|
|
stream.serial (nOverSampling);
|
|
stream.serial (bExcludeNonSelected);
|
|
}
|
|
}
|
|
};
|
|
|
|
// ***************************************************************************
|
|
|
|
class CExportDesc;
|
|
|
|
// ***************************************************************************
|
|
|
|
typedef std::map<INode*, sint32> TInodePtrInt;
|
|
|
|
|
|
// ***************************************************************************
|
|
/** Descriptor of a WindTree VertexProgram AppData
|
|
*/
|
|
class CVPWindTreeAppData
|
|
{
|
|
public:
|
|
enum {HrcDepth= 3, NumTicks=100};
|
|
|
|
/// Scale value for sliders
|
|
float FreqScale;
|
|
float DistScale;
|
|
|
|
/// Frequency of the wind for 3 Hierachy levels. Slider Value
|
|
int Frequency[HrcDepth];
|
|
/// Additional frequency, multiplied by the globalWindPower. Slider Value
|
|
int FrequencyWindFactor[HrcDepth];
|
|
/// Power of the wind on XY. Mul by globalWindPower. Slider Value
|
|
int DistXY[HrcDepth];
|
|
/// Power of the wind on Z. Mul by globalWindPower. Slider Value
|
|
int DistZ[HrcDepth];
|
|
/// Bias result of the cosinus: f= cos(time)+bias. Slider Value
|
|
int Bias[HrcDepth];
|
|
|
|
/// BST_CHECKED if want Specular Lighting.
|
|
int SpecularLighting;
|
|
};
|
|
|
|
|
|
// ***************************************************************************
|
|
/// Skeleton Spawn Script build, used at addAnimation()
|
|
class CSSSBuild
|
|
{
|
|
public:
|
|
struct CKey
|
|
{
|
|
std::string Value;
|
|
NL3D::TAnimationTime Time;
|
|
};
|
|
struct CBoneScript
|
|
{
|
|
// The name of the bone on which the track is bound
|
|
std::string BoneName;
|
|
// The Temp Track definition
|
|
std::vector<CKey> Track;
|
|
};
|
|
std::vector<CBoneScript> Bones;
|
|
|
|
// if not empty, compile all bone scripts, and add to the animation of the skeleton
|
|
void compile(NL3D::CAnimation &dest, const char* sBaseName);
|
|
};
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
/**
|
|
* 3dsmax to NeL export interface for other things that landscape.
|
|
* \author Cyril Corvazier
|
|
* \author Nevrax France
|
|
* \date 2000
|
|
*/
|
|
class CExportNel
|
|
{
|
|
private:
|
|
class CAnimationBuildCtx;
|
|
public:
|
|
enum
|
|
{
|
|
NoError=0,
|
|
VertexWithoutWeight,
|
|
InvalidSkeleton,
|
|
CodeCount
|
|
};
|
|
|
|
static const char* ErrorMessage[CodeCount];
|
|
|
|
typedef std::map<INode*, Matrix3> mapBoneBindPos;
|
|
|
|
/// Constructor
|
|
CExportNel (bool errorInDialog, bool view, bool absolutePath, Interface *ip, std::string errorTitle, CExportNelOptions *opt);
|
|
|
|
// *********************
|
|
// *** Export mesh
|
|
// *********************
|
|
|
|
/**
|
|
* Build a NeL mesh
|
|
*
|
|
* skeletonShape must be NULL if no bones.
|
|
*/
|
|
NLMISC::CSmartPtr<NL3D::IShape> buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap,
|
|
bool buildLods);
|
|
|
|
/**
|
|
* Build a NeL meshBuild
|
|
*
|
|
* This method does not care of the skeletonShape
|
|
* if isMorphTarget is true, no "mrm/normal mesh interface" is built
|
|
*/
|
|
NL3D::CMesh::CMeshBuild* createMeshBuild(INode& node, TimeValue tvTime, NL3D::CMesh::CMeshBaseBuild*& baseBuild, const NLMISC::CMatrix &finalSpace = NLMISC::CMatrix::Identity, bool isMorphTarget= false);
|
|
|
|
/** Test wether the node has app datas specifying interface meshs.
|
|
* \see applyInterfaceToMeshBuild
|
|
*/
|
|
static bool useInterfaceMesh(INode &node);
|
|
|
|
|
|
/** Use interface mesh from a max file to unify normal at extremities of a mesh
|
|
* Example : a character is sliced in slots, each parts being stored in a file.
|
|
* The normals at the junction part are incorrect.
|
|
* An "interface" is a polygon that is used to unify normal between various meshs
|
|
* IMPORTANT : the meshbuild should have been exported in WORLD SPACE
|
|
* Note : the name of the max file that contains the name of the interface is stored in an app data attached to this node
|
|
* \param node the node from which datas must be retrieved (name of the .max file containing the interfaces)
|
|
* \param meshBuildToModify The mesh build whose normal will be modified
|
|
* \param toWorldMat a matrix to put the meshbuild vertices into worldspace
|
|
* \param tvTime time aty which evaluate the mesh
|
|
*/
|
|
void applyInterfaceToMeshBuild(INode &node, NL3D::CMesh::CMeshBuild &meshBuildToModify,
|
|
const NLMISC::CMatrix &toWorldMat,
|
|
TimeValue tvTime);
|
|
|
|
/** This takes a max mesh, and select the vertices that match vertices of a mesh interface
|
|
* This has no effect if the mesh has no app datas specifying a mesh interface
|
|
* \see applyInterfaceToMeshBuild
|
|
* \return true if the operation succeed
|
|
*/
|
|
bool selectInterfaceVertices(INode &node, TimeValue time);
|
|
|
|
/**
|
|
* Build a NeL instance group
|
|
*/
|
|
NL3D::CInstanceGroup* buildInstanceGroup(const std::vector<INode*>& vectNode, std::vector<INode*>& resultInstanceNode, TimeValue tvTime);
|
|
|
|
/**
|
|
* Build a complete NeL scene with objects attached to the scene root node
|
|
*
|
|
* \param scene is the scene to build
|
|
* \param shapeBank is the shape bank to use with the scene
|
|
* \param tvTime if the time to use to build the scene
|
|
* \param options is the options structure to use to build the scene
|
|
* \param landscape is a pointer ona landscape created with the scene. Can be NULL if you dan't want to build landscape zones.
|
|
* \param progress is the progress bar to use to display build progression. Can be NULL if no prgoress bar is needed
|
|
* \param buildHidden If it is true, build hidden nodes
|
|
* \param onlySelected If it is true, build only selected nodes
|
|
* \param buildLods If it is true, build lod of objects
|
|
*/
|
|
void buildScene (NL3D::CScene &scene, NL3D::CShapeBank &shapeBank, NL3D::IDriver &driver, TimeValue tvTime,
|
|
NL3D::CLandscape *landscape, IProgress *progress, bool buildHidden, bool onlySelected, bool buildLods);
|
|
|
|
/**
|
|
* Build a NeL camera
|
|
*/
|
|
void buildCamera(NL3D::CCameraInfo &cameraInfo, INode& node, TimeValue time);
|
|
|
|
/**
|
|
* Return true if it is a mesh.
|
|
*
|
|
* skeletonShape must be NULL if no bones.
|
|
*
|
|
* if excludeCollision then return false if the mesh is a collision (NL3D_APPDATA_COLLISION)
|
|
* else don't test NL3D_APPDATA_COLLISION.
|
|
*/
|
|
static bool isMesh (INode& node, TimeValue time, bool excludeCollision= true);
|
|
static bool isCamera (INode& node, TimeValue time);
|
|
static bool isDummy (INode& node, TimeValue time);
|
|
static bool isVegetable (INode& node, TimeValue time);
|
|
|
|
/** Compute an aabbox of a mesh, in world.
|
|
* \return true if the conversion succeed.
|
|
*/
|
|
static bool buildMeshAABBox(INode &node, NLMISC::CAABBox &dest, TimeValue time);
|
|
|
|
/**
|
|
* Return true if the node is a mesh and has a Nel_Material attached to it
|
|
*/
|
|
static bool hasLightMap (INode& node, TimeValue time);
|
|
void deleteLM (INode& node);
|
|
bool calculateLM (NL3D::CMesh::CMeshBuild *pZeMeshBuild,
|
|
NL3D::CMeshBase::CMeshBaseBuild *pZeMeshBaseBuild,
|
|
INode& ZeNode,
|
|
TimeValue tvTime, uint firstMaterial, bool outputLightmapLog);
|
|
|
|
bool calculateLMRad(NL3D::CMesh::CMeshBuild *pZeMeshBuild,
|
|
NL3D::CMeshBase::CMeshBaseBuild *pZeMeshBaseBuild,
|
|
INode& ZeNode,
|
|
TimeValue tvTime);
|
|
|
|
|
|
// *********************
|
|
// *** Export animation
|
|
// *********************
|
|
|
|
// Add animation track of this node into the animation object pass in parameter.
|
|
void addAnimation (NL3D::CAnimation& animation, INode& node, const char* sBaseName, bool root);
|
|
|
|
// Build a NeL track with a 3dsmax node and a controller.
|
|
NL3D::ITrack* buildATrack (NL3D::CAnimation& animation, Control& c, TNelValueType type, Animatable& node, const CExportDesc& desc,
|
|
CAnimationBuildCtx *animBuildCtx, bool bodyBiped=false);
|
|
|
|
// Build a Nel bool track from a On/Off max Controller (doesn't work with buildATRack, which require a keyframer interface
|
|
// , which isn't provided by an on / off controller)
|
|
static NL3D::CTrackKeyFramerConstBool* buildOnOffTrack(Control& c);
|
|
|
|
// Add tracks for particle systems
|
|
void addParticleSystemTracks(NL3D::CAnimation& animation, INode& node, const char* parentName) ;
|
|
|
|
// Add tracks for the bone and its children (recursive)
|
|
void addBoneTracks (NL3D::CAnimation& animation, INode& node, const char* parentName,
|
|
CAnimationBuildCtx *animBuildCtx, bool root, CSSSBuild &ssBuilder);
|
|
|
|
// Add biped tracks
|
|
void addBipedNodeTracks (NL3D::CAnimation& animation, INode& node, const char* parentName,
|
|
CAnimationBuildCtx *animBuildCtx, bool root, CSSSBuild &ssBuilder);
|
|
|
|
|
|
// Add a note track. It tackes the first note track of the object
|
|
static void addNoteTrack(NL3D::CAnimation& animation, INode& node);
|
|
|
|
// Add a SkeletonSpawnScript track. It takes the first note track of the object
|
|
static void addSSSTrack(CSSSBuild &ssBuilder, INode& node);
|
|
|
|
// Build a Nel String track from the first NoteTrack
|
|
static NL3D::CTrackKeyFramerConstString* buildFromNoteTrack(INode& node);
|
|
|
|
// Convert keyframe methods
|
|
static void buildNelKey (NL3D::CKeyFloat& nelKey, ILinFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyInt& nelKey, ILinFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBool& nelKey, ILinFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyVector& nelKey, ILinPoint3Key& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyRGBA& nelKey, ILinPoint3Key& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyQuat& nelKey, ILinRotKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyVector& nelKey, ILinScaleKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
|
|
static void buildNelKey (NL3D::CKeyBezierFloat& nelKey, IBezFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBool& nelKey, IBezFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBezierVector& nelKey, IBezPoint3Key& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBezierQuat& nelKey, IBezQuatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBezierVector& nelKey, IBezScaleKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
|
|
static void buildNelKey (NL3D::CKeyTCBFloat& nelKey, ITCBFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyBool& nelKey, ITCBFloatKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyTCBVector& nelKey, ITCBPoint3Key& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyTCBQuat& nelKey, ITCBRotKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
static void buildNelKey (NL3D::CKeyTCBVector& nelKey, ITCBScaleKey& maxKey, float ticksPerSecond, const CExportDesc& desc, Control& c);
|
|
|
|
|
|
// Create the transform matrix tracks
|
|
void createBipedKeyFramer (NL3D::ITrack *&nelRot, NL3D::ITrack *&nelPos, bool isRot, bool isPos,
|
|
float ticksPerSecond, const Interval& range, int oRT, const CExportDesc& desc,
|
|
INode& node, CAnimationBuildCtx *animBuildCtx);
|
|
|
|
// convert to nel time value
|
|
static NL3D::TAnimationTime convertTime (TimeValue time);
|
|
|
|
// ************************************
|
|
// *** Export skeleton and skinning
|
|
// ************************************
|
|
|
|
/*
|
|
* Build a skeleton shape
|
|
*
|
|
* mapBindPos is the pointer of the map of bind pos by bone. Can be NULL if the skeleton is already in the bind pos.
|
|
*/
|
|
void buildSkeletonShape (NL3D::CSkeletonShape& skeletonShape, INode& node, mapBoneBindPos* mapBindPos,
|
|
TInodePtrInt& mapId, TimeValue time);
|
|
|
|
// Build an array of CBoneBase
|
|
void buildSkeleton (std::vector<NL3D::CBoneBase>& bonesArray, INode& node, mapBoneBindPos* mapBindPos,
|
|
TInodePtrInt& mapId, std::set<std::string> &nameSet,
|
|
TimeValue time, sint32& idCount, sint32 father=-1);
|
|
|
|
/*
|
|
* Add Skinning data into the build structure.
|
|
* You must call first isSkin. If isSkin return true, then you can call this method.
|
|
* Can return the following errors:
|
|
*
|
|
* skeletonShape must be NULL if no bones.
|
|
*
|
|
* NoError
|
|
* VertexWithoutWeight
|
|
* InvalidSkeleton
|
|
*/
|
|
static uint buildSkinning (NL3D::CMesh::CMeshBuild& buildMesh, const TInodePtrInt& skeletonShape, INode& node);
|
|
|
|
// Return true if the mesh is a skin, else return false.
|
|
static bool isSkin (INode& node);
|
|
|
|
// Return the root node of the skeleton attached to the node. Return NULL if no skeleton.
|
|
static INode* getSkeletonRootBone (INode& node);
|
|
|
|
// Add bind pose matrix of the bone used by the model in the map.
|
|
static void addSkeletonBindPos (INode& node, mapBoneBindPos& boneBindPos);
|
|
|
|
// Enable / disable the skin modifier
|
|
static void enableSkinModifier (INode& node, bool enable);
|
|
|
|
/// return true if the bone must unherit his father scale. Special cases for biped, biped father etc...
|
|
bool getNELUnHeritFatherScale(INode &node);
|
|
|
|
/** This method do the same thing as getLocalMatrix() mut manages complexs cases of Scale unheritance,
|
|
strange Biped node Scale stuff, etc....
|
|
*/
|
|
void getNELBoneLocalTM(INode &node, TimeValue time,
|
|
NLMISC::CVector &nelScale, NLMISC::CQuat &nelQuat, NLMISC::CVector &nelPos);
|
|
|
|
/// Physique Mirroring
|
|
bool mirrorPhysiqueSelection(INode &node, TimeValue time, const std::vector<uint> &vertIn,
|
|
float threshold);
|
|
|
|
// **************
|
|
// *** Export Lod
|
|
// **************
|
|
|
|
void addChildLodNode (std::set<INode*> &lodListToExclude, INode *current = NULL);
|
|
void addParentLodNode (INode &node, std::set<INode*> &lodListToExclude, INode *current = NULL);
|
|
|
|
// *********************
|
|
// *** Export collision
|
|
// *********************
|
|
|
|
/** Export a CCollisionMeshBuild from a list of node.
|
|
* NB: do not check NEL3D_APPDATA_COLLISION.
|
|
*/
|
|
NLPACS::CCollisionMeshBuild* createCollisionMeshBuild(std::vector<INode *> &nodes, TimeValue tvTime);
|
|
|
|
/** Export a list of CCollisionMeshBuild from a list of node, grouped by igName. User must delete the meshBuilds.
|
|
* meshBuildList is a vector of tuple igName-Cmb
|
|
* NB: check NEL3D_APPDATA_COLLISION. if not set, the node is not exported
|
|
*/
|
|
bool createCollisionMeshBuildList(std::vector<INode *> &nodes, TimeValue time,
|
|
std::vector<std::pair<std::string, NLPACS::CCollisionMeshBuild*> > &meshBuildList);
|
|
|
|
/**
|
|
* Parse all the scene and build retrieverBank and globalRetriever. NULL if no collisions mesh found.
|
|
* \param retIgName eg: if IgName of a collisionMesh "col_pipo_1" is found in the scene, and if
|
|
* igNamePrefix=="col_" and igNameSuffix=="_", then retIgName returned is "pipo".
|
|
* If different igName may match, result is undefined (random).
|
|
*/
|
|
void computeCollisionRetrieverFromScene(TimeValue time,
|
|
NLPACS::CRetrieverBank *&retrieverBank, NLPACS::CGlobalRetriever *&globalRetriever,
|
|
const char *igNamePrefix, const char *igNameSuffix, std::string &retIgName);
|
|
|
|
/**
|
|
* Retrieve the Z rotation in radian of an object with its I matrix vector, assuming that the K matrix vector is near CVector::K
|
|
*/
|
|
static float getZRot (const NLMISC::CVector &i);
|
|
|
|
/**
|
|
* Build a primtive block with an array of inode. Return false if one of the object is not a PACS primitive object.
|
|
*/
|
|
bool buildPrimitiveBlock (TimeValue time, std::vector<INode*> objects, NLPACS::CPrimitiveBlock &primitiveBlock);
|
|
|
|
// *********************
|
|
// *** Export misc
|
|
// *********************
|
|
|
|
// Transforme a 3dsmax view matrix to camera matrix.
|
|
static Matrix3 viewMatrix2CameraMatrix (const Matrix3& viewMatrix);
|
|
|
|
// Convert a 3dsmax matrix in NeL matrix
|
|
static void convertMatrix (NLMISC::CMatrix& nelMatrix, const Matrix3& maxMatrix);
|
|
|
|
// Convert a NeL matrix in 3dsmax matrix
|
|
static void convertMatrix (Matrix3& maxMatrix, const NLMISC::CMatrix& nelMatrix);
|
|
|
|
/// Convert a 3dsmax uv matrix to a nel uv matrix
|
|
static void uvMatrix2NelUVMatrix (const Matrix3& uvMatrix, NLMISC::CMatrix &dest);
|
|
|
|
// Convert a 3dsmax vector in NeL vector
|
|
static void convertVector (NLMISC::CVector& nelVector, const Point3& maxVector);
|
|
|
|
// Get local node matrix
|
|
static void getLocalMatrix (Matrix3& localMatrix, INode& node, TimeValue time);
|
|
|
|
// Decompose a 3dsmax matrix in NeL translation, scale, quat.
|
|
static void decompMatrix (NLMISC::CVector& nelScale, NLMISC::CQuat& nelRot, NLMISC::CVector& nelPos,
|
|
const Matrix3& maxMatrix);
|
|
// Convert a 3dsmax color in NeL color
|
|
static void convertColor (NLMISC::CRGBA& nelColor, const Color& maxColor);
|
|
|
|
// Return true if the node as the classId classid or is derived from a class with classId class id
|
|
static bool isClassIdCompatible (Animatable& node, Class_ID& classId);
|
|
|
|
// Return the pointer on ther subanim with the name sName of the node. If it doesn't exist, return NULL.
|
|
static Animatable* getSubAnimByName (Animatable& node, const char* sName);
|
|
|
|
// Get the node name
|
|
static std::string getName (MtlBase& mtl);
|
|
|
|
// Get the node name
|
|
static std::string getName (INode& node);
|
|
|
|
// Get the NEL node name. ie either NEL3D_APPDATA_INSTANCE_SHAPE appData or just GetName().
|
|
static std::string getNelObjectName (INode& node);
|
|
|
|
// Get lights
|
|
void getLights (std::vector<NL3D::CLight>& vectLight, TimeValue time, INode* node=NULL);
|
|
|
|
// Get the root node of the scene
|
|
INode *getRootNode() const;
|
|
// Get All node (objects only) of a hierarchy. NULL => all the scene
|
|
void getObjectNodes (std::vector<INode*>& vectNode, TimeValue time, INode* node=NULL);
|
|
|
|
// *** Paramblock2 access
|
|
|
|
// Return the pointer on the subanim with the name sName of the node. If it doesn't exist, return NULL.
|
|
static Control* getControlerByName (Animatable& node, const char* sName);
|
|
|
|
// Return the pointer on the subanim with the name sName of the node. If it doesn't exist, return NULL.
|
|
// Support only those type:
|
|
// TYPE_FLOAT
|
|
// TYPE_INT
|
|
// TYPE_POINT3
|
|
// TYPE_BOOL
|
|
static bool getValueByNameUsingParamBlock2 (Animatable& node, const char* sName,
|
|
ParamType2 type, void *pValue, TimeValue time, bool verbose = true);
|
|
|
|
// Get the first modifier in the pipeline of a node by its class identifier
|
|
static Modifier* getModifier (INode* pNode, Class_ID modCID);
|
|
|
|
// Get the ambient value
|
|
NLMISC::CRGBA getAmbientColor (TimeValue time);
|
|
|
|
// Get the backgorund value
|
|
NLMISC::CRGBA getBackGroundColor (TimeValue time);
|
|
|
|
// Get the light group
|
|
static uint getLightGroup (INode *node);
|
|
|
|
// Get the light animation name
|
|
static std::string getAnimatedLight (INode *node);
|
|
|
|
// *** Script access
|
|
|
|
// Eval a scripted function
|
|
static bool scriptEvaluate (const char *script, void *out, TNelScriptValueType type);
|
|
|
|
// *** Appdata access
|
|
|
|
// Get an appData float
|
|
static float getScriptAppData (Animatable *node, uint32 id, float def);
|
|
|
|
// Set an appData float
|
|
static void setScriptAppData (Animatable *node, uint32 id, float value);
|
|
|
|
// Get an appData integer
|
|
static int getScriptAppData (Animatable *node, uint32 id, int def);
|
|
|
|
// Set an appData integer
|
|
static void setScriptAppData (Animatable *node, uint32 id, int value);
|
|
|
|
// Get an appData integer
|
|
static std::string getScriptAppData (Animatable *node, uint32 id, const std::string& def);
|
|
|
|
// Set an appData integer
|
|
static void setScriptAppData (Animatable *node, uint32 id, const std::string& value);
|
|
|
|
// Get an appData RGBA
|
|
static NLMISC::CRGBA getScriptAppData (Animatable *node, uint32 id, NLMISC::CRGBA def);
|
|
|
|
// Set an appData RGBA
|
|
static void setScriptAppData (Animatable *node, uint32 id, NLMISC::CRGBA val);
|
|
|
|
// Output error message
|
|
void outputErrorMessage (const char *message);
|
|
void outputWarningMessage (const char *message);
|
|
|
|
|
|
// Get an appData VertexProgram WindTree (ensure same default values for all retrieve).
|
|
static void getScriptAppDataVPWT (Animatable *node, CVPWindTreeAppData &apd);
|
|
|
|
// Set an appData VertexProgram WindTree.
|
|
static void setScriptAppDataVPWT (Animatable *node, const CVPWindTreeAppData &apd);
|
|
|
|
/** private func : this convert a polygon expressed as a max mesh into a list of ordered vectors.
|
|
* This also gives an average normal by averaging faces normals.
|
|
*/
|
|
static void maxPolygonMeshToOrderedPoly(Mesh &mesh, std::vector<NLMISC::CVector> &dest, const NLMISC::CMatrix &basis, NLMISC::CVector &avgNormal);
|
|
|
|
|
|
// ********************
|
|
// *** Export Vegetable
|
|
// ********************
|
|
|
|
/*
|
|
* Build a skeleton shape
|
|
*
|
|
* mapBindPos is the pointer of the map of bind pos by bone. Can be NULL if the skeleton is already in the bind pos.
|
|
*/
|
|
bool buildVegetableShape (NL3D::CVegetableShape& skeletonShape, INode& node, TimeValue time);
|
|
|
|
|
|
// ********************
|
|
// *** Export Lod Character
|
|
// ********************
|
|
|
|
/* is this node a lod character ???
|
|
*/
|
|
static bool isLodCharacter (INode& node, TimeValue time);
|
|
|
|
/*
|
|
* Build a lod character from a node
|
|
*/
|
|
bool buildLodCharacter (NL3D::CLodCharacterShapeBuild& lodBuild, INode& node, TimeValue time, const TInodePtrInt *nodeMap);
|
|
|
|
// *************
|
|
// *** Misc ***
|
|
// *************
|
|
|
|
// get a ptr to max interface
|
|
Interface *getInterface() const { return _Ip; }
|
|
|
|
/// Return true if error must be in dialog, false if error must not stop the process.
|
|
bool isErrorInDialog () const;
|
|
|
|
private:
|
|
|
|
// A class that describe how build a NeL material with a max one
|
|
class CMaterialDesc
|
|
{
|
|
public:
|
|
friend class CExportNel;
|
|
|
|
// Default constructor init _IndexInMaxMaterial to MISSING_VALUE, _UVMatrix to indentity and clamp to 0, 0, 1, 1
|
|
CMaterialDesc ()
|
|
{
|
|
_IndexInMaxMaterial=UVGEN_MISSING;
|
|
_IndexInMaxMaterialAlternative=UVGEN_MISSING;
|
|
_UVMatrix.IdentityMatrix();
|
|
_CropU=0.f;
|
|
_CropV=0.f;
|
|
_CropW=1.f;
|
|
_CropH=1.f;
|
|
}
|
|
const Matrix3 &getUVMatrix() const { return _UVMatrix; }
|
|
private:
|
|
// *** Data
|
|
|
|
// Index in material
|
|
sint _IndexInMaxMaterial;
|
|
sint _IndexInMaxMaterialAlternative;
|
|
|
|
// Matrix for UVs
|
|
Matrix3 _UVMatrix;
|
|
|
|
// Crop region
|
|
float _CropU;
|
|
float _CropV;
|
|
float _CropW;
|
|
float _CropH;
|
|
};
|
|
|
|
// Max material info
|
|
class CMaxMaterialInfo
|
|
{
|
|
public:
|
|
// Default constructor
|
|
CMaxMaterialInfo ()
|
|
{
|
|
AlphaVertex = false;
|
|
ColorVertex = false;
|
|
AlphaVertexChannel = 0;
|
|
TextureMatrixEnabled = false;
|
|
uint i;
|
|
for (i=0; i<MAX_MAX_TEXTURE; i++)
|
|
UVRouting[i] = 0xff;
|
|
};
|
|
|
|
// Remap UV channel
|
|
std::vector<CMaterialDesc> RemapChannel;
|
|
|
|
// Material names
|
|
std::string MaterialName;
|
|
|
|
// Alpha vertex in this material
|
|
bool AlphaVertex;
|
|
|
|
/* UV channel routing :
|
|
* (UVRouting[i] == 0xff) UV channel i is not needed
|
|
* (UVRouting[i] != 0xff) UV channel i is needed for the material
|
|
* (UVRouting[i] == i) UV channel i is present in the vertex buffer
|
|
* (UVRouting[i] != i) UV channel i is not present in the vertex buffer. It is routed to another UV channel.*/
|
|
uint8 UVRouting[MAX_MAX_TEXTURE];
|
|
|
|
// Color vertex in this material
|
|
bool ColorVertex;
|
|
|
|
// Alpha vertex channel for this material
|
|
uint AlphaVertexChannel;
|
|
|
|
// allow to export a user texture matrix
|
|
bool TextureMatrixEnabled;
|
|
};
|
|
|
|
// Max base build structure
|
|
class CMaxMeshBaseBuild
|
|
{
|
|
public:
|
|
CMaxMeshBaseBuild ()
|
|
{
|
|
NeedVertexColor = false;
|
|
uint i;
|
|
for (i=0; i<MAX_MAX_TEXTURE; i++)
|
|
UVRouting[i] = 0xff;
|
|
}
|
|
|
|
// First material in the array
|
|
uint FirstMaterial;
|
|
|
|
// Num of materials
|
|
uint NumMaterials;
|
|
|
|
/* UV channel routing :
|
|
* (UVRouting[i] == 0xff) UV channel i is not needed
|
|
* (UVRouting[i] != 0xff) UV channel i is needed for the material
|
|
* (UVRouting[i] == i) UV channel i is present in the vertex buffer
|
|
* (UVRouting[i] != i) UV channel i is not present in the vertex buffer. It is routed to another UV channel.*/
|
|
uint8 UVRouting[MAX_MAX_TEXTURE];
|
|
|
|
// Need vertex color
|
|
bool NeedVertexColor;
|
|
|
|
// Remap UV channel
|
|
std::vector<CMaxMaterialInfo> MaterialInfo;
|
|
};
|
|
|
|
// *********************
|
|
// *** Export mesh
|
|
// *********************
|
|
|
|
// Get 3ds UVs channel used by a texmap and make a good index channel
|
|
// Can return an interger in [0; MAX_MESHMAPS-1] or on of the following value: UVGEN_REFLEXION, UVGEN_MISSING
|
|
static int getVertMapChannel (Texmap& texmap, Matrix3& channelMatrix, TimeValue time);
|
|
|
|
// Build a CLight
|
|
static bool buildLight (GenLight &maxLight, NL3D::CLight& nelLight, INode& node, TimeValue time);
|
|
|
|
/**
|
|
* Build a NeL base mesh interface
|
|
*
|
|
* if skeletonShape is NULL, no skinning is exported.
|
|
*/
|
|
void buildBaseMeshInterface (NL3D::CMeshBase::CMeshBaseBuild& buildMesh, CMaxMeshBaseBuild& maxBaseBuild, INode& node,
|
|
TimeValue time, const NLMISC::CMatrix& basis);
|
|
|
|
/**
|
|
* Build a NeL mesh interface
|
|
*
|
|
* if skeletonShape is NULL, no skinning is exported.
|
|
* if isMorphTarget is true, no "mrm/normal mesh interface" is built
|
|
*/
|
|
void buildMeshInterface (TriObject &tri, NL3D::CMesh::CMeshBuild& buildMesh, const NL3D::CMeshBase::CMeshBaseBuild& buildBaseMesh,
|
|
const CMaxMeshBaseBuild& maxBaseBuild, INode& node, TimeValue time, const TInodePtrInt* nodeMap,
|
|
const NLMISC::CMatrix& newBasis=NLMISC::CMatrix::Identity,
|
|
const NLMISC::CMatrix& finalSpace=NLMISC::CMatrix::Identity,
|
|
bool isMorphTarget= false);
|
|
|
|
|
|
/**
|
|
* Get all the blend shapes from a node in the meshbuild form
|
|
*/
|
|
void getBSMeshBuild (std::vector<NL3D::CMesh::CMeshBuild*> &bsList, INode &node, TimeValue time, bool skined);
|
|
|
|
/**
|
|
* Build a NeL mrm parameters block
|
|
*/
|
|
static void buildMRMParameters (Animatable& node, NL3D::CMRMParameters& params);
|
|
|
|
/**
|
|
* Build a mesh geom with a node
|
|
*/
|
|
NL3D::IMeshGeom *buildMeshGeom (INode& node, TimeValue time, const TInodePtrInt *nodeMap,
|
|
NL3D::CMeshBase::CMeshBaseBuild &buildBaseMesh, std::vector<std::string>& listMaterialName,
|
|
bool& isTransparent, bool& isOpaque, const NLMISC::CMatrix& parentMatrix);
|
|
/**
|
|
* Build the mesh morpher info in the mesh geom */
|
|
void buildMeshMorph (NL3D::CMesh::CMeshBuild& buildMesh, INode &node, TimeValue time, bool skined);
|
|
|
|
// Get the normal of a face for a given corner in localSpace
|
|
static Point3 getLocalNormal (int face, int corner, Mesh& mesh);
|
|
|
|
// Build a water shape. The given node must have a water materiel, an assertion is raised otherwise
|
|
NL3D::IShape *buildWaterShape(INode& node, TimeValue time);
|
|
|
|
// build a wave maker shape
|
|
NL3D::IShape *buildWaveMakerShape(INode& node, TimeValue time);
|
|
|
|
|
|
|
|
// *********************
|
|
// *** Export FXs ***
|
|
// *********************
|
|
// Build shape from a particle system node
|
|
NL3D::IShape *buildParticleSystem(INode& node, TimeValue time);
|
|
// Build shape from a remanence node
|
|
NL3D::IShape *buildRemanence(INode& node, TimeValue time);
|
|
// Build shape from a flare node
|
|
NL3D::IShape *buildFlare(INode& node, TimeValue time);
|
|
|
|
|
|
// *********************
|
|
// *** Export material
|
|
// *********************
|
|
|
|
/** Test wether the given max node has a water material. A water object should only have one material, and must have planar, convex geometry.
|
|
* Morevover, the mapping should only have scale and offsets, no rotation
|
|
*/
|
|
static bool hasWaterMaterial(INode& node, TimeValue time);
|
|
|
|
// Build an array of NeL material corresponding with max material at this node.
|
|
void buildMaterials (std::vector<NL3D::CMaterial>& Materials, CMaxMeshBaseBuild& maxBaseBuild, INode& node,
|
|
TimeValue time);
|
|
|
|
// Build a NeL material corresponding with a max material.
|
|
void buildAMaterial (NL3D::CMaterial& material, CMaxMaterialInfo& materialInfo, Mtl& mtl, TimeValue time);
|
|
|
|
// Build a NeL texture corresponding with a max Texmap.
|
|
NL3D::ITexture* buildATexture (Texmap& texmap, CMaterialDesc& remap3dsTexChannel, TimeValue time, bool forceCubic=false);
|
|
|
|
/// Build a NeL texture cube from a Reflect/refract map containing 6 textures.
|
|
NL3D::CTextureCube *buildTextureCubeFromReflectRefract(Texmap &texmap, TimeValue time);
|
|
|
|
/// Build a NeL texture cube from a Composite map containing 6 textures. (note: no re-ordering is done, because it didn't reorder composite cube in previous version either).
|
|
NL3D::CTextureCube *buildTextureCubeFromComposite(Texmap &texmap, TimeValue time);
|
|
|
|
/// Build a NeL texture cube from a single texture.
|
|
NL3D::CTextureCube *buildTextureCubeFromTexture(Texmap &texmap, TimeValue time);
|
|
|
|
public:
|
|
/** Return true if a mesh has a material whose shader requires a specific vertex shader to work (for example, per-pixel lighting).
|
|
* This also stores the result in shader
|
|
*/
|
|
static bool hasMaterialWithShaderForVP(INode &node, TimeValue time, NL3D::CMaterial::TShader &shader);
|
|
|
|
/// Test wether the given material need a specific vertex program to work correctly
|
|
static bool needVP(Mtl &mat, TimeValue time, NL3D::CMaterial::TShader &shader);
|
|
private:
|
|
|
|
/** Build a mesh vertex program associated with the given shader
|
|
* For now there can be only one vertex program per mesh, so you must specify the shader this v.p must be built for.
|
|
* The meshBuild may be modfied by this operation (to add tangent space infos for example)
|
|
* \return The vertex program or NULL if the op failed, or if there's no need for a v.p.
|
|
*/
|
|
static NL3D::IMeshVertexProgram *buildMeshMaterialShaderVP(NL3D::CMaterial::TShader shader, NL3D::CMesh::CMeshBuild *mb);
|
|
|
|
/// Test wether a material need a vertex program
|
|
|
|
// *********************
|
|
// *** Export Animation
|
|
// *********************
|
|
|
|
// Add tracks for the node
|
|
void addNodeTracks (NL3D::CAnimation& animation, INode& node, const char* parentName,
|
|
CAnimationBuildCtx *animBuildCtx, bool root, CSSSBuild &ssBuilder,
|
|
bool bodyBiped=false);
|
|
|
|
// Add tracks for the light
|
|
void addLightTracks (NL3D::CAnimation& animation, INode& node, const char* parentName);
|
|
|
|
// Add tracks for the morphing
|
|
void addMorphTracks (NL3D::CAnimation& animation, INode& node, const char* parentName);
|
|
|
|
// Add tracks for the object
|
|
void addObjTracks (NL3D::CAnimation& animation, Object& obj, const char* parentName);
|
|
|
|
// Add tracks for the material
|
|
void addMtlTracks (NL3D::CAnimation& animation, Mtl& mtl, const char* parentName);
|
|
|
|
// Add tracks for the texture
|
|
void addTexTracks (NL3D::CAnimation& animation, Texmap& tex, uint stage, const char* parentName);
|
|
|
|
|
|
// Get a biped key parameter using script
|
|
bool getBipedKeyInfo (const char* nodeName, const char* paramName, uint key, float& res);
|
|
|
|
// Get inplace biped mode
|
|
bool getBipedInplaceMode (const char* nodeName, const char* inplaceFunction,
|
|
bool &res);
|
|
|
|
// Change inplace biped mode
|
|
bool setBipedInplaceMode (const char* nodeName, const char* inplaceFunction,
|
|
bool onOff);
|
|
|
|
// Current context for addAnimation()
|
|
class CAnimationBuildCtx
|
|
{
|
|
public:
|
|
struct CBipedKey
|
|
{
|
|
TimeValue Time;
|
|
// The correct Nel Local TM
|
|
NLMISC::CVector Pos;
|
|
NLMISC::CQuat Quat;
|
|
NLMISC::CVector Scale;
|
|
};
|
|
|
|
struct CBipedNode
|
|
{
|
|
INode *Node;
|
|
// Oversampled position
|
|
std::vector<CBipedKey> Keys;
|
|
};
|
|
|
|
// The animation range for Biped Nodes. BipedRangeMin and BipedRangeMax are inclusive
|
|
TimeValue BipedRangeMin;
|
|
TimeValue BipedRangeMax;
|
|
|
|
// All biped nodes we must export.
|
|
std::vector<CBipedNode> BipedNodes;
|
|
|
|
public:
|
|
CAnimationBuildCtx();
|
|
|
|
bool hasBipedNodes() const {return BipedNodes.size()>0;}
|
|
|
|
// compile the bipedMap from BipedNodes, and other infos
|
|
void compileBiped();
|
|
|
|
// From a node, get its associated CBipedNode in the BipedNodes array.
|
|
CBipedNode *getBipedNodeInfo(INode *node);
|
|
|
|
/* return true if this node must export Track Position. It returns true for bodyBiped and LClavicle and RClavicle
|
|
limb for now.
|
|
NB: We use script to now if the node is a clavicle (ie not hack-tested by node name)
|
|
But this slow test is done in compileBiped().
|
|
*/
|
|
bool mustExportBipedBonePos(INode *node);
|
|
|
|
private:
|
|
// Map from INode * to CBiped Id in BipedNodes
|
|
typedef std::map<INode*, uint> TBipedMap;
|
|
TBipedMap _BipedMap;
|
|
|
|
// List of node which must export their position.
|
|
typedef std::set<INode*> TBipedSet;
|
|
TBipedSet _ExportBipedBonePosSet;
|
|
|
|
// Add a limb node to the _ExportBipedBonePosSet. eg: #larm.
|
|
void addLimbNodeToExportPos(INode *rootNode, const char *limbId);
|
|
};
|
|
|
|
// Bkup ctx of a biped bone.
|
|
struct CBipedNodePlaceMode
|
|
{
|
|
INode *Node;
|
|
bool InPlaceMode;
|
|
bool InPlaceYMode;
|
|
bool InPlaceXMode;
|
|
};
|
|
|
|
|
|
//
|
|
void buildBipedInformation(CAnimationBuildCtx &animBuildCtx, INode &node);
|
|
//
|
|
void overSampleBipedAnimation(CAnimationBuildCtx &animBuildCtx, uint overSampleValue);
|
|
|
|
|
|
/// return the Nel Scale Reference node if any.
|
|
INode *getNELScaleReferenceNode(INode &node);
|
|
|
|
/// return true if the node has a biped controller (either body or slave).
|
|
bool isBipedNode(INode &node);
|
|
|
|
/// As part of getNELBoneLocalTM.
|
|
void getNELBoneLocalScale(INode &node, TimeValue time, NLMISC::CVector &nelScale);
|
|
|
|
private:
|
|
|
|
// Pointer on the interface
|
|
Interface *_Ip;
|
|
|
|
// Texture are built path absolute
|
|
bool _AbsolutePath;
|
|
|
|
// Build to view the scene
|
|
bool _View;
|
|
|
|
// Errors goes in dialog
|
|
bool _ErrorInDialog;
|
|
|
|
// Error title
|
|
std::string _ErrorTitle;
|
|
|
|
// Build options
|
|
CExportNelOptions _Options;
|
|
};
|
|
|
|
/** replacment for sprintf scanf (because of localisation in max)
|
|
*/
|
|
float toFloatMax(const char *src);
|
|
// Same as to float max, but returns true if succeed
|
|
bool toFloatMax(const char *src, float &dest);
|
|
std::string toStringMax(float value);
|
|
std::string toStringMax(int value);
|
|
|
|
|
|
|
|
|
|
#endif // NL_EXPORT_NEL_H
|
|
|
|
/* End of export_nel.h */
|