Giter Club home page Giter Club logo

unimenu's Introduction

UniMenu (Universal Menu)

PyPI Downloads Wiki

A pure python module to add python commands to the menu.

Supports Unreal Engine, Blender, Marmoset
and any app that uses QT: Maya, Krita, Substance Painter, 3ds Max, FreeCAD, CryEngine ...

For more info read the wiki

If you use Blender, you can try the unimenu_addon

how to use

load from config (YAML & JSON)

items:
  - label: my menu
    items:
      - label: my item
        command: print("Hello World")
import unimenu
config_path = "path/to/config.yaml"
unimenu.setup(config_path)

load from a dict

import unimenu
data = {"items": [{"label": "test","command": 'print("hello world")'}]}
unimenu.setup(data)

with code

import unimenu
menu = unimenu.Node(label="my menu")  # create a menu
item = unimenu.Node(label="hi", command='print("hi")')  # create a menu item
menu.items.append(item)  # add the item to the menu
menu.setup()  # setup the menu in the app, parented by default to the main menu bar

from a folder of scripts (or a Python module)

To auto construct a menu from a folder, with a menu entry for every tool in a folder:

  1. ensure the folder is importable (in the sys.path)
  2. create a menthod in all submodules with the same name, e.g. def show()
import unimenu
unimenu.module_setup('name_of_folder', function_name='show', menu_name="My tools")

When to use

some software e.g. Unity & Maya already have good ways to make custom menus. If you only use 1 software and find it easy to make a menu, you don't need unimenu.

The power of this module comes from standardising menu creation across multiple software. Great for studio-pipelines with several programs. Unimenu makes menu creation less complex, e.g. in Blender.

Notes

  • support loading multiple configs. Great for a single studio config and several project configs. Or a team config.
  • support creating another config to a previously created menu, or submenu!

Supports

unimenu was tested in the following versions, and might work in other versions.

  • Unreal 5.0.2
  • Blender 3.2, 2.93, 2.8 (minimum)
  • Maya 2023, 2022 (minimum)
  • Substance Painter 8.2.0
  • Max 2024
  • Marmoset 3.08
  • Nuke 13 (minimum)
  • Hiero 13 (minimum)
  • Katana 5 (minimum)
  • Mari 6.0 (minimum)

python 3.7+ due to f-strings and pathlib

Development

main platform is windows, would be interested to hear from mac & linux users.

feel free to create a PR to help out.

to add support for your favorite software, add a python module named after the software with a setup_menu function where possible stick to the windows menu design guidelines

  • add editable install instructions

samples

You can install the unimenu samples with

pip install git+https://github.com/hannesdelbeke/unimenu@main#subdirectory=dev

then you can run them with e.g.

import unimenu_samples.any_dcc_test

unimenu's People

Contributors

hannesdelbeke avatar hasielhassan avatar jlhayde avatar zuokangbo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

unimenu's Issues

Maya - on setup - Object's name '' is not unique

import unimenu

def hello_world():
    print("hello world")

config = {}
node = unimenu.load(config)
node.name = 'hello_world'
node.command = hello_world
app_node = node.setup()
# root : UNIMENU: detected maya # 
# Error: RuntimeError: file C:\Program Files\Autodesk\Maya2022\Python37\lib\site-packages\pymel\internal\pmcmds.py line 217: 
  Object's name '' is not unique. # 

ideas for other software to support

todo

Other

test multiple OS

  • ? linux
  • ? mac darwin
    ✅windows

test python versions
? 3+

non python native

  • unity c# yaml reader
  • photoshop, javascript?

Tried implementing

❌ mixer - no support for extending
✅substance painter
✅ krita
✅ marmoset
✅ unreal
✅ blender
✅ autodesk 3ds max
✅ autodesk maya

add automated tests

the more features we add / refactor the more software we need to test.
add automated tests/workflows to speed this up a lot!
catch issues etc.

just a simple load menu from config for evey dcc would help a lot

photoshop RnD

Should UniMenu be added to Photoshop?
Get some plugins to use as a testcase, it might not make sense to use UniMenu.

research

official plugin docs: menu entries are mentioned here
https://developer.adobe.com/photoshop/uxp/2022/

In Photoshop it's easily possible to customize the menu with Edit > Menus
https://community.adobe.com/t5/illustrator-discussions/can-i-customize-the-illustrator-menu-like-the-photoshop-menu/td-p/9190487

2010 claims you can't edit menu
https://community.adobe.com/t5/photoshop-ecosystem-discussions/add-new-menu-item-like-file-view-to-photoshop/m-p/2427059

