fix: Registration of keymaps and associated errors.
parent
55235c7032
commit
383f7d9bfd
|
@ -18,8 +18,8 @@
|
|||
|
||||
from functools import reduce
|
||||
|
||||
# from . import node_trees, operators, preferences, registration
|
||||
from . import assets, preferences, registration
|
||||
# from . import node_trees
|
||||
from . import assets, operators, preferences, registration
|
||||
from . import contracts as ct
|
||||
from .utils import logger
|
||||
|
||||
|
@ -30,8 +30,8 @@ log = logger.get(__name__)
|
|||
# - Load and Register Addon
|
||||
####################
|
||||
BL_REGISTER: list[ct.BLClass] = [
|
||||
# *operators.BL_REGISTER,
|
||||
# *assets.BL_REGISTER,
|
||||
*operators.BL_REGISTER,
|
||||
*assets.BL_REGISTER,
|
||||
# *node_trees.BL_REGISTER,
|
||||
]
|
||||
|
||||
|
@ -39,20 +39,18 @@ BL_HANDLERS: ct.BLHandlers = reduce(
|
|||
lambda a, b: a + b,
|
||||
[
|
||||
assets.BL_HANDLERS,
|
||||
# *operators.BL_HANDLERS,
|
||||
# *assets.BL_HANDLERS,
|
||||
# *node_trees.BL_HANDLERS,
|
||||
operators.BL_HANDLERS,
|
||||
assets.BL_HANDLERS,
|
||||
# node_trees.BL_HANDLERS,
|
||||
],
|
||||
ct.BLHandlers(),
|
||||
)
|
||||
|
||||
BL_HOTKEYS: list[ct.KeymapItemDef] = [
|
||||
# *operators.BL_HOTKEYS,
|
||||
# *assets.BL_HOTKEYS,
|
||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
||||
*assets.BL_KEYMAP_ITEMS,
|
||||
*operators.BL_KEYMAP_ITEMS,
|
||||
]
|
||||
|
||||
## TODO: BL_HANDLERS and BL_SOCKET_DEFS
|
||||
|
||||
|
||||
####################
|
||||
# - Registration
|
||||
|
@ -79,7 +77,7 @@ def register() -> None:
|
|||
|
||||
registration.register_classes(BL_REGISTER)
|
||||
registration.register_handlers(BL_HANDLERS)
|
||||
registration.register_hotkeys(BL_HOTKEYS)
|
||||
registration.register_keymaps(BL_KEYMAP_ITEMS)
|
||||
|
||||
log.info('Finished Registration of Addon: %s', ct.addon.NAME)
|
||||
else:
|
||||
|
@ -98,7 +96,7 @@ def unregister() -> None:
|
|||
"""
|
||||
log.info('Starting %s Unregister', ct.addon.NAME)
|
||||
|
||||
registration.unregister_hotkeys()
|
||||
registration.unregister_keymaps()
|
||||
registration.unregister_handlers()
|
||||
registration.unregister_classes()
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Internal assets for use via the Python API and/or directly by the user as an asset library."""
|
||||
|
||||
from functools import reduce
|
||||
|
||||
import oscillode.contracts as ct
|
||||
|
@ -32,8 +34,8 @@ BL_HANDLERS: ct.BLHandlers = reduce(
|
|||
ct.BLHandlers(),
|
||||
)
|
||||
|
||||
BL_HOTKEYS: list[ct.KeymapItemDef] = [
|
||||
*geonodes.BL_HOTKEYS,
|
||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
||||
*geonodes.BL_KEYMAP_ITEMS,
|
||||
]
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -31,17 +31,17 @@ log = logger.get(__name__)
|
|||
####################
|
||||
# GeoNodes Paths
|
||||
## Internal
|
||||
GN_INTERNAL_PATH = ct.addon.PATH_ASSETS / 'internal'
|
||||
GN_INTERNAL_INPUTS_PATH = GN_INTERNAL_PATH / 'input'
|
||||
GN_INTERNAL_SOURCES_PATH = GN_INTERNAL_PATH / 'source'
|
||||
GN_INTERNAL_STRUCTURES_PATH = GN_INTERNAL_PATH / 'structure'
|
||||
GN_INTERNAL_MONITORS_PATH = GN_INTERNAL_PATH / 'monitor'
|
||||
GN_INTERNAL_SIMULATIONS_PATH = GN_INTERNAL_PATH / 'simulation'
|
||||
GN_INTERNAL_PATH: Path = ct.addon.PATH_ASSETS / 'internal'
|
||||
GN_INTERNAL_INPUTS_PATH: Path = GN_INTERNAL_PATH / 'input'
|
||||
GN_INTERNAL_SOURCES_PATH: Path = GN_INTERNAL_PATH / 'source'
|
||||
GN_INTERNAL_STRUCTURES_PATH: Path = GN_INTERNAL_PATH / 'structure'
|
||||
GN_INTERNAL_MONITORS_PATH: Path = GN_INTERNAL_PATH / 'monitor'
|
||||
GN_INTERNAL_SIMULATIONS_PATH: Path = GN_INTERNAL_PATH / 'simulation'
|
||||
|
||||
## Structures
|
||||
GN_STRUCTURES_PATH = ct.addon.PATH_ASSETS / 'structures'
|
||||
GN_STRUCTURES_PRIMITIVES_PATH = GN_STRUCTURES_PATH / 'primitives'
|
||||
GN_STRUCTURES_ARRAYS_PATH = GN_STRUCTURES_PATH / 'arrays'
|
||||
GN_STRUCTURES_PATH: Path = ct.addon.PATH_ASSETS / 'structures'
|
||||
GN_STRUCTURES_PRIMITIVES_PATH: Path = GN_STRUCTURES_PATH / 'primitives'
|
||||
GN_STRUCTURES_ARRAYS_PATH: Path = GN_STRUCTURES_PATH / 'arrays'
|
||||
|
||||
|
||||
class GeoNodes(enum.StrEnum):
|
||||
|
@ -473,10 +473,10 @@ class GeoNodesToStructureNode(bpy.types.Operator):
|
|||
## 3. We compute it manually, to avoid the jank.
|
||||
node_location = get_view_location(
|
||||
editor_region,
|
||||
[
|
||||
(
|
||||
event.mouse_x - editor_region.x,
|
||||
event.mouse_y - editor_region.y,
|
||||
],
|
||||
),
|
||||
context.preferences.system.ui_scale,
|
||||
)
|
||||
|
||||
|
@ -525,8 +525,8 @@ ASSET_LIB_SPECS: dict[str, Path] = {
|
|||
}
|
||||
|
||||
|
||||
@bpy.app.handlers.persistent
|
||||
def initialize_asset_libraries(_: bpy.types.Scene):
|
||||
@bpy.app.handlers.persistent # type: ignore[misc]
|
||||
def initialize_asset_libraries(_: bpy.types.Scene) -> None:
|
||||
"""Before loading a `.blend` file, ensure that the WindowManager properties relied on by NodeAssetPanel are available.
|
||||
|
||||
- Several asset libraries, defined under the global `ASSET_LIB_SPECS`, are added/replaced such that the name:path map is respected.
|
||||
|
@ -586,4 +586,4 @@ BL_REGISTER = [
|
|||
|
||||
BL_HANDLERS: ct.BLHandlers = ct.BLHandlers(load_pre=(initialize_asset_libraries,))
|
||||
|
||||
BL_HOTKEYS: list[ct.KeymapItemDef] = []
|
||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = []
|
||||
|
|
|
@ -22,24 +22,25 @@ from .bl import (
|
|||
BLColorRGBA,
|
||||
BLEnumElement,
|
||||
BLEnumID,
|
||||
BLEventType,
|
||||
BLEventValue,
|
||||
BLIcon,
|
||||
BLIconSet,
|
||||
BLIDStruct,
|
||||
BLImportMethod,
|
||||
BLKeymapItem,
|
||||
BLModifierType,
|
||||
BLNodeTreeInterfaceID,
|
||||
BLOperatorStatus,
|
||||
BLPropFlag,
|
||||
BLRegionType,
|
||||
BLSpaceType,
|
||||
KeymapItemDef,
|
||||
ManagedObjName,
|
||||
PresetName,
|
||||
PropName,
|
||||
SocketName,
|
||||
)
|
||||
from .bl_handlers import BLHandlers
|
||||
from .bl_keymap import BLKeymapItem
|
||||
from .icons import Icon
|
||||
from .mobj_types import ManagedObjType
|
||||
from .node_tree_types import (
|
||||
|
@ -58,6 +59,8 @@ __all__ = [
|
|||
'BLColorRGBA',
|
||||
'BLEnumElement',
|
||||
'BLEnumID',
|
||||
'BLEventType',
|
||||
'BLEventValue',
|
||||
'BLIcon',
|
||||
'BLIconSet',
|
||||
'BLIDStruct',
|
||||
|
|
|
@ -45,7 +45,7 @@ if 'RUNNING_BLEXT_TESTS' in os.environ:
|
|||
PATH_ADDON_ROOT.parent / 'dev' / 'local'
|
||||
) ## TODO: Consult init_settings
|
||||
else:
|
||||
PATH_CACHE: Path = Path(bpy.utils.extension_path_user(__package__, create=True))
|
||||
PATH_CACHE: Path = Path(bpy.utils.extension_path_user(__package__, create=True)) # type: ignore[no-redef]
|
||||
|
||||
|
||||
####################
|
||||
|
|
|
@ -95,7 +95,6 @@ BLIDStruct: typ.TypeAlias = (
|
|||
| bpy.types.WorkSpace
|
||||
| bpy.types.World
|
||||
)
|
||||
BLKeymapItem: typ.TypeAlias = typ.Any ## TODO: Better Type
|
||||
BLPropFlag: typ.TypeAlias = typ.Literal[
|
||||
'HIDDEN',
|
||||
'SKIP_SAVE',
|
||||
|
@ -112,6 +111,24 @@ BLColorRGBA = tuple[float, float, float, float]
|
|||
####################
|
||||
# - Operators
|
||||
####################
|
||||
BLRegionType: typ.TypeAlias = typ.Literal[
|
||||
'WINDOW',
|
||||
'HEADER',
|
||||
'CHANNELS',
|
||||
'TEMPORARY',
|
||||
'UI',
|
||||
'TOOLS',
|
||||
'TOOL_PROPS',
|
||||
'ASSET_SHELF',
|
||||
'ASSET_SHELF_HEADER',
|
||||
'PREVIEW',
|
||||
'HUD',
|
||||
'NAVIGATION_BAR',
|
||||
'EXECUTE',
|
||||
'FOOTER',
|
||||
'TOOL_HEADER',
|
||||
'XR',
|
||||
]
|
||||
BLSpaceType: typ.TypeAlias = typ.Literal[
|
||||
'EMPTY',
|
||||
'VIEW_3D',
|
||||
|
@ -133,32 +150,151 @@ BLSpaceType: typ.TypeAlias = typ.Literal[
|
|||
'SPREADSHEET',
|
||||
'PREFERENCES',
|
||||
]
|
||||
BLRegionType: typ.TypeAlias = typ.Literal[
|
||||
'WINDOW',
|
||||
'HEADER',
|
||||
'CHANNELS',
|
||||
'TEMPORARY',
|
||||
'UI',
|
||||
'TOOLS',
|
||||
'TOOL_PROPS',
|
||||
'ASSET_SHELF',
|
||||
'ASSET_SHELF_HEADER',
|
||||
'PREVIEW',
|
||||
'HUD',
|
||||
'NAVIGATION_BAR',
|
||||
'EXECUTE',
|
||||
'FOOTER',
|
||||
'TOOL_HEADER',
|
||||
'XR',
|
||||
]
|
||||
BLOperatorStatus: typ.TypeAlias = set[
|
||||
typ.Literal['RUNNING_MODAL', 'CANCELLED', 'FINISHED', 'PASS_THROUGH', 'INTERFACE']
|
||||
]
|
||||
|
||||
####################
|
||||
# - Operators
|
||||
####################
|
||||
## TODO: Write the rest in.
|
||||
BLEventType: typ.TypeAlias = typ.Literal[
|
||||
'NONE',
|
||||
'LEFTMOUSE',
|
||||
'MIDDLEMOUSE',
|
||||
'RIGHTMOUSE',
|
||||
'BUTTON4MOUSE',
|
||||
'BUTTON5MOUSE',
|
||||
'BUTTON6MOUSE',
|
||||
'BUTTON7MOUSE',
|
||||
'PEN',
|
||||
'ERASOR',
|
||||
'MOUSEMOVE',
|
||||
'INBETWEEN_MOUSEMOVE',
|
||||
'TRACKPADPAN',
|
||||
'TRACKPADZOOM',
|
||||
'MOUSEROTATE',
|
||||
'MOUSESMARTZOOM',
|
||||
'WHEELUPMOUSE',
|
||||
'WHEELDOWNMOUSE',
|
||||
'WHEELINMOUSE',
|
||||
'WHEELOUTMOUSE',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
'ZERO',
|
||||
'ONE',
|
||||
'TWO',
|
||||
'THREE',
|
||||
'FOUR',
|
||||
'FIVE',
|
||||
'SIX',
|
||||
'SEVEN',
|
||||
'EIGHT',
|
||||
'NINE',
|
||||
'LEFT_CTRL',
|
||||
'LEFT_ALT',
|
||||
'LEFT_SHIFT',
|
||||
'RIGHT_ALT',
|
||||
'RIGHT_CTRL',
|
||||
'RIGHT_SHIFT',
|
||||
'ESC',
|
||||
'TAB',
|
||||
'RET', ## Enter
|
||||
'SPACE',
|
||||
'LINE_FEED',
|
||||
'BACK_SPACE',
|
||||
'DEL',
|
||||
'SEMI_COLON',
|
||||
'PERIOD',
|
||||
'COMMA',
|
||||
'QUOTE',
|
||||
'ACCENT_GRAVE',
|
||||
'MINUS',
|
||||
'PLUS',
|
||||
'SLASH',
|
||||
'BACK_SLASH',
|
||||
'EQUAL',
|
||||
'LEFT_BRACKET',
|
||||
'RIGHT_BRACKET',
|
||||
'LEFT_ARROW',
|
||||
'DOWN_ARROW',
|
||||
'RIGHT_ARROW',
|
||||
'UP_ARROW',
|
||||
'NUMPAD_0',
|
||||
'NUMPAD_1',
|
||||
'NUMPAD_2',
|
||||
'NUMPAD_3',
|
||||
'NUMPAD_4',
|
||||
'NUMPAD_5',
|
||||
'NUMPAD_6',
|
||||
'NUMPAD_7',
|
||||
'NUMPAD_8',
|
||||
'NUMPAD_9',
|
||||
'NUMPAD_PERIOD',
|
||||
'NUMPAD_SLASH',
|
||||
'NUMPAD_ASTERIX',
|
||||
'NUMPAD_MINUS',
|
||||
'NUMPAD_PLUS',
|
||||
'NUMPAD_ENTER',
|
||||
'F1',
|
||||
'F2',
|
||||
'F3',
|
||||
'F4',
|
||||
'F5',
|
||||
'F6',
|
||||
'F7',
|
||||
'F8',
|
||||
'F9',
|
||||
'F10',
|
||||
'F11',
|
||||
'F12',
|
||||
'PAUSE',
|
||||
'INSERT',
|
||||
'HOME',
|
||||
'PAGE_UP',
|
||||
'PAGE_DOWN',
|
||||
'END',
|
||||
'MEDIA_PLAY',
|
||||
'MEDIA_STOP',
|
||||
'MEDIA_FIRST',
|
||||
'MEDIA_LAST',
|
||||
]
|
||||
BLEventValue: typ.TypeAlias = typ.Literal[
|
||||
'ANY',
|
||||
'PRESS',
|
||||
'RELEASE',
|
||||
'CLICK',
|
||||
'DOUBLE_CLICK',
|
||||
'CLICK_DRAG',
|
||||
'NOTHING',
|
||||
]
|
||||
####################
|
||||
# - Addon Types
|
||||
####################
|
||||
KeymapItemDef: typ.TypeAlias = typ.Any
|
||||
ManagedObjName = str
|
||||
|
||||
####################
|
||||
|
|
|
@ -58,6 +58,9 @@ class BLHandlers(pyd.BaseModel):
|
|||
render_post: tuple[BLHandler, ...] = ()
|
||||
render_pre: tuple[BLHandler, ...] = ()
|
||||
render_stats: tuple[BLHandler, ...] = ()
|
||||
## TODO: Verify these type signatures.
|
||||
|
||||
## TODO: A validator to check that all handlers are decorated with bpy.app.handlers.persistent
|
||||
|
||||
####################
|
||||
# - Properties
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# oscillode
|
||||
# Copyright (C) 2024 oscillode Project Contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Declares types for working with `bpy.types.KeyMap`s."""
|
||||
|
||||
import bpy
|
||||
import pydantic as pyd
|
||||
|
||||
from .bl import BLEventType, BLEventValue, BLSpaceType
|
||||
from .operator_types import OperatorType
|
||||
|
||||
|
||||
class BLKeymapItem(pyd.BaseModel):
|
||||
"""Contains lists of handlers associated with this addon."""
|
||||
|
||||
operator: OperatorType
|
||||
|
||||
event_type: BLEventType
|
||||
event_value: BLEventValue
|
||||
|
||||
shift: bool = False
|
||||
ctrl: bool = False
|
||||
alt: bool = False
|
||||
key_modifier: BLEventType = 'NONE'
|
||||
|
||||
space_type: BLSpaceType = 'EMPTY'
|
||||
|
||||
def register(self, addon_keymap: bpy.types.KeyMap) -> bpy.types.KeymapItem:
|
||||
"""Registers this hotkey with an addon keymap.
|
||||
|
||||
Raises:
|
||||
ValueError: If the `space_type` constraint of the addon keymap does not match the `space_type` constraint of this `BLKeymapItem`.
|
||||
"""
|
||||
if self.space_type == addon_keymap.space_type:
|
||||
addon_keymap.keymap_items.new(
|
||||
self.operator,
|
||||
self.event_type,
|
||||
self.event_value,
|
||||
shift=self.shift,
|
||||
ctrl=self.ctrl,
|
||||
alt=self.alt,
|
||||
key_modifier=self.key_modifier,
|
||||
)
|
||||
|
||||
msg = f'Addon keymap space type {addon_keymap.space_type} does not match space_type of BLKeymapItem to register: {self}'
|
||||
raise ValueError(msg)
|
||||
## TODO: Check if space_type matches?
|
|
@ -312,6 +312,8 @@ class MaxwellSimTree(bpy.types.NodeTree):
|
|||
default=True,
|
||||
)
|
||||
|
||||
viewer_node_type: ct.NodeType = ct.NodeType.Viewer
|
||||
|
||||
####################
|
||||
# - Init Methods
|
||||
####################
|
||||
|
|
|
@ -16,11 +16,22 @@
|
|||
|
||||
"""Blender operators that ship with Oscillode."""
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from oscillode import contracts as ct
|
||||
|
||||
from . import connect_viewer
|
||||
|
||||
BL_REGISTER = [
|
||||
BL_REGISTER: list[ct.BLClass] = [
|
||||
*connect_viewer.BL_REGISTER,
|
||||
]
|
||||
BL_HOTKEYS = [
|
||||
*connect_viewer.BL_HOTKEYS,
|
||||
BL_HANDLERS: ct.BLHandlers = reduce(
|
||||
lambda a, b: a + b,
|
||||
[
|
||||
*connect_viewer.BL_HANDLERS,
|
||||
],
|
||||
ct.BLHandlers(),
|
||||
)
|
||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
||||
*connect_viewer.BL_KEYMAP_ITEMS,
|
||||
]
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import bpy
|
||||
|
||||
from oscillode import contracts as ct
|
||||
from oscillode.node_trees.maxwell_sim_nodes.contracts import node_types
|
||||
from oscillode.utils import logger
|
||||
|
||||
log = logger.get(__name__)
|
||||
|
@ -79,16 +78,17 @@ class ConnectViewerNode(bpy.types.Operator):
|
|||
selected_node = context.selected_nodes[0]
|
||||
|
||||
# Find Viewer Node...
|
||||
viewer_node_type = node_tree.viewer_node_type
|
||||
for node in node_tree.nodes:
|
||||
# TODO: Support multiple viewer nodes.
|
||||
if hasattr(node, 'node_type') and node.node_type is node_types.Viewer:
|
||||
if hasattr(node, 'node_type') and node.node_type is viewer_node_type:
|
||||
viewer_node = node
|
||||
break
|
||||
|
||||
# ...OR: Create Viewer Node
|
||||
else:
|
||||
# TODO: Place viewer where it doesn't overlap other nodes.
|
||||
viewer_node = node_tree.nodes.new(node_types.Viewer.value)
|
||||
viewer_node = node_tree.nodes.new(viewer_node_type)
|
||||
viewer_node.location.x = selected_node.location.x + 250
|
||||
viewer_node.location.y = selected_node.location.y
|
||||
selected_node.select = False
|
||||
|
@ -112,19 +112,19 @@ class ConnectViewerNode(bpy.types.Operator):
|
|||
####################
|
||||
# - Blender Registration
|
||||
####################
|
||||
BL_REGISTER = [
|
||||
BL_REGISTER: list[ct.BLClass] = [
|
||||
ConnectViewerNode,
|
||||
]
|
||||
|
||||
BL_HOTKEYS = [
|
||||
{
|
||||
'_': (
|
||||
BL_HANDLERS: ct.BLHandlers = ct.BLHandlers()
|
||||
|
||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
||||
ct.BLKeymapItem(
|
||||
ct.OperatorType.ConnectViewerNode,
|
||||
'LEFTMOUSE',
|
||||
'PRESS',
|
||||
),
|
||||
'ctrl': True,
|
||||
'shift': True,
|
||||
'alt': False,
|
||||
},
|
||||
event_type='LEFTMOUSE',
|
||||
event_value='PRESS',
|
||||
ctrl=True,
|
||||
shift=True,
|
||||
space_type='NODE_EDITOR',
|
||||
)
|
||||
]
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
"""Manages the registration of Blender classes, including delayed registrations that require access to Python dependencies.
|
||||
|
||||
Attributes:
|
||||
_ADDON_KEYMAP: Addon-specific keymap used to register operator hotkeys.
|
||||
REG__CLASSES: Currently registered Blender classes.
|
||||
_REGISTERED_HOTKEYS: Currently registered Blender keymap items.
|
||||
_REGISTERED_CLASSES: Blender classes currently registered by this addon.
|
||||
_REGISTERED_KEYMAPS: Addon keymaps currently registered by this addon.
|
||||
Each addon keymap is constrained to a single `space_type`, which is the key.
|
||||
_REGISTERED_KEYMAP_ITEMS: Addon keymap items currently registered by this addon.
|
||||
Each keymap item is paired to the keymap within which it is registered.
|
||||
_Each keymap is guaranteed to also be found in `_REGISTERED_KEYMAPS`._
|
||||
_REGISTERED_HANDLERS: Addon handlers currently registered by this addon.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
@ -34,8 +38,8 @@ log = logger.get(__name__)
|
|||
####################
|
||||
_REGISTERED_CLASSES: list[ct.BLClass] = []
|
||||
|
||||
_ADDON_KEYMAP: bpy.types.KeyMap | None = None
|
||||
_REGISTERED_HOTKEYS: list[ct.BLKeymapItem] = []
|
||||
_REGISTERED_KEYMAPS: dict[ct.BLSpaceType, bpy.types.KeyMap] = {}
|
||||
_REGISTERED_KEYMAP_ITEMS: list[tuple[bpy.types.KeyMap, bpy.types.KeymapItem]] = []
|
||||
|
||||
_REGISTERED_HANDLERS: ct.BLHandlers | None = None
|
||||
|
||||
|
@ -109,59 +113,47 @@ def unregister_handlers() -> None:
|
|||
####################
|
||||
# - Keymap Registration
|
||||
####################
|
||||
def register_hotkeys(hotkey_defs: list[dict]) -> None:
|
||||
def register_keymaps(keymap_items: list[ct.BLKeymapItem]) -> None:
|
||||
"""Registers a list of Blender hotkey definitions.
|
||||
|
||||
Parameters:
|
||||
hotkey_defs: List of Blender hotkey definitions to register.
|
||||
bl_keymap_items: List of Blender hotkey definitions to register.
|
||||
"""
|
||||
# Lazy-Load BL_NODE_KEYMAP
|
||||
global _ADDON_KEYMAP # noqa: PLW0603
|
||||
if _ADDON_KEYMAP is None:
|
||||
_ADDON_KEYMAP = bpy.context.window_manager.keyconfigs.addon.keymaps.new(
|
||||
name='Node Editor',
|
||||
space_type='NODE_EDITOR',
|
||||
)
|
||||
log.info(
|
||||
'Registered Addon Keymap (Base for Keymap Items): %s',
|
||||
str(_ADDON_KEYMAP),
|
||||
)
|
||||
# Aggregate Requested Spaces of All Keymap Items
|
||||
keymap_space_types: set[ct.BLSpaceType] = {
|
||||
keymap_item.space_type for keymap_item in keymap_items
|
||||
}
|
||||
|
||||
# Register Keymaps
|
||||
log.info('Registering %s Keymap Items', len(hotkey_defs))
|
||||
for keymap_item_def in hotkey_defs:
|
||||
keymap_item = _ADDON_KEYMAP.keymap_items.new(
|
||||
*keymap_item_def['_'],
|
||||
ctrl=keymap_item_def['ctrl'],
|
||||
shift=keymap_item_def['shift'],
|
||||
alt=keymap_item_def['alt'],
|
||||
# Create Addon Keymap per Requested Space
|
||||
for keymap_space_type in keymap_space_types:
|
||||
log.info('Registering %s Keymap', keymap_space_type)
|
||||
bl_keymap = bpy.context.window_manager.keyconfigs.addon.keymaps.new(
|
||||
name=f'{ct.addon.NAME} - {keymap_space_type}',
|
||||
space_type=keymap_space_type,
|
||||
)
|
||||
log.debug(
|
||||
'Registered Keymap Item %s with spec %s',
|
||||
repr(keymap_item),
|
||||
keymap_item_def,
|
||||
)
|
||||
_REGISTERED_HOTKEYS.append(keymap_item)
|
||||
_REGISTERED_KEYMAPS[keymap_space_type] = bl_keymap
|
||||
|
||||
# Register Keymap Items in Correct Addon Keymap
|
||||
for keymap_item in keymap_items:
|
||||
log.info('Registering %s Keymap Item', keymap_item)
|
||||
bl_keymap = _REGISTERED_KEYMAPS[keymap_item.space_type]
|
||||
bl_keymap_item = keymap_item.register(bl_keymap)
|
||||
|
||||
_REGISTERED_KEYMAP_ITEMS.append((bl_keymap, bl_keymap_item))
|
||||
|
||||
|
||||
def unregister_hotkeys() -> None:
|
||||
"""Unregisters all Blender hotkeys associated with the addon."""
|
||||
global _ADDON_KEYMAP # noqa: PLW0603
|
||||
def unregister_keymaps() -> None:
|
||||
"""Unregisters all Blender keymaps associated with the addon."""
|
||||
# Unregister Keymap Items from Correct Addon Keymap
|
||||
for bl_keymap, bl_keymap_item in reversed(_REGISTERED_KEYMAP_ITEMS):
|
||||
log.info('Unregistering %s BL Keymap Item', bl_keymap_item)
|
||||
bl_keymap.keymap_items.remove(bl_keymap_item)
|
||||
|
||||
# Unregister Keymaps
|
||||
log.info('Unregistering %s Keymap Items', len(_REGISTERED_HOTKEYS))
|
||||
for keymap_item in reversed(_REGISTERED_HOTKEYS):
|
||||
log.debug(
|
||||
'Unregistered Keymap Item %s',
|
||||
repr(keymap_item),
|
||||
)
|
||||
_ADDON_KEYMAP.keymap_items.remove(keymap_item)
|
||||
_REGISTERED_KEYMAP_ITEMS.clear()
|
||||
|
||||
# Lazy-Unload BL_NODE_KEYMAP
|
||||
if _ADDON_KEYMAP is not None:
|
||||
log.info(
|
||||
'Unregistered Keymap %s',
|
||||
repr(_ADDON_KEYMAP),
|
||||
)
|
||||
_REGISTERED_HOTKEYS.clear()
|
||||
_ADDON_KEYMAP = None
|
||||
# Delete Addon Keymaps
|
||||
for bl_keymap in reversed(_REGISTERED_KEYMAPS.values()):
|
||||
log.info('Unregistering %s Keymap', bl_keymap)
|
||||
bpy.context.window_manager.keyconfigs.addon.keymaps.remove(bl_keymap)
|
||||
|
||||
_REGISTERED_KEYMAPS.clear()
|
||||
|
|
Loading…
Reference in New Issue