feat: Added handler bubble-up logic.
parent
12362b3cbd
commit
55235c7032
|
@ -16,7 +16,10 @@
|
||||||
|
|
||||||
"""A visual DSL for electromagnetic simulation design and analysis implemented as a Blender node editor."""
|
"""A visual DSL for electromagnetic simulation design and analysis implemented as a Blender node editor."""
|
||||||
|
|
||||||
# from . import assets, node_trees, operators, preferences, registration
|
from functools import reduce
|
||||||
|
|
||||||
|
# from . import node_trees, operators, preferences, registration
|
||||||
|
from . import assets, preferences, registration
|
||||||
from . import contracts as ct
|
from . import contracts as ct
|
||||||
from .utils import logger
|
from .utils import logger
|
||||||
|
|
||||||
|
@ -32,6 +35,17 @@ BL_REGISTER: list[ct.BLClass] = [
|
||||||
# *node_trees.BL_REGISTER,
|
# *node_trees.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
BL_HANDLERS: ct.BLHandlers = reduce(
|
||||||
|
lambda a, b: a + b,
|
||||||
|
[
|
||||||
|
assets.BL_HANDLERS,
|
||||||
|
# *operators.BL_HANDLERS,
|
||||||
|
# *assets.BL_HANDLERS,
|
||||||
|
# *node_trees.BL_HANDLERS,
|
||||||
|
],
|
||||||
|
ct.BLHandlers(),
|
||||||
|
)
|
||||||
|
|
||||||
BL_HOTKEYS: list[ct.KeymapItemDef] = [
|
BL_HOTKEYS: list[ct.KeymapItemDef] = [
|
||||||
# *operators.BL_HOTKEYS,
|
# *operators.BL_HOTKEYS,
|
||||||
# *assets.BL_HOTKEYS,
|
# *assets.BL_HOTKEYS,
|
||||||
|
@ -64,6 +78,7 @@ def register() -> None:
|
||||||
log.info('Registering Addon: %s', ct.addon.NAME)
|
log.info('Registering Addon: %s', ct.addon.NAME)
|
||||||
|
|
||||||
registration.register_classes(BL_REGISTER)
|
registration.register_classes(BL_REGISTER)
|
||||||
|
registration.register_handlers(BL_HANDLERS)
|
||||||
registration.register_hotkeys(BL_HOTKEYS)
|
registration.register_hotkeys(BL_HOTKEYS)
|
||||||
|
|
||||||
log.info('Finished Registration of Addon: %s', ct.addon.NAME)
|
log.info('Finished Registration of Addon: %s', ct.addon.NAME)
|
||||||
|
@ -83,7 +98,8 @@ def unregister() -> None:
|
||||||
"""
|
"""
|
||||||
log.info('Starting %s Unregister', ct.addon.NAME)
|
log.info('Starting %s Unregister', ct.addon.NAME)
|
||||||
|
|
||||||
registration.unregister_classes()
|
|
||||||
registration.unregister_hotkeys()
|
registration.unregister_hotkeys()
|
||||||
|
registration.unregister_handlers()
|
||||||
|
registration.unregister_classes()
|
||||||
|
|
||||||
log.info('Finished %s Unregister', ct.addon.NAME)
|
log.info('Finished %s Unregister', ct.addon.NAME)
|
||||||
|
|
|
@ -14,17 +14,30 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
import oscillode.contracts as ct
|
||||||
|
|
||||||
from . import geonodes
|
from . import geonodes
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER: list[ct.BLClass] = [
|
||||||
*geonodes.BL_REGISTER,
|
*geonodes.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
||||||
BL_HOTKEYS = [
|
BL_HANDLERS: ct.BLHandlers = reduce(
|
||||||
|
lambda a, b: a + b,
|
||||||
|
[
|
||||||
|
geonodes.BL_HANDLERS,
|
||||||
|
],
|
||||||
|
ct.BLHandlers(),
|
||||||
|
)
|
||||||
|
|
||||||
|
BL_HOTKEYS: list[ct.KeymapItemDef] = [
|
||||||
*geonodes.BL_HOTKEYS,
|
*geonodes.BL_HOTKEYS,
|
||||||
]
|
]
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'BL_REGISTER',
|
'BL_REGISTER',
|
||||||
|
'BL_HANDLERS',
|
||||||
'BL_HOTKEYS',
|
'BL_HOTKEYS',
|
||||||
]
|
]
|
||||||
|
|
|
@ -579,11 +579,11 @@ def initialize_asset_libraries(_: bpy.types.Scene):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
bpy.app.handlers.load_pre.append(initialize_asset_libraries)
|
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
NodeAssetPanel,
|
NodeAssetPanel,
|
||||||
GeoNodesToStructureNode,
|
GeoNodesToStructureNode,
|
||||||
]
|
]
|
||||||
|
|
||||||
BL_HOTKEYS = []
|
BL_HANDLERS: ct.BLHandlers = ct.BLHandlers(load_pre=(initialize_asset_libraries,))
|
||||||
|
|
||||||
|
BL_HOTKEYS: list[ct.KeymapItemDef] = []
|
||||||
|
|
|
@ -39,6 +39,7 @@ from .bl import (
|
||||||
PropName,
|
PropName,
|
||||||
SocketName,
|
SocketName,
|
||||||
)
|
)
|
||||||
|
from .bl_handlers import BLHandlers
|
||||||
from .icons import Icon
|
from .icons import Icon
|
||||||
from .mobj_types import ManagedObjType
|
from .mobj_types import ManagedObjType
|
||||||
from .node_tree_types import (
|
from .node_tree_types import (
|
||||||
|
@ -74,6 +75,7 @@ __all__ = [
|
||||||
'PresetName',
|
'PresetName',
|
||||||
'PropName',
|
'PropName',
|
||||||
'SocketName',
|
'SocketName',
|
||||||
|
'BLHandlers',
|
||||||
'Icon',
|
'Icon',
|
||||||
'BLInstance',
|
'BLInstance',
|
||||||
'InstanceID',
|
'InstanceID',
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
# 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.app.handlers` callbacks."""
|
||||||
|
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import pydantic as pyd
|
||||||
|
|
||||||
|
from oscillode.utils.staticproperty import staticproperty
|
||||||
|
|
||||||
|
BLHandler = typ.Callable[[], None]
|
||||||
|
BLHandlerWithFile = typ.Callable[[str], None]
|
||||||
|
BLHandlerWithRenderStats = typ.Callable[[typ.Any], None]
|
||||||
|
|
||||||
|
|
||||||
|
class BLHandlers(pyd.BaseModel):
|
||||||
|
"""Contains lists of handlers associated with this addon."""
|
||||||
|
|
||||||
|
animation_playback_post: tuple[BLHandler, ...] = ()
|
||||||
|
animation_playback_pre: tuple[BLHandler, ...] = ()
|
||||||
|
annotation_post: tuple[BLHandler, ...] = ()
|
||||||
|
annotation_pre: tuple[BLHandler, ...] = ()
|
||||||
|
composite_cancel: tuple[BLHandler, ...] = ()
|
||||||
|
composite_post: tuple[BLHandler, ...] = ()
|
||||||
|
composite_pre: tuple[BLHandler, ...] = ()
|
||||||
|
depsgraph_update_post: tuple[BLHandler, ...] = ()
|
||||||
|
depsgraph_update_pre: tuple[BLHandler, ...] = ()
|
||||||
|
frame_change_post: tuple[BLHandler, ...] = ()
|
||||||
|
frame_change_pre: tuple[BLHandler, ...] = ()
|
||||||
|
load_factory_preferences_post: tuple[BLHandler, ...] = ()
|
||||||
|
load_factory_startup_post: tuple[BLHandler, ...] = ()
|
||||||
|
load_post: tuple[BLHandlerWithFile, ...] = ()
|
||||||
|
load_post_fail: tuple[BLHandlerWithFile, ...] = ()
|
||||||
|
load_pre: tuple[BLHandlerWithFile, ...] = ()
|
||||||
|
object_bake_cancel: tuple[BLHandler, ...] = ()
|
||||||
|
object_bake_complete: tuple[BLHandler, ...] = ()
|
||||||
|
object_bake_pre: tuple[BLHandler, ...] = ()
|
||||||
|
redo_post: tuple[BLHandler, ...] = ()
|
||||||
|
redo_pre: tuple[BLHandler, ...] = ()
|
||||||
|
render_cancel: tuple[BLHandler, ...] = ()
|
||||||
|
render_complete: tuple[BLHandler, ...] = ()
|
||||||
|
render_init: tuple[BLHandler, ...] = ()
|
||||||
|
render_post: tuple[BLHandler, ...] = ()
|
||||||
|
render_pre: tuple[BLHandler, ...] = ()
|
||||||
|
render_stats: tuple[BLHandler, ...] = ()
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
@staticproperty # type: ignore[arg-type]
|
||||||
|
def hander_categories() -> tuple[str, ...]: # type: ignore[misc]
|
||||||
|
"""Returns an immutable string sequence of handler categories."""
|
||||||
|
return (
|
||||||
|
'animation_playback_post',
|
||||||
|
'animation_playback_pre',
|
||||||
|
'annotation_post',
|
||||||
|
'annotation_pre',
|
||||||
|
'composite_cancel',
|
||||||
|
'composite_post',
|
||||||
|
'composite_pre',
|
||||||
|
'depsgraph_update_post',
|
||||||
|
'depsgraph_update_pre',
|
||||||
|
'frame_change_post',
|
||||||
|
'frame_change_pre',
|
||||||
|
'load_factory_preferences_post',
|
||||||
|
'load_factory_startup_post',
|
||||||
|
'load_post',
|
||||||
|
'load_post_fail',
|
||||||
|
'load_pre',
|
||||||
|
'object_bake_cancel',
|
||||||
|
'object_bake_complete',
|
||||||
|
'object_bake_pre',
|
||||||
|
'redo_post',
|
||||||
|
'redo_pre',
|
||||||
|
'render_cancel',
|
||||||
|
'render_complete',
|
||||||
|
'render_init',
|
||||||
|
'render_post',
|
||||||
|
'render_pre',
|
||||||
|
'render_stats',
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Merging
|
||||||
|
####################
|
||||||
|
def __add__(self, other: typ.Self) -> typ.Self:
|
||||||
|
"""Concatenate the handlers of two `BLHandlers` objects."""
|
||||||
|
return BLHandlers(
|
||||||
|
**{
|
||||||
|
hndl_cat: getattr(self, hndl_cat) + getattr(self, hndl_cat)
|
||||||
|
for hndl_cat in self.handler_categories
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def register(self) -> None:
|
||||||
|
"""Registers all handlers declared by-category."""
|
||||||
|
for handler_category in BLHandlers.handler_categories:
|
||||||
|
for handler in getattr(self, handler_category):
|
||||||
|
getattr(bpy.app.handlers, handler_category).append(handler)
|
||||||
|
|
||||||
|
def unregister(self) -> None:
|
||||||
|
"""Unregisters only this addon's handlers from bpy.app.handlers."""
|
||||||
|
for handler_category in BLHandlers.handler_categories:
|
||||||
|
for handler in getattr(self, handler_category):
|
||||||
|
bpy_handlers = getattr(bpy.app.handlers, handler_category)
|
||||||
|
if handler in bpy_handlers:
|
||||||
|
bpy_handlers.remove(handler)
|
|
@ -33,9 +33,12 @@ log = logger.get(__name__)
|
||||||
# - Globals
|
# - Globals
|
||||||
####################
|
####################
|
||||||
_REGISTERED_CLASSES: list[ct.BLClass] = []
|
_REGISTERED_CLASSES: list[ct.BLClass] = []
|
||||||
|
|
||||||
_ADDON_KEYMAP: bpy.types.KeyMap | None = None
|
_ADDON_KEYMAP: bpy.types.KeyMap | None = None
|
||||||
_REGISTERED_HOTKEYS: list[ct.BLKeymapItem] = []
|
_REGISTERED_HOTKEYS: list[ct.BLKeymapItem] = []
|
||||||
|
|
||||||
|
_REGISTERED_HANDLERS: ct.BLHandlers | None = None
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Class Registration
|
# - Class Registration
|
||||||
|
@ -74,6 +77,35 @@ def unregister_classes() -> None:
|
||||||
_REGISTERED_CLASSES.clear()
|
_REGISTERED_CLASSES.clear()
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Handler Registration
|
||||||
|
####################
|
||||||
|
def register_handlers(bl_handlers: ct.BLHandlers) -> None:
|
||||||
|
"""Register the given Blender handlers."""
|
||||||
|
global _REGISTERED_HANDLERS # noqa: PLW0603
|
||||||
|
|
||||||
|
log.info('Registering BLHandlers') ## TODO: More information
|
||||||
|
if _REGISTERED_HANDLERS is None:
|
||||||
|
bl_handlers.register()
|
||||||
|
_REGISTERED_HANDLERS = bl_handlers
|
||||||
|
|
||||||
|
msg = 'There are already BLHandlers registered; they must be unregistered before a new set can be registered.'
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister_handlers() -> None:
|
||||||
|
"""Unregister this addon's registered Blender handlers."""
|
||||||
|
global _REGISTERED_HANDLERS # noqa: PLW0603
|
||||||
|
|
||||||
|
log.info('Unregistering BLHandlers') ## TODO: More information
|
||||||
|
if _REGISTERED_HANDLERS is not None:
|
||||||
|
_REGISTERED_HANDLERS.register()
|
||||||
|
_REGISTERED_HANDLERS = None
|
||||||
|
|
||||||
|
msg = 'There are no BLHandlers registered; therefore, there is nothing to register.'
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Keymap Registration
|
# - Keymap Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -193,6 +193,12 @@ ignore = [
|
||||||
"E501", # Let Formatter Worry about Line Length
|
"E501", # Let Formatter Worry about Line Length
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"tests/*" = [
|
||||||
|
"D100", # It's okay to not have module-level docstrings in test modules.
|
||||||
|
"D104", # Same for packages.
|
||||||
|
]
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Tooling: Ruff Sublinters
|
# - Tooling: Ruff Sublinters
|
||||||
####################
|
####################
|
||||||
|
|
Loading…
Reference in New Issue