Compare commits
No commits in common. "b921c3b5cd0a2bbbc271260e219dba4298f72d18" and "e6ada5028d88c47714ea35d9a0a08d621b119ce1" have entirely different histories.
b921c3b5cd
...
e6ada5028d
|
@ -20,7 +20,7 @@ repos:
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
# Ruff version.
|
# Ruff version.
|
||||||
rev: v0.6.8
|
rev: v0.4.3
|
||||||
hooks:
|
hooks:
|
||||||
# ruff lint
|
# ruff lint
|
||||||
#- id: ruff
|
#- id: ruff
|
||||||
|
@ -29,18 +29,8 @@ repos:
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
|
||||||
- repo: https://github.com/commitizen-tools/commitizen
|
- repo: https://github.com/commitizen-tools/commitizen
|
||||||
rev: v3.29.1
|
rev: master
|
||||||
hooks:
|
hooks:
|
||||||
- id: commitizen
|
- id: commitizen
|
||||||
- id: commitizen-branch
|
- id: commitizen-branch
|
||||||
stages: [push]
|
stages: [push]
|
||||||
|
|
||||||
- repo: local
|
|
||||||
hooks:
|
|
||||||
- id: pytest
|
|
||||||
name: pytest
|
|
||||||
entry: ./.venv/bin/pytest tests
|
|
||||||
language: system
|
|
||||||
types: [python]
|
|
||||||
pass_filenames: false
|
|
||||||
always_run: true
|
|
||||||
|
|
|
@ -14,88 +14,221 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""A visual DSL for electromagnetic simulation design and analysis implemented as a Blender node editor."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from functools import reduce
|
"""A Blender-based system for electromagnetic simulation design and analysis, with deep Tidy3D integration.
|
||||||
|
|
||||||
from . import contracts as ct
|
# `bl_info`
|
||||||
|
`bl_info` declares information about the addon to Blender.
|
||||||
|
|
||||||
# from . import node_trees
|
However, it is not _dynamically_ read: Blender traverses it using `ast.parse`.
|
||||||
from . import operators, preferences, registration
|
This makes it difficult to synchronize `bl_info` with the project's `pyproject.toml`.
|
||||||
from .utils import logger
|
As a workaround, **the addon zip-packer will replace `bl_info` entries**.
|
||||||
|
|
||||||
log = logger.get(__name__)
|
The following `bl_info` entries are currently replaced when the ZIP is built:
|
||||||
|
|
||||||
|
- `description`: To match the description in `pyproject.toml`.
|
||||||
|
- `version`: To match the version in `pyproject.toml`.
|
||||||
|
|
||||||
|
For more information, see `scripts.pack.BL_INFO_REPLACEMENTS`.
|
||||||
|
|
||||||
|
**NOTE**: The find/replace procedure is "dumb" (aka. no regex, no `ast` traversal, etc.).
|
||||||
|
|
||||||
|
This is surprisingly robust, so long as use of the deterministic code-formatter `ruff fmt` is enforced.
|
||||||
|
|
||||||
|
Still. Be careful around `bl_info`.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
bl_info: Information about the addon declared to Blender.
|
||||||
|
BL_REGISTER_BEFORE_DEPS: Blender classes to register before dependencies are verified as installed.
|
||||||
|
BL_HOTKEYS: Blender keymap item defs to register before dependencies are verified as installed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .nodeps.utils import simple_logger
|
||||||
|
|
||||||
|
# Initialize Logging Defaults
|
||||||
|
## Initial logger settings (ex. log level) must be set somehow.
|
||||||
|
## The Addon ZIP-packer makes this decision, and packs it into files.
|
||||||
|
## AddonPreferences will, once loaded, override this.
|
||||||
|
_PATH_ADDON_ROOT = Path(__file__).resolve().parent
|
||||||
|
_PATH_BOOTSTRAP_LOG_LEVEL = _PATH_ADDON_ROOT / '.bootstrap_log_level'
|
||||||
|
with _PATH_BOOTSTRAP_LOG_LEVEL.open('r') as f:
|
||||||
|
_BOOTSTRAP_LOG_LEVEL = int(f.read().strip())
|
||||||
|
|
||||||
|
simple_logger.init_simple_logger_defaults(console_level=_BOOTSTRAP_LOG_LEVEL)
|
||||||
|
|
||||||
|
# Import Statements
|
||||||
|
import bpy # noqa: E402
|
||||||
|
|
||||||
|
from . import contracts as ct # noqa: E402
|
||||||
|
from . import preferences, registration # noqa: E402
|
||||||
|
from .nodeps import operators as nodeps_operators # noqa: E402
|
||||||
|
from .nodeps.utils import pydeps # noqa: E402
|
||||||
|
|
||||||
|
log = simple_logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Load and Register Addon
|
# - Load and Register Addon
|
||||||
####################
|
####################
|
||||||
BL_REGISTER: list[ct.BLClass] = [
|
BL_REGISTER_BEFORE_DEPS: list[ct.BLClass] = [
|
||||||
*operators.BL_REGISTER,
|
*nodeps_operators.BL_REGISTER,
|
||||||
# *node_trees.BL_REGISTER,
|
*preferences.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
||||||
BL_HANDLERS: ct.BLHandlers = reduce(
|
## TODO: BL_HANDLERS and BL_SOCKET_DEFS
|
||||||
lambda a, b: a + b,
|
|
||||||
[
|
|
||||||
operators.BL_HANDLERS,
|
|
||||||
# node_trees.BL_HANDLERS,
|
|
||||||
],
|
|
||||||
ct.BLHandlers(),
|
|
||||||
)
|
|
||||||
|
|
||||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
BL_HOTKEYS_BEFORE_DEPS: list[ct.KeymapItemDef] = [
|
||||||
*operators.BL_KEYMAP_ITEMS,
|
*nodeps_operators.BL_HOTKEYS,
|
||||||
# node_trees.BL_KEYMAP_ITEMS,
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def load_main_blclasses(path_pydeps: Path) -> list[ct.BLClass]:
|
||||||
|
"""Imports all addon classes that rely on Python dependencies.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
`sys.path` is modified while executing this function.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
path_pydeps: The path to the Python dependencies.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An ordered list of Blender classes to register.
|
||||||
|
"""
|
||||||
|
with pydeps.importable_addon_deps(path_pydeps):
|
||||||
|
from . import assets, node_trees, operators
|
||||||
|
return [
|
||||||
|
*operators.BL_REGISTER,
|
||||||
|
*assets.BL_REGISTER,
|
||||||
|
*node_trees.BL_REGISTER,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def load_main_blhotkeys(path_deps: Path) -> list[ct.KeymapItemDef]:
|
||||||
|
"""Imports all keymap item defs that rely on Python dependencies.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
`sys.path` is modified while executing this function.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
path_pydeps: The path to the Python dependencies.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An ordered list of Blender keymap item defs to register.
|
||||||
|
"""
|
||||||
|
with pydeps.importable_addon_deps(path_deps):
|
||||||
|
from . import assets, operators
|
||||||
|
return [
|
||||||
|
*operators.BL_HOTKEYS,
|
||||||
|
*assets.BL_HOTKEYS,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Registration
|
# - Registration
|
||||||
####################
|
####################
|
||||||
|
@bpy.app.handlers.persistent
|
||||||
|
def manage_pydeps(*_):
|
||||||
|
# ct.addon.operator(
|
||||||
|
# ct.OperatorType.ManagePyDeps,
|
||||||
|
# 'INVOKE_DEFAULT',
|
||||||
|
# path_addon_pydeps='',
|
||||||
|
# path_addon_reqs='',
|
||||||
|
# )
|
||||||
|
log.debug('PyDeps: Analyzing Post-File Load')
|
||||||
|
ct.addon.prefs().on_addon_pydeps_changed(show_popup_if_deps_invalid=True)
|
||||||
|
|
||||||
|
|
||||||
def register() -> None:
|
def register() -> None:
|
||||||
"""Implements addon registration in a way that respects the availability of addon preferences and loggers.
|
"""Implements a multi-stage addon registration, which accounts for Python dependency management.
|
||||||
|
|
||||||
|
# Multi-Stage Registration
|
||||||
|
The trouble is that many classes in our addon might require Python dependencies.
|
||||||
|
|
||||||
|
## Stage 1: Barebones Addon
|
||||||
|
Many classes in our addon might require Python dependencies.
|
||||||
|
However, they may not yet be installed.
|
||||||
|
|
||||||
|
To solve this bootstrapping problem in a streamlined manner, we only **guarantee** the registration of a few key classes, including:
|
||||||
|
|
||||||
|
- `AddonPreferences`: The addon preferences provide an interface for the user to fix Python dependency problems, thereby triggering subsequent stages.
|
||||||
|
- `InstallPyDeps`: An operator that installs missing Python dependencies, using Blender's embeded `pip`.
|
||||||
|
- `UninstallPyDeps`: An operator that uninstalls Python dependencies.
|
||||||
|
|
||||||
|
**These classes provide just enough interface to help the user install the missing Python dependencies**.
|
||||||
|
|
||||||
|
## Stage 2: Declare Delayed Registration
|
||||||
|
We may not be able to register any classes that rely on Python dependencies.
|
||||||
|
However, we can use `registration.delay_registration()` to **delay the registration until it is determined that the Python dependencies are satisfied**.`
|
||||||
|
|
||||||
|
For now, we just pass a callback that will import + return a list of classes to register (`load_main_blclasses()`) when the time comes.
|
||||||
|
|
||||||
|
## Stage 3: Trigger "PyDeps Changed"
|
||||||
|
The addon preferences is responsible for storing (and exposing to the user) the path to the Python dependencies.
|
||||||
|
|
||||||
|
Thus, the addon preferences method `on_addon_pydeps_changed()` has the responsibility for checking when the dependencies are valid, and running the delayed registrations (and any other delayed setup) in response.
|
||||||
|
In general, `on_addon_pydeps_changed()` runs whenever the PyDeps path is changed, but it can also be run manually.
|
||||||
|
|
||||||
|
As the last part of this process, that's exactly what `register()` does: Runs `on_addon_pydeps_changed()` manually.
|
||||||
|
Depending on the addon preferences (which persist), one of two things can happen:
|
||||||
|
|
||||||
|
1. **Deps Satisfied**: The addon will load without issue: The just-declared "delayed registrations" will run immediately, and all is well.
|
||||||
|
2. **Deps Not Satisfied**: The user must take action to fix the conflicts due to Python dependencies, before the addon can load. **A popup will show to help the user do so.
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
Called by Blender when enabling the addon.
|
Called by Blender when enabling the addon.
|
||||||
|
|
||||||
Raises:
|
|
||||||
RuntimeError: If addon preferences fail to register.
|
|
||||||
"""
|
"""
|
||||||
log.info('Registering Addon Preferences: %s', ct.addon.NAME)
|
log.info('Commencing Registration of Addon: %s', ct.addon.NAME)
|
||||||
registration.register_classes(preferences.BL_REGISTER)
|
bpy.app.handlers.load_post.append(manage_pydeps)
|
||||||
|
|
||||||
addon_prefs = ct.addon.prefs()
|
# Register Barebones Addon
|
||||||
if addon_prefs is not None:
|
## Contains all no-dependency BLClasses:
|
||||||
# Update Loggers
|
## - Contains AddonPreferences.
|
||||||
# - This updates existing loggers to use settings defined by preferences.
|
## Contains all BLClasses from 'nodeps'.
|
||||||
addon_prefs.on_addon_logging_changed()
|
registration.register_classes(BL_REGISTER_BEFORE_DEPS)
|
||||||
|
registration.register_hotkeys(BL_HOTKEYS_BEFORE_DEPS)
|
||||||
|
|
||||||
log.info('Registering Addon: %s', ct.addon.NAME)
|
# Delay Complete Registration until DEPS_SATISFIED
|
||||||
|
registration.delay_registration_until(
|
||||||
|
registration.BLRegisterEvent.DepsSatisfied,
|
||||||
|
then_register_classes=load_main_blclasses,
|
||||||
|
then_register_hotkeys=load_main_blhotkeys,
|
||||||
|
)
|
||||||
|
|
||||||
registration.register_classes(BL_REGISTER)
|
# Trigger PyDeps Check
|
||||||
registration.register_handlers(BL_HANDLERS)
|
## Deps ARE OK: Delayed registration will trigger.
|
||||||
registration.register_keymaps(BL_KEYMAP_ITEMS)
|
## Deps NOT OK: User must fix the pydeps, then trigger this method.
|
||||||
|
ct.addon.prefs().on_addon_pydeps_changed()
|
||||||
log.info('Finished Registration of Addon: %s', ct.addon.NAME)
|
|
||||||
else:
|
|
||||||
msg = 'Addon preferences did not register for addon {ct.addon.NAME} - something is very wrong!'
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def unregister() -> None:
|
def unregister() -> None:
|
||||||
"""Unregisters anything that was registered by the addon.
|
"""Unregisters anything that was registered by the addon.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
Run by Blender when disabling and/or uninstalling the addon.
|
Run by Blender when disabling the addon.
|
||||||
|
|
||||||
This doesn't clean `sys.modules`.
|
This doesn't clean `sys.modules`.
|
||||||
We rely on the hope that Blender has extension-extension module isolation.
|
To fully revert to Blender's state before the addon was in use (especially various import-related caches in the Python process), Blender must be restarted.
|
||||||
"""
|
"""
|
||||||
log.info('Starting %s Unregister', ct.addon.NAME)
|
log.info('Starting %s Unregister', ct.addon.NAME)
|
||||||
|
|
||||||
registration.unregister_keymaps()
|
|
||||||
registration.unregister_handlers()
|
|
||||||
registration.unregister_classes()
|
registration.unregister_classes()
|
||||||
|
registration.unregister_hotkeys()
|
||||||
|
registration.clear_delayed_registrations()
|
||||||
log.info('Finished %s Unregister', ct.addon.NAME)
|
log.info('Finished %s Unregister', ct.addon.NAME)
|
||||||
|
|
|
@ -14,32 +14,33 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Internal assets for use via the Python API and/or directly by the user as an asset library."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell Project Contributors
|
||||||
from functools import reduce
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
import oscillode.contracts as ct
|
# 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/>.
|
||||||
|
|
||||||
from . import geonodes
|
from . import geonodes
|
||||||
|
|
||||||
BL_REGISTER: list[ct.BLClass] = [
|
BL_REGISTER = [
|
||||||
*geonodes.BL_REGISTER,
|
*geonodes.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
||||||
BL_HANDLERS: ct.BLHandlers = reduce(
|
BL_HOTKEYS = [
|
||||||
lambda a, b: a + b,
|
*geonodes.BL_HOTKEYS,
|
||||||
[
|
|
||||||
geonodes.BL_HANDLERS,
|
|
||||||
],
|
|
||||||
ct.BLHandlers(),
|
|
||||||
)
|
|
||||||
|
|
||||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = [
|
|
||||||
*geonodes.BL_KEYMAP_ITEMS,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'BL_REGISTER',
|
'BL_REGISTER',
|
||||||
'BL_HANDLERS',
|
|
||||||
'BL_HOTKEYS',
|
'BL_HOTKEYS',
|
||||||
]
|
]
|
BIN
oscillode/assets/converters/tdsphere_to_kp.blend (Stored with Git LFS)
BIN
oscillode/assets/converters/tdsphere_to_kp.blend (Stored with Git LFS)
Binary file not shown.
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
"""Provides for the linking and/or appending of geometry nodes trees from vendored libraries included in Blender maxwell."""
|
"""Provides for the linking and/or appending of geometry nodes trees from vendored libraries included in Blender maxwell."""
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
@ -21,8 +37,8 @@ from pathlib import Path
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from oscillode import contracts as ct
|
from blender_maxwell import contracts as ct
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
@ -32,17 +48,17 @@ log = logger.get(__name__)
|
||||||
####################
|
####################
|
||||||
# GeoNodes Paths
|
# GeoNodes Paths
|
||||||
## Internal
|
## Internal
|
||||||
GN_INTERNAL_PATH: Path = ct.addon.PATH_ASSETS / 'internal'
|
GN_INTERNAL_PATH = ct.addon.PATH_ASSETS / 'internal'
|
||||||
GN_INTERNAL_INPUTS_PATH: Path = GN_INTERNAL_PATH / 'input'
|
GN_INTERNAL_INPUTS_PATH = GN_INTERNAL_PATH / 'input'
|
||||||
GN_INTERNAL_SOURCES_PATH: Path = GN_INTERNAL_PATH / 'source'
|
GN_INTERNAL_SOURCES_PATH = GN_INTERNAL_PATH / 'source'
|
||||||
GN_INTERNAL_STRUCTURES_PATH: Path = GN_INTERNAL_PATH / 'structure'
|
GN_INTERNAL_STRUCTURES_PATH = GN_INTERNAL_PATH / 'structure'
|
||||||
GN_INTERNAL_MONITORS_PATH: Path = GN_INTERNAL_PATH / 'monitor'
|
GN_INTERNAL_MONITORS_PATH = GN_INTERNAL_PATH / 'monitor'
|
||||||
GN_INTERNAL_SIMULATIONS_PATH: Path = GN_INTERNAL_PATH / 'simulation'
|
GN_INTERNAL_SIMULATIONS_PATH = GN_INTERNAL_PATH / 'simulation'
|
||||||
|
|
||||||
## Structures
|
## Structures
|
||||||
GN_STRUCTURES_PATH: Path = ct.addon.PATH_ASSETS / 'structures'
|
GN_STRUCTURES_PATH = ct.addon.PATH_ASSETS / 'structures'
|
||||||
GN_STRUCTURES_PRIMITIVES_PATH: Path = GN_STRUCTURES_PATH / 'primitives'
|
GN_STRUCTURES_PRIMITIVES_PATH = GN_STRUCTURES_PATH / 'primitives'
|
||||||
GN_STRUCTURES_ARRAYS_PATH: Path = GN_STRUCTURES_PATH / 'arrays'
|
GN_STRUCTURES_ARRAYS_PATH = GN_STRUCTURES_PATH / 'arrays'
|
||||||
|
|
||||||
|
|
||||||
class GeoNodes(enum.StrEnum):
|
class GeoNodes(enum.StrEnum):
|
||||||
|
@ -105,7 +121,7 @@ class GeoNodes(enum.StrEnum):
|
||||||
ArrayRing = 'array_ring'
|
ArrayRing = 'array_ring'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dedicated_node_type(self) -> str: ## TODO: How to correlate to node_tree?
|
def dedicated_node_type(self) -> ct.BLImportMethod:
|
||||||
"""Deduces the denode type that implements a vendored GeoNodes tree (usually just "GeoNodes Structure").
|
"""Deduces the denode type that implements a vendored GeoNodes tree (usually just "GeoNodes Structure").
|
||||||
|
|
||||||
Generally, "GeoNodes Structure' is the generic triangle-mesh node that can do everything.
|
Generally, "GeoNodes Structure' is the generic triangle-mesh node that can do everything.
|
||||||
|
@ -385,7 +401,7 @@ class GeoNodesToStructureNode(bpy.types.Operator):
|
||||||
####################
|
####################
|
||||||
def invoke(
|
def invoke(
|
||||||
self, context: bpy.types.Context, _: bpy.types.Event
|
self, context: bpy.types.Context, _: bpy.types.Event
|
||||||
) -> ct.BLOperatorStatus:
|
) -> set[ct.BLOperatorStatus]:
|
||||||
"""Commences the drag-and-drop of a GeoNodes asset.
|
"""Commences the drag-and-drop of a GeoNodes asset.
|
||||||
|
|
||||||
- Starts the modal timer, which listens for a mouse-release event.
|
- Starts the modal timer, which listens for a mouse-release event.
|
||||||
|
@ -474,10 +490,10 @@ class GeoNodesToStructureNode(bpy.types.Operator):
|
||||||
## 3. We compute it manually, to avoid the jank.
|
## 3. We compute it manually, to avoid the jank.
|
||||||
node_location = get_view_location(
|
node_location = get_view_location(
|
||||||
editor_region,
|
editor_region,
|
||||||
(
|
[
|
||||||
event.mouse_x - editor_region.x,
|
event.mouse_x - editor_region.x,
|
||||||
event.mouse_y - editor_region.y,
|
event.mouse_y - editor_region.y,
|
||||||
),
|
],
|
||||||
context.preferences.system.ui_scale,
|
context.preferences.system.ui_scale,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -526,8 +542,8 @@ ASSET_LIB_SPECS: dict[str, Path] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@bpy.app.handlers.persistent # type: ignore[misc]
|
@bpy.app.handlers.persistent
|
||||||
def initialize_asset_libraries(_: bpy.types.Scene) -> None:
|
def initialize_asset_libraries(_: bpy.types.Scene):
|
||||||
"""Before loading a `.blend` file, ensure that the WindowManager properties relied on by NodeAssetPanel are available.
|
"""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.
|
- Several asset libraries, defined under the global `ASSET_LIB_SPECS`, are added/replaced such that the name:path map is respected.
|
||||||
|
@ -580,11 +596,11 @@ def initialize_asset_libraries(_: bpy.types.Scene) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
bpy.app.handlers.load_pre.append(initialize_asset_libraries)
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
NodeAssetPanel,
|
NodeAssetPanel,
|
||||||
GeoNodesToStructureNode,
|
GeoNodesToStructureNode,
|
||||||
]
|
]
|
||||||
|
|
||||||
BL_HANDLERS: ct.BLHandlers = ct.BLHandlers(load_pre=(initialize_asset_libraries,))
|
BL_HOTKEYS = []
|
||||||
|
|
||||||
BL_KEYMAP_ITEMS: list[ct.BLKeymapItem] = []
|
|
BIN
oscillode/assets/primitives/arrow.blend (Stored with Git LFS)
BIN
oscillode/assets/primitives/arrow.blend (Stored with Git LFS)
Binary file not shown.
|
@ -14,7 +14,21 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Independent constants and types, which represent a kind of 'social contract' governing communication between all components of the addon."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from . import addon
|
from . import addon
|
||||||
from .bl import (
|
from .bl import (
|
||||||
|
@ -22,30 +36,24 @@ from .bl import (
|
||||||
BLColorRGBA,
|
BLColorRGBA,
|
||||||
BLEnumElement,
|
BLEnumElement,
|
||||||
BLEnumID,
|
BLEnumID,
|
||||||
BLEventType,
|
|
||||||
BLEventValue,
|
|
||||||
BLIcon,
|
BLIcon,
|
||||||
BLIconSet,
|
BLIconSet,
|
||||||
BLIDStruct,
|
BLIDStruct,
|
||||||
BLImportMethod,
|
BLImportMethod,
|
||||||
|
BLKeymapItem,
|
||||||
BLModifierType,
|
BLModifierType,
|
||||||
BLNodeTreeInterfaceID,
|
BLNodeTreeInterfaceID,
|
||||||
BLOperatorStatus,
|
BLOperatorStatus,
|
||||||
BLPropFlag,
|
BLPropFlag,
|
||||||
BLRegionType,
|
BLRegionType,
|
||||||
BLSpaceType,
|
BLSpaceType,
|
||||||
|
KeymapItemDef,
|
||||||
ManagedObjName,
|
ManagedObjName,
|
||||||
PresetName,
|
PresetName,
|
||||||
PropName,
|
PropName,
|
||||||
SocketName,
|
SocketName,
|
||||||
)
|
)
|
||||||
from .bl_handlers import BLHandlers
|
from .bl_types import BLEnumStrEnum
|
||||||
from .bl_keymap import BLKeymapItem
|
|
||||||
from .icons import Icon
|
|
||||||
from .mobj_types import ManagedObjType
|
|
||||||
from .node_tree_types import (
|
|
||||||
NodeTreeType,
|
|
||||||
)
|
|
||||||
from .operator_types import (
|
from .operator_types import (
|
||||||
OperatorType,
|
OperatorType,
|
||||||
)
|
)
|
||||||
|
@ -59,8 +67,6 @@ __all__ = [
|
||||||
'BLColorRGBA',
|
'BLColorRGBA',
|
||||||
'BLEnumElement',
|
'BLEnumElement',
|
||||||
'BLEnumID',
|
'BLEnumID',
|
||||||
'BLEventType',
|
|
||||||
'BLEventValue',
|
|
||||||
'BLIcon',
|
'BLIcon',
|
||||||
'BLIconSet',
|
'BLIconSet',
|
||||||
'BLIDStruct',
|
'BLIDStruct',
|
||||||
|
@ -74,15 +80,12 @@ __all__ = [
|
||||||
'BLSpaceType',
|
'BLSpaceType',
|
||||||
'KeymapItemDef',
|
'KeymapItemDef',
|
||||||
'ManagedObjName',
|
'ManagedObjName',
|
||||||
'ManagedObjType',
|
|
||||||
'PresetName',
|
'PresetName',
|
||||||
'PropName',
|
'PropName',
|
||||||
'SocketName',
|
'SocketName',
|
||||||
'BLHandlers',
|
'BLEnumStrEnum',
|
||||||
'Icon',
|
|
||||||
'BLInstance',
|
'BLInstance',
|
||||||
'InstanceID',
|
'InstanceID',
|
||||||
'NodeTreeType',
|
|
||||||
'OperatorType',
|
'OperatorType',
|
||||||
'PanelType',
|
'PanelType',
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,82 +14,105 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Basic 'single-source-of-truth' static and dynamic information about this addon.
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
Information is mined both from `bpy`, and from the addon's bundled manifest file.
|
import sys
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import tomllib
|
import tomllib
|
||||||
import typing as typ
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import bpy_restrict_state
|
||||||
|
|
||||||
PATH_ADDON_ROOT = Path(__file__).resolve().parent.parent
|
PATH_ADDON_ROOT = Path(__file__).resolve().parent.parent
|
||||||
PATH_MANIFEST = PATH_ADDON_ROOT / 'blender_manifest.toml'
|
with (PATH_ADDON_ROOT / 'pyproject.toml').open('rb') as f:
|
||||||
|
PROJ_SPEC = tomllib.load(f)
|
||||||
|
## bl_info is filled with PROJ_SPEC when packing the .zip.
|
||||||
|
|
||||||
with PATH_MANIFEST.open('rb') as f:
|
NAME = PROJ_SPEC['project']['name']
|
||||||
MANIFEST = tomllib.load(f)
|
VERSION = PROJ_SPEC['project']['version']
|
||||||
|
|
||||||
NAME: str = MANIFEST['id']
|
|
||||||
VERSION: str = MANIFEST['version']
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Assets
|
# - Assets
|
||||||
####################
|
####################
|
||||||
PATH_ASSETS: Path = PATH_ADDON_ROOT / 'assets'
|
PATH_ASSETS = PATH_ADDON_ROOT / 'assets'
|
||||||
|
|
||||||
if 'RUNNING_BLEXT_TESTS' in os.environ:
|
####################
|
||||||
PATH_CACHE: Path = (
|
# - PyDeps Info
|
||||||
PATH_ADDON_ROOT.parent / 'dev' / 'local'
|
####################
|
||||||
) ## TODO: Consult init_settings
|
PATH_REQS = PATH_ADDON_ROOT / 'requirements.lock'
|
||||||
else:
|
DEFAULT_PATH_DEPS = PATH_ADDON_ROOT / '.addon_dependencies'
|
||||||
PATH_CACHE: Path = Path(bpy.utils.extension_path_user(__package__, create=True)) # type: ignore[no-redef]
|
DEFAULT_PATH_DEPS.mkdir(exist_ok=True)
|
||||||
|
## requirements.lock is written when packing the .zip.
|
||||||
|
## By default, the addon pydeps are kept in the addon dir.
|
||||||
|
|
||||||
|
ORIGINAL_SYS_PATH = sys.path.copy()
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Local Addon Cache
|
||||||
|
####################
|
||||||
|
DEFAULT_ADDON_CACHE = PATH_ADDON_ROOT / '.addon_cache'
|
||||||
|
DEFAULT_ADDON_CACHE.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
PIP_INSTALL_LOG = DEFAULT_ADDON_CACHE / 'pip_install.log'
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Dynamic Addon Information
|
# - Dynamic Addon Information
|
||||||
####################
|
####################
|
||||||
def operator(
|
def is_loading() -> bool:
|
||||||
name: str, *operator_args: list[typ.Any], **operator_kwargs: dict[str, typ.Any]
|
"""Checks whether the addon is currently loading.
|
||||||
) -> None:
|
|
||||||
"""Convenienve method to call an operator from this addon.
|
|
||||||
|
|
||||||
This avoids having to use `bpy.ops.<addon_name>.operator_name`, which isn't generic.
|
While an addon is loading, `bpy.context` is temporarily very limited.
|
||||||
|
For example, operators can't run while the addon is loading.
|
||||||
|
|
||||||
Only operators from this addon may be called using this method.
|
By checking whether `bpy.context` is limited like this, we can determine whether the addon is currently loading.
|
||||||
|
|
||||||
Raises:
|
Notes:
|
||||||
ValueError: If an addon from outside this operator is attempted to be used.
|
Since `bpy_restrict_state._RestrictContext` is a very internal thing, this function may be prone to breakage on Blender updates.
|
||||||
|
|
||||||
|
**Keep an eye out**!
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Whether the addon has been fully loaded, such that `bpy.context` is fully accessible.
|
||||||
"""
|
"""
|
||||||
|
return isinstance(bpy.context, bpy_restrict_state._RestrictContext)
|
||||||
|
|
||||||
|
|
||||||
|
def operator(name: str, *operator_args, **operator_kwargs) -> None:
|
||||||
# Parse Operator Name
|
# Parse Operator Name
|
||||||
operator_namespace, operator_name = name.split('.')
|
operator_namespace, operator_name = name.split('.')
|
||||||
if operator_namespace != NAME:
|
if operator_namespace != NAME:
|
||||||
msg = f'Tried to call operator {operator_name}, but addon operators may only use the addon operator namespace "{operator_namespace}.<name>"'
|
msg = f'Tried to call operator {operator_name}, but addon operators may only use the addon operator namespace "{operator_namespace}.<name>"'
|
||||||
raise ValueError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
# Run Operator
|
# Addon Not Loading: Run Operator
|
||||||
bl_operator = getattr(getattr(bpy.ops, NAME), operator_name)
|
if not is_loading():
|
||||||
bl_operator(*operator_args, **operator_kwargs)
|
operator = getattr(getattr(bpy.ops, NAME), operator_name)
|
||||||
## TODO: Can't we constrain 'name' to be an OperatorType somehow?
|
operator(*operator_args, **operator_kwargs)
|
||||||
|
else:
|
||||||
|
msg = f'Tried to call operator "{operator_name}" while addon is loading'
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
|
||||||
def prefs() -> bpy.types.AddonPreferences | None:
|
def prefs() -> bpy.types.AddonPreferences | None:
|
||||||
"""Retrieve the preferences of this addon, if they are available yet.
|
if (addon := bpy.context.preferences.addons.get(NAME)) is None:
|
||||||
|
msg = 'Addon is not installed'
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
Notes:
|
|
||||||
While registering the addon, one may wish to use the addon preferences.
|
|
||||||
This isn't possible - not even for default values.
|
|
||||||
|
|
||||||
Either a bad idea is at work, or `oscillode.utils.init_settings` should be consulted until the preferences are available.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The addon preferences, if the addon is registered and loaded - otherwise None.
|
|
||||||
"""
|
|
||||||
addon = bpy.context.preferences.addons.get(NAME)
|
|
||||||
if addon is None:
|
|
||||||
return None
|
|
||||||
return addon.preferences
|
return addon.preferences
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,21 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Explicit type annotations for Blender objects, making it easier to guarantee correctness in communications with Blender."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
@ -95,6 +109,7 @@ BLIDStruct: typ.TypeAlias = (
|
||||||
| bpy.types.WorkSpace
|
| bpy.types.WorkSpace
|
||||||
| bpy.types.World
|
| bpy.types.World
|
||||||
)
|
)
|
||||||
|
BLKeymapItem: typ.TypeAlias = typ.Any ## TODO: Better Type
|
||||||
BLPropFlag: typ.TypeAlias = typ.Literal[
|
BLPropFlag: typ.TypeAlias = typ.Literal[
|
||||||
'HIDDEN',
|
'HIDDEN',
|
||||||
'SKIP_SAVE',
|
'SKIP_SAVE',
|
||||||
|
@ -111,24 +126,6 @@ BLColorRGBA = tuple[float, float, float, float]
|
||||||
####################
|
####################
|
||||||
# - Operators
|
# - 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[
|
BLSpaceType: typ.TypeAlias = typ.Literal[
|
||||||
'EMPTY',
|
'EMPTY',
|
||||||
'VIEW_3D',
|
'VIEW_3D',
|
||||||
|
@ -150,151 +147,32 @@ BLSpaceType: typ.TypeAlias = typ.Literal[
|
||||||
'SPREADSHEET',
|
'SPREADSHEET',
|
||||||
'PREFERENCES',
|
'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[
|
BLOperatorStatus: typ.TypeAlias = set[
|
||||||
typ.Literal['RUNNING_MODAL', 'CANCELLED', 'FINISHED', 'PASS_THROUGH', 'INTERFACE']
|
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
|
# - Addon Types
|
||||||
####################
|
####################
|
||||||
|
KeymapItemDef: typ.TypeAlias = typ.Any
|
||||||
ManagedObjName = str
|
ManagedObjName = str
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
# 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, ...] = ()
|
|
||||||
## TODO: Verify these type signatures.
|
|
||||||
|
|
||||||
## TODO: A validator to check that all handlers are decorated with bpy.app.handlers.persistent
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Properties
|
|
||||||
####################
|
|
||||||
@staticproperty # type: ignore[arg-type]
|
|
||||||
def handler_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)
|
|
|
@ -1,60 +0,0 @@
|
||||||
# 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?
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Enum (w/EnumProperty support)
|
||||||
|
####################
|
||||||
|
class BLEnumStrEnum(typ.Protocol):
|
||||||
|
@staticmethod
|
||||||
|
def to_name(value: typ.Self) -> str: ...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_icon(value: typ.Self) -> str: ...
|
|
@ -1,28 +0,0 @@
|
||||||
# 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/>.
|
|
||||||
|
|
||||||
"""Provides identifiers for node trees defined by this addon."""
|
|
||||||
|
|
||||||
import enum
|
|
||||||
|
|
||||||
from oscillode.utils import blender_type_enum
|
|
||||||
|
|
||||||
|
|
||||||
@blender_type_enum.append_cls_name_to_values
|
|
||||||
class NodeTreeType(blender_type_enum.BlenderTypeEnum):
|
|
||||||
"""Identifiers for addon-defined node trees."""
|
|
||||||
|
|
||||||
MaxwellSim = enum.auto()
|
|
|
@ -14,12 +14,27 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Provides identifiers for Blender operators defined by this addon."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
|
"""Defines Operator Types as an enum, making it easy for any part of the addon to refer to any operator."""
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from oscillode.utils import blender_type_enum
|
from ..nodeps.utils import blender_type_enum
|
||||||
|
|
||||||
from .addon import NAME as ADDON_NAME
|
from .addon import NAME as ADDON_NAME
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,27 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
"""Defines Panel Types as an enum, making it easy for any part of the addon to refer to any panel."""
|
"""Defines Panel Types as an enum, making it easy for any part of the addon to refer to any panel."""
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from oscillode.utils import blender_type_enum
|
from blender_maxwell.nodeps.utils import blender_type_enum
|
||||||
|
|
||||||
from .addon import NAME as ADDON_NAME
|
from .addon import NAME as ADDON_NAME
|
||||||
|
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
# 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/>.
|
|
||||||
|
|
||||||
"""Provides the base protocol on which all ManagedObjs are derived, as well as explicit protocols describing common features supported by some `ManagedObjs`."""
|
|
||||||
|
|
||||||
import abc
|
|
||||||
import typing as typ
|
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, serialize
|
|
||||||
|
|
||||||
from .. import contracts as ct
|
|
||||||
|
|
||||||
log = logger.get(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ManagedObj(typ.Protocol):
|
|
||||||
"""A weak name-based reference to some kind of object external to this software.
|
|
||||||
|
|
||||||
While the object doesn't have to come from Blender's `bpy.types`, that is the driving motivation for this class: To encapsulate access to the powerful visual tools granted by Blender's 3D viewport, image editor, and UI.
|
|
||||||
Through extensive trial-and-error, this transparently-cached immediate-mode interface has emerged as the best compromise.
|
|
||||||
|
|
||||||
While not suited to all use cases, the `ManagedObj` paradigm is ideal for the common situation of 'node ownership of external logic'.
|
|
||||||
For example, a plotting node needs access to its own image buffer; however, for it to be displayable, that image buffer must be owned by Blender.
|
|
||||||
This is where `ManagedObj` provides the ability of the plotting node to "loosely own" a particular Blender image, which both allows the user to see/interact with the image as a typical Blender image, but also allows the node to drive ex. lifecycle (like removing the image plot when the node is deleted).
|
|
||||||
|
|
||||||
This approach of loose name-coupling is not perfect. To name a few examples:
|
|
||||||
|
|
||||||
- A particular challenge is that of identifying and namespacing managed datablocks. The user may, for example, change the name of an object - and what do we do then? Is generating new data under the now-vacant name a feature? Or is it a systematic memory leak backed by dangling fake-owned datablocks?
|
|
||||||
- The precise definition of "loose ownership" is itself a matter of taste. Stronger ownership presumptions allow for stronger guarantees and simpler caching - but at the cost of more brittle breaks when the underlying objects are manipulated in ways we don't expect.
|
|
||||||
- `.blend` persistance is not the default when it comes to certain Blender objects, which raises deeper UX questions about how opinionated we should be about where users put data.
|
|
||||||
- Solving this doesn't help actually deal with data. There's a lot of very specific nuance in every single data pipeline, and that complexity is only added to watever this approach incurs.
|
|
||||||
|
|
||||||
This abstract base class serves to provide a few of the most basic of commonly-available operations.
|
|
||||||
In particular, implementations of `dump_as_msgspec`/`parse_as_msgspec` are enforced, for use with `oscillode.utils.serialize`.
|
|
||||||
This way, ex. opening a `.blend` file will allow a newly-deserialized `ManagedObj` to re-attach transparently to the also-persisted underlying datablock.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
managed_obj_type: Enum identifier indicating which of the `ct.ManagedObjType` the instance should declare itself as.
|
|
||||||
"""
|
|
||||||
|
|
||||||
managed_obj_type: ct.ManagedObjType
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def __init__(self, name: ct.ManagedObjName, prev_name: str | None = None):
|
|
||||||
"""Initializes the managed object with a unique name.
|
|
||||||
|
|
||||||
Use `prev_name` to indicate that the managed object will initially be avaiable under `prev_name`, but that it should be renamed to `name`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Properties
|
|
||||||
####################
|
|
||||||
@property
|
|
||||||
@abc.abstractmethod
|
|
||||||
def name(self) -> str:
|
|
||||||
"""Retrieve the name of the managed object."""
|
|
||||||
|
|
||||||
@name.setter
|
|
||||||
@abc.abstractmethod
|
|
||||||
def name(self, value: str) -> None:
|
|
||||||
"""Retrieve the name of the managed object."""
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Methods
|
|
||||||
####################
|
|
||||||
@abc.abstractmethod
|
|
||||||
def free(self) -> None:
|
|
||||||
"""Cleanup the resources managed by the managed object."""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def hide_preview(self) -> None:
|
|
||||||
"""Hide any active preview of the managed object, if it exists, and if such an operation makes sense."""
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Serialization
|
|
||||||
####################
|
|
||||||
def dump_as_msgspec(self) -> serialize.NaiveRepresentation:
|
|
||||||
"""Bijectively transform this managed object into a 'naive representation' that uses only basic Python types, which may be serialized cleanly."""
|
|
||||||
return [
|
|
||||||
serialize.TypeID.ManagedObj,
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.name,
|
|
||||||
]
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self:
|
|
||||||
"""Bijectively construct an instance of this managed object from the 'naive representation', which may have been deserialized into."""
|
|
||||||
return next(
|
|
||||||
subclass(obj[2])
|
|
||||||
for subclass in ManagedObj.__subclasses__()
|
|
||||||
if subclass.__name__ == obj[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Support Flags
|
|
||||||
####################
|
|
||||||
class SupportsBlenderSelect(typ.Protocol):
|
|
||||||
"""Protocol guaranteeing the ability to select the object in Blender."""
|
|
||||||
|
|
||||||
def bl_select(self) -> None:
|
|
||||||
"""Select the managed object in Blender."""
|
|
||||||
|
|
||||||
|
|
||||||
class Supportsreview(typ.Protocol):
|
|
||||||
"""Protocol guaranteeing support for previewing the object."""
|
|
||||||
|
|
||||||
def show_preview(self) -> None:
|
|
||||||
"""Shows a preview of the managed object."""
|
|
||||||
|
|
||||||
def hide_preview(self) -> None:
|
|
||||||
"""Hide any active preview of the managed object, if it exists."""
|
|
|
@ -38,6 +38,7 @@ Attributes:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from blender_maxwell.utils import logger as _logger
|
from blender_maxwell.utils import logger as _logger
|
||||||
|
|
||||||
from . import contracts as ct
|
from . import contracts as ct
|
||||||
|
@ -45,8 +46,6 @@ from . import sockets
|
||||||
|
|
||||||
log = _logger.get(__name__)
|
log = _logger.get(__name__)
|
||||||
|
|
||||||
## TODO: Coordinate w/refactor of managed modifiers; for example, the contents of this file would be ideally specified as the implementation of a Protocol, for the particular case of this node tree.
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender -> Socket Def(s)
|
# - Blender -> Socket Def(s)
|
||||||
|
|
|
@ -38,9 +38,6 @@ import nodeitems_utils
|
||||||
from . import contracts as ct
|
from . import contracts as ct
|
||||||
from .nodes import BL_NODES
|
from .nodes import BL_NODES
|
||||||
|
|
||||||
## TODO: Completely refactor this file, and rename it to reflect that it doesn't define or implement any categories - it simply, dumbly, implements the menu.
|
|
||||||
## - Actually; we could delete this file by refactoring it, implementing the logic in a utils/ module, then running the dangling registration as a rote-registration matter in __init__.py.
|
|
||||||
|
|
||||||
DYNAMIC_SUBMENU_REGISTRATIONS = []
|
DYNAMIC_SUBMENU_REGISTRATIONS = []
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,7 +117,7 @@ BL_REGISTER = [*DYNAMIC_SUBMENU_REGISTRATIONS] ## Must be run after, right now.
|
||||||
|
|
||||||
|
|
||||||
def menu_draw(self, context):
|
def menu_draw(self, context):
|
||||||
if context.space_data.tree_type == ct.NodeTreeType.MaxwellSim.value:
|
if context.space_data.tree_type == ct.TreeType.MaxwellSim.value:
|
||||||
for nodeitem_or_submenu in BL_NODE_CATEGORIES:
|
for nodeitem_or_submenu in BL_NODE_CATEGORIES:
|
||||||
if isinstance(nodeitem_or_submenu, str):
|
if isinstance(nodeitem_or_submenu, str):
|
||||||
submenu_id = nodeitem_or_submenu
|
submenu_id = nodeitem_or_submenu
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
# 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 blender_maxwell.contracts import (
|
from blender_maxwell.contracts import (
|
||||||
UNITS_BLENDER,
|
|
||||||
UNITS_TIDY3D,
|
|
||||||
BLClass,
|
BLClass,
|
||||||
BLColorRGBA,
|
BLColorRGBA,
|
||||||
BLEnumElement,
|
BLEnumElement,
|
||||||
|
@ -47,11 +45,8 @@ from blender_maxwell.contracts import (
|
||||||
BLPropFlag,
|
BLPropFlag,
|
||||||
BLRegionType,
|
BLRegionType,
|
||||||
BLSpaceType,
|
BLSpaceType,
|
||||||
Icon,
|
|
||||||
KeymapItemDef,
|
KeymapItemDef,
|
||||||
ManagedObjName,
|
ManagedObjName,
|
||||||
ManagedObjType,
|
|
||||||
NodeTreeType,
|
|
||||||
OperatorType,
|
OperatorType,
|
||||||
PanelType,
|
PanelType,
|
||||||
PresetName,
|
PresetName,
|
||||||
|
@ -77,6 +72,8 @@ from .flow_kinds import (
|
||||||
ValueFlow,
|
ValueFlow,
|
||||||
)
|
)
|
||||||
from .flow_signals import FlowSignal
|
from .flow_signals import FlowSignal
|
||||||
|
from .icons import Icon
|
||||||
|
from .mobj_types import ManagedObjType
|
||||||
from .node_types import NodeType
|
from .node_types import NodeType
|
||||||
from .sim_types import (
|
from .sim_types import (
|
||||||
BoundCondType,
|
BoundCondType,
|
||||||
|
@ -93,6 +90,8 @@ from .sim_types import (
|
||||||
)
|
)
|
||||||
from .socket_colors import SOCKET_COLORS
|
from .socket_colors import SOCKET_COLORS
|
||||||
from .socket_types import SocketType
|
from .socket_types import SocketType
|
||||||
|
from .tree_types import TreeType
|
||||||
|
from .unit_systems import UNITS_BLENDER, UNITS_TIDY3D
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'BLClass',
|
'BLClass',
|
||||||
|
@ -109,17 +108,16 @@ __all__ = [
|
||||||
'BLPropFlag',
|
'BLPropFlag',
|
||||||
'BLRegionType',
|
'BLRegionType',
|
||||||
'BLSpaceType',
|
'BLSpaceType',
|
||||||
'Icon',
|
|
||||||
'KeymapItemDef',
|
'KeymapItemDef',
|
||||||
'ManagedObjName',
|
'ManagedObjName',
|
||||||
'ManagedObjType',
|
|
||||||
'NodeTreeType',
|
|
||||||
'OperatorType',
|
'OperatorType',
|
||||||
'PanelType',
|
'PanelType',
|
||||||
'PresetName',
|
'PresetName',
|
||||||
'PropName',
|
'PropName',
|
||||||
'SocketName',
|
'SocketName',
|
||||||
'addon',
|
'addon',
|
||||||
|
'Icon',
|
||||||
|
'TreeType',
|
||||||
'SocketType',
|
'SocketType',
|
||||||
'SOCKET_COLORS',
|
'SOCKET_COLORS',
|
||||||
'SOCKET_SHAPES',
|
'SOCKET_SHAPES',
|
||||||
|
@ -141,6 +139,7 @@ __all__ = [
|
||||||
'manual_amp_time',
|
'manual_amp_time',
|
||||||
'NodeCategory',
|
'NodeCategory',
|
||||||
'NODE_CAT_LABELS',
|
'NODE_CAT_LABELS',
|
||||||
|
'ManagedObjType',
|
||||||
'FlowEvent',
|
'FlowEvent',
|
||||||
'ArrayFlow',
|
'ArrayFlow',
|
||||||
'CapabilitiesFlow',
|
'CapabilitiesFlow',
|
||||||
|
|
|
@ -14,6 +14,21 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
|
@ -24,6 +39,8 @@ import bpy
|
||||||
import jax
|
import jax
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
## TODO: Unify w/category_types.py
|
|
||||||
|
|
||||||
from .category_types import NodeCategory as NC # noqa: N817
|
from .category_types import NodeCategory as NC # noqa: N817
|
||||||
|
|
||||||
NODE_CAT_LABELS = {
|
NODE_CAT_LABELS = {
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from .array import ArrayFlow
|
from .array import ArrayFlow
|
||||||
from .capabilities import CapabilitiesFlow
|
from .capabilities import CapabilitiesFlow
|
||||||
from .flow_kinds import FlowKind
|
from .flow_kinds import FlowKind
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import functools
|
import functools
|
||||||
import io
|
import io
|
||||||
|
@ -22,13 +38,14 @@ import typing as typ
|
||||||
import jax
|
import jax
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
import jaxtyping as jtyp
|
import jaxtyping as jtyp
|
||||||
|
import numpy as np
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.jaxarray import JaxArrayBytes
|
from blender_maxwell.utils.jaxarray import JaxArrayBytes
|
||||||
from oscillode.utils.lru_method import method_lru
|
from blender_maxwell.utils.lru_method import method_lru
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
|
@ -14,8 +14,25 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
from types import MappingProxyType
|
||||||
|
|
||||||
from ..socket_types import SocketType
|
from ..socket_types import SocketType
|
||||||
from .flow_kinds import FlowKind
|
from .flow_kinds import FlowKind
|
|
@ -14,7 +14,21 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
# TODO: Consider moving this to the new math system.
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
|
@ -14,14 +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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
from oscillode.contracts import BLEnumElement
|
from blender_maxwell.contracts import BLEnumElement
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.staticproperty import staticproperty
|
from blender_maxwell.utils.staticproperty import staticproperty
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
|
@ -36,10 +36,10 @@ import typing as typ
|
||||||
|
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from oscillode.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.frozendict import FrozenDict, frozendict
|
from blender_maxwell.utils.frozendict import FrozenDict, frozendict
|
||||||
from oscillode.utils.lru_method import method_lru
|
from blender_maxwell.utils.lru_method import method_lru
|
||||||
|
|
||||||
from .array import ArrayFlow
|
from .array import ArrayFlow
|
||||||
from .lazy_range import RangeFlow
|
from .lazy_range import RangeFlow
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
r"""Implements the core of the math system via `FuncFlow`, which allows high-performance, fully-expressive workflows with data that can be "very large", and/or whose input parameters are not yet fully known.
|
r"""Implements the core of the math system via `FuncFlow`, which allows high-performance, fully-expressive workflows with data that can be "very large", and/or whose input parameters are not yet fully known.
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
@ -219,16 +235,17 @@ But above all, we hope that this math system is fun, practical, and maybe even i
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
from types import MappingProxyType
|
||||||
|
|
||||||
import jax
|
import jax
|
||||||
import jaxtyping as jtyp
|
import jaxtyping as jtyp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from oscillode.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.frozendict import FrozenDict, frozendict
|
from blender_maxwell.utils.frozendict import FrozenDict, frozendict
|
||||||
from oscillode.utils.lru_method import method_lru
|
from blender_maxwell.utils.lru_method import method_lru
|
||||||
|
|
||||||
from .array import ArrayFlow
|
from .array import ArrayFlow
|
||||||
from .info import InfoFlow
|
from .info import InfoFlow
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
@ -23,10 +39,10 @@ import jaxtyping as jtyp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from oscillode.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.frozendict import frozendict
|
from blender_maxwell.utils.frozendict import frozendict
|
||||||
from oscillode.utils.lru_method import method_lru
|
from blender_maxwell.utils.lru_method import method_lru
|
||||||
|
|
||||||
from .array import ArrayFlow
|
from .array import ArrayFlow
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
@ -23,10 +39,10 @@ import jaxtyping as jtyp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from oscillode.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from oscillode.utils.frozendict import FrozenDict, frozendict
|
from blender_maxwell.utils.frozendict import FrozenDict, frozendict
|
||||||
from oscillode.utils.lru_method import method_lru
|
from blender_maxwell.utils.lru_method import method_lru
|
||||||
|
|
||||||
from .array import ArrayFlow
|
from .array import ArrayFlow
|
||||||
from .expr_info import ExprInfo
|
from .expr_info import ExprInfo
|
|
@ -14,12 +14,28 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
IMAGE_AREA_TYPE = 'IMAGE_EDITOR'
|
IMAGE_AREA_TYPE = 'IMAGE_EDITOR'
|
||||||
IMAGE_SPACE_TYPE = 'IMAGE_EDITOR'
|
IMAGE_SPACE_TYPE = 'IMAGE_EDITOR'
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
|
@ -14,14 +14,26 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Provides an enum that semantically constrains the use of icons throughout the addon."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
|
|
||||||
class Icon(enum.StrEnum):
|
class Icon(enum.StrEnum):
|
||||||
"""Identifiers for icons used throughout this addon."""
|
|
||||||
|
|
||||||
# Node Tree
|
# Node Tree
|
||||||
SimNodeEditor = 'MOD_SIMPLEDEFORM'
|
SimNodeEditor = 'MOD_SIMPLEDEFORM'
|
||||||
|
|
|
@ -14,16 +14,28 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Provides identifiers for objects in Blender that are managed on behalf of the user, for use by the addon, in order to provide a safe and streamlined integration of more complex data representations that flow between the addon and Blender."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from oscillode.utils import blender_type_enum
|
from blender_maxwell.utils import blender_type_enum
|
||||||
|
|
||||||
|
|
||||||
class ManagedObjType(blender_type_enum.BlenderTypeEnum):
|
class ManagedObjType(blender_type_enum.BlenderTypeEnum):
|
||||||
"""Identifiers for 'managed objects', which encapsulates a particular Blender object and provides alternative semantics more suited to the needs of this addon."""
|
|
||||||
|
|
||||||
ManagedBLImage = enum.auto()
|
ManagedBLImage = enum.auto()
|
||||||
|
|
||||||
ManagedBLCollection = enum.auto()
|
ManagedBLCollection = enum.auto()
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from blender_maxwell.utils import blender_type_enum
|
from blender_maxwell.utils import blender_type_enum
|
||||||
|
|
|
@ -36,6 +36,7 @@ import dataclasses
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
from fractions import Fraction
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
|
@ -44,6 +45,7 @@ import numpy as np
|
||||||
import polars as pl
|
import polars as pl
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.contracts import BLEnumElement
|
from blender_maxwell.contracts import BLEnumElement
|
||||||
from blender_maxwell.services import tdcloud
|
from blender_maxwell.services import tdcloud
|
||||||
from blender_maxwell.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
|
@ -51,8 +53,6 @@ from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
from .flow_kinds.info import InfoFlow
|
from .flow_kinds.info import InfoFlow
|
||||||
|
|
||||||
## TODO: Use a Protocol interface from data_pipelines/
|
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,23 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Socket base colors for Maxwell Sim sockets."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from .socket_types import SocketType as ST # noqa: N817
|
from .socket_types import SocketType as ST
|
||||||
|
|
||||||
## TODO: Don't just presume sRGB.
|
## TODO: Don't just presume sRGB.
|
||||||
SOCKET_COLORS = {
|
SOCKET_COLORS = {
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from blender_maxwell.utils import blender_type_enum
|
from blender_maxwell.utils import blender_type_enum
|
||||||
|
@ -21,8 +37,6 @@ from blender_maxwell.utils import blender_type_enum
|
||||||
|
|
||||||
@blender_type_enum.append_cls_name_to_values
|
@blender_type_enum.append_cls_name_to_values
|
||||||
class SocketType(blender_type_enum.BlenderTypeEnum):
|
class SocketType(blender_type_enum.BlenderTypeEnum):
|
||||||
"""Identifiers for valid sockets in Maxwell Sim node trees."""
|
|
||||||
|
|
||||||
Expr = enum.auto()
|
Expr = enum.auto()
|
||||||
|
|
||||||
# Base
|
# Base
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
|
import enum
|
||||||
|
|
||||||
|
from blender_maxwell.utils import blender_type_enum
|
||||||
|
|
||||||
|
|
||||||
|
@blender_type_enum.append_cls_name_to_values
|
||||||
|
class TreeType(blender_type_enum.BlenderTypeEnum):
|
||||||
|
MaxwellSim = enum.auto()
|
|
@ -14,7 +14,23 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Provides particular pre-defined unit systems for use by the addon.
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
|
"""Specifies unit systems for use in the node tree.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
UNITS_BLENDER: A unit system that serves as a reasonable default for the a 3D workspace that interprets the results of electromagnetic simulations.
|
UNITS_BLENDER: A unit system that serves as a reasonable default for the a 3D workspace that interprets the results of electromagnetic simulations.
|
||||||
|
@ -29,7 +45,7 @@ import typing as typ
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
from frozendict import frozendict
|
from frozendict import frozendict
|
||||||
|
|
||||||
from oscillode.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Unit Systems
|
# - Unit Systems
|
|
@ -14,10 +14,29 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Provides various useful managed objects, which enables the clean and safe use of objects external to this addon."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from .base import ManagedObj
|
from .base import ManagedObj
|
||||||
|
|
||||||
|
# from .managed_bl_empty import ManagedBLEmpty
|
||||||
from .managed_bl_image import ManagedBLImage
|
from .managed_bl_image import ManagedBLImage
|
||||||
|
|
||||||
|
# from .managed_bl_collection import ManagedBLCollection
|
||||||
|
# from .managed_bl_object import ManagedBLObject
|
||||||
from .managed_bl_mesh import ManagedBLMesh
|
from .managed_bl_mesh import ManagedBLMesh
|
||||||
|
|
||||||
# from .managed_bl_volume import ManagedBLVolume
|
# from .managed_bl_volume import ManagedBLVolume
|
||||||
|
@ -25,8 +44,13 @@ from .managed_bl_modifier import ManagedBLModifier
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'ManagedObj',
|
'ManagedObj',
|
||||||
|
#'ManagedBLEmpty',
|
||||||
'ManagedBLImage',
|
'ManagedBLImage',
|
||||||
|
#'ManagedBLCollection',
|
||||||
|
#'ManagedBLObject',
|
||||||
'ManagedBLMesh',
|
'ManagedBLMesh',
|
||||||
#'ManagedBLVolume',
|
#'ManagedBLVolume',
|
||||||
'ManagedBLModifier',
|
'ManagedBLModifier',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
## REMEMBER: Add the appropriate entry to the bl_cache.DECODER
|
|
@ -0,0 +1,111 @@
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
from blender_maxwell.utils import logger, serialize
|
||||||
|
|
||||||
|
from .. import contracts as ct
|
||||||
|
|
||||||
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ManagedObj(abc.ABC):
|
||||||
|
"""A weak name-based reference to some kind of object external to this software.
|
||||||
|
|
||||||
|
While the object doesn't have to come from Blender's `bpy.types`, that is admittedly the driving motivation for this class: To encapsulate access to the powerful visual tools granted by Blender's 3D viewport, image editor, and UI.
|
||||||
|
Through extensive testing, the functionality of an implicitly-cached, semi-strictly immediate-mode interface, demanding only a weakly-referenced name as persistance, has emerged (with all of the associated tradeoffs).
|
||||||
|
|
||||||
|
While not suited to all use cases, the `ManagedObj` paradigm is perfect for many situations where a node needs to "loosely own" something external and non-trivial.
|
||||||
|
Intriguingly, the precise definition of "loose" has grown to vary greatly between subclasses, as it ends of demonstrating itself to be a matter of taste more than determinism.
|
||||||
|
|
||||||
|
This abstract base class serves to provide a few of the most basic of commonly-available - especially the `dump_as_msgspec`/`parse_as_msgspec` methods that allow it to be persisted using `blender_maxwell.utils.serialize`.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
managed_obj_type: Enum identifier indicating which of the `ct.ManagedObjType` the instance should declare itself as.
|
||||||
|
"""
|
||||||
|
|
||||||
|
managed_obj_type: ct.ManagedObjType
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def __init__(self, name: ct.ManagedObjName, prev_name: str | None = None):
|
||||||
|
"""Initializes the managed object with a unique name.
|
||||||
|
|
||||||
|
Use `prev_name` to indicate that the managed object will initially be avaiable under `prev_name`, but that it should be renamed to `name`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
@property
|
||||||
|
@abc.abstractmethod
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Retrieve the name of the managed object."""
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
@abc.abstractmethod
|
||||||
|
def name(self, value: str) -> None:
|
||||||
|
"""Retrieve the name of the managed object."""
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Methods
|
||||||
|
####################
|
||||||
|
@abc.abstractmethod
|
||||||
|
def free(self) -> None:
|
||||||
|
"""Cleanup the resources managed by the managed object."""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def bl_select(self) -> None:
|
||||||
|
"""Select the managed object in Blender, if such an operation makes sense."""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def hide_preview(self) -> None:
|
||||||
|
"""Hide any active preview of the managed object, if it exists, and if such an operation makes sense."""
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Serialization
|
||||||
|
####################
|
||||||
|
def dump_as_msgspec(self) -> serialize.NaiveRepresentation:
|
||||||
|
return [
|
||||||
|
serialize.TypeID.ManagedObj,
|
||||||
|
self.__class__.__name__,
|
||||||
|
self.name,
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self:
|
||||||
|
return next(
|
||||||
|
subclass(obj[2])
|
||||||
|
for subclass in ManagedObj.__subclasses__()
|
||||||
|
if subclass.__name__ == obj[1]
|
||||||
|
)
|
|
@ -32,12 +32,12 @@
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
MANAGED_COLLECTION_NAME = 'Oscillode'
|
MANAGED_COLLECTION_NAME = 'BLMaxwell'
|
||||||
PREVIEW_COLLECTION_NAME = 'Oscillode Visible'
|
PREVIEW_COLLECTION_NAME = 'BLMaxwell Visible'
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
|
@ -0,0 +1,32 @@
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
|
@ -14,7 +14,23 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""Declares an object encapsulating access to a Blender image datablock from this addon."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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 `ManagedBLImage`."""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
@ -23,17 +39,15 @@ import bpy
|
||||||
import matplotlib.axis as mpl_ax
|
import matplotlib.axis as mpl_ax
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from oscillode.utils import image_ops, logger
|
from blender_maxwell.utils import image_ops, logger
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
from . import base
|
from . import base
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
AREA_TYPE: ct.BLSpaceType = (
|
AREA_TYPE = 'IMAGE_EDITOR'
|
||||||
'IMAGE_EDITOR' ##TODO: Is SpaceType different than AreaType?
|
SPACE_TYPE = 'IMAGE_EDITOR'
|
||||||
)
|
|
||||||
SPACE_TYPE: ct.BLSpaceType = 'IMAGE_EDITOR'
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -46,7 +60,7 @@ class ManagedBLImage(base.ManagedObj):
|
||||||
name: The name of the image.
|
name: The name of the image.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
managed_obj_type: str = ct.ManagedObjType.ManagedBLImage
|
managed_obj_type = ct.ManagedObjType.ManagedBLImage
|
||||||
_bl_image_name: str
|
_bl_image_name: str
|
||||||
|
|
||||||
def __init__(self, name: str, prev_name: str | None = None):
|
def __init__(self, name: str, prev_name: str | None = None):
|
||||||
|
@ -172,7 +186,6 @@ class ManagedBLImage(base.ManagedObj):
|
||||||
####################
|
####################
|
||||||
# - Methods
|
# - Methods
|
||||||
####################
|
####################
|
||||||
## TODO: Rename to show_preview()
|
|
||||||
def bl_select(self) -> None:
|
def bl_select(self) -> None:
|
||||||
"""Selects the image by loading it into an on-screen UI area/space.
|
"""Selects the image by loading it into an on-screen UI area/space.
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
import bmesh
|
import bmesh
|
||||||
|
@ -21,7 +37,7 @@ import bpy
|
||||||
import jax
|
import jax
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
from . import base
|
from . import base
|
|
@ -14,9 +14,23 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
"""A managed Blender modifier, associated with some Blender object."""
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
## TODO: Make a common core for modifier manipulation, then specify each modifier as a seperate ManagedObj.
|
"""A managed Blender modifier, associated with some Blender object."""
|
||||||
|
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
@ -24,7 +38,7 @@ import bpy
|
||||||
import jax
|
import jax
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
from .. import bl_socket_map
|
from .. import bl_socket_map
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
@ -126,7 +140,7 @@ def write_modifier_geonodes(
|
||||||
modifier_altered = True
|
modifier_altered = True
|
||||||
## TODO: More fine-grained alterations?
|
## TODO: More fine-grained alterations?
|
||||||
|
|
||||||
return modifier_altered
|
return modifier_altered # noqa: RET504
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -156,8 +170,6 @@ def write_modifier(
|
||||||
# - ManagedObj
|
# - ManagedObj
|
||||||
####################
|
####################
|
||||||
class ManagedBLModifier(base.ManagedObj):
|
class ManagedBLModifier(base.ManagedObj):
|
||||||
"""Manages a particular modifier attached to a Blender mesh also managed by this construction."""
|
|
||||||
|
|
||||||
managed_obj_type = ct.ManagedObjType.ManagedBLModifier
|
managed_obj_type = ct.ManagedObjType.ManagedBLModifier
|
||||||
_modifier_name: str | None = None
|
_modifier_name: str | None = None
|
||||||
twin_bl_mesh: ManagedBLMesh | None = None
|
twin_bl_mesh: ManagedBLMesh | None = None
|
|
@ -14,13 +14,32 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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 `ManagedBLText`."""
|
"""Declares `ManagedBLText`."""
|
||||||
|
|
||||||
|
import time
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import matplotlib.axis as mpl_ax
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from oscillode.utils import logger
|
from blender_maxwell.utils import image_ops, logger
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
from . import base
|
from . import base
|
||||||
|
@ -35,10 +54,10 @@ SPACE_TYPE = 'IMAGE_EDITOR'
|
||||||
# - Managed BL Image
|
# - Managed BL Image
|
||||||
####################
|
####################
|
||||||
class ManagedBLText(base.ManagedObj):
|
class ManagedBLText(base.ManagedObj):
|
||||||
"""Represents a Blender text datablock, encapsulating various useful interactions with it.
|
"""Represents a Blender Image datablock, encapsulating various useful interactions with it.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
name: The name of the text datablock.
|
name: The name of the image.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
managed_obj_type = ct.ManagedObjType.ManagedBLText
|
managed_obj_type = ct.ManagedObjType.ManagedBLText
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
|
|
||||||
import jax.lax as jlax
|
import jax.lax as jlax
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
@ -157,7 +158,7 @@ class FilterOperation(enum.StrEnum):
|
||||||
## -> Mathematically valid (I suppose) for 2. But not so useful.
|
## -> Mathematically valid (I suppose) for 2. But not so useful.
|
||||||
# if any(
|
# if any(
|
||||||
# (dim.has_idx_discrete(dim) or dim.has_idx_labels(dim))
|
# (dim.has_idx_discrete(dim) or dim.has_idx_labels(dim))
|
||||||
# and len(dim_idx) > 5
|
# and len(dim_idx) > 5 # noqa: PLR2004
|
||||||
# for dim, dim_idx in info.dims.items()
|
# for dim, dim_idx in info.dims.items()
|
||||||
# ):
|
# ):
|
||||||
# ops += [FO.ZScore15, FO.ZScore30]
|
# ops += [FO.ZScore15, FO.ZScore30]
|
|
@ -39,6 +39,7 @@ import jax.numpy as jnp
|
||||||
import jaxtyping as jtyp
|
import jaxtyping as jtyp
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -39,6 +39,7 @@ import typing as typ
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ PT = spux.PhysicalType
|
||||||
# for ax_l, ax_r in itertools.zip_longest(
|
# for ax_l, ax_r in itertools.zip_longest(
|
||||||
# expanded_shape_l, expanded_shape_r, fillvalue=1
|
# expanded_shape_l, expanded_shape_r, fillvalue=1
|
||||||
# ):
|
# ):
|
||||||
# if ax_l == 1 or ax_r == 1 or ax_l == ax_r:
|
# if ax_l == 1 or ax_r == 1 or ax_l == ax_r: # noqa: PLR1714
|
||||||
# new_shape.append(max([ax_l, ax_r]))
|
# new_shape.append(max([ax_l, ax_r]))
|
||||||
# else:
|
# else:
|
||||||
# return None
|
# return None
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
import jaxtyping as jtyp
|
import jaxtyping as jtyp
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, sim_symbols
|
from blender_maxwell.utils import logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
import jaxtyping as jtyp
|
import jaxtyping as jtyp
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import logger, sci_constants, sim_symbols
|
from blender_maxwell.utils import logger, sci_constants, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -14,17 +14,33 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
# TODO: Factor this stuff into a dedicated utils/ module, so that this particular node tree becomes simple (aka. the deathly complicated logic is factored out, and can be ex. unit tested all on its own).
|
# blender_maxwell
|
||||||
## - Then this file can focus on what is special about a Maxwell Sim node tree, as opposed to the lower-level details of how we've chosen to structure our node trees in general.
|
# Copyright (C) 2024 blender_maxwell Project Contributors
|
||||||
## - Right now there may not be a distinction. And there may never be. But it's a healthy way to think about the problem.
|
#
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import functools
|
||||||
import queue
|
import queue
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from blender_maxwell.utils import logger
|
|
||||||
|
from blender_maxwell.utils import logger, serialize
|
||||||
|
|
||||||
from . import contracts as ct
|
from . import contracts as ct
|
||||||
|
from .managed_objs.managed_bl_image import ManagedBLImage
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
@ -304,7 +320,7 @@ class MaxwellSimTree(bpy.types.NodeTree):
|
||||||
In general, only one `MaxwellSimTree` should be active at a time.
|
In general, only one `MaxwellSimTree` should be active at a time.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bl_idname = ct.NodeTreeType.MaxwellSim.value
|
bl_idname = ct.TreeType.MaxwellSim.value
|
||||||
bl_label = 'Maxwell Sim Editor'
|
bl_label = 'Maxwell Sim Editor'
|
||||||
bl_icon = ct.Icon.SimNodeEditor
|
bl_icon = ct.Icon.SimNodeEditor
|
||||||
|
|
||||||
|
@ -312,8 +328,6 @@ class MaxwellSimTree(bpy.types.NodeTree):
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
viewer_node_type: ct.NodeType = ct.NodeType.Viewer
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Init Methods
|
# - Init Methods
|
||||||
####################
|
####################
|
||||||
|
@ -538,8 +552,7 @@ def populate_missing_persistence(_) -> None:
|
||||||
for node_tree in [
|
for node_tree in [
|
||||||
_node_tree
|
_node_tree
|
||||||
for _node_tree in bpy.data.node_groups
|
for _node_tree in bpy.data.node_groups
|
||||||
if _node_tree.bl_idname == ct.NodeTreeType.MaxwellSim.value
|
if _node_tree.bl_idname == ct.TreeType.MaxwellSim.value and _node_tree.is_active
|
||||||
and _node_tree.is_active
|
|
||||||
]:
|
]:
|
||||||
log.debug(
|
log.debug(
|
||||||
'%s: Regenerating Dynamic Field Persistance for NodeTree nodes/sockets',
|
'%s: Regenerating Dynamic Field Persistance for NodeTree nodes/sockets',
|
||||||
|
|
|
@ -14,6 +14,22 @@
|
||||||
# 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/>.
|
||||||
|
|
||||||
|
# blender_maxwell
|
||||||
|
# Copyright (C) 2024 blender_maxwell 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/>.
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
analysis,
|
analysis,
|
||||||
inputs,
|
inputs,
|
||||||
|
|
|
@ -41,6 +41,7 @@ import jax.numpy as jnp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
import xarray
|
import xarray
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
|
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
|
@ -37,6 +37,7 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ See `blender_maxwell.maxwell_sim_nodes.math_system` for the actual mathematics i
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ import bpy
|
||||||
import jax
|
import jax
|
||||||
import jax.numpy as jnp
|
import jax.numpy as jnp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
|
|
||||||
from .... import contracts as ct
|
from .... import contracts as ct
|
||||||
|
|
|
@ -37,6 +37,7 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,10 @@ import jaxtyping as jtyp
|
||||||
import matplotlib.axis as mpl_ax
|
import matplotlib.axis as mpl_ax
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
from frozendict import frozendict
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, image_ops, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, image_ops, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from frozendict import frozendict
|
|
||||||
|
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
from ... import managed_objs, sockets
|
from ... import managed_objs, sockets
|
||||||
|
|
|
@ -43,6 +43,7 @@ from collections import defaultdict
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, bl_instance, logger
|
from blender_maxwell.utils import bl_cache, bl_instance, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
@ -1195,7 +1196,7 @@ class MaxwellSimNode(bpy.types.Node, bl_instance.BLInstance):
|
||||||
Returns:
|
Returns:
|
||||||
Whether or not the node can be instantiated within the given node tree.
|
Whether or not the node can be instantiated within the given node tree.
|
||||||
"""
|
"""
|
||||||
return node_tree.bl_idname == ct.NodeTreeType.MaxwellSim
|
return node_tree.bl_idname == ct.TreeType.MaxwellSim.value
|
||||||
|
|
||||||
def init(self, _: bpy.types.Context) -> None:
|
def init(self, _: bpy.types.Context) -> None:
|
||||||
"""Initialize the node instance, including ID, name, socket, presets, and the execution of any `on_value_changed` methods with the `run_on_init` keyword set.
|
"""Initialize the node instance, including ID, name, socket, presets, and the execution of any `on_value_changed` methods with the `run_on_init` keyword set.
|
||||||
|
|
|
@ -36,11 +36,14 @@ import typing as typ
|
||||||
import uuid
|
import uuid
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
from types import MappingProxyType
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import jax
|
import jax
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from blender_maxwell.utils.frozendict import FrozenDict, frozendict
|
from blender_maxwell.utils.frozendict import FrozenDict, frozendict
|
||||||
|
|
|
@ -36,9 +36,10 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
from frozendict import frozendict
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, sci_constants, sim_symbols
|
from blender_maxwell.utils import bl_cache, sci_constants, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
from frozendict import frozendict
|
|
||||||
|
|
||||||
from .... import contracts as ct
|
from .... import contracts as ct
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
|
|
|
@ -38,6 +38,7 @@ from fractions import Fraction
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ from pathlib import Path
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ from pathlib import Path
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
|
|
||||||
from .... import contracts as ct
|
from .... import contracts as ct
|
||||||
|
|
|
@ -37,6 +37,7 @@ import typing as typ
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
@ -145,8 +146,7 @@ def update_scene_node_after_frame_changed(
|
||||||
for node_tree in [
|
for node_tree in [
|
||||||
_node_tree
|
_node_tree
|
||||||
for _node_tree in bpy.data.node_groups
|
for _node_tree in bpy.data.node_groups
|
||||||
if _node_tree.bl_idname == ct.NodeTreeType.MaxwellSim.value
|
if _node_tree.bl_idname == ct.TreeType.MaxwellSim.value and _node_tree.is_active
|
||||||
and _node_tree.is_active
|
|
||||||
]:
|
]:
|
||||||
for node in [
|
for node in [
|
||||||
_node
|
_node
|
||||||
|
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.services import tdcloud
|
from blender_maxwell.services import tdcloud
|
||||||
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
from blender_maxwell.utils import bl_cache, logger, sim_symbols
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -40,11 +40,12 @@ import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
from blender_maxwell.utils import bl_cache, logger, sci_constants
|
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
|
||||||
from tidy3d.material_library.material_library import MaterialItem as Tidy3DMediumItem
|
from tidy3d.material_library.material_library import MaterialItem as Tidy3DMediumItem
|
||||||
from tidy3d.material_library.material_library import VariantItem as Tidy3DMediumVariant
|
from tidy3d.material_library.material_library import VariantItem as Tidy3DMediumVariant
|
||||||
|
|
||||||
|
from blender_maxwell.utils import bl_cache, logger, sci_constants
|
||||||
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
from ... import managed_objs, sockets
|
from ... import managed_objs, sockets
|
||||||
from .. import base, events
|
from .. import base, events
|
||||||
|
|
|
@ -36,6 +36,7 @@ import functools
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import typing as typ
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import bpy
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
import tidy3d.plugins.dispersion as td_dispersion
|
import tidy3d.plugins.dispersion as td_dispersion
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -39,6 +39,7 @@ import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -34,6 +34,7 @@ import typing as typ
|
||||||
|
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
from blender_maxwell.assets.geonodes import GeoNodes, import_geonodes
|
||||||
from blender_maxwell.utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
|
@ -34,6 +34,7 @@ import typing as typ
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from blender_maxwell.utils import bl_cache, logger
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
from blender_maxwell.utils import sympy_extra as spux
|
from blender_maxwell.utils import sympy_extra as spux
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue