Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions integration/houdini/Conduct.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"hpath" : "$HFS/packages/Conduct"
}
20 changes: 20 additions & 0 deletions integration/houdini/MainMenuCommon.xml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is it possible to set this up as two menu items, where each one hides itself by some expression when it shouldn't be available, instead of as one menu item which switches between two states?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or not necessarily hidden, but im pretty sure there is a way for menu items to be disabled/grayed out based on an expression, which would be preferable i think - it might be more intuitive for me to try and implement it this way in blender too...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was definitely the easiest solution instead of having two entries that hide.
But greying out should be easy, assuming there is a native way to grey them out, which Im really confident about.

@Devostated Devostated Dec 23, 2024

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: I have no idea how to do that.
The only menu item I found that has such feature was the redo/undo function.
It uses following for that:

      <menuStripDynamic id="undo_strip">
        <value>undo.menu</value>
      </menuStripDynamic>

No idea where undo.menu is coming from.

Another Menu had , but I didn't manage to get it working, it always told me that it's an unknown command.

While writing this I found following:
"It is not currently possible to dynamically enable and disable user-defined menus/items."
https://www.sidefx.com/docs/houdini/basics/config_menus.html#menu-items

I'm not sure if that is just the top level item in the menu bar or also it's scriptItems

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could still split that into two <scriptItems> and use an <expression> to en-/disable them accordingly, if you would prefer that.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah thats a shame... I think splitting them in to two menus will be less prone to bugs. I can see a scenario where the two expressions for controlling the text and the logic for the single menu become out of sync and lead to unexpected behaviour

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, it's not much stored. Department, Asset, Shot and if it's imported. Could also just do a check if department exists. Usually try to avoid working with strings as much as possible, that's why I didn't like the idea of hardcoding the conduct node path.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>

<mainMenu>
<menuBar>

<subMenu id="conduct_menu">
<label>Conduct</label>
<scriptItem id="conduct_select">
<label>Select Project</label>
<insertAtIndex>0</insertAtIndex>
<scriptCode><![CDATA[
import ConductPlugin.select_project as select_project
select_project.create_setup()

]]>
</scriptCode>
</scriptItem>
</subMenu>
</menuBar>
</mainMenu>
3 changes: 3 additions & 0 deletions integration/houdini/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Installation
Place the `Conduct.json` in `Houdini <version_name>/packages`
Either adjust it's path or place the `MainMenuCommon.xml` file and `scripts` folder into `Houdini <version_name>/packages/Conduct`
Empty file.
56 changes: 56 additions & 0 deletions integration/houdini/scripts/python/ConductPlugin/select_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import hou
from . import utils
import os


# Thinking about splitting this into multiple functions for better readability
def create_setup():
path = utils.select_project()
path = hou.expandString(path)

setup_network: hou.Node = hou.node("/obj").createNode("subnet")
setup_network.setName("setup")
setup_network.setPosition((0, 0))

import_network: hou.Node = hou.node("/obj").createNode("subnet")
import_network.setName("import")
setup_network.setPosition((0, -1))

# Might using subnet instead of null, cause a null adds an extra object to the scene
data_node: hou.Node = setup_network.createNode("null")
data_node.setName("conduct")

data_node.addSpareParmTuple(
hou.StringParmTemplate("project", "Project", 1))
data_node.addSpareParmTuple(
hou.StringParmTemplate("department", "Department", 1))
data_node.addSpareParmTuple(hou.StringParmTemplate("asset", "Asset", 1))
data_node.addSpareParmTuple(hou.StringParmTemplate("shot", "Shot", 1))

projectParm: hou.Parm = data_node.parm("project")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need to store this, and if we did it would only be a valid path for the person who initially did this. If i opened the project on a machine where the project is stored elsewhere, it wouldn't be accurate anymore

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree on the project path.
The pSelected is a check to hide the Select Project button in the Conduct node. I could try taking a different approach, but not sure how worth that it would be.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could just check if the the current file is saved, if you feel like it also could check that its saved to a valid project location - doing so would have some extra io calls so im not sure if there would be a performance impact.

Generally I would prefer to avoid hidden parms like this where possible, it can be prone to adding weird behaviour

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion is setUserData() probably the best approach, as you mentioned in the original issue.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe, for me I prefer to store as little information as possible, and to derive this kind of state from elsewhere - the way I see it the more state you are storing, the more chances there are to end up in weird invalid states

projectParm.set(path)

conduct = utils.get_conduct_object()

result = conduct.setup()
if result['result'] != 'ok':
return {'FINISHED'}

dialog_data = result['data']

deptParm: hou.Parm = data_node.parm("department")
deptParm.set(dialog_data['department'])

assetParm: hou.Parm = data_node.parm("asset")
assetParm.set(dialog_data['asset'])

shot = dialog_data['shot']
if shot is not None:
shotParm: hou.Parm = data_node.parm("shot")
shotParm.set(shot)

# We have to discuss a properway of doing this. Houdini does not support the \\?\ prefix. Only tested on Windows
file_name = os.path.join(dialog_data['path'][4:] if dialog_data['path'].startswith(
Comment thread
Devostated marked this conversation as resolved.
Outdated
r"\\?") else dialog_data['path'], dialog_data['file_name'] + ".hip")
Comment thread
Devostated marked this conversation as resolved.
Outdated

hou.hipFile.save(file_name)
27 changes: 27 additions & 0 deletions integration/houdini/scripts/python/ConductPlugin/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import hou
from . import conduct


def get_conduct_data_node() -> hou.Node:
return hou.node("/obj/setup/conduct")


def get_conduct_object() -> conduct.Conduct:
data = get_conduct_data_node()
projectParm: hou.Parm = data.parm("project")
dir = os.path.dirname(projectParm.evalAsString())
exe = os.path.join(dir, "conduct.exe")
Comment thread
Airyzz marked this conversation as resolved.
Outdated

return conduct.Conduct(exe, "houdini")


def select_project():
file_path = hou.ui.selectFile(
start_directory=hou.hipFile.path(),
title="Select a project",
pattern="*.yml,*.yaml",
chooser_mode=hou.fileChooserMode.Read
)

return file_path