├── .gitignore ├── otls ├── sop_lattice_v001.hda ├── sop_objRender_v001.hda ├── sop_variantMerge_v001.hda ├── LEO.linkedsubnet.1.0.hdalc ├── LEO.linkedsubnet.1.1.hdalc ├── sop_attributeSplit_v001.hda ├── sop_colorRampPicker_v003.hda ├── sop_objRenderChild_v001.hda ├── sop_weightedRandom_v001.hda ├── sop_connectPointsIntersect_v001.hda └── sop_groupIntersectingObject_v001.hda ├── docs ├── callWarningError.md ├── docs_randomRamp.md ├── F1_docs_template.md ├── vexFunctions.md └── HDA Python Tips.md ├── LEOTools_package.json ├── create_package_json.py ├── HDA Creation.md ├── toolbar └── leo.shelf ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── README.md ├── misc └── LEO_logo_v001.svg ├── desktop ├── LEO_Custom.desk └── LEO_Custom_split.desk └── scripts └── python ├── leo_random_ramp.py └── leo_random_ramp.ui /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | /otls/backup/* -------------------------------------------------------------------------------- /otls/sop_lattice_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_lattice_v001.hda -------------------------------------------------------------------------------- /otls/sop_objRender_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_objRender_v001.hda -------------------------------------------------------------------------------- /otls/sop_variantMerge_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_variantMerge_v001.hda -------------------------------------------------------------------------------- /otls/LEO.linkedsubnet.1.0.hdalc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/LEO.linkedsubnet.1.0.hdalc -------------------------------------------------------------------------------- /otls/LEO.linkedsubnet.1.1.hdalc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/LEO.linkedsubnet.1.1.hdalc -------------------------------------------------------------------------------- /otls/sop_attributeSplit_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_attributeSplit_v001.hda -------------------------------------------------------------------------------- /otls/sop_colorRampPicker_v003.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_colorRampPicker_v003.hda -------------------------------------------------------------------------------- /otls/sop_objRenderChild_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_objRenderChild_v001.hda -------------------------------------------------------------------------------- /otls/sop_weightedRandom_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_weightedRandom_v001.hda -------------------------------------------------------------------------------- /otls/sop_connectPointsIntersect_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_connectPointsIntersect_v001.hda -------------------------------------------------------------------------------- /otls/sop_groupIntersectingObject_v001.hda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kilbau/LEO_Tools/HEAD/otls/sop_groupIntersectingObject_v001.hda -------------------------------------------------------------------------------- /docs/callWarningError.md: -------------------------------------------------------------------------------- 1 | # HDA Warning / Error 2 | 3 | 1. use vex warning() or error() functions or error sop to create a warning / error. 4 | 2. add the nodes to *Node - Message Nodes*. That way the error is displayed on the HDA. 5 | -------------------------------------------------------------------------------- /docs/docs_randomRamp.md: -------------------------------------------------------------------------------- 1 | ### shelf tool: LEO_randomRamp ### 2 | 3 | ## Use: ## 4 | Override or modify a *Channel Ramp Parameter* 5 | 6 | This tool updates a linear channel ramp with random values to generate more variation for modeling, fx, shading etc. 7 | -------------------------------------------------------------------------------- /LEOTools_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommends": "houdini_version >= '18.0'", 3 | "env": [ 4 | { 5 | "LEO": "D:/Resources/HDA/LEO_Tools" 6 | }, 7 | { 8 | "PYTHONPATH": "$LEO/scripts/python", 9 | "method": "append" 10 | } 11 | ], 12 | "path": "$LEO" 13 | } -------------------------------------------------------------------------------- /create_package_json.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | 5 | def run(): 6 | path = os.getcwd().replace("\\", "/") 7 | 8 | content = { 9 | "recommends": "houdini_version >= '18.0'", 10 | "env": [ 11 | {"LEO": path}, 12 | {"PYTHONPATH": "$LEO/scripts/python", "method": "append"}, 13 | ], 14 | "path": "$LEO", 15 | } 16 | 17 | with open("LEOTools_package.json", "w") as f: 18 | json.dump(content, f, indent=4) 19 | 20 | 21 | if __name__ == "__main__": 22 | run() 23 | -------------------------------------------------------------------------------- /HDA Creation.md: -------------------------------------------------------------------------------- 1 | ## HDA Naming Reference: 2 | Follow this naming reference to have a consitent workflow! 3 | 4 | Operator Name: LEO::[hdaName]::[x] 5 | 6 | * *LEO::variantMerge::1* 7 | 8 | Operator Label: LEO [Hda Name] 9 | 10 | * *LEO Variant Merge* 11 | 12 | File Name: [type]_[hdaName]_v[xxx].hda 13 | 14 | * *sop_variantMerge_v001.hda* 15 | 16 | Version: x 17 | 18 | * *1* 19 | 20 | Interactive - Shelf Tools - Context - Network Pane - [type] 21 | 22 | * *SOP* 23 | 24 | Interactive - Shelf Tools - Context - Tab Submenu Path - LEO 25 | 26 | * *LEO* 27 | 28 | Icon: 29 | * *$LEO/misc/LEO_logo_v001.svg* 30 | -------------------------------------------------------------------------------- /toolbar/leo.shelf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/F1_docs_template.md: -------------------------------------------------------------------------------- 1 | = My Asset = 2 | #version: 3 | #icon: opdef:.?LEO_logo_v001.svg 4 | 5 | """A quick summary of what the node does.""" 6 | 7 | == Overview == 8 | 9 | Explanation of the node's purpose and operation. 10 | 11 | @inputs 12 | 13 | Label: 14 | What the input is for. 15 | 16 | @parameters 17 | 18 | Label: 19 | #id: internalname 20 | 21 | Explanation of what the parameter does. 22 | 23 | Label: 24 | #id: internalname 25 | 26 | Explanation of what the parameter does. 27 | 28 | @related 29 | 30 | * [Node:sop/copy] 31 | 32 | 33 | ############################# 34 | [Include:/nodes/sop/extractcentroid#method/] referencing attribute docs from another node -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an HDA / Improvement of an HDA 4 | title: '' 5 | labels: enhancement 6 | assignees: Kilbau 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: Kilbau 7 | 8 | --- 9 | 10 | **What Asset is problematic?** 11 | Name of the HDA 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. 28 | 29 | **Desktop (please complete the following information):** 30 | - OS: [e.g. iOS] 31 | - Browser [e.g. chrome, safari] 32 | - Version [e.g. 22] 33 | 34 | **Smartphone (please complete the following information):** 35 | - Device: [e.g. iPhone6] 36 | - OS: [e.g. iOS8.1] 37 | - Browser [e.g. stock browser, safari] 38 | - Version [e.g. 22] 39 | 40 | **Additional context** 41 | Add any other context about the problem here. 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kilian Baur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/vexFunctions.md: -------------------------------------------------------------------------------- 1 | ### Creating Custom Vex Functions ### 2 | 3 | 4 | ## Modify input parameters and return them ## 5 | ```C 6 | //create function with multiplier parameter 7 | function void test(int in_a, in_b, multiplier) 8 | { 9 | //no need to return those values 10 | //they automatically replace the input paramters 11 | in_a *= multiplier; 12 | in_b *= multiplier; 13 | } 14 | //create function w/o multiplier parameter 15 | function void test(int in_a, in_b) 16 | { 17 | in_a *= 2; 18 | in_b *= 2; 19 | } 20 | 21 | //initialize variables to allow houdini to read/write 22 | int user_a = 2; 23 | int user_b = 4; 24 | 25 | //houdini uses the function with the same paramters 26 | //test(user_a, user_b); 27 | test(user_a, user_b, 4); 28 | //test(2,4,4) doesnt work. the first two variables are read only 29 | 30 | i@a = user_a; 31 | i@b = user_b; 32 | ``` 33 | ## Save functions to file and read them in wrangles ## 34 | * Save the vex functions in a new file "Filename.h" 35 | * In a wrangle import functions from the file 36 | ```C 37 | #include PATH/TO/FILE/Filename.h 38 | //e.g. #include "$LEO/vex/LEO_evalLSystems.h" 39 | ``` 40 | * Use the functions as normally 41 | ```C 42 | float test = lsysMultValue(1,3); 43 | f@value = test; 44 | ``` 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LEO_Tools (Beta): 2 | A collection of HDAs for SideFX Houdini. 3 | I'll upload them whenever I created a new one for my projects. 4 | 5 | They are made with Houdini 18(.5) **Indie** and should only work with Indie, Apprentice or Educational. 6 | 7 | Also I'll add some useful code to the useful folder whenever I encounter something cool. 8 | Newer tools are made for Python 3 but should still work with Python 2 builds of Houdini. 9 | 10 | ## List of current HDAs: 11 | All nodes are documentated via the houdini documentation. To view the documentation press F1 or the questionmark-icon in the parameters. 12 | 13 | ### SHELF TOOLS: 14 | * **LEO Random Ramp**: Updates or adjusts ramp parameters by random values to generate more interesting results. 15 | 16 | ### SOP: 17 | * **LEO Color Ramp Picker**: Allows the interactive creation of a color ramp in the viewport. [Demo Video](https://vimeo.com/448546910) 18 | * **LEO Group Intersecting Object**: Generates a group based on the intersection with another geometry. 19 | * **LEO Variant Merge**: Merges geometry and simultaneously creates a variant attribute for the "Copy to Points"-SOP. [Demo Video](https://vimeo.com/448293988) 20 | * **LEO Connect Points Intersect**: Creates lines between nearby points which do not intersect with another geometry. 21 | * **LEO Object Render**: Creates an object-level node which only renders the incoming geometry. 22 | * **LEO Attribute Split**: Splits an incoming geometry based on an attribute. 23 | * **LEO Weighted Random**: Creates an random attribute based on weighted inputs. [Demo Video](https://vimeo.com/448293988) 24 | * **LEO Lattice**: Easily place a lattice deformer anywhere on a mesh. [Demo Video](https://vimeo.com/535531223) 25 | * **LEO Linked Subnets**: Connects subnets together to copy nodes and parameters. [Demo Video](https://vimeo.com/618260092) or [More Information](https://www.sidefx.com/forum/topic/80497/#post-348519) 26 | 27 | ### OBJ: 28 | * **LEO Object Render Child**: Object-level node created by LEO Object Render. 29 | 30 | ### MAT: 31 | 32 | ## Installation: 33 | Download or clone this repo and place it somewhere safe. 34 | 35 | ### Method 1: houdini.env 36 | The houdini.env on Windows 10 should be located at 37 | 38 | ```c:/users/[username]/Documents/houdini[version]``` 39 | 40 | Add following to the env but change the "LEO" path to the downloaded directionary 41 | 42 | Add the path to both the ```HOUDINI_PATH``` as well as the ```PYTHONPATH``` 43 | 44 | Example houdini.env file 45 | ``` 46 | LEO = "E:/Projects/LEO_Tools" 47 | 48 | HOUDINI_PATH = $LEO;& 49 | PYTHONPATH = "$LEO/scripts/python;&" 50 | ``` 51 | 52 | ### Method 2: Plugin / Packages 53 | ***Requires Houdini 17.5+*** 54 | 55 | Put the LEOTools_package.json file into the packages folder. 56 | 57 | It should be located here on Windows: 58 | 59 | ```c:/users/[username]/Documents/houdini[version]/packages``` 60 | 61 | On Linux: 62 | 63 | ```~Library/Preferences/Houdini``` 64 | 65 | Finally update following line to match your downloaded directionary 66 | 67 | ```"LEO": "D:/Resources/HDA/LEO_Tools"``` 68 | 69 | ***NOTE:*** 70 | If you have Python installed on your system you can run the included ```create_package_json.py``` file. 71 | This will create a new LEOTools_package.json with the path to the current directionary. 72 | ### Display Shelf ### 73 | 74 | Add the "LEO Tools" shelf by clicking on the plus by the shelves 75 | "+" -> "Shelves" -> "LEO Tools" 76 | -------------------------------------------------------------------------------- /misc/LEO_logo_v001.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /docs/HDA Python Tips.md: -------------------------------------------------------------------------------- 1 | # Action Button Group # 2 | ### Use this code inside the "Action Button" Tab for **String Parameters**: 3 | 4 | ```python 5 | import soputils 6 | kwargs['geometrytype'] = hou.geometryType.Points 7 | kwargs['inputindex'] = 0 8 | soputils.selectGroupParm(kwargs) 9 | ``` 10 | 11 | change the Points to the required selection type: 12 | * Edges 13 | * Points 14 | * Primitives 15 | * Vertices 16 | 17 | change the 0 to the current nodes input 18 | 19 | ### For a group dropdown menu 20 | enable **Use Menu** under Menu and change the dropdown to **Toggle (Field + Multiple Selection Menu)** 21 | 22 | ### To get the little arrow symbol 23 | 24 | add a new Tag on the Parameter Menu 25 | 26 | Tag Name: script_action_icon 27 | 28 | Tag Value: BUTTONS_reselect 29 | 30 | # Callback Script # 31 | It is possible to call a function from a parameter. For example when a button is pressed or a value changed. 32 | 33 | The easiest way is defining the functions in "scripts" - "PythonModule". 34 | Then in the parameter callback script field run the script. 35 | ``` python 36 | hou.phm().myFunction(kwargs) #replace myFunction 37 | ``` 38 | 39 | # Scripts Tab define functions # 40 | When multiple events (e.g. OnCreated, OnDeleted ...) are supposed to call the same function, it is easiest to define it in another file. 41 | 42 | First create the extra file using the "Event Handler" dropdown using "Custom Script". 43 | Then define the function as normal. 44 | To call the function use this code. 45 | ```python 46 | import toolutils 47 | 48 | mymodule = toolutils.createModuleFromSection("mymodule", kwargs['type'], "myCustomScript") #replace myCustomScript 49 | mymodule.myFunction(kwargs) #replace myFunction() 50 | ``` 51 | 52 | # On Copy Event # 53 | There sadly currently is no event to call code when a node is copied. To work around this user Stalkerx777 on odforce created following script to check if the node is beeing copied. 54 | 55 | ```python 56 | def is_copy_paste_event(kwargs): 57 | #code by Stalkerx777 on odforce 58 | if not kwargs['node'].name().startswith('original') and not kwargs['old_name'].startswith('original'): 59 | original_node = kwargs['node'].parent().node('original0_of_%s' % kwargs['old_name']) 60 | return True if original_node else False 61 | ``` 62 | 63 | # Unordered Inputs # 64 | Nodes like the merge node have so called "unordered inputs". This means that the order of the connections doesn't matter. 65 | 66 | When a HDA has 28 or more inputs the inputs are displayed as a long solid bar (like the merge sop) but unlike the merge sop those inputs are still ordered. This can cause some problems. 67 | 68 | For example the "Variant Merge" allows up to 9999 inputs. If the user has 5 inputs connected but decides to remove input number 3. The HDA will still loop over the 5 inputs. This might cause issues when using the current loop iteration as an attribute because the geos will now have values like 0,1,3,4. 69 | 70 | To fix this the Variant Merge sop has an "OnInputChanged" event. This event removes all current connections and rewires them in the same order but skipping empty connections. 71 | This code requires a "cleanstate" integer parameter because every connection that is modified by the script would also call the "OnInputChanged" event which would cause infinte loops and finally crashes Houdini. 72 | 73 | ```python 74 | def orderInputs(): 75 | """ 76 | problem with ordered inputs: 77 | if inputs are removed they leave empty connections 78 | this causes problems with the numvar attribute because the empty connections are still counted 79 | 80 | deletes all inputs and reconnnects them to remove empty connections 81 | """ 82 | node = kwargs["node"] 83 | 84 | # sets parameter on the hda to avoid triggering the OnInputChanged event every time this function changes the inputs 85 | stateparm = node.parm("cleanstate") 86 | stateparm.set(1) 87 | 88 | # save current connections 89 | connections = node.inputConnections() 90 | 91 | # remove all connections 92 | for idx in range(len(node.inputs())): 93 | node.setInput(idx,None,0) 94 | 95 | # rewire input connections to remove empty connections 96 | for idx, input_con in enumerate(connections): 97 | 98 | input_node = input_con.inputNode() 99 | output_idx = input_con.outputIndex() 100 | 101 | node.setInput(idx, input_node, output_idx) 102 | 103 | stateparm.set(0) 104 | 105 | 106 | if not kwargs["node"].parm("cleanstate").eval(): 107 | orderInputs() 108 | ``` 109 | 110 | -------------------------------------------------------------------------------- /desktop/LEO_Custom.desk: -------------------------------------------------------------------------------- 1 | fullscreen -1 2 | playbarshown 1 3 | playbar -1 4 | shelf -1 5 | menubar -1 6 | statusbar -1 7 | radial menu set main 8 | root { 9 | split 0.518765 H { 10 | split 0.118462 H L { 11 | tabs 0 1 { 12 | pane panetab14 -a 0 -l 10 -H /obj/ -T OBJ -m treecontrol 13 | } 14 | split 0.217355 V { 15 | tabs 0 1 { 16 | pane panetab1 -a 0 -l 10 -H /obj/ -T OBJ -m sceneview 17 | pane panetab2 -a 0 -l 10 -H /obj/ -T OBJ -m chaneditor 18 | pane panetab3 -a 0 -l 10 -H /obj/ -T OBJ -m iprviewer 19 | pane panetab4 -a 0 -l 10 -H /img/comp1/ -T COP2 -m imageview 20 | pane panetab13 -a 0 -l 10 -H /ch/ -T CHOPNET -m channelview 21 | pane panetab11 -a 0 -l 10 -H /obj/ -T OBJ -m details 22 | } 23 | tabs 1 1 { 24 | pane panetab15 -a 0 -l 10 -H /obj/ -T OBJ -m python 25 | pane panetab16 -a 0 -l 10 -H /obj/ -T OBJ -m details 26 | } 27 | } 28 | } 29 | split 0.498804 V L { 30 | tabs 0 1 { 31 | pane panetab5 -a 0 -l 10 -H /obj/ -T OBJ -m parmeditor 32 | pane panetab6 -a 0 -l 10 -H /obj/ -T OBJ -m takelist 33 | pane panetab12 -a 0 -l 0 -H /obj/ -T OBJ -m perfmon 34 | } 35 | tabs 0 1 { 36 | pane panetab7 -a 0 -l 10 -H /obj/ -T OBJ -m neteditor 37 | pane panetab8 -a 0 -l 0 -H /obj/ -T OBJ -m treecontrol 38 | pane panetab9 -a 0 -l 10 -H /obj/ -T OBJ -m materialpalette 39 | pane panetab10 -a 0 -l 0 -H /obj/ -T OBJ -m assetbrowser 40 | } 41 | } 42 | } 43 | } 44 | shelfdock -o 1 -l icon_and_text -G "0.46 0.50" add shelf_set_1 shelf_set_2 45 | treecontrol -a 0 -h 0 -i 1 -f 0 -O 0 -S 0 -D 0 -H 0 -V 0 -C 0 -I 0 -R 0 panetab14 46 | viewerstow -x open -b open -l open -m hide -c hide -d open ${DESKNAME}.panetab1.world 47 | vieweroption -a 2 ${DESKNAME}.panetab1.world 48 | viewlayout -s 2 ${DESKNAME}.panetab1.world 49 | viewtype -t ortho_right ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",4)` 50 | viewtype -t ortho_front ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",3)` 51 | viewtype -t ortho_top ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",1)` 52 | viewtype -t perspective ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",2)` 53 | iprview -t 0.1 -l 0 -e 1 -u 1 panetab3 54 | chopview -a 0 -c "" -k 1 -m 1 -b 1 -e 1 -f 0 -g 0 -H 1 -i 0 -j 1 -l 0 -n 1 -V 0 -y 0 -B 0 -s 0 -S 0.034375 -u 0 -v 0 -h -10 310 -r -1.5 1.5 panetab13 55 | parmeditor -T 0.25 -w 0 panetab5 56 | takelist -w 1 -G 0.5 panetab6 57 | performance -c on -d on -f on -g off -j on -k on -m off -n on -o on -t off -v on -p on -y on -u on -e off -r absolute -R seconds -w tree panetab12 58 | networkeditor -p '{\n "obj:listmode":"0",\n "sop:listmode":"0",\n "showchilddep":"1",\n "showdep":"0",\n "showtaskgraphperf":"0",\n "taskgraphperfstatname":"Cook Time",\n "perfstatname":"Time",\n "showperfstats":"1",\n "grouplistsplit":"0.75",\n "showtree":"0",\n "showtypesidebar":"0",\n "taskgraphsortcriteria":"Automatic",\n "showparmdialogmax":"1",\n "treesplit":"0.25",\n "palettesize":"150 150",\n "typesidebarsplit":"0.25",\n "taskgraphcollapsemode":"Off",\n "gridmode":"0",\n "showtimedep":"0",\n "overviewbounds":"0.000000 0.000000 367.200000 330.600000",\n "overviewmode":"2",\n "showgrouplist":"0",\n "palettemode":"0",\n "showtasksmenu":"1",\n "backgroundimageediting":"0",\n "backgroundimagebrightness":"1.0",\n "gridystep":"1.0",\n "palettecolors":"",\n "showmenu":"1",\n "gridxstep":"2.0",\n "showparmdialog":"1"\n}\n' panetab7 59 | netcolumns -c display,xray,select,origin,capture,bone -n OBJ panetab7 60 | netcolumns -c display,render,template,selectabletemplate,highlight,unload,bypass,lock -n SOP panetab7 61 | netcolumns -c delscript,comment -n CHOPNET panetab7 62 | netcolumns -c display,export,audio,bypass,lock -n CHOP panetab7 63 | netcolumns -c startrender,bypass,lock -n ROP panetab7 64 | netcolumns -c delscript,comment -n SHOP panetab7 65 | netcolumns -c display,render,template,bypass -n COP2 panetab7 66 | netcolumns -c delscript,comment -n IMG panetab7 67 | netcolumns -c delscript,comment,input -n VOP panetab7 68 | netcolumns -c delscript,comment -n VOPNET panetab7 69 | netcolumns -c delscript,comment -n DOP panetab7 70 | netcolumns -c delscript,comment -n TOP panetab7 71 | netcolumns -c delscript,comment -n TOPNET panetab7 72 | netcolumns -c display,bypass,delscript,comment,input -n LOP panetab7 73 | netcolumns -c delscript,comment -n MGR panetab7 74 | netcolumns -c delscript,comment -n DIR panetab7 75 | treecontrol -a 0 -h 0 -i 1 -f 0 -O 0 -S 0 -D 0 -H 0 -V 0 -C 0 -I 0 -R 0 panetab8 76 | -------------------------------------------------------------------------------- /desktop/LEO_Custom_split.desk: -------------------------------------------------------------------------------- 1 | fullscreen -1 2 | playbarshown 1 3 | playbar -1 4 | shelf -1 5 | menubar -1 6 | statusbar -1 7 | radial menu set main 8 | root { 9 | split 0.457292 H { 10 | split 0.118462 H L { 11 | tabs 0 1 { 12 | pane panetab14 -a 0 -l 10 -H /obj/ -T OBJ -m treecontrol 13 | } 14 | split 0.197978 V { 15 | tabs 0 1 { 16 | pane panetab1 -a 0 -l 10 -H /obj/ -T OBJ -m sceneview 17 | pane panetab2 -a 0 -l 10 -H /obj/ -T OBJ -m chaneditor 18 | pane panetab3 -a 0 -l 10 -H /obj/ -T OBJ -m iprviewer 19 | pane panetab4 -a 0 -l 10 -H /img/comp1/ -T COP2 -m imageview 20 | pane panetab13 -a 0 -l 10 -H /ch/ -T CHOPNET -m channelview 21 | pane panetab11 -a 0 -l 10 -H /obj/ -T OBJ -m details 22 | } 23 | tabs 1 1 { 24 | pane panetab15 -a 0 -l 10 -H /obj/ -T OBJ -m python 25 | pane panetab16 -a 0 -l 10 -H /obj/ -T OBJ -m details 26 | } 27 | } 28 | } 29 | split 0.498804 V L { 30 | tabs 0 1 { 31 | pane panetab5 -a 0 -l 10 -H /obj/ -T OBJ -m parmeditor 32 | pane panetab6 -a 0 -l 10 -H /obj/ -T OBJ -m takelist 33 | pane panetab12 -a 0 -l 0 -H /obj/ -T OBJ -m perfmon 34 | } 35 | split 0.5 H { 36 | tabs 0 1 { 37 | pane panetab7 -a 0 -l 1 -H /obj/ -T OBJ -m neteditor 38 | } 39 | tabs 0 1 { 40 | pane panetab17 -a 0 -l 2 -H /obj/ -T OBJ -m neteditor 41 | } 42 | } 43 | } 44 | } 45 | } 46 | shelfdock -o 1 -l icon_and_text -G "0.46 0.50" add shelf_set_1 shelf_set_2 47 | treecontrol -a 0 -h 0 -i 1 -f 0 -O 0 -S 0 -D 0 -H 0 -V 0 -C 0 -I 0 -R 0 panetab14 48 | viewerstow -x open -b open -l open -m hide -c hide -d open ${DESKNAME}.panetab1.world 49 | vieweroption -a 2 ${DESKNAME}.panetab1.world 50 | viewlayout -s 2 ${DESKNAME}.panetab1.world 51 | viewtype -t ortho_right ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",4)` 52 | viewtype -t ortho_front ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",3)` 53 | viewtype -t ortho_top ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",1)` 54 | viewtype -t perspective ${DESKNAME}.panetab1.world.`vpname("${DESKNAME}.panetab1.world",2)` 55 | iprview -t 0.1 -l 0 -e 1 -u 1 panetab3 56 | chopview -a 0 -c "" -k 1 -m 1 -b 1 -e 1 -f 0 -g 0 -H 1 -i 0 -j 1 -l 0 -n 1 -V 0 -y 0 -B 0 -s 0 -S 0.034375 -u 0 -v 0 -h -10 310 -r -1.5 1.5 panetab13 57 | parmeditor -T 0.25 -w 0 panetab5 58 | takelist -w 1 -G 0.5 panetab6 59 | performance -c on -d on -f on -g off -j on -k on -m off -n on -o on -t off -v on -p on -y on -u on -e off -r absolute -R seconds -w tree panetab12 60 | networkeditor -p '{\n "obj:listmode":"0",\n "sop:listmode":"0",\n "showchilddep":"1",\n "showdep":"0",\n "showtaskgraphperf":"0",\n "taskgraphperfstatname":"Cook Time",\n "perfstatname":"Time",\n "showperfstats":"1",\n "grouplistsplit":"0.75",\n "showtree":"0",\n "showtypesidebar":"0",\n "taskgraphsortcriteria":"Automatic",\n "showparmdialogmax":"1",\n "treesplit":"0.25",\n "palettesize":"150 150",\n "typesidebarsplit":"0.25",\n "taskgraphcollapsemode":"Off",\n "gridmode":"0",\n "showtimedep":"0",\n "overviewbounds":"0.000000 0.000000 129.985753 207.300000",\n "overviewmode":"2",\n "showgrouplist":"0",\n "palettemode":"0",\n "showtasksmenu":"1",\n "backgroundimageediting":"0",\n "backgroundimagebrightness":"1.0",\n "gridystep":"1.0",\n "palettecolors":"",\n "showmenu":"1",\n "gridxstep":"2.0",\n "showparmdialog":"1"\n}\n' panetab7 61 | netcolumns -c display,xray,select,origin,capture,bone -n OBJ panetab7 62 | netcolumns -c display,render,template,selectabletemplate,highlight,unload,bypass,lock -n SOP panetab7 63 | netcolumns -c delscript,comment -n CHOPNET panetab7 64 | netcolumns -c display,export,audio,bypass,lock -n CHOP panetab7 65 | netcolumns -c startrender,bypass,lock -n ROP panetab7 66 | netcolumns -c delscript,comment -n SHOP panetab7 67 | netcolumns -c display,render,template,bypass -n COP2 panetab7 68 | netcolumns -c delscript,comment -n IMG panetab7 69 | netcolumns -c delscript,comment,input -n VOP panetab7 70 | netcolumns -c delscript,comment -n VOPNET panetab7 71 | netcolumns -c delscript,comment -n DOP panetab7 72 | netcolumns -c delscript,comment -n TOP panetab7 73 | netcolumns -c delscript,comment -n TOPNET panetab7 74 | netcolumns -c display,bypass,delscript,comment,input -n LOP panetab7 75 | netcolumns -c delscript,comment -n MGR panetab7 76 | netcolumns -c delscript,comment -n DIR panetab7 77 | networkeditor -p '{\n "showchilddep":"1",\n "showdep":"0",\n "showtaskgraphperf":"0",\n "taskgraphperfstatname":"Cook Time",\n "perfstatname":"Time",\n "showperfstats":"1",\n "grouplistsplit":"0.75",\n "showtree":"0",\n "showtypesidebar":"0",\n "taskgraphsortcriteria":"Automatic",\n "showparmdialogmax":"1",\n "treesplit":"0.25",\n "palettesize":"150 150",\n "typesidebarsplit":"0.25",\n "taskgraphcollapsemode":"Off",\n "gridmode":"0",\n "overviewbounds":"0.000000 0.000000 126.993376 204.900000",\n "overviewmode":"2",\n "showgrouplist":"0",\n "palettemode":"0",\n "showtasksmenu":"1",\n "backgroundimageediting":"0",\n "backgroundimagebrightness":"1.0",\n "gridystep":"1.0",\n "palettecolors":"",\n "showmenu":"1",\n "gridxstep":"2.0",\n "showparmdialog":"1"\n}\n' panetab17 78 | netcolumns -c display,xray,select,origin,capture,bone -n OBJ panetab17 79 | netcolumns -c display,render,template,selectabletemplate,highlight,unload,bypass,lock -n SOP panetab17 80 | netcolumns -c delscript,comment -n CHOPNET panetab17 81 | netcolumns -c display,export,audio,bypass,lock -n CHOP panetab17 82 | netcolumns -c startrender,bypass,lock -n ROP panetab17 83 | netcolumns -c delscript,comment -n SHOP panetab17 84 | netcolumns -c display,render,template,bypass -n COP2 panetab17 85 | netcolumns -c delscript,comment -n IMG panetab17 86 | netcolumns -c delscript,comment,input -n VOP panetab17 87 | netcolumns -c delscript,comment -n VOPNET panetab17 88 | netcolumns -c delscript,comment -n DOP panetab17 89 | netcolumns -c delscript,comment -n TOP panetab17 90 | netcolumns -c delscript,comment -n TOPNET panetab17 91 | netcolumns -c display,bypass,delscript,comment,input -n LOP panetab17 92 | netcolumns -c delscript,comment -n MGR panetab17 93 | netcolumns -c delscript,comment -n DIR panetab17 94 | -------------------------------------------------------------------------------- /scripts/python/leo_random_ramp.py: -------------------------------------------------------------------------------- 1 | import hou 2 | import random 3 | import numpy 4 | from PySide2 import QtCore, QtUiTools, QtWidgets 5 | 6 | 7 | class RandomRamp(QtWidgets.QWidget): 8 | def __init__(self): 9 | super(RandomRamp, self).__init__() 10 | ui_file = hou.getenv("LEO") + "/scripts/python/leo_random_ramp.ui" 11 | self.ui = QtUiTools.QUiLoader().load(ui_file, parentWidget=self) 12 | self.setParent(hou.ui.mainQtWindow(), QtCore.Qt.Window) 13 | 14 | self.ui.button_apply.clicked.connect(self.apply_button) 15 | self.ui.button_update_node.clicked.connect(self.update_button) 16 | 17 | # self.ui.setWindowTitle("LEO Random Ramp") # doesnt work 18 | # self.ui.setFixedSize(300,600) # Doesnt disable resizing 19 | 20 | # init values 21 | self.node = None 22 | self.node_name = None 23 | self.ramp_parms = [] 24 | self.ramp_parm = None 25 | self.basis_types = [ 26 | "Linear", 27 | "Constant", 28 | "CatmullRom", 29 | "MonotoneCubic", 30 | "Bezier", 31 | "BSpline", 32 | "Hermite", 33 | ] 34 | self.ramp_basis = None 35 | self.resolution = None 36 | 37 | self.min_set_value = None 38 | self.max_set_value = None 39 | 40 | self.min_adj_value = None 41 | self.max_adj_value = None 42 | 43 | self.ramp_values = None 44 | self.ramp_keys = None 45 | 46 | # set basis dropdown 47 | self.ui.dropdown_basis.clear() 48 | self.ui.dropdown_basis.addItems(self.basis_types) 49 | 50 | # def calc_mean(self,data): 51 | # """ 52 | # workaround since the statistics module doesnt exist for Python 2.x 53 | # """ 54 | # return float(sum(data)) / float(len(data)) 55 | 56 | def update_values(self): 57 | """ 58 | updates variables to match the current ui state 59 | """ 60 | self.resolution = self.ui.value_samples.value() 61 | 62 | self.min_set_value = self.ui.value_set_min.value() 63 | self.max_set_value = self.ui.value_set_max.value() 64 | self.min_adj_value = self.ui.value_adjust_min.value() 65 | self.max_adj_value = self.ui.value_adjust_max.value() 66 | 67 | def update_ui(self): 68 | """ 69 | updates the ui to represent current values 70 | """ 71 | 72 | # updates Selected Node Label 73 | self.ui.label_node_name.setText("Selected Node: {}".format(self.node_name)) 74 | 75 | # updates parms dropdown 76 | self.ui.dropdown_parm.clear() 77 | self.ui.dropdown_parm.addItems(self.ramp_parms) 78 | 79 | def get_selected_node(self): 80 | """ 81 | returns the first selected node and name 82 | """ 83 | try: 84 | self.node = hou.selectedNodes()[0] 85 | self.node_name = self.node.name() 86 | except IndexError: 87 | self.node = None 88 | self.node_name = None 89 | 90 | def get_ramp_parms(self): 91 | """ 92 | for the selected node return a list of all ramp parameters. 93 | """ 94 | try: 95 | ramp_parms = [ 96 | parm.name() 97 | for parm in self.node.parms() 98 | if parm.parmTemplate().type() == hou.parmTemplateType.Ramp 99 | ] 100 | except AttributeError: 101 | ramp_parms = [] 102 | except hou.ObjectWasDeleted: 103 | ramp_parms = [] 104 | 105 | if len(ramp_parms) == 0: 106 | self.ramp_parms = ["No Ramp Parameter Found!"] 107 | else: 108 | self.ramp_parms = ramp_parms 109 | 110 | def get_ramp_basis(self): 111 | """ 112 | returns hou.rampBasis object which is responsible for the interpolation 113 | """ 114 | selected_basis = self.ui.dropdown_basis.currentText() 115 | self.ramp_basis = getattr(hou.rampBasis, selected_basis) 116 | 117 | def create_new_ramp_values(self): 118 | """ 119 | returns a new ramp with random values between in_min and in_max 120 | resolution is the number of points in the ramp 121 | """ 122 | ramp_values = tuple( 123 | random.uniform(self.min_set_value, self.max_set_value) 124 | for _ in range(self.resolution) 125 | ) 126 | self.ramp_values = ramp_values 127 | 128 | def create_adj_ramp_values(self): 129 | """ 130 | returns a new ramp based on the existing ramp but the values are offset 131 | optional the output values are clamped to 0 - 1 to avoid negative values 132 | """ 133 | old_ramp = self.ramp_parm.evalAsRamp() 134 | 135 | if old_ramp.isColor(): 136 | # Ramp parm is color 137 | ramp_values = [] 138 | for position in self.ramp_keys: 139 | random_value = random.uniform(self.min_adj_value, self.max_adj_value) 140 | r, g, b = old_ramp.lookup(position) 141 | 142 | if self.ui.radiobutton_add.isChecked(): 143 | r += random_value 144 | g += random_value 145 | b += random_value 146 | elif self.ui.radiobutton_mult.isChecked(): 147 | r *= random_value 148 | g *= random_value 149 | b *= random_value 150 | else: 151 | pass 152 | 153 | ramp_values.append((r, g, b)) 154 | 155 | else: 156 | # Ramp parm is float 157 | if self.ui.radiobutton_add.isChecked(): 158 | ramp_values = [ 159 | old_ramp.lookup(position) 160 | + random.uniform(self.min_adj_value, self.max_adj_value) 161 | for position in self.ramp_keys 162 | ] 163 | elif self.ui.radiobutton_mult.isChecked(): 164 | ramp_values = [ 165 | old_ramp.lookup(position) 166 | * random.uniform(self.min_adj_value, self.max_adj_value) 167 | for position in self.ramp_keys 168 | ] 169 | else: 170 | ramp_values = [old_ramp.lookup(position) for position in self.ramp_keys] 171 | 172 | if self.ui.checkbox_adjust_clamp.isChecked(): 173 | ramp_values = numpy.clip(ramp_values, 0, 1) 174 | 175 | self.ramp_values = tuple(ramp_values) 176 | 177 | def create_ramp_keys(self): 178 | """ 179 | returns a tuple from 0 to inclusive 1 evenly distributed 180 | requires numpy as range() doesnt support floats 181 | output tuple is len() == resolution, starts with 0.0 and ends with 1.0 182 | """ 183 | try: 184 | ramp_keys = list(numpy.linspace(0, 1, self.resolution)) 185 | except ZeroDivisionError: 186 | ramp_keys = [] 187 | 188 | ramp_keys = tuple(ramp_keys) 189 | self.ramp_keys = ramp_keys 190 | 191 | def get_ramp_parm(self): 192 | """ 193 | updates the hou.node.parm with the selected parm 194 | if the node or parm is not found this will return False 195 | """ 196 | ramp_parm_name = self.ui.dropdown_parm.currentText() 197 | try: 198 | ramp_parm = self.node.parm(ramp_parm_name) 199 | self.ramp_parm = ramp_parm 200 | if self.ramp_parm: 201 | return True 202 | else: 203 | return False 204 | except hou.ObjectWasDeleted: 205 | return False 206 | except AttributeError: 207 | return False 208 | 209 | def set_ramp(self): 210 | """ 211 | applies the new ramp to the selected parameter. 212 | """ 213 | # hou.Ramp((basis, basis),(0, 1),(2.5, 4.5)) 214 | ramp = hou.Ramp( 215 | (self.ramp_basis, self.ramp_basis), self.ramp_keys, self.ramp_values 216 | ) 217 | self.ramp_parm.set(ramp) 218 | 219 | def set_warning(self, message): 220 | self.ui.label_node_name.setText("Warning: {}".format(message)) 221 | 222 | def update_button(self): 223 | """ 224 | functionality for the "update selected node" button 225 | """ 226 | self.get_selected_node() 227 | 228 | if self.node: 229 | self.get_ramp_parms() 230 | self.update_ui() 231 | else: 232 | self.get_ramp_parms() 233 | self.update_ui() 234 | self.set_warning("No Valid Node Selected!") 235 | 236 | def apply_button(self): 237 | """ 238 | functionality for the "apply" button 239 | """ 240 | if self.get_ramp_parm(): 241 | 242 | self.get_ramp_basis() 243 | 244 | self.update_values() 245 | 246 | self.create_ramp_keys() 247 | 248 | if self.ui.radiobutton_override.isChecked(): 249 | self.create_new_ramp_values() 250 | self.set_ramp() 251 | elif self.ui.radiobutton_adjust.isChecked(): 252 | self.create_adj_ramp_values() 253 | self.set_ramp() 254 | else: 255 | self.set_warning("Abort: Invalid Radio Button selection") 256 | 257 | else: 258 | self.get_ramp_parms() 259 | self.update_ui() 260 | self.set_warning("Select A Valid Node And Parameter") 261 | 262 | def test(self): 263 | print(self.ui.value_set_min.value()) 264 | 265 | 266 | def run(): 267 | win = RandomRamp() 268 | win.show() 269 | -------------------------------------------------------------------------------- /scripts/python/leo_random_ramp.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | true 7 | 8 | 9 | 10 | 0 11 | 0 12 | 300 13 | 528 14 | 15 | 16 | 17 | 18 | 0 19 | 0 20 | 21 | 22 | 23 | 24 | 0 25 | 0 26 | 27 | 28 | 29 | 30 | 300 31 | 600 32 | 33 | 34 | 35 | LEO Random Ramp 36 | 37 | 38 | 1.000000000000000 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 9 47 | 17 48 | 281 49 | 501 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 16777215 58 | 20 59 | 60 | 61 | 62 | Selected Node: None 63 | 64 | 65 | 66 | 67 | 68 | 69 | Update Selected Node 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Linear 81 | 82 | 83 | 84 | 85 | Constant 86 | 87 | 88 | 89 | 90 | CatmullRom 91 | 92 | 93 | 94 | 95 | MonotoneCubic 96 | 97 | 98 | 99 | 100 | Bezier 101 | 102 | 103 | 104 | 105 | BSpline 106 | 107 | 108 | 109 | 110 | Hermite 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 16777215 120 | 20 121 | 122 | 123 | 124 | Number Of Points: 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 50 133 | 16777215 134 | 135 | 136 | 137 | 1 138 | 139 | 140 | 999 141 | 142 | 143 | 10 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 16777215 152 | 60 153 | 154 | 155 | 156 | 157 | 0 158 | 159 | 160 | 0 161 | 162 | 163 | 164 | 165 | Override Current Values 166 | 167 | 168 | true 169 | 170 | 171 | 172 | 173 | 174 | 175 | Adjust Current Values 176 | 177 | 178 | false 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | true 189 | 190 | 191 | 192 | 16777215 193 | 50 194 | 195 | 196 | 197 | Override Current values 198 | 199 | 200 | false 201 | 202 | 203 | 204 | 205 | 80 206 | 20 207 | 62 208 | 22 209 | 210 | 211 | 212 | ArrowCursor 213 | 214 | 215 | QAbstractSpinBox::UpDownArrows 216 | 217 | 218 | -99.989999999999995 219 | 220 | 221 | 0.100000000000000 222 | 223 | 224 | 1.000000000000000 225 | 226 | 227 | 228 | 229 | 230 | 10 231 | 20 232 | 62 233 | 22 234 | 235 | 236 | 237 | ArrowCursor 238 | 239 | 240 | QAbstractSpinBox::UpDownArrows 241 | 242 | 243 | -99.989999999999995 244 | 245 | 246 | 0.100000000000000 247 | 248 | 249 | 0.000000000000000 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | false 258 | 259 | 260 | 261 | 16777215 262 | 120 263 | 264 | 265 | 266 | Adjust Current values 267 | 268 | 269 | 270 | 271 | 10 272 | 20 273 | 134 274 | 93 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | true 284 | 285 | 286 | QAbstractSpinBox::UpDownArrows 287 | 288 | 289 | -99.989999999999995 290 | 291 | 292 | -0.100000000000000 293 | 294 | 295 | 296 | 297 | 298 | 299 | ArrowCursor 300 | 301 | 302 | QAbstractSpinBox::UpDownArrows 303 | 304 | 305 | -99.989999999999995 306 | 307 | 308 | 0.100000000000000 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | Clamp Value To 0 - 1 318 | 319 | 320 | true 321 | 322 | 323 | 324 | 325 | 326 | 327 | Add 328 | 329 | 330 | true 331 | 332 | 333 | 334 | 335 | 336 | 337 | Multiply 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | Apply 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | dropdown_parm 357 | 358 | 359 | 360 | 361 | radiobutton_override 362 | toggled(bool) 363 | override_box 364 | setEnabled(bool) 365 | 366 | 367 | 35 368 | 236 369 | 370 | 371 | 48 372 | 299 373 | 374 | 375 | 376 | 377 | radiobutton_adjust 378 | toggled(bool) 379 | adjust_box 380 | setEnabled(bool) 381 | 382 | 383 | 84 384 | 263 385 | 386 | 387 | 95 388 | 360 389 | 390 | 391 | 392 | 393 | 394 | --------------------------------------------------------------------------------