// NeL - MMORPG Framework // 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 . #ifndef __RYKOL_PATCH_OBJ_H #define __RYKOL_PATCH_OBJ_H #pragma warning (disable : 4786) #include "nel/misc/debug.h" #include #include #include #include #include "nel/3d/tile_bank.h" #include "nel/misc/file.h" #include "nel_patch_mesh.h" //#define USE_CACHE typedef unsigned int uint; #define RYKOLPATCHOBJ_CLASS_ID Class_ID(0x368c679f, 0x711c22ee) extern TCHAR *GetString(int id); extern HINSTANCE hInstance; #define RPO_SERIALIZE_VERSION 0 #define EP_OBJECT 0 #define EP_VERTEX 1 #define EP_EDGE 2 #define EP_PATCH 3 #define EP_TILE 4 #define PO_TILE 4 #define PATCH_HIT_TILE (PATCH_HIT_INTERIOR+1) #define MAX_TILE_IN_PATCH 16 #define NUM_TILE_SEL (MAX_TILE_IN_PATCH*MAX_TILE_IN_PATCH) #pragma warning (disable : 4786) // ------------------------------------------------------------------------------------------------------------------------------------------------ class RPO : public PatchObject { public: // PatchObject PO; RPatchMesh *rpatch; // User info for this RykolPatchObject // bug hack bool bBigHack; // Validity Interval topoValid; Interval geomValid; Interval selectValid; Interval texmapValid; /*Interval vcolorValid; Interval gfxdataValid;*/ DWORD validBits; // for the remaining constant channels //Class vars static IObjParam *ip; //Access to the interface BOOL suspendSnap; //A flag for setting snapping on/off // From BaseObject CreateMouseCallBack* GetCreateMouseCallBack(); int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags); int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt); void Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt); //TODO: Return the name that will appear in the history browser (modifier stack) TCHAR *GetObjectName() { return "Rykol Patch Object";} void GetWorldBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box ); void GetLocalBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box ); void GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel ); //TODO: Return the default name of the node when it is created. void InitNodeName(TSTR& s) { s = "Rykol Patch Object"; } // From Object BOOL HasUVW(); void SetGenUVW(BOOL sw); int CanConvertToType(Class_ID obtype); Object* ConvertToType(TimeValue t, Class_ID obtype); void GetCollapseTypes(Tab &clist,Tab &nlist); int IntersectRay(TimeValue t, Ray& ray, float& at, Point3& norm); void PointsWereChanged(); //TODO: Evaluate the object and return the ObjectState ObjectState Eval(TimeValue t) { return ObjectState(this); }; //TODO: Return the validity interval of the object as a whole Interval ObjectValidity(TimeValue t) { Interval iv; iv.SetInfinite(); iv &= geomValid; //iv &= vcolorValid; iv &= topoValid; iv &= texmapValid; iv &= selectValid; //iv &= gfxdataValid; if (!(validBits&chMask[SUBSEL_TYPE_CHAN_NUM])) iv.SetEmpty(); if (!(validBits&chMask[DISP_ATTRIB_CHAN_NUM])) iv.SetEmpty(); return iv; } Interval ChannelValidity(TimeValue t, int nchan) { switch(nchan) { case GEOM_CHAN_NUM: return geomValid; break; case TOPO_CHAN_NUM: return topoValid; break; case TEXMAP_CHAN_NUM: return texmapValid; break; case SELECT_CHAN_NUM: return selectValid; break; default: return((chMask[nchan]&validBits) ? FOREVER: NEVER); } } void SetChannelValidity(int nchan, Interval v) { switch(nchan) { case GEOM_CHAN_NUM: geomValid = v; break; //case VERT_COLOR_CHAN_NUM: vcolorValid = v; break; case TOPO_CHAN_NUM: topoValid = v; break; case TEXMAP_CHAN_NUM: texmapValid = v; break; case SELECT_CHAN_NUM: selectValid = v; break; //case GFX_DATA_CHAN_NUM: gfxdataValid = v; break; default : //if (v.InInterval(0)) validBits|= chMask[nchan]; if (!(v==NEVER)) validBits|= chMask[nchan]; else validBits &= ~chMask[nchan]; break; } } Interval ConvertValidity(TimeValue t) { Interval iv = FOREVER; if (geomValid.InInterval(t)) iv &= geomValid; //if (vcolorValid.InInterval(t)) iv &= vcolorValid; if (topoValid.InInterval(t)) iv &= topoValid; if (texmapValid.InInterval(t)) iv &= texmapValid; if (selectValid.InInterval(t)) iv &= selectValid; return iv; } #define copyFlags(dest, source, mask) dest = ((dest&(~mask))|(source&mask)) void CopyValidity(RPO *fromOb, ChannelMask channels) { if (channels&GEOM_CHANNEL) geomValid = fromOb->geomValid; //if (channels&VERTCOLOR_CHANNEL) vcolorValid = fromOb->vcolorValid; if (channels&TOPO_CHANNEL) topoValid = fromOb->topoValid; if (channels&TEXMAP_CHANNEL) texmapValid = fromOb->texmapValid; if (channels&SELECT_CHANNEL) selectValid = fromOb->selectValid; //if (channels&GFX_DATA_CHANNEL) gfxdataValid = fromOb->gfxdataValid; copyFlags(validBits, fromOb->validBits,channels); } void InvalidateChannels(ChannelMask channels); // From Animatable void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev); void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next); // From GeomObject Mesh* GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete); // Loading/Saving IOResult Load(ILoad *iload); IOResult Save(ISave *isave); //From Animatable Class_ID ClassID() { if (bBigHack) return Class_ID(PATCHOBJ_CLASS_ID,0); else return RYKOLPATCHOBJ_CLASS_ID; } BOOL IsSubClassOf(Class_ID classID) { return classID == ClassID() ? true : PatchObject::IsSubClassOf(classID); } SClass_ID SuperClassID() { return GEOMOBJECT_CLASS_ID; } void GetClassName(TSTR& s) {s = "Rykol Patch Object";} RefTargetHandle Clone ( RemapDir &remap ); RefResult NotifyRefChanged (Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message); int NumSubs() { return PatchObject::NumSubs (); } //TSTR SubAnimName(int i) { return NULL; } Animatable* SubAnim(int i) { return PatchObject::SubAnim(i); // return pblock; } int NumRefs() { return PatchObject::NumRefs(); } RefTargetHandle GetReference(int i) { return PatchObject::GetReference(i); //return pblock; } void SetReference(int i, RefTargetHandle rtarg) { PatchObject::SetReference(i, rtarg); //pblock=(IParamBlock2*)rtarg; } /*int NumParamBlocks() { //return PatchObject::NumParamBlocks(); return 1; } // return number of ParamBlocks in this instance IParamBlock2* GetParamBlock(int i) { //return PatchObject::GetParamBlock(i); return pblock; } // return i'th ParamBlock IParamBlock2* GetParamBlockByID(BlockID id) { return PatchObject::GetParamBlockByID(id); //return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock*/ void DeleteThis() { delete this; } Object *MakeShallowCopy(ChannelMask channels); void ShallowCopy(Object* fromOb, ChannelMask channels); void NewAndCopyChannels(ChannelMask channels); void FreeChannels(ChannelMask channels); //Constructor/Destructor RPO(); RPO(PatchObject& pPO); virtual ~RPO(); void SetPoint(int i, const Point3& p) { PatchObject::SetPoint(i, p); } /** * Return true if it is a zone. * * skeletonShape must be NULL if no bones. */ static bool isZone (INode& node, TimeValue time); #if MAX_RELEASE >= 4000 // ace: These functions are needed in max 4 // NS: New SubObjType API int NumSubObjTypes() { return 0; } ISubObjType *GetSubObjType(int i) { return NULL; } #endif }; #endif // __RYKOL_PATCH_OBJ_H