Append Unreal ContentBrowser Folder Context Menu?

FolderContextAppend

parent_path: ContentBrowser.FolderContextMenu


label: FolderContextMenu # also tried ContentBrowser.FolderContextMenu
items:
- label: TA Tool
  separator: True
  
- label: SyncToAssetByPath
  command: from utility.sync_to_asset_by_path import SyncToAssetByPath;SyncToAssetByPath()
  
- label: CheckAssets
  command: from utility.asset_check import CheckAssets;CheckAssets()

Better to have no submenu here.

cleaner github release

currently only releases source code
would be nice if we can also release the module, maybe even packaged up.

support extending menus

uniemnu already supports parent menus. or parent to a toolbar.

but what if there's an existing menu. e.g. File/Settings/....
and we want to append to this?
believe not all apps support this currently

and the option to, if it doesn't exist, create it. (maybe a separate issue/task)

global local vars issue

when we use exec to run python code from a text file, the locals and globals inside the exec are lost.
so w = QWidget() will instantly be garbage collected.

How can we keep the reference?
tried but no luck so far

exec(self._command, globals(), globals())

it seems to pass the var correctly but widget still garbage collected.
testing with import buttonizer.main; global w; w = buttonizer.main.show()

see https://www.programiz.com/python-programming/methods/built-in/exec

  • the exec globals and locals are supposed to be used by exec
  • when printing afterwards, they appear modified
  • https://docs.python.org/3/library/functions.html#locals says to not edit the locals
  • when saving the locals to the operator, the widget still appears to be garbage collected

maya sample errors

import unimenu
menu = unimenu.Node(label="my menu")  # create a menu
item = unimenu.Node(label="hi", command='print("hi")')  # create a menu item
menu.items.append(item)  # add the item to the menu
menu.setup()  # setup the menu in the app, parented by default to the main menu bar

produces this in Maya 2022.

Errror: 'NoneType' object has no attribute 'findChild'
Traceback (most recent call last):
File "", line 5, in
File "c:\users\johannes\packages\unimenu\0.4.1\88a70aca30cb79a278872594adf043dc6c40af99\python\unimenu\apps_abstract.py", line 205, in setup
parent_app_node = parent_app_node or self._default_root_parent File "c:\users\johannes\packages\unimenu\0.4.1\88a70aca30cb79a278872594adf043dc6c40af99\python\unimenu\apps\qt.py", line 48, in _default_root_parent
menu_bar = main_window.findChild(QtWidgets.QMenuBar)
AttributeError: 'NoneType' object has no attribute 'findChild' #

Originally posted by @nebukadhezer in #46 (comment)

add menu manager functionality, to avoid clutter caused by 3rd party menu entries

sample case:

a large AAA project uses multiple 3rd party unity plugins/tools.
each creates and handles their own menu entry.

the inhouse dev team is large, and has multiple departments.
each creates their own menu entries for their own tools

when pulling the project, you have a messy menu with 100's of menu entries scatterred in various groups/submenus

suggested solution

it would make sense to have a regroup feature to bring order to the chaos.
and hide certain tools not used by certain user groups.
e.g. hide network profiling tools if a 3d artist launches the software.

blender: handle operators with same name

ex. if we have
menu/test --> print hello 1
menu/submenu/test --> print hello 2

ensure they both print their own thing and not the same message
despite them having the same name
unsure if we add submenu to the name correctly atm

unclear warning if yaml not installed

...  unimenu.apps.qt.MenuNodeQt() argument after ** must be a mapping, not NoneType
// Warning: file: C:/Program Files/Autodesk/Maya2024/scripts/others/pluginWin.mel line 316: Failed to call script initialize function

getting this in Maya when yaml is not installed

try command not hooked up

currently try command is commandstring only, no callable commands.
and not hooked up in most cases

prettier marmoset

setup

currently you need to create a plugin in the plugin folder.
refresh, or restart marmoset
then go to the menu and run your plugin.
with commandline args this could be run on startup
image

improvement

when running the plugin, you see a window with the menu
image

the window can be more "menu-like" with smarter layouts
image
might even be better to replace the dropdown layout with a normal button. and spawn buttons underneath when clicked

sample plugin

setup the env
run config setup
(reload is usefull for dev purposes)

import sys
sys.path.append(r'C:\Users\hanne\OneDrive\Documents\repos\openmenu')
sys.path.append(r'path to my yaml module installation')  # yaml

