CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
reply share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 02-26-2013, 08:01 AM   #61
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
it is a bit of a catch all... maybe a selective pick of what you really need would help ? also InvalidateSurfaceUI call interacts with the editable poly UI which can't help.

Code:
void EditPolyObject::LocalDataChanged (DWORD parts) { bool sel = (parts & PART_SELECT) ? TRUE : FALSE; bool topo = (parts & PART_TOPO) ? TRUE : FALSE; bool geom = (parts & PART_GEOM) ? TRUE : FALSE; bool vertCol = (parts & PART_VERTCOLOR) ? true : false; InvalidateTempData (parts); if (topo||sel||vertCol) InvalidateSurfaceUI (); if (topo) { SynchContArray(mm.numv); // We need to make sure our named selection sets' sizes match our sizes: selSet[0].SetSize (mm.numv); selSet[1].SetSize (mm.nume); selSet[2].SetSize (mm.numf); mm.InvalidateTopoCache( false ); } if (geom||topo) { MNNormalSpec *pNorm = mm.GetSpecifiedNormals(); if (pNorm) { // If we have specified normals, we need to clear flags to indicate that they need to be updated. // If we have a PART_TOPO change, the nonspecified normals need to be rebuilt. // If we have a PART_GEOM change, the nonexplicit normals need to be recomputed. if (topo) pNorm->ClearFlag (MNNORMAL_NORMALS_BUILT); else pNorm->ClearFlag (MNNORMAL_NORMALS_COMPUTED); } mm.InvalidateGeomCache (); if (topo) mm.freeRVerts (); } else if (vertCol) mm.InvalidateHardwareMesh (); if (sel) { InvalidateNumberSelected (); UpdateNamedSelDropDown (); } subdivValid.SetEmpty (); if (killRefmsg.DistributeRefmsg()) NotifyDependents(FOREVER, parts, REFMSG_CHANGE); }


Code:
void EditPolyObject::InvalidateTempData (PartID parts) { if (!tempMove) { if (tempData) tempData->Invalidate (parts); if (parts & (PART_TOPO|PART_GEOM|PART_SELECT|PART_SUBSEL_TYPE) ) { //only invalidate the cache when it's actually being used. //invalidating the soft selection cache causes the subdivided mesh to be rebuilt if it's on int useSoftSel = 0; pblock->GetValue (ep_ss_use, GetCOREInterface()->GetTime(), useSoftSel, arValid); if ( useSoftSel ) { InvalidateSoftSelectionCache (); } } } // we NEVER call InvalidateTopoCache, since that trashes the edge list. if (parts & PART_TOPO) { mm.ClearFlag(MN_MESH_PARTIALCACHEINVALID); mm.SetFlag(MN_CACHEINVALID); mm.freeRVerts(); } if (parts & PART_GEOM) mm.InvalidateGeomCache (); if ((parts & PART_SELECT) && tempData) tempData->freeBevelInfo(); // Any change in mesh should invalidate the preview. if (EpPreviewOn()) EpPreviewInvalidate (); }

Last edited by Klunk : 02-26-2013 at 08:05 AM.
 
Old 04-22-2013, 05:34 PM   #62
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
i have no idea why this useful function is not exposed for MXS:
Code:
def_visible_primitive (formatRenderTime, "formatRenderTime"); Value* formatRenderTime_cf(Value** arg_list, int count) { check_arg_count_with_keys(all, 1, count); int time = arg_list[0]->to_int(); BOOL hundredths = key_arg_or_default(all, &false_value)->to_bool(); MSTR str; MAXScript_interface11->FormatRenderTime(time, str, hundredths); return new String(str); }
 
Old 04-25-2013, 10:35 PM   #63
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
i can't build this simple function:
Code:
def_visible_primitive(getControlHWND, "getControlHWND"); Value* getControlHWND_cf(Value **arg_list, int count) { check_arg_count(getControlHWND, 1, count); if (is_rolloutcontrol(arg_list[0])) { HWND hwnd = ((RolloutControl*)arg_list[0])->GetHWND(); return IntegerPtr::intern((INT_PTR)hwnd); } return &undefined; }

i have this error message:
error LNK2019: unresolved external symbol "public: struct HWND__ * __cdecl RolloutControl::GetHWND(void)" (?GetHWND@RolloutControl@@QEAAPEAUHWND__@@XZ) referenced in function "class Value * __cdecl getControlHWND_cf(class Value * *,int)"

as i understand the compiler can't find some lib file. but i have no idea which one missed. Any ideas?
thanks
 
Old 04-26-2013, 07:47 AM   #64
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
don't think you can use that as it's not part of the "interface" e.g. it's not virtual... In the rolloutcontrols I've look at (mxsagni project in samples) and the one I attempted to implement the hwnd is defined in the child class with no imperative to implement a GetHWND() function.

though i maybe wrong and very often are the libraries are listed here

another edit doesn't link in one of my projects with a working custom rollout control so it should have all the necessary linkages.

Last edited by Klunk : 04-26-2013 at 08:45 AM.
 
Old 04-26-2013, 02:23 PM   #65
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
Quote:
Originally Posted by Klunk
don't think you can use that as it's not part of the "interface" e.g. it's not virtual... In the rolloutcontrols I've look at (mxsagni project in samples) and the one I attempted to implement the hwnd is defined in the child class with no imperative to implement a GetHWND() function.

this is from header "rollouts.h"
Code:
visible_class (RolloutControl) class RolloutControl : public Value, public ReferenceMaker { public: Value* name; Value* caption; Value* init_caption; <...> // added for r11 HWND GetHWND(); };

it's public. it's visible... why is it not working?
 
Old 04-26-2013, 06:03 PM   #66
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
i found a workaround:
Code:
def_visible_primitive(getControlHWND, "getControlHWND"); Value* getControlHWND_cf(Value **arg_list, int count) { check_arg_count_with_keys(getControlHWND, 1, count); int id = key_arg_or_default(id,Integer::intern(0))->to_int(); if (is_rolloutcontrol(arg_list[0])) { RolloutControl *control = (RolloutControl*)arg_list[0]; HWND hwnd = GetDlgItem(control->parent_rollout->page, control->control_ID + id); return IntegerPtr::intern((INT_PTR)hwnd); } return &undefined; }

actually the new way is power powerful. using optional ID argument it can return HWND for a 'multi-controls' control (like a spinner)
 
Old 10-15-2013, 05:38 PM   #67
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
Quote:
Originally Posted by Klunk
I was hoping this would be more than a 2 man show Denis, if you don't already have these I think you will like them.....

exposes editable poly specified normals without using the edit normal modifier and having the target node selected and the modify panel open for it to work. It would be easy to expand on these if the functionality you need is not here, anyway enjoy....


Code:
def_visible_primitive(buildSpecifiedNormals,"buildSpecifiedNormals"); Value* buildSpecifiedNormals_cf(Value **arg_list, int count) { check_arg_count(buildSpecifiedNormals, 1, count); MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, buildSpecifiedNormals); // clear any existing normals if(pmesh->GetSpecifiedNormals()) pmesh->ClearSpecifiedNormals(); // create an empty specified normals pmesh->SpecifyNormals(); MNNormalSpec* nspec = pmesh->GetSpecifiedNormals(); if(nspec) { // initialize the normals nspec->Initialize(); // create the faces if(nspec->FAlloc(pmesh->numf)) { // build the normals nspec->BuildNormals(); numfaces = nspec->GetNumFaces(); return Integer::intern(numfaces); } } return &undefined; }



thanks, Klunk for this set of very useful functions... the only problem I have is to get MNMesh updated. as you see i've modifies the function above to return the number of nspec faces. the function returns 0 all the time, but the right number was allocated and built! what do we have to update the return the right number?

thanks
 
Old 10-15-2013, 09:30 PM   #68
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
it's an odd one for sure....

if you call the getNumSpecNormalFaces function in mxs directly after the build function it returns the correct number of faces and that is using the same code !

Code:
nspec->GetNumFaces();


I've tried this changing this

Code:
if(nspec->FAlloc(pmesh->numf))


to

Code:
if(nspec->SetNumNormals(pmesh->numf))


makes no difference though may well be the proper way to do it though, but who can tell when the reference is so vague, never mind though we'll just plough on with python.


if you trust that max will always build the normals you can use

Code:
return Integer::intern(pmesh->numf);


it's not pretty or elegant or might not even be correct but maybe better than zero
 
Old 10-15-2013, 11:26 PM   #69
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
Quote:
Originally Posted by Klunk
it's an odd one for sure....

if you call the getNumSpecNormalFaces function in mxs directly after the build function it returns the correct number of faces and that is using the same code !

Code:
nspec->GetNumFaces();


Quote:
I've tried this changing this

Code:
if(nspec->FAlloc(pmesh->numf))


to

Code:
if(nspec->SetNumNormals(pmesh->numf))


makes no difference though may well be the proper way to do it though, but who can tell when the reference is so vague, never mind though we'll just plough on with python.

i've tried to set number faces... it doesn't work either
Quote:
if you trust that max will always build the normals you can use

Code:
return Integer::intern(pmesh->numf);


it's not pretty or elegant or might not even be correct but maybe better than zero

do i look like as a person who trusts max?

well... but i have an idea. there is a metod CheckNormals. it needs the Parent MNMesh to be set. so ...
Code:
nspec->SetParent(pmesh); nspec->CheckNormals();

it has to do all for us... and probably doesn't need any Allocation and Build. i don't have max right now to try. if you can try it, please, let me know how it works
 
Old 10-16-2013, 07:36 AM   #70
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
sorry late night brain scramble should be using SetNumFaces not SetNumNormals

anyway this works for me

Code:
Value* buildSpecifiedNormals_cf(Value **arg_list, int count) { check_arg_count(buildSpecifiedNormals, 1, count); MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_WRITE_ACCESS, NULL, buildSpecifiedNormals); // clear any existing normals if(pmesh->GetSpecifiedNormals()) pmesh->ClearSpecifiedNormals(); // create an empty specified normals pmesh->SpecifyNormals(); MNNormalSpec* nspec = pmesh->GetSpecifiedNormals(); if(nspec) { // initialize the normals nspec->Initialize(); // create the faces if(nspec->SetNumFaces(pmesh->numf)) { // build the normals nspec->BuildNormals(); return Integer::intern(nspec->GetNumFaces()); } } return &undefined; }

Last edited by Klunk : 10-16-2013 at 07:41 AM.
 
Old 10-17-2013, 03:33 AM   #71
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,334
Send a message via ICQ to denisT
i've tried it... yes. it sets the number of faces, but it still doesn't update the nspec topology
 
Old 11-05-2013, 05:25 PM   #72
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
getting the command panel rollup window hwnd, though possible via other means this is a more direct method

Code:
def_visible_primitive(getCommandPanelHWND, "getCommandPanelHWND"); Value* getCommandPanelHWND_cf(Value **arg_list, int count) { check_arg_count(getCommandPanelHWND, 0, count); return IntegerPtr::intern((INT_PTR)MAXScript_interface->GetCommandPanelRollup()->GetHwnd()); }
 
Old 11-13-2013, 07:17 PM   #73
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
by product of something else I was working on and I needed this info...

mxs usage

<array point3> getShapePolyLine <shape> <curve>

returns an array of points that make up the the drawn spline curve will take into account steps, optimize and adaptive.

Code:
def_visible_primitive(getShapePolyLine, "getShapePolyLine"); Value* getShapePolyLine_cf(Value **arg_list, int count) { check_arg_count(getShapePolyLine, 2, count); // handle the shape arg MAXNode* shape = (MAXNode*)arg_list[0]; INode* node = get_valid_node(shape, getShapePolyLine); Object* obj = node->GetObjectRef(); if (obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) obj = ((IDerivedObject*)obj)->FindBaseObject(); if(obj->ClassID() != splineShapeClassID && obj->ClassID() != Class_ID(SPLINE3D_CLASS_ID,0)) throw RuntimeError (GetString(IDS_SHAPE_OPERATION_ON_NONSPLINESHAPE), obj->GetObjectName()); // confident we have a shape object SplineShape* spline = dynamic_cast<SplineShape*>(obj); // handle the curve index int index = arg_list[1]->to_int(); if (index < 1 || index > spline->shape.splineCount) throw RuntimeError (GetString(IDS_SHAPE_SPLINE_INDEX_OUT_OF_RANGE), Integer::intern(index)); // grab the polyshape from our spline PolyShape pshape; spline->MakePolyShape(MAXScript_interface->GetTime(), pshape, PSHAPE_BUILTIN_STEPS, spline->shape.optimize); // create an array from the curve we want PolyLine* pline = &pshape.lines[index-1]; int numPts = pline->numPts; one_typed_value_local(Array* result); vl.result = new Array(numPts); Point3 p; for(int i = 0; i < numPts; i++) { p = (*pline)[i].p; shape->object_to_current_coordsys(p); vl.result->append(new Point3Value(p)); } return_value(vl.result); }
 
Old 11-18-2013, 11:36 AM   #74
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
two functions that appear in meshop interface but not the polyop. they are called from using something like

Code:
polyop.getMapVertsUsingMapFace $ 1 3 polyop.getMapFacesUsingMapVert $ 1 3


the ValueToBitArray to bit array function can be found in the common_functions.cpp of the mxsagni project in the samples.

Code:
void checkMapChannel(MNMesh* poly, int channel) { range_check(channel, -NUM_HIDDENMAPS, MAX_MESHMAPS-1, GetString(IDS_MESH_MAP_CHANNEL_OUT_OF_RANGE)); if (channel >= poly->numm) throw RuntimeError (GetString(IDS_MAP_SUPPORT_NOT_ENABLED_FOR_CHANNEL ), Integer::intern(channel)); if (poly->M(channel)->GetFlag(MN_DEAD)) throw RuntimeError(GetString(IDS_MAP_SUPPORT_NOT_ENABLED _FOR_CHANNEL), Integer::intern(channel)); } //************************************************** ****************************************** def_struct_primitive(polyop_getMapVertsUsingMapFac e, polyop, "getMapVertsUsingMapFace"); // <bitarray> getMapVertsUsingMapFace Value* polyop_getMapVertsUsingMapFace_cf(Value** arg_list, int arg_count) { // the usual arg check check_arg_count(getMapVertsUsingMapFace, 3, arg_count); // get the poly mesh MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getMapVertsUsingMapFace); // get map channel arg and check for support and in range int channel = arg_list[1]->to_int(); checkMapChannel(pmesh,channel); // ok to access the map MNMap* map = pmesh->M(channel); int nMapVerts = map->numv; int nMapFaces = map->numf; // create a new bitarray from input which could be a bitarray, int or array of ints BitArray mapFaces(nMapFaces); ValueToBitArray(arg_list[2], mapFaces, nMapFaces, GetString(IDS_POLY_MAP_FACE_INDEX_OUT_OF_RANGE)); // create the return variable on the stack one_typed_value_local(BitArrayValue* mapVerts); vl.mapVerts = new BitArrayValue(nMapVerts); for(int f = 0; f < nMapFaces; f++) // for all map faces { if(mapFaces[f]) // if set { MNMapFace* face = map->F(f); // get our face and for(int v = 0; v < face->deg; v++) // for all verts in the map face vl.mapVerts->bits.Set(face->tv[v]); // set the corresponding bit } } return_value(vl.mapVerts); } //************************************************** ****************************************** def_struct_primitive(polyop_getMapFacesUsingMapVer t, polyop, "getMapFacesUsingMapVert"); // <bitarray> getMapFacesUsingMapVert Value* polyop_getMapFacesUsingMapVert_cf(Value** arg_list, int arg_count) { // the usual arg check check_arg_count(getMapFacesUsingMapVert, 3, arg_count); // get the poly mesh MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getMapFacesUsingMapVert); // get map channel arg and check for support and in range int channel = arg_list[1]->to_int(); checkMapChannel(pmesh,channel); // ok to access the map MNMap* map = pmesh->M(channel); int nMapVerts = map->numv; int nMapFaces = map->numf; // create a new bitarray from input which could be a bitarray, int or array of ints BitArray mapVerts(nMapVerts); ValueToBitArray(arg_list[2], mapVerts, nMapVerts, GetString(IDS_POLY_MAP_VERTEX_INDEX_OUT_OF_RANGE)) ; // create the return variable on the stack one_typed_value_local(BitArrayValue* mapFaces); vl.mapFaces = new BitArrayValue (nMapFaces); // iterate through the faces set the bit array if using the the verts for(int f = 0; f < nMapFaces; f++) { MNMapFace* face = map->F(f); for(int v = 0; v < face->deg; v++ ) // for all verts in the face { if(mapVerts[face->tv[v]]) // is this face using this vert ? { vl.mapFaces->bits.Set(f); break; // face is being used we don't need to know anymore } } } return_value(vl.mapFaces); }
 
Old 12-08-2013, 10:25 AM   #75
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
I'm sure there are ways to create meshes that defeat it both ways but it should work for most cases....


Code:
def_visible_primitive(isMeshClosed,"isMeshClosed"); Value* isMeshClosed_cf(Value **arg_list, int count) { check_arg_count(isMeshClosed, 1, count); Mesh* pmesh = get_meshForValue(arg_list[0], MESH_READ_ACCESS, NULL, isMeshClosed); int numEdges; Edge* edges = pmesh->MakeEdgeList(&numEdges); BOOL openEdge = FALSE; for(int i = 0; i < numEdges; ++i) { Edge& edge = edges[i]; if(edge.f[0] == -1 || edge.f[1] == -1) { openEdge = TRUE; break; } } delete [] edges; return bool_result(!openEdge); }

Last edited by Klunk : 12-08-2013 at 10:48 AM.
 
reply share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 07:57 PM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.