feat: Re-Implemented Unit System Node (+ other fixes)

main
Sofus Albert Høgsbro Rose 2024-03-22 10:12:14 +01:00
parent f54a9031e8
commit 74e79649fb
Signed by: so-rose
GPG Key ID: AD901CB0F3701434
5 changed files with 79 additions and 96 deletions

View File

@ -1,21 +1,22 @@
from . import wave_constant from . import (
# from . import unit_system constants,
unit_system,
wave_constant,
web_importers,
)
from . import constants
from . import web_importers
# from . import file_importers # from . import file_importers
BL_REGISTER = [ BL_REGISTER = [
*wave_constant.BL_REGISTER, *wave_constant.BL_REGISTER,
# *unit_system.BL_REGISTER, *unit_system.BL_REGISTER,
*constants.BL_REGISTER, *constants.BL_REGISTER,
*web_importers.BL_REGISTER, *web_importers.BL_REGISTER,
# *file_importers.BL_REGISTER, # *file_importers.BL_REGISTER,
] ]
BL_NODES = { BL_NODES = {
**wave_constant.BL_NODES, **wave_constant.BL_NODES,
# **unit_system.BL_NODES, **unit_system.BL_NODES,
**constants.BL_NODES, **constants.BL_NODES,
**web_importers.BL_NODES, **web_importers.BL_NODES,
# *file_importers.BL_REGISTER, # *file_importers.BL_REGISTER,

View File

@ -1,11 +1,7 @@
import bpy
import sympy as sp
from ... import contracts as ct from ... import contracts as ct
from ... import sockets from ... import sockets
from .. import base from .. import base
class PhysicalUnitSystemNode(base.MaxwellSimNode): class PhysicalUnitSystemNode(base.MaxwellSimNode):
node_type = ct.NodeType.UnitSystem node_type = ct.NodeType.UnitSystem
bl_label = 'Unit System' bl_label = 'Unit System'
@ -26,7 +22,7 @@ class PhysicalUnitSystemNode(base.MaxwellSimNode):
'Unit System', 'Unit System',
input_sockets={'Unit System'}, input_sockets={'Unit System'},
) )
def compute_value(self, input_sockets) -> dict: def compute_unit_system(self, input_sockets) -> dict:
return input_sockets['Unit System'] return input_sockets['Unit System']

View File

@ -1,16 +1,14 @@
import typing as typ
import bpy import bpy
import sympy as sp
import sympy.physics.units as spu
import pydantic as pyd import pydantic as pyd
from .....utils.pydantic_sympy import SympyExpr from .....utils.pydantic_sympy import SympyExpr
from .. import base
from ... import contracts as ct from ... import contracts as ct
from .. import base
ST = ct.SocketType ST = ct.SocketType
SU = lambda socket_type: ct.SOCKET_UNITS[socket_type]['values'] def SU(socket_type): # noqa: N802, D103
return ct.SOCKET_UNITS[socket_type]['values']
#################### ####################
@ -195,58 +193,69 @@ class PhysicalUnitSystemBLSocket(base.MaxwellSimSocket):
def draw_value(self, col: bpy.types.UILayout) -> None: def draw_value(self, col: bpy.types.UILayout) -> None:
if self.show_definition: if self.show_definition:
# TODO: We need panels instead of rows!! row = col.row()
col_row = col.row(align=False) row.alignment = 'CENTER'
col_row.alignment = 'EXPAND' row.label(text='Time | Angle')
col_row.prop(self, 'unit_time', text='') col.prop(self, 'unit_time', text='t')
col_row.prop(self, 'unit_angle', text='') col.prop(self, 'unit_angle', text='θ')
col.separator(factor=1.0)
col_row = col.row(align=False) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.prop(self, 'unit_length', text='') row.label(text='Len | Area | Vol')
col_row.prop(self, 'unit_area', text='') col.prop(self, 'unit_length', text='l')
col_row.prop(self, 'unit_volume', text='') col.prop(self, 'unit_area', text='')
col.prop(self, 'unit_volume', text='')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.label(text='Point') row.label(text='Point')
col_row.prop(self, 'unit_point_2d', text='') col.prop(self, 'unit_point_2d', text='P₂')
col_row.prop(self, 'unit_point_3d', text='') col.prop(self, 'unit_point_3d', text='P₃')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.label(text='Size') row.label(text='Size')
col_row.prop(self, 'unit_size_2d', text='') col.prop(self, 'unit_size_2d', text='S₂')
col_row.prop(self, 'unit_size_3d', text='') col.prop(self, 'unit_size_3d', text='S₃')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.label(text='Mass') row.label(text='Mass')
col_row.prop(self, 'unit_mass', text='') col.prop(self, 'unit_mass', text='M')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.label(text='Vel') row.label(text='Vel')
col_row.prop(self, 'unit_speed', text='') col.prop(self, 'unit_speed', text='|v|')
# col_row.prop(self, "unit_vel_2d_vector", text="") # col.prop(self, "unit_vel_2d_vector", text="")
# col_row.prop(self, "unit_vel_3d_vector", text="") # col.prop(self, "unit_vel_3d_vector", text="")
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.label(text='Accel') row.alignment = 'CENTER'
col_row.prop(self, 'unit_accel_scalar', text='') row.label(text='Accel')
# col_row.prop(self, "unit_accel_2d_vector", text="") col.prop(self, 'unit_accel_scalar', text='|a|')
col_row.prop(self, 'unit_accel_3d', text='') # col.prop(self, "unit_accel_2d_vector", text="")
col.prop(self, 'unit_accel_3d', text='a₃')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.label(text='Force') row.alignment = 'CENTER'
col_row.prop(self, 'unit_force_scalar', text='') row.label(text='Force')
# col_row.prop(self, "unit_force_2d_vector", text="") col.prop(self, 'unit_force_scalar', text='|F|')
col_row.prop(self, 'unit_force_3d', text='') # col.prop(self, "unit_force_2d_vector", text="")
col.prop(self, 'unit_force_3d', text='F₃')
col.separator(factor=1.0)
col_row = col.row(align=True) row = col.row()
col_row.alignment = 'EXPAND' row.alignment = 'CENTER'
col_row.label(text='Freq') row.label(text='Freq')
col_row.prop(self, 'unit_freq', text='') col.prop(self, 'unit_freq', text='t⁽⁻¹⁾')
#################### ####################
# - Default Value # - Default Value