cfg = r"C:\Users\hanne\OneDrive\Documents\repos\openmenu\samples\config.json"
import openmenu
import openmenu.core as c

import openmenu.marmoset as b
from importlib import reload
reload(b)
reload(c)
reload(openmenu)

openmenu.config_setup(cfg)

License?

Discussed in #49

Originally posted by AlexSegal July 17, 2023
Hello @hannesdelbeke!

I tried unimenu and I really love the neat way you came up with to create menus in different DCCs! Thank you so much! One question though: you did not specify the license (unless I missed it). As far as I understand that prevents me from using the code in the studio environment, since it's not open source by default. It would be great if you could add the license to the project (or point me to one if it exists).

Thanks again!

blender icon bug

TypeError: UILayout.operator(): error with keyword argument "icon" - enum "polySphere.png" not found in

if icon is not found it crashes menu creation.
Icons failing should not block this!

unicodeescape error trying to read config in maya from path

# Error: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

error trying to read config in maya from path
no idea how to repro. maybe caused by using importlib.resources to load the file?

add tooltip support

most dccs dont yet support tooltips

tooltip is implemented in max but doesnt work yet

query feature

add ability to query the native app's menu as a unimenu menuNode tree.
would open up more modifications etc but pretty advanced, not a real need for now.

auto release pypi

☑️ build action is setup
☑️ next is setup.py or pyproject.toml
☑️ make new API token on pypi for project only and replace in repo secrets

support workspaces

blender maya max have workspaces, how does unimenu interact with these

support qt widgets (parent)

we already support qt widgets with abstract qt module, e.g. used in krita.
but this doesn't work with autodetect dcc.

would be great if we can pass a qt menubar, and setup our menu in there.
without having to know how unimenu code works. and avoid using the abstract qt module.

add icon support

list icons in krita

from PyQt5.QtCore import QDirIterator

it = QDirIterator(":", QDirIterator.Subdirectories)
while it.hasNext():
    name = it.next()
    if name.endswith(".svg"):
        print(name)

add separator support unreal

a section needs to first be added
then we set section name in the labels/command entries

# create section named test
return parent_app_node.add_section(section_name="test", label=self.label + "_label", insert_name="test_insert_name")
# assign entry to section test
parent_app_node.add_menu_entry("test", entry)

Unreal Menu setup , parent_p

I pulled in latest in into the unreal context menu branch and got this error. and check out this main branch to make sure, and i'm getting this issue. The root menu is created in the window/Context menu but none of the submenus & actions are created.
I ran the any_dcc_sample(changed the label to bypass the exception from duplicated name) and get this.

def get_name_path(self):

LogPython: Error:   File "D:/Users/Hayden/Programming/studiolauncher/sample_config/unreal-engine/init_unreal.py", line 55, in <module>
LogPython: Error:     app_menu_node = unimenu.setup(MainToolbar,backlink=False)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\core.py", line 139, in setup
LogPython: Error:     app_node = menu_node.setup(parent_app_node=parent_app_node, backlink=backlink)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\unreal.py", line 18, in setup
LogPython: Error:     super().setup(parent_app_node=parent_app_node, backlink=backlink)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\_abstract.py", line 222, in setup
LogPython: Error:     item.setup(parent_app_node=self.app_node)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\unreal.py", line 18, in setup
LogPython: Error:     super().setup(parent_app_node=parent_app_node, backlink=backlink)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\_abstract.py", line 217, in setup
LogPython: Error:     self.app_node = self._setup_menu_item(parent_app_node=parent_app_node)
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\unreal.py", line 38, in _setup_menu_item
LogPython: Error:     if not self.check_unique_name():
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\unreal.py", line 78, in check_unique_name
LogPython: Error:     exists = unreal_menus.find_menu(self.get_name_path())
LogPython: Error:   File "D:\Users\Hayden\Programming\fromGit\unimenu\unimenu\apps\unreal.py", line 92, in get_name_path
LogPython: Error:     return self.parent_path + "." + self.id
LogPython: Error: TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

it seems as if at this check, the parent path has been set yet?

bug in blender

TypeError: MenuNode.__init__() got an unexpected keyword argument 'icon_name'
        item2 = unimenu.Node(
            label="label",
            command="pass",
            tooltip="tooltip.",
            icon_name="RENDER_STILL",
        )

icon name is not supported

code quality improvement

one of our lines in the code relies on name of classes.
this breaks easily and is not clear. can this be changed?

return getattr(self.menu_module, "MenuNode" + name)

apps / __init__.py

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.