Notifications
Clear all

[Closed] MaxSQL

Got a new contraption that got a bit out of hand. It’s a way to get anything from the scene using something that resembles how you would interact with a mysql.database.

Have a look at the examples, I think it’s quiite powerfull, think of it like getClassInstances on steroids! The concept is to build up a query by setting the struct parameters and then _run() it to get the result.

It’s a bit of a polished prototype at the moment so if anyone sees room for improvements feel free to add. I avoided class specific code and or executes. Maybe the lambda functions are a bit messy, if there is a better way let me know!

(be careful if you run this in an existing scene, example #4 renames all things dirived from the texturemap class)

Enjoy!


  
struct maxSQL
(
    private

         fn recursive_find_subanim  sa out =
        (
            if (classof sa == subanim) do
            (
      
                for i=1 to sa.numSubs  do (
                    if (classof sa[1] == subanim) do
                    (
                        appendifunique out sa[i]
                        out  = recursive_find_subanim sa[i] out
                    )
                )
                
            )
            out
        ),
            
        fn recursive_find_inherted_classes _class _trg out =
        (
            items = refs.dependson _trg

            for item in items do
            (
                tmp=classof item
                while (classof tmp != Value AND  classof tmp != MaxWrapper ) do
                (
                    if (classof tmp == _class ) do ( append out item;   )
                    tmp=classof tmp
                )
                 out  = this.recursive_find_inherted_classes _class item out
            )

            out
        ),

        fn getInheretedClassInstances _class target:false = ( this.recursive_find_inherted_classes _class target #() ),

    public
        _select = false,
        _from = #(),
        _where,
        _order = #(),
        _set,
        _result =#(),
        collection,

        verbose = false,
        fn debug msg = ( if this.verbose do print msg ),

        fn _run _select:this._select _from:this._from  _where:this._where  _order:this._order  _set:this._set  nocache:false =
        (
            if (_where == undefined) then ( _where = fn __ item = (true); )

            if (classof _from == subanim) do ( _from = this.recursive_find_subanim _from #(); )  -- get all nested sub anims.
            
            if (classof _from != array) do (_from=#(_from))
            
            -- select requested items
            collection= #();

            if (classof _select != Array )  do ( _select = #(_select))

            i=0;

            for sel in _select do
            (
                for src  in _from do
                (
                    items = #()

                    case of
                    (
                        ( classof sel == ObjectSet )  : ( items = src )                                                            --work with sets of nodes  (Objects, Cameras, etc)
                        ( isProperty sel "creatable" == false )    : ( items = this.getInheretedClassInstances sel  target:src )    --select instances which are extended from a given 'deeper' class  (texturemap,  rotationcontroller, etc)
                           default: items =  getClassInstances sel  target:src                                                                           --select a creatable class
                    )

               for item in items where ( _where item items:items i:i )  do ( if (appendifunique collection item) do ( i+=1 ) )

                )
            )

            --Order items
            if (_order.count > 0) do
            (

                if (_order[2]==#desc) then ( _order[2] = 1 ) else (_order[2]=-1)

                qsort collection (
                    fn __ item1  item2 data: = (
                        a=b=false;
                        if ( isproperty item1 data[1] ) do ( a=getProperty item1 data[1] )
                        if ( isproperty item2 data[1] ) do ( b=getProperty item2 data[1] )


                        if ( a==b )  do ( return 0 );
                        if ( a>b ) do ( return -1*data[2] )

                        return 1*data[2]
                    )
                ) data:_order;
            )

            --set properties
            if (_set !=undefined) do
            (
                for i = 1 to collection.count do ( _set collection[i] items:collection i:i )
            )

            --if allowed cache the latest result in the struct
            if (not nocache ) do (this._result = collection)

            collection
        )

)




(     ----  USAGE  EXAMPLES -----


    print "example 1"
    q=maxSQL()  -- create new struct
    q._select=PRS;  -- give me all the PRS controllers
    q._from=cameras;  --that are in this set of objects
    result = q._run()  -- run query
    print result #nomap
    print "---------"


    print "example 2"
    q=maxSQL()  -- create new struct
    q._select=bitmaptexture;  -- give me all the bitmaptexture instances
    q._from=objects ;  --that are used on anything in this set of objects
    q._where= ( fn __ item = ( not doesfileexist item.fileName  ))  -- where the file does not exist;
    result = q._run()  -- run query, you'll get an array with all isntances that have missing bitmaps
    print result #nomap
    print "---------"


    print "example 3"
    q=maxSQL()  -- create new struct
    q._select=texturemap;  -- give me all the instances of texturemaps (noise, checker, bitmaptexture etc)
    q._from=objects ;  --that are used on anything in this set of objects
    q._where= ( fn __ item = ( not  (classof item == Noise AND item.color1== color 0 0 0   )))  -- but not the noise maps that have a black #1 color
    result = q._run()
    print result #nomap
    print "---------"


    print "example 4"
    q=maxSQL()  -- create new struct
    q._select=texturemap;  -- give me all the instances of texturemaps (noise, checker, bitmaptexture etc)
    q._from=objects ;  --that are used on anything in this set of objects
    q._order = #( "name", #asc )  -- order them by name ascending   ( #desc  for the reverse)
    --q._set = fn __  item  i: = (  item.name = "map_" + i as string;  )    --  uncomment to set map names to incremental names.
    result = q._run()  -- run query, you'll get al maps renamed
    print result #nomap
    print "---------"



    print "example 5"
    q=maxSQL()  -- create new struct
    q._select=material;  -- give me anything that is a maxtrix3 conroller
    q._from=selection ;  --that are used on anything in this set of objects
    q._where= ( fn __ item = (   findstring (classof item as string ) "corona"  != undefined   ))  -- that have the 'corona' in their classname
    result = q._run()  -- run query, you'll get an array with all corona material instances  used in the scene
    print result #nomap
    print "---------"



    print "example 6"
    q=maxSQL()

    --Items from a  class or inhereted class we are looking for
    q._select=texturemap;

    --Array or single item of anything on which hierachy to search in
    q._from=objects;

    -- a function that take 'item' as parameter. if it returns true the item will be inthe result
    q._where = ( fn __ item = (  if (isProperty item "coords" AND classof item.coords == StandardUVGen ) then ( item.coords.U_Offset  != 0 or  item.coords.V_Offset  != 0 ) else (false); ) )

    -- a  property and a #desc or #asc
    q._order = #( "name", #asc )

     -- run the query, it will return the result
    result = q._run()

    -- get the lastest cached result again.
    result = q._result
    print result
    print "reversed:"

    --now override the order set in the struct, but keep all the other quaery parameters but don't overwrite teh internal cache.
    result = q._run _order:#( "name", #desc) nocache:true

    print result
    print "---------"

    print "example 7"
    --get selected items in the SME
    q=maxSQL()  -- create new struct
    q._select=#(texturemap, material);
    q._from=trackViewNodes[#sme][sme.activeView]  ;
    q._where = ( fn __  item  = ( a= ((sme.GetView (sme.activeView)).GetNodeByRef item); if isproperty a "selected" then  a.selected else false))  --; 
    result = q._run()
    print result #nomap

 
)

5 Replies

Here is another useful example to get all animated float controllers that are part of the selected object’s transform.


    q=maxSQL()  -- create new struct 
    q._select=bezier_float;  -- give me all the bezier_float controllers
    q._from=#($.transform.controller)  ;  --that are used on anything in this array
    q._where= ( fn __ item = ( item.keys.count > 0  ))  -- which does have keys on it.
    result = q._run()  -- run query, you'll get an array with all animated controllers related to transform
    print result #nomap
 

Updated the code in the OP.

the _where and _set function now have optional params, like so:


 q._where = ( fn __  item = ( print item;  true ) )    --only use item
 q._where = ( fn __  item items: = ( print item; print items.count;  true ) )   --use item and all items
 q._where = ( fn __  item items: i: = ( print item; print items.count; print  i;  true ) ) - use item, all items, and current item index

The _select can now be either a sinlge item or an array of classes:


q._select=bezier_float;  -- get all float controller
q._select=#(bezier_float, PRS);  --get all float  and PRS controllers

(do make sure the _where and _set function can handle different classes.

And now also support for _from subanims,


    --And inspired by Dave's SME endeavors:  get all items in the SME that don't have unique names

    q=maxSQL()  -- create new struct 
    q._select=#(texturemap, material );  
    q._from=trackViewNodes[#sme][sme.activeView]  ;  
    q._where = ( fn __  item items: =
                            (
                                check=false;
                                n="";
                                if ( isproperty item "name" ) do ( n=getProperty item "name"; );
                                for chk in items where  (  (  chk != item AND (isproperty chk  "name" ) AND  chk.name == n  )  )  do ( check = true; );
                                check
                            )
                    )
    result = q._run()  -- run query, you'll get an array with all instances with non unique names
    print result #nomap


Perhaps you can take some ideas from here:
http://forums.cgsociety.org/showthread.php?t=1438311

Yeah I saw that, cool project!

Proper docs and link to up-to-date source from my free tools repo:

http://www.jdbgraphics.nl/maxscripts/maxsql