View File

@ -17,8 +17,8 @@ log = simple_logger.get(__name__)
# - Preferences # - Preferences
#################### ####################
class BLMaxwellAddonPrefs(bpy.types.AddonPreferences): class BLMaxwellAddonPrefs(bpy.types.AddonPreferences):
"""Manages user preferences and settings for the Blender Maxwell addon. """Manages user preferences and settings for the Blender Maxwell addon."""
"""
bl_idname = info.ADDON_NAME ## MUST match addon package name bl_idname = info.ADDON_NAME ## MUST match addon package name
#################### ####################

View File

@ -29,10 +29,6 @@ IS_ONLINE = False
IS_AUTHENTICATED = False IS_AUTHENTICATED = False
def is_online():
return IS_ONLINE
def set_online(): def set_online():
global IS_ONLINE # noqa: PLW0603 global IS_ONLINE # noqa: PLW0603
IS_ONLINE = True IS_ONLINE = True
@ -99,8 +95,7 @@ class TidyCloudFolders:
raise RuntimeError(msg) from ex raise RuntimeError(msg) from ex
folders = { folders = {
cloud_folder.folder_id: cloud_folder cloud_folder.folder_id: cloud_folder for cloud_folder in cloud_folders
for cloud_folder in cloud_folders
} }
cls.cache_folders = folders cls.cache_folders = folders
return folders return folders
@ -117,9 +112,7 @@ class TidyCloudFolders:
set_online() set_online()
except td.exceptions.WebError as ex: except td.exceptions.WebError as ex:
set_offline() set_offline()
msg = ( msg = 'Tried to create cloud folder, but cannot connect to cloud'
'Tried to create cloud folder, but cannot connect to cloud'
)
raise RuntimeError(msg) from ex raise RuntimeError(msg) from ex
if cls.cache_folders is None: if cls.cache_folders is None:
@ -184,9 +177,7 @@ class TidyCloudTasks:
""" """
cache_tasks: typ.ClassVar[dict[CloudTaskID, CloudTask]] = {} cache_tasks: typ.ClassVar[dict[CloudTaskID, CloudTask]] = {}
cache_folder_tasks: typ.ClassVar[ cache_folder_tasks: typ.ClassVar[dict[CloudFolderID, set[CloudTaskID]]] = {}
dict[CloudFolderID, set[CloudTaskID]]
] = {}
cache_task_info: typ.ClassVar[dict[CloudTaskID, CloudTaskInfo]] = {} cache_task_info: typ.ClassVar[dict[CloudTaskID, CloudTaskInfo]] = {}
@classmethod @classmethod
@ -208,9 +199,7 @@ class TidyCloudTasks:
def tasks(cls, cloud_folder: CloudFolder) -> dict[CloudTaskID, CloudTask]: def tasks(cls, cloud_folder: CloudFolder) -> dict[CloudTaskID, CloudTask]:
"""Get all cloud tasks within a particular cloud folder as a set.""" """Get all cloud tasks within a particular cloud folder as a set."""
# Retrieve Cached Tasks # Retrieve Cached Tasks
if ( if (task_ids := cls.cache_folder_tasks.get(cloud_folder.folder_id)) is not None:
task_ids := cls.cache_folder_tasks.get(cloud_folder.folder_id)
) is not None:
return {task_id: cls.cache_tasks[task_id] for task_id in task_ids} return {task_id: cls.cache_tasks[task_id] for task_id in task_ids}
# Retrieve Tasks by-Folder # Retrieve Tasks by-Folder
@ -219,9 +208,7 @@ class TidyCloudTasks:
set_online() set_online()
except td.exceptions.WebError as ex: except td.exceptions.WebError as ex:
set_offline() set_offline()
msg = ( msg = 'Tried to get tasks of a cloud folder, but cannot access cloud'
'Tried to get tasks of a cloud folder, but cannot access cloud'
)
raise RuntimeError(msg) from ex raise RuntimeError(msg) from ex
# No Tasks: Empty Set # No Tasks: Empty Set
@ -231,9 +218,7 @@ class TidyCloudTasks:
# Populate Caches # Populate Caches
## Direct Task Cache ## Direct Task Cache
cloud_tasks = { cloud_tasks = {cloud_task.task_id: cloud_task for cloud_task in folder_tasks}
cloud_task.task_id: cloud_task for cloud_task in folder_tasks
}
cls.cache_tasks |= cloud_tasks cls.cache_tasks |= cloud_tasks
## Task Info Cache ## Task Info Cache
@ -242,9 +227,7 @@ class TidyCloudTasks:
task_name=cloud_task.taskName, task_name=cloud_task.taskName,
status=cloud_task.status, status=cloud_task.status,
created_at=cloud_task.created_at, created_at=cloud_task.created_at,
cost_est=functools.partial( cost_est=functools.partial(td_web.estimate_cost, cloud_task.task_id),
td_web.estimate_cost, cloud_task.task_id
),
run_info=cloud_task.get_running_info, run_info=cloud_task.get_running_info,
callback_url=cloud_task.callback_url, callback_url=cloud_task.callback_url,
) )
@ -314,18 +297,14 @@ class TidyCloudTasks:
task_name=cloud_task.taskName, task_name=cloud_task.taskName,
status=cloud_task.status, status=cloud_task.status,
created_at=cloud_task.created_at, created_at=cloud_task.created_at,
cost_est=functools.partial( cost_est=functools.partial(td_web.estimate_cost, cloud_task.task_id),
td_web.estimate_cost, cloud_task.task_id
),
run_info=cloud_task.get_running_info, run_info=cloud_task.get_running_info,
callback_url=cloud_task.callback_url, callback_url=cloud_task.callback_url,
) )
## Task by-Folder Cache ## Task by-Folder Cache
if cls.cache_folder_tasks.get(cloud_task.folder_id): if cls.cache_folder_tasks.get(cloud_task.folder_id):
cls.cache_folder_tasks[cloud_task.folder_id].add( cls.cache_folder_tasks[cloud_task.folder_id].add(cloud_task.task_id)
cloud_task.task_id
)
else: else:
cls.cache_folder_tasks[cloud_task.folder_id] = {cloud_task.task_id} cls.cache_folder_tasks[cloud_task.folder_id] = {cloud_task.task_id}
@ -379,9 +358,7 @@ class TidyCloudTasks:
return cls.tasks(cloud_folder)[task_id] return cls.tasks(cloud_folder)[task_id]
@classmethod @classmethod
def update_tasks( def update_tasks(cls, folder_id: CloudFolderID) -> dict[CloudTaskID, CloudTask]:
cls, folder_id: CloudFolderID
) -> dict[CloudTaskID, CloudTask]:
"""Updates the CloudTask to the latest ex. status attributes.""" """Updates the CloudTask to the latest ex. status attributes."""
# BUG: td_web.core.task_core.SimulationTask.get(task_id) doesn't return the `created_at` field. # BUG: td_web.core.task_core.SimulationTask.get(task_id) doesn't return the `created_at` field.
## Therefore, we unfortunately need to get all tasks for the folder ID just to update one. ## Therefore, we unfortunately need to get all tasks for the folder ID just to update one.