[Closed] Viewport Statistics Improvement
I had an idea for a much improved viewport statistics, I made something that did the basics then Daniel Santana got involved and improved it. There’s still a lag with a large amount of objects for getting the total poly counts or if you have a lot of objects selected.
Can anyone make it faster? @DenisT the viewport statistics that exist would be nice to expose
/*
Advanced Viewport Stats
(c) 2015 Dave Wortley & Daniel Santana
*/
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
gc light:true
global drawStatsInfo
try(dw_ds_callback.enabled = false)catch()
dw_ds_callback = undefined
global dw_ds_callback
fn dw_ds_formatNumber val =
(
local l = val.count
while (l - 2) > 1 do (val = replace val (l - 2) 0 ","; l -= 3)
val
)
struct drawStatsInfo
(
lastObjectHandle,
lastObjectName,
lastObjectLayer,
lastObjectClass,
lastObjectSuperClass,
lastObjectParent,
lastObjectChilds,
lastObjectMat,
lastObjectFaceCount,
lastObjectVertCount,
lastObjectSize,
lastObjectDebug = "",
totalCounts,
totalFaceCount,
totalVertCount,
totalDebug = "",
updateObjectSizeDebug ="
",
disableTotalCount = true,
debug = false,
cfg = "$plugcfg/drawstatsinfo.ini",
ver = 0.7,
enabled = false,
fn updateObjectStats force:false =
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
if force == false and drawStatsInfo.lastObjectHandle == GetHandleByAnim obj do return()
drawStatsInfo.lastObjectHandle = GetHandleByAnim obj
drawStatsInfo.lastObjectName = obj.name
drawStatsInfo.lastObjectClass = (classof obj) as string
drawStatsInfo.lastObjectSuperClass = (superclassof obj) as string
drawStatsInfo.lastObjectLayer = obj.layer.name
drawStatsInfo.lastObjectParent = (if obj.parent == undefined then "sceneRootNode" else obj.parent.name)
drawStatsInfo.lastObjectChilds = dw_ds_formatNumber (obj.children.count as string)
drawStatsInfo.lastObjectMat = (if obj.material != undefined then classof obj.material as string + ": " + obj.material.name as string else "Unassigned")
drawStatsInfo.lastObjectFaceCount = (if superclassof obj == geometryclass then "
Faces: " + (dw_ds_formatNumber (obj.mesh.faces.count as string)) else "")
drawStatsInfo.lastObjectVertCount = (if superclassof obj == geometryclass then "
Vertices: " + (dw_ds_formatNumber (obj.mesh.vertices.count as string)) else "")
s = obj.max - obj.min
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
[DEBUG]
updateObject took: %s
" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.lastObjectDebug = ss as string
--format (ss as string)
)
),
fn drawObjNameInfo =
(
try
(
textColour = (colorMan.getColor #activeViewportBorder) * 255.0
textColour = color 196 196 196
--tt = fileProperties.getItems "Mesh Totals"
--st = fileProperties.getItems "Scene Totals"
drawStatsInfo.updateObjectStats()
dtext = case of
(
(selection.count == 0): (
""
)
(selection.count == 1): (
"Object: " + drawStatsInfo.lastObjectName + \
"
Class: " + drawStatsInfo.lastObjectClass + " (" + drawStatsInfo.lastObjectSuperClass + ")" + \
"
Layer: " + drawStatsInfo.lastObjectLayer + \
"
Parent: " + drawStatsInfo.lastObjectParent + \
"
Children: " + drawStatsInfo.lastObjectChilds + \
"
Material: " + drawStatsInfo.lastObjectMat + \
drawStatsInfo.lastObjectFaceCount + \
drawStatsInfo.lastObjectVertCount + \
drawStatsInfo.lastObjectSize + \
(if drawStatsInfo.debug then drawStatsInfo.lastObjectDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.totalDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.updateObjectSizeDebug as string else "") + \
(if not drawStatsInfo.disableTotalCount then "
Total Faces: " + drawStatsInfo.totalFaceCount else "
") + \
--"
Total Vertices: " + drawStatsInfo.totalVertCount + \
"
Scene Object Count: " + objects.count as string + \
"
FPS: " + viewport.getFPS() as string
)
(selection.count > 1): (
types = #()
for o in selection do appendifunique types ((classof o))
(selection.count as string) + " Objects Selected" + \
"
" + (types.count as string) + " classes " + (types as string) + \
"
Geometry: " + (for o in selection where superclassof o == geometryclass collect o).count as string + \
"
Shapes: " + (for o in selection where superclassof o == shape collect o).count as string + \
"
Lights: " + (for o in selection where superclassof o == light collect o).count as string + \
"
Cameras: " + (for o in selection where superclassof o == camera collect o).count as string + \
"
Helpers: " + (for o in selection where superclassof o == helper collect o).count as string + \
"
Space Warps: " + (for o in selection where superclassof o == spacewarpObject collect o).count as string --+ \
--"
Particle Systems: " + (for o in selection where superclassof o == particlesystem collect o).count as string + \
--"
Bone Objects: " + (for o in selection where superclassof o == geometryclass collect o).count as string
)
)
local pos = [10,38]
gw.setTransform(Matrix3 1)
gw.wText [pos.x, pos.y, 0] dtext color:textColour
)
catch(print ("issue" + (getCurrentException())))
),
fn loadSettings =
(
if not doesfileexist cfg do return false
if hasINISetting drawStatsInfo.cfg "Options" "Debug" do
drawStatsInfo.debug = getIniSetting drawStatsInfo.cfg "Options" "Debug" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "TotalCount" do
drawStatsInfo.disableTotalCount = getIniSetting drawStatsInfo.cfg "Options" "TotalCount" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "Enabled" do
drawStatsInfo.enabled = getIniSetting drawStatsInfo.cfg "Options" "Enabled" as BooleanClass
),
fn show =
(
global dw_ds_DrawStatsInfoUI
try(destroydialog dw_ds_DrawStatsInfoUI)catch()
rollout dw_ds_DrawStatsInfoUI "Viewport Stat Options" width:245
(
group "Options"
(
checkbox ckbDebug "Debug mode" checked:drawStatsInfo.debug
on ckbDebug changed val do drawStatsInfo.debug = ckbDebug.checked
checkbox ckbTotal "Enable total face count" checked:(not drawStatsInfo.disableTotalCount)
)
checkbutton ckbEnable "Enabled" checked:drawStatsInfo.enabled
button btnClose "Close" align:#right
on btnClose pressed do try(destroydialog dw_ds_DrawStatsInfoUI)catch()
label lblVer "Version: 0.000" align:#left
hyperLink lblAbout1 "© 2015 Dave Wortley" address:"http://www.taylorjames.com/" across:3 align:#left
label lblAboutM "and" align:#middle offset:[15,0]
hyperLink lblAbout2 "Daniel Santana" address:"http://www.ycdivfx.com/" align:#left
on dw_ds_DrawStatsInfoUI open do lblVer.text = "Version: " + drawStatsInfo.ver as string
on dw_ds_DrawStatsInfoUI close do
(
setIniSetting drawStatsInfo.cfg "Options" "Debug" (drawStatsInfo.debug as string)
setIniSetting drawStatsInfo.cfg "Options" "TotalCount" (drawStatsInfo.disableTotalCount as string)
setIniSetting drawStatsInfo.cfg "Options" "Enabled" (drawStatsInfo.enabled as string)
)
on ckbTotal changed val do
(
drawStatsInfo.disableTotalCount = not val
if not drawStatsInfo.disableTotalCount do ::dw_ds_updateTotals ok ok
)
on ckbEnable changed val do
(
::drawStatsInfo.enabled = val
::drawStatsInfo.enable()
)
)
createdialog dw_ds_DrawStatsInfoUI
),
fn createMacros =
(
files = getfiles (pathConfig.appendPath (getdir #usermacros) "*.mcr")
macr = for f in files where findstring (tolower (getfilenamefile f)) "dwdsviewportstats" != undefined collect f
if macr.count == 0 do
(
macros.new "Views" "Macro_DwDsViewportStats" "DrawStatsInfoUI" "DrawStatsInfoUI" "
on execute do
(
::drawStatsInfo.show();
)
"
format "DrawStatsInfo Macro created.
"
)
),
fn enable =
(
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
if drawStatsInfo.enabled do registerRedrawViewsCallback (drawStatsInfo.drawObjNameInfo)
),
fn setup =
(
drawStatsInfo.loadSettings()
drawStatsInfo.createMacros()
drawStatsInfo.enable()
)--,
--init = setup()
)
if not IsNetServer() do
(
drawStatsInfo = drawStatsInfo()
drawStatsInfo.setup()
global dw_ds_updateTotals
global dw_ds_updateObject
global dw_ds_updateObjectSize
fn dw_ds_updateTotals evt nds =
(
try(
st = timestamp()
drawStatsInfo.totalCounts = objects.count as string
--tv = 0
tf = 0
--for o in objects where superclassof o == geometryclass do (try(tv += o.mesh.numvertices)catch())
if not drawStatsInfo.disableTotalCount do for o in objects where superclassof o == geometryclass do (try(tf += o.mesh.numfaces)catch())
drawStatsInfo.totalFaceCount = dw_ds_formatNumber (tf as string)
--drawStatsInfo.totalVertCount = tv as string
drawStatsInfo.updateObjectStats force:true
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "updateTotals took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.totalDebug = ss as string
--format (ss as string)
)
)catch()
)
fn dw_ds_updateObject evt nds =
(
try
(
drawStatsInfo.updateObjectStats force:true
)
catch()
)
fn dw_ds_updateObjectSize evt nds =
(
try
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
s = obj.max - obj.min
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
updateObjectSize took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.updateObjectSizeDebug = ss as string
--format (ss as string)
)
)
catch(print "ooops")
)
dw_ds_updateTotals undefined undefined
dw_ds_callback = NodeEventCallback enabled:true mouseup:true delay:50 topologyChanged:(dw_ds_updateTotals) added:(dw_ds_updateTotals) deleted:(dw_ds_updateTotals) materialStructured:(dw_ds_updateObject) nameChanged:(dw_ds_updateObject) geometryChanged:(dw_ds_updateObjectSize) controllerOtherEvent:(dw_ds_updateObjectSize)
)
I did a quick test and the whole slowdown seems to revolve around this:
for o in objects where superclassof o == geometryclass do (try(tf += o.mesh.numfaces)catch())
– time:1734 ram:178776L tris:19245792
As you are getting the mesh of every object, it will be indeed slow. Even the build in Polygon Counter Utility is as slow as your script.
Do you need to get the number of polygons or triangles?
Do you have Editable Poly and Editable Mesh on the same scene?
*.mesh access is a bottleneck. if you count editable meshes and editable polys it might faster because you can get number verts and faces(polys) using deformable object polycount.
def_visible_primitive(getPolygonCount, "getPolygonCount");
Value* getPolygonCount_cf(Value** arg_list, int count)
{
check_arg_count(getPolygonCount, 1, count);
INode* node = arg_list[0]->to_node();
TimeValue t = MAXScript_time();
ObjectState os = node->EvalWorldState(t);
if (os.obj && os.obj->IsRenderable() && os.obj->IsDeformable())
{
int numv, numf;
os.obj->PolygonCount(t, numf, numv);
return new Point2Value(Point2(numv, numf));
}
return new Point2Value(0.0f, 0.0f);
}
also you can get verts and faces count using render mesh instead of trimesh which is faster because doesn’t need conversion
def_visible_primitive(numVertsAndTris, "numVertsAndTris");
Value* numVertsAndTris_cf(Value** arg_list, int count)
{
check_arg_count(numVertsAndTris, 1, count);
INode* node = arg_list[0]->to_node();
TimeValue t = MAXScript_time();
const ObjectState& os = node->EvalWorldState(t); // Get the object that is referenced at the time
Object* ob = os.obj;
if (ob && (ob->SuperClassID() == GEOMOBJECT_CLASS_ID || ob->SuperClassID() == SHAPE_CLASS_ID))
{
BOOL needDel;
NullView nullView; // Set up a null viewport so that we get the right mesh..
Mesh *mesh = ((GeomObject*)ob)->GetRenderMesh(t, node, nullView, needDel); // Type cast to a geometric object and then retriev
int numv = mesh->numVerts;
int numf = mesh->numFaces;
if (needDel) delete mesh;
return new Point2Value(Point2(numv, numf));
}
return new Point2Value(0.0f, 0.0f);
}
I like it.
But, tell everyone that the script installs a macro under “Views” category. I spend few minutes wondering why the script not works. Only reading the code can tell us how to use the script.
The Size of the object measure the world boundingbox of the object and shows that dimension – the same as is shown in the Utilities – Measure. But when you open the Object Properties(from the quad menu) you will get the size of the object using its local bounding box.
I remember that I’ve told you about the same when you released the Object Properties 2.0 script.
PolyTools3D
o.mesh creates a copy of the mesh each time when it is executed, right?
I remember that there is a command in maxscript that returns the count of the faces/polygons, verts, etc as array, but I can’t find it.
If someone knows it…
For polys or objects with modifiers yes:
(
poly = converttopoly (sphere segments:200)
mesh = converttomesh (sphere segments:200)
gc()
st=timestamp(); sh=heapfree
tris = 0
for j = 1 to 100 do tris += poly.mesh.numfaces
format "time:% ram:% tris:%
" (timestamp()-st) (sh-heapfree) tris
gc()
st=timestamp(); sh=heapfree
tris = 0
for j = 1 to 100 do tris += mesh.mesh.numfaces
format "time:% ram:% tris:%
" (timestamp()-st) (sh-heapfree) tris
delete #(poly, mesh)
)
– time:281 ram:7488L tris:3960000
– time:0 ram:7496L tris:3960000
In 2016, seems to work ok, and its fast. For 13 millions took 0.038s, which for me seems aceptable. I will try DennisT solution also, but if we could keep this without needing extra files, it would be great. Easy sharing
with a modifier on top
The same. Thank you. I have often to use INDEX tab when using maxscritp reference, because SEARCH tab returns nothing for “getPoly” or “getPolygon”.
dgsantana, what about the size issue?
What was the problem, exactly? Right now it uses the bounding box for determine the size.
I was building the c++ version that dennisT posted, and also doing a c# version, (dynamic compile), and check the results, see if I could get away from using an extra dlx. Just so we could get the right count results (tris).
Create a box. Rotate it. Then check its size using Utilities-Measure and right click – Object Properties. You will see that there are two diferent sizes of the same object.
Utilities-Measure gives you the size according the world boundingbox ($.min-$.max), the ObjectProperties gives you the size using the local bbox of the object.
For example:
- box with X = 100 Y = 100, Z = 100 units size.
- rotate it 45 deg along the X axis
- Utilities – Measure(and your script) will gives you: Dimensions: X = 100, Y = 141.421, Z = 141.421
- riglh click – Object Properties will gives you: Dimensins: X = 100, Y = 100, Z = 100.
Yes, it is much faster.
Unfortunately it doesn’t seem to be fixed in Max 2016. According to the documentation it should return the number of triangles.
it depends on base mesh type. if the base mesh is Mesh it returns tris, if the base is MNMesh it returns polygons
Not exactly.
A base Mesh with an Edit Poly modifier returns polygons.
A base Poly with an Edit Mesh modifier returns tris.
And from the help:
“…The number of faces and vertices returned are the number that would be present if the node was converted to a mesh object…”
Which is not true.
Daniel, if getPolygonCount() does the work you are looking for then you might want to just use obj.numfaces or getnumfaces(), both are 20 times faster than getPolygonCount()
Well, there was some (probably strange) reason for me and Dave not using it. I still need to try in a few real scenes, this last solution.
It might not be strange at all. The number of polygons and the number of triangles are two completely different things.
For real time engines development, the number of polygons is not much relevant, so what you would often want to know is the number of triangles.
For getting the number of triangles of any object class, the only MXS build-in solution I know is the one you are currently using, get the mesh of the object and then the number of faces.
But I wouldn’t be surprised if there is another easter egg lost in the undocumented MXS universe.
i forgot. it returns according to current object state. where
A base Mesh with an Edit Poly modifier is PolyMeshObject
A base Poly with an Edit Mesh modifier is Editable_mesh
There is indeed a native method for getting the number of Tris.
GetTriMeshFaceCount()
And it is well documented.
I may should say: “It is, well, documented”.
Better yet: “Well, it is documented”
Now that we have:
[b]GetPolygonCount[/b]() -- Returns the number of polygons at the top of the modifier stack
[b]GetTriMeshFaceCount[/b]() -- Returns the number of triangles at the top of the modifier stack
I think both work well, as they were planned. It is just the documentation of the GetPolygonCount() function what is wrong.
Great find Jorge . miauu, you are right I will change it during the day to use the local bbox instead of the world one.
Here is the changed code.
/*
Advanced Viewport Stats
(c) 2015 Dave Wortley & Daniel Santana
*/
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
gc light:true
global drawStatsInfo
try(dw_ds_callback.enabled = false)catch()
dw_ds_callback = undefined
global dw_ds_callback
fn dw_ds_formatNumber val =
(
local l = val.count
while (l - 2) > 1 do (val = replace val (l - 2) 0 ","; l -= 3)
val
)
struct drawStatsInfo
(
lastObjectHandle,
lastObjectName,
lastObjectLayer,
lastObjectClass,
lastObjectSuperClass,
lastObjectParent,
lastObjectChilds,
lastObjectMat,
lastObjectFaceCount,
lastObjectVertCount,
lastObjectSize,
lastObjectDebug = "",
totalCounts,
totalFaceCount,
totalVertCount,
totalDebug = "",
updateObjectSizeDebug ="
",
disableTotalCount = true,
debug = false,
cfg = "$plugcfg/drawstatsinfo.ini",
ver = 0.8,
enabled = false,
fn updateObjectStats force:false =
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
if force == false and drawStatsInfo.lastObjectHandle == GetHandleByAnim obj do return()
drawStatsInfo.lastObjectHandle = GetHandleByAnim obj
drawStatsInfo.lastObjectName = obj.name
drawStatsInfo.lastObjectClass = (classof obj) as string
drawStatsInfo.lastObjectSuperClass = (superclassof obj) as string
drawStatsInfo.lastObjectLayer = obj.layer.name
drawStatsInfo.lastObjectParent = (if obj.parent == undefined then "sceneRootNode" else obj.parent.name)
drawStatsInfo.lastObjectChilds = dw_ds_formatNumber (obj.children.count as string)
drawStatsInfo.lastObjectMat = (if obj.material != undefined then classof obj.material as string + ": " + obj.material.name as string else "Unassigned")
drawStatsInfo.lastObjectFaceCount = (if superclassof obj == geometryclass then "
Faces: " + (dw_ds_formatNumber (obj.mesh.faces.count as string)) else "")
drawStatsInfo.lastObjectVertCount = (if superclassof obj == geometryclass then "
Vertices: " + (dw_ds_formatNumber (obj.mesh.vertices.count as string)) else "")
s = obj.max - obj.min
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
[DEBUG]
updateObject took: %s
" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.lastObjectDebug = ss as string
--format (ss as string)
)
),
fn drawObjNameInfo =
(
try
(
textColour = (colorMan.getColor #activeViewportBorder) * 255.0
textColour = color 196 196 196
--tt = fileProperties.getItems "Mesh Totals"
--st = fileProperties.getItems "Scene Totals"
drawStatsInfo.updateObjectStats()
dtext = case of
(
(selection.count == 0): (
""
)
(selection.count == 1): (
"Object: " + drawStatsInfo.lastObjectName + \
"
Class: " + drawStatsInfo.lastObjectClass + " (" + drawStatsInfo.lastObjectSuperClass + ")" + \
"
Layer: " + drawStatsInfo.lastObjectLayer + \
"
Parent: " + drawStatsInfo.lastObjectParent + \
"
Children: " + drawStatsInfo.lastObjectChilds + \
"
Material: " + drawStatsInfo.lastObjectMat + \
drawStatsInfo.lastObjectFaceCount + \
drawStatsInfo.lastObjectVertCount + \
drawStatsInfo.lastObjectSize + \
(if drawStatsInfo.debug then drawStatsInfo.lastObjectDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.totalDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.updateObjectSizeDebug as string else "") + \
(if not drawStatsInfo.disableTotalCount then "
Total Faces: " + drawStatsInfo.totalFaceCount else "
") + \
--"
Total Vertices: " + drawStatsInfo.totalVertCount + \
"
Scene Object Count: " + objects.count as string + \
"
FPS: " + viewport.getFPS() as string
)
(selection.count > 1): (
types = #()
for o in selection do appendifunique types ((classof o))
(selection.count as string) + " Objects Selected" + \
"
" + (types.count as string) + " classes " + (types as string) + \
"
Geometry: " + (for o in selection where superclassof o == geometryclass collect o).count as string + \
"
Shapes: " + (for o in selection where superclassof o == shape collect o).count as string + \
"
Lights: " + (for o in selection where superclassof o == light collect o).count as string + \
"
Cameras: " + (for o in selection where superclassof o == camera collect o).count as string + \
"
Helpers: " + (for o in selection where superclassof o == helper collect o).count as string + \
"
Space Warps: " + (for o in selection where superclassof o == spacewarpObject collect o).count as string + \
"
Particle Systems: " + (for o in selection where superclassof o == particlesystem collect o).count as string + \
"
Bone Objects: " + (for o in selection where superclassof o == geometryclass collect o).count as string
)
)
local pos = [10,38]
gw.setTransform(Matrix3 1)
gw.wText [pos.x, pos.y, 0] dtext color:textColour
)
catch(print ("issue" + (getCurrentException())))
),
fn loadSettings =
(
if not doesfileexist cfg do return false
if hasINISetting drawStatsInfo.cfg "Options" "Debug" do
drawStatsInfo.debug = getIniSetting drawStatsInfo.cfg "Options" "Debug" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "TotalCount" do
drawStatsInfo.disableTotalCount = getIniSetting drawStatsInfo.cfg "Options" "TotalCount" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "Enabled" do
drawStatsInfo.enabled = getIniSetting drawStatsInfo.cfg "Options" "Enabled" as BooleanClass
),
fn show =
(
global dw_ds_DrawStatsInfoUI
try(destroydialog dw_ds_DrawStatsInfoUI)catch()
rollout dw_ds_DrawStatsInfoUI "Viewport Stat Options" width:245
(
group "Options"
(
checkbox ckbDebug "Debug mode" checked:drawStatsInfo.debug
on ckbDebug changed val do drawStatsInfo.debug = ckbDebug.checked
checkbox ckbTotal "Enable total face count" checked:(not drawStatsInfo.disableTotalCount)
)
checkbutton ckbEnable "Enabled" checked:drawStatsInfo.enabled
button btnClose "Close" align:#right
on btnClose pressed do try(destroydialog dw_ds_DrawStatsInfoUI)catch()
label lblVer "Version: 0.000" align:#left
hyperLink lblAbout1 "© 2015 Dave Wortley" address:"http://www.taylorjames.com/" across:3 align:#left
label lblAboutM "and" align:#middle offset:[15,0]
hyperLink lblAbout2 "Daniel Santana" address:"http://www.ycdivfx.com/" align:#left
on dw_ds_DrawStatsInfoUI open do lblVer.text = "Version: " + drawStatsInfo.ver as string
on dw_ds_DrawStatsInfoUI close do
(
setIniSetting drawStatsInfo.cfg "Options" "Debug" (drawStatsInfo.debug as string)
setIniSetting drawStatsInfo.cfg "Options" "TotalCount" (drawStatsInfo.disableTotalCount as string)
setIniSetting drawStatsInfo.cfg "Options" "Enabled" (drawStatsInfo.enabled as string)
)
on ckbTotal changed val do
(
drawStatsInfo.disableTotalCount = not val
if not drawStatsInfo.disableTotalCount do ::dw_ds_updateTotals ok ok
)
on ckbEnable changed val do
(
::drawStatsInfo.enabled = val
::drawStatsInfo.enable()
)
)
createdialog dw_ds_DrawStatsInfoUI
),
fn createMacros =
(
files = getfiles (pathConfig.appendPath (getdir #usermacros) "*.mcr")
macr = for f in files where findstring (tolower (getfilenamefile f)) "dwdsviewportstats" != undefined collect f
if macr.count == 0 do
(
macros.new "Views" "Macro_DwDsViewportStats" "DrawStatsInfoUI" "DrawStatsInfoUI" "
on execute do
(
::drawStatsInfo.show();
)
"
format "DrawStatsInfo Macro created.
"
)
),
fn enable =
(
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
if drawStatsInfo.enabled do registerRedrawViewsCallback (drawStatsInfo.drawObjNameInfo)
),
fn setup =
(
drawStatsInfo.loadSettings()
drawStatsInfo.createMacros()
drawStatsInfo.enable()
)--,
--init = setup()
)
if not IsNetServer() do
(
drawStatsInfo = drawStatsInfo()
drawStatsInfo.setup()
global dw_ds_updateTotals
global dw_ds_updateObject
global dw_ds_updateObjectSize
fn dw_ds_updateTotals evt nds =
(
try(
st = timestamp()
drawStatsInfo.totalCounts = objects.count as string
--tv = 0
tf = 0
--for o in objects where superclassof o == geometryclass do (try(tv += o.mesh.numvertices)catch())
if not drawStatsInfo.disableTotalCount do for o in objects where superclassof o == geometryclass do (try(tf += (GetTriMeshFaceCount o)[1]/*o.mesh.numfaces*/)catch())
drawStatsInfo.totalFaceCount = dw_ds_formatNumber (tf as string)
--drawStatsInfo.totalVertCount = tv as string
drawStatsInfo.updateObjectStats force:true
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "updateTotals took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.totalDebug = ss as string
--format (ss as string)
)
)catch()
)
fn dw_ds_updateObject evt nds =
(
try
(
drawStatsInfo.updateObjectStats force:true
)
catch()
)
fn dw_ds_updateObjectSize evt nds =
(
try
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
s = obj.max - obj.min
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
updateObjectSize took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.updateObjectSizeDebug = ss as string
--format (ss as string)
)
)
catch(print "ooops")
)
dw_ds_updateTotals undefined undefined
dw_ds_callback = NodeEventCallback enabled:true mouseup:true delay:50 topologyChanged:(dw_ds_updateTotals) added:(dw_ds_updateTotals) deleted:(dw_ds_updateTotals) materialStructured:(dw_ds_updateObject) nameChanged:(dw_ds_updateObject) geometryChanged:(dw_ds_updateObjectSize) controllerOtherEvent:(dw_ds_updateObjectSize)
)