Home Technical Talk

[MaxScript] regular expressions doubts

polycounter lvl 7
Offline / Send Message
EspiSensei polycounter lvl 7
Hi everybody!

It's my first encounter with regular expressions ( i never used it) and i don't know how to get read a multiples files (previously selected), and change the param "normal_map" from "False" to "True" and vice versa.
this a example file.

{
							"$name": "Model_Tree_LOD_blue",
							"$type": "@tts::editor::MaterialEntity",
							"$params": {
									"normalMap": {
										"$isSet": false,
										"$hasValue": false
									},
									"normalMapUVChannelIdx": 1,
									"diffuseMapUVChannelIdx": 1,
								},
								"features": [
									{
										"$name": "albedo_map",
										"$type": "::bool",
										"$value": true
									},
									{
										"$name": "normal_map",
										"$type": "::bool",
										"$value": false
									},
								],
}


If anyone can lighting my way, i'll love forever and ever and ever :blush:

Replies

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    my advice would be don't use maxscript and regex 

    Python has easy to use libraries for accessing JSON elements and making changes.  I'd strongly suggest doing that instead 
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    mmm, the problem is, i don't know python  :# .

    Well, I'll study some Python.  Thanks poopipe !! ^^
  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    If you don't fancy trying it out in Python you could use the .NET JSON libraries through maxscript.  I've not done it myself but I have used the .NET XML library to good effect. 

    I'm not sure it'd be any less effort than learning and doing it in python though. 

  • monster
    Options
    Offline / Send Message
    monster polycounter
    poopipe is right, don't bother with Regex.

    The python code for this is pretty easy. The only issue was I had to paste your Json text in to an online linter before Python could read it.

    https://jsonlint.com/

    import json
    
    #open file for reading
    data_file = open("C:\Users\monst\Desktop\data.json", mode='r')
    
    #load the json file into a dict
    data = json.load( data_file )
    
    #update the dict
    data['$params']['normalMap']['$isSet'] = not data['$params']['normalMap']['$isSet']
    
    #open the file for writing
    data_file = open("C:\Users\monst\Desktop\data.json", mode='w')
    
    #write the dict back to json format
    data_file.write(json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')))
    
    #close the file
    data_file.close()

  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Python in max works fine alone? or need to works with maxscript? all of this is for create the next tools in maxscript or Python.

    monster thank you so much for the script! ^^ you rock! 
  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    You can use python in max.  It appears to be more arseache than using maxscript natively but less arseache than using  .Net libraries

    Disclaimer . ..  I've got very little experience beyond doing a hello world experiment in max python as I only get paid to script for maya.

    Python is worth learning,  it's initially disgusting if you're used to C style languages but it's so widely used in CG that you'd be dumb to dismiss it. 
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Mmm, i saw that the best way maybe will be use the both, isn't it? for example, Maxscript for native functions and Python better to develop the interface ?

    I'll to take advantage of this thread, with another mini question. What MaxScript/Python editor which editor can to execute the scripts into the 3ds MAx 2017 recommend me?  

    Sorry if i'll being heavy or abuse into this thread, but i think it's better tan create a differents threads.

    And thank you so much again for the help! ^^
  • monster
    Options
    Offline / Send Message
    monster polycounter
    I use Sublime Text 3 with a couple of packages.
    • Send To Max - binds Ctrl + E (like the maxscript Editor) to execute the current file in Max.
    • Anaconda - Python IDE and Autocomplete
    • Perforce - for source control
    • Theme - Freesia - dark theme, like my soul

  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Another question guys.

    I'm reading somethings about Python and 3ds max. What is the best way to create scripts throught MaxPlus or pymxs?

    In Monster's picture, i see that you use MaxPlus.

    So far i'm very noob in python  and It with 3ds Max.

    If i want to recreate some of my mxs scripts, i would have to use MaxPlus?

    Thanks for all the help guys! ^^
  • monster
    Options
    Offline / Send Message
    monster polycounter
    You'll probably need both.

    MaxPlus is access to most of the 3ds Max API through python. (Same API you get from C++, just not all of it.)
    pymxs is a bridge to maxscript commands though Python.


  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    I think that i got it.

    I need two, because will be cases with Maxplus doesn't have the correctly command or function and i need pymxs. So, in any cases of this, i understand that i could refactor my mxs scripts with Python ( obviously with MaxPlus and pymxs ), aren't they? 


  • RN
    Options
    Offline / Send Message
    RN sublime tool
    I'm also practising regex, so I wanted to try it anyway. This is untested:
    import re
    
    for file_path in my_files: # A list or tuple with your file paths.
        with open(file_path, 'r+' ) as f:
            content = f.read()
            new_content = re.sub(r'(normal_map.*?value.*?)(false|true)',
            	             lambda m: m.group(1) + 'true' if m.group(2) == 'false' else m.group(1) + 'false',
            	             content, flags=re.DOTALL)
            f.seek(0)
            f.write(new_content)
            f.truncate() # In case the amount of new content is less than the original content.
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    RN thanks for your help! ^^

    Another Python question guys. 

    How do you create the Python UI? i've seen that the people, uso QT creator or designer. this tool is usefull for this?
  • Mark Dygert
    Options
    Offline / Send Message
    Yea QT designer is great, coding a UI by hand is for the birds...

    This blog post from 2014 has some great info that is still relevant. http://www.losart3d.com/?p=828


  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Mark! thank you for the info, I'll have a look this link! ^^
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    in my first steps with python and Qt more or less i understand how it works, in next steps i have a mini troubles for example  i don't know how does this fix:



    if evaluate in max, it works. Someone could light my way, please ^^



  • Axi5
    Options
    Offline / Send Message
    Axi5 interpolator
    in my first steps with python and Qt more or less i understand how it works, in next steps i have a mini troubles for example  i don't know how does this fix:



    if evaluate in max, it works. Someone could light my way, please ^^



    It's because the interpreter/linter in Visual Studio Code doesn't know of the existence of the MaxPlus/pymxs module, those modules only exist in the Max specific interpreter. You can change the settings for this somewhere to point to it I'm sure but I'm not a Max user and don't have it installed (nor did I know until now that there was a Python Interpreter for Max) so you'll have to wing it.
  • monster
    Options
    Offline / Send Message
    monster polycounter
    Axi5 is right. The interpreter is in the root application folder named 3dsmaxpy.exe.
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Cool guys!
    but how can i change this settings in VScode?  
    thank for all this help! ^^
  • Axi5
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Hi guys!

    i have a little doubt about custom functions (its a dle, this function call a C++ script), the sintax in maxscript is the following:

    local customScriptOK = customSript theObjs thePath settings:customScriptSettingsFile log:customScriptLogFiletheObjs = #(obj1,obj2)
    thePath = "C://"
    
    this script you can call like other maxscripts function.

    But I don't know how to do works this in Python, i thoug this:
    customScriptOK = rt.customSript(theObjs thePath settings:customScriptSettingsFile log:customScriptLogFile)import pymxs
    
    theObjs = [obj1,obj2]
    thePath = "C:\"
    
    
    OR
    customScriptOK = rt.customSript(theObjs thePath rt.settings:customScriptSettingsFile rt.log:customScriptLogFile)import pymxs
    
    <pre class="CodeBlock"><code>theObjs = [obj1,obj2]
    thePath = "C:\"
    
    But i don't get anything.
    can someone help me with this? 

    Thanks for all again and thanks axi5 for your previous help ^^ (i forgot to say you)



  • Axi5
    Options
    Offline / Send Message
    Axi5 interpolator

    You're importing the pymxs module but you're not using it! I assume you went to the documentation and saw rt.customScript() and assumed it would work, but you first need to define the rt object.

    This is the line I believe you need:
    rt = pymxs.runtime
    Place it somewhere before line 5. This will load the pymxs module, then the runtime commands and copy them into the object rt. Now you can access commands through the rt variable.

    Also you have a typo, you put customSript instead of customScript.

    I'm also unsure about your syntax regarding the rt.settings portion of your python code, and I'm doubtful that this will work. It'll likely be rt.settings(customScriptSettingsFile) and rt.log(customScriptLogFile), since python uses the colon : operator to access function/if/loop blocks.
  • RN
    Options
    Offline / Send Message
    RN sublime tool
    In that case, an alternative way to import runtime (to save up on one line):
    from pymxs import runtime as rt

  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Doh!, sorry guys for this noobs mistakes! haha

    But I've tried with your feedback and doesn`t work :( the error which 3ds max gave me was: 



    The same error gave the Listener:

     "Traceback (most recent call last):
    SyntaxError: invalid syntax (<input>, line 132)"

    And in my IDE(Visual Studio Code), the pylynt says the same: "E0001:invalid syntax (<string>, line 132)"

    Surele, I'm writting wrong the sintax but i don't know where :sweat:

    My actual syntax is this: 

    customScriptSettingsFile) rt.log(customScriptLogFile))import pymxs
    rt = pymxs.runtime
    
    theObjs = [obj1, obj2]
    thePath = "C:/"
    customScriptOK = rt.customScript(theObjs thePath rt.settings(


    The script in maxscript works perfectly, the problem by me is I don't know how to translate this in python code (using MaxPlus or/and pymxs).

    thanks again guys!

  • RN
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    Thank you RN!
    i've try this correction:
    customScriptOK= rt.customScript(theObjs, thePath, rt.settings(customScriptSettingsFile), rt.log(customScriptLogFile))
     and now the listener show me new error:

    AttributeError: 'pymxs.runtime' object has no attribute 'settings'

    I tried with this syntax:

    customScriptOK= rt.customScript(theObjs, thePath, settings(customScriptSettingsFile), log(customScriptLogFile))
    But appear the following errors, are obvius:
    [pylint] E0602:Undefined variable 'settings'
    [pylint] E0602:Undefined variable 'log'

    And this:

    customScriptOK= rt.customScript(theObjs, thePath, settings:customScriptSettingsFile, log:customScriptLogFile)
    But appear the following error:
    E0001:invalid syntax (<string>, line 132) 


    customScriptOK= rt.customScript(theObjs, thePath, rt.settings:customScriptSettingsFile, rt.log:customScriptLogFile)But appear the following error:
    E0001:invalid syntax (<string>, line 132) 

    this 3 options are incorrect.
    i'm searching by google how to translate this things (Maxscript --> function var var  option:  option:) but the moment i haven't found anything.

    thank you again guys! ^^



  • Swordslayer
    Options
    Offline / Send Message
    Swordslayer interpolator
    For optional arguments, it should be rt.customScript(theObjs, thePath, settings=customScriptSettingsFile, log=customScriptLogFile)
  • EspiSensei
    Options
    Offline / Send Message
    EspiSensei polycounter lvl 7
    that`s it!
    It works! 

    thanks again for your help guys! ^^
Sign In or Register to comment.