The following tutorials demonstrates the use of the .GetHashCode()
method exposed by the "System.String
" dotNetObject for determining whether specific data collected in the form of a string has changed between two runs of the script.
Related topics:
NATURAL LANGUAGE
Define a MAXScript function to calculate the Hash code of all scene objects.
Collect the name, transformation matrix and parent of every object in a string.
Get the HashCode of the string and return it.
EXAMPLE
fn getHashCodeFromGeometry = (
local hashStr = stringstream ""
for obj in objects do (
print obj.name to:hashStr
print obj.transform to:hashStr
if obj.parent != undefined then print obj.parent.name to:hashStr
)--end for loop
(dotNetObject "System.String" hashStr).GetHashCode()
)--end function
fn getHashCodeFromGeometry = (
Define a MAXScript function to be called by the Timer.
local hashStr = stringstream ""
Create an empty string stream to collect the data to convert to Hash Code.
for obj in objects do (
Loop through all scene objects...
print obj.name to:hashStr print obj.transform to:hashStr
And print the name and transform of the current object to the stream.
if obj.parent != undefined then print obj.parent.name to:hashStr
If the object has a parent, also print the parent's name to the stream.
)
(dotNetObject "System.String" hashStr).GetHashCode()
Finally, create an instance of the System.String class from the collected string stream and get its Hash Code.
)--end function
Let's see how this function could be useful in a real-world situation.
Let's assume we are developing a script which has to perform complex time consuming calculations when the scene content has changed. For example, it would have to rebuild all its data when
the object count in the scene has changed (objects were added or removed),
one or more objects were renamed
one or more objects were moved, rotated or scaled
the hierarchy has changed (objects were linked or unlinked to/from parent objects)
It would be useful to cache the last results and return the same value next time the script is executed if the scene has not changed since the previous run. If checking the scene for changes is significantly faster than actually processing the data again, this would lead to a nice speed up.
One possible approach would be to store all this scene state data in some user variables - assign the objects.count value to a variable, collect the names, transformation matrices and parent names of all objects into arrays the first time the script is run and then, the next time the script has to determine whether it needs to recalculate its initial data, it could collect the same information once again and compare all values with the results from the previous run.
Obviously, if the scene contains 10,000+ objects, the amount of data to store (and the time needed to collect and compare the two data sets) would be quite substantial.
But since we are not interested in the actual data values but only want to know whether they have changed between runs, we can use the HashCode value which represents ALL the above conditions with a single long integer value. All we have to do is run the function once to get a HashCode number reflecting the count, names, transforms and parents of all scene objects, then if we want to know if any of these properties have changed since the last time we run our script, we can call the function again and compare the two values. If the numbers are the same, the scene has not changed. In that case we can skip any data rebuilding steps since we can be confident the scene is in the same state as before. If the hash values are different, we must reprocess the scene to collect the actual data.
Of course, the above function is just one example of possible HashCode usage. It can be changed to reflect more or less properties of objects, or could be used to track the state of other values that can be represented as strings.