Skip to content

Commit

Permalink
[EDITOR & SERVER] EDITOR-NTUEELightDance#520 (NTUEELightDance#527)
Browse files Browse the repository at this point in the history
* add dancer layer to LED map

* auto create effects when adding color

* support new led map structure

* attach led effects to models and allow model used by multiple dancers

* support new led map and model-dancer structure in editor
  • Loading branch information
tom1484 authored and ppg0921 committed Feb 19, 2024
1 parent dbc649b commit 85d6e9a
Show file tree
Hide file tree
Showing 48 changed files with 5,990 additions and 9,063 deletions.
29 changes: 29 additions & 0 deletions editor-blender/api/model_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import asyncio
from dataclasses import dataclass
from typing import Optional

from ..client import client
from ..core.models import ModelsArray
from ..core.utils.convert import models_query_to_state
from ..graphqls.queries import GET_MODELS, QueryModelPayload


@dataclass
class ModelAgent:
async def get_models(self) -> Optional[ModelsArray]:
try:
response = await client.execute(QueryModelPayload, GET_MODELS)
models = response["models"]

return models_query_to_state(models)

except asyncio.CancelledError:
pass

except Exception as e:
print(e)

return None


model_agent = ModelAgent()
9 changes: 9 additions & 0 deletions editor-blender/core/actions/property/led_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
from ...states import state


def update_edit_model(self: bpy.types.PropertyGroup, context: bpy.types.Context):
dancer_name: str = getattr(self, "edit_dancer")
dancer_obj: Optional[bpy.types.Object] = bpy.data.objects.get(dancer_name)

if dancer_obj is not None:
dancer_obj.select_set(True)
bpy.context.view_layer.objects.active = dancer_obj


def update_edit_dancer(self: bpy.types.PropertyGroup, context: bpy.types.Context):
dancer_name: str = getattr(self, "edit_dancer")
dancer_obj: Optional[bpy.types.Object] = bpy.data.objects.get(dancer_name)
Expand Down
1 change: 1 addition & 0 deletions editor-blender/core/actions/state/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def setup_led_editor():
clear_selection()

ld_ui_led_editor = getattr(bpy.context.window_manager, "ld_ui_led_editor")
ld_ui_led_editor["edit_model"] = -1
ld_ui_led_editor["edit_dancer"] = -1
ld_ui_led_editor["edit_part"] = -1

Expand Down
46 changes: 43 additions & 3 deletions editor-blender/core/actions/state/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from ....api.color_agent import color_agent
from ....api.dancer_agent import dancer_agent
from ....api.led_agent import led_agent
from ....api.model_agent import model_agent
from ....client import client

# from ....client.cache import FieldPolicy, InMemoryCache, TypePolicy
Expand Down Expand Up @@ -49,10 +50,14 @@
from ....handlers import mount, unmount
from ....storage import get_storage
from ...models import (
DancerName,
DancerPartIndexMap,
DancerPartIndexMapItem,
Dancers,
LEDPartLengthMap,
ModelDancerIndexMap,
ModelDancerIndexMapItem,
Models,
PartName,
PartType,
PartTypeMap,
Expand Down Expand Up @@ -185,9 +190,9 @@ async def init_editor():

batches_functions = [
# [load_data, init_color_map],
[init_color_map],
[init_dancers, init_current_pos],
[init_led_map, init_current_status],
[init_models, init_dancers],
[init_color_map, init_led_map],
[init_current_pos, init_current_status],
# [init_current_status, init_current_pos, init_current_led_status, sync_led_effect_record],
# [sync_current_led_status],
]
Expand Down Expand Up @@ -242,6 +247,41 @@ async def init_editor():
redraw_area({"VIEW_3D", "DOPESHEET_EDITOR"})


async def init_models():
models_array = await model_agent.get_models()

if models_array is None:
raise Exception("Failed to initialize models")

model_names = [model.name for model in models_array]
models: Models = dict(
[
(model.name, [dancer_name for dancer_name in model.dancers])
for model in models_array
]
)

model_dancer_index_map: ModelDancerIndexMap = {}

for index, model in enumerate(models_array):
dancers: Dict[DancerName, int] = dict(
[
(dancer_name, dancer_index)
for dancer_index, dancer_name in enumerate(model.dancers)
]
)
model_dancer_index_map[model.name] = ModelDancerIndexMapItem(
index=index, dancers=dancers
)

state.models = models
state.model_names = model_names
state.models_array = models_array
state.model_dancer_index_map = model_dancer_index_map

print("Models initialized")


async def init_dancers():
dancers_array = await dancer_agent.get_dancers()

Expand Down
11 changes: 7 additions & 4 deletions editor-blender/core/actions/state/led_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ def exit_editing_led_effect():
ld_ui_led_editor: LEDEditorStatusType = getattr(
bpy.context.window_manager, "ld_ui_led_editor"
)
ld_ui_led_editor.edit_mode = LEDEditorEditModeType.IDLE.value

edit_dancer = ld_ui_led_editor.edit_dancer
edit_part = ld_ui_led_editor.edit_part
Expand All @@ -107,9 +106,6 @@ def exit_editing_led_effect():

dancer_obj: bpy.types.Object = bpy.data.objects.get(edit_dancer) # type: ignore

# Set edit state
state.edit_state = EditMode.IDLE

# Mute fcurves of dancer and LED bulbs
for i in range(3):
dancer_obj.animation_data.action.fcurves.find("location", index=i).mute = False
Expand All @@ -132,6 +128,13 @@ def exit_editing_led_effect():
bpy.context.view_layer.objects.active = part_obj
part_obj.select_set(True)

for obj in part_obj.children:
obj.select_set(True)

# Set edit state
state.edit_state = EditMode.IDLE
ld_ui_led_editor.edit_mode = LEDEditorEditModeType.IDLE.value

# Reset outliner filter
set_outliner_filter("")
set_outliner_hide_mesh()
Expand Down
7 changes: 4 additions & 3 deletions editor-blender/core/actions/state/led_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ def set_led_map(led_map: LEDMap):
state.led_map = led_map
state.led_effect_id_table = {}

for part_effects in led_map.values():
for effect in part_effects.values():
state.led_effect_id_table[effect.id] = effect
for model_effects in led_map.values():
for part_effects in model_effects.values():
for effect in part_effects.values():
state.led_effect_id_table[effect.id] = effect

# TODO: Setup LED Effect List
redraw_area({"VIEW_3D", "DOPESHEET_EDITOR"})
42 changes: 33 additions & 9 deletions editor-blender/core/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ class LEDEffect:
PartName = str
DancerName = str

LEDModelName = str
LEDPartName = str

LEDMap = Dict[LEDPartName, Dict[LEDEffectName, LEDEffect]]
LEDMap = Dict[LEDModelName, Dict[LEDPartName, Dict[LEDEffectName, LEDEffect]]]

MapID = int

Expand Down Expand Up @@ -214,6 +215,29 @@ class SelectMode(Enum):
PART_MODE = 1


ModelName = str

Models = Dict[ModelName, List[DancerName]]


@dataclass
class ModelsArrayItem:
name: ModelName
dancers: List[DancerName]


ModelsArray = List[ModelsArrayItem]


@dataclass
class ModelDancerIndexMapItem:
index: int
dancers: Dict[DancerName, int]


ModelDancerIndexMap = Dict[ModelName, ModelDancerIndexMapItem]


@dataclass
class State:
running: bool
Expand Down Expand Up @@ -264,13 +288,10 @@ class State:
editor: Editor
editing_data: EditingData
shifting: bool
# NOTE: Guess we can't implement this

# NOTE: Maybe we don't need these
selection_mode: SelectMode
selected_obj_names: List[str]
selected_obj_type: Optional[SelectedPartType]
# selected_leds: List[int]

# TODO: Add these
# current_led_effect_reference_dancer: Optional[DancerName] # the dancer whose LED part is being edited
Expand All @@ -279,18 +300,21 @@ class State:
# current_led_effect_start: int # the start time on the timeline where currentLEDEffect is displayed during editing
# current_led_effect: Optional[LEDEffect] # the LED effect being edited

# TODO: Add these
models: Models
model_names: List[ModelName]
models_array: ModelsArray
model_dancer_index_map: ModelDancerIndexMap

dancers: Dancers
dancer_names: List[DancerName]
dancers_array: DancersArray
dancer_part_index_map: DancerPartIndexMap

part_type_map: PartTypeMap
led_part_length_map: LEDPartLengthMap
color_map: ColorMap
# effect_list: EffectListType

# TODO: Add these
dancers_array: DancersArray
dancer_part_index_map: DancerPartIndexMap

# TODO: Add these
# rpi_status: RPiStatus
# shell_history: ShellHistory
Expand Down
8 changes: 6 additions & 2 deletions editor-blender/core/states/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@
# current_led_effect_name
# current_led_effect_start
# current_led_effect
models={},
model_names=[],
models_array=[],
model_dancer_index_map={},
dancers={},
dancer_names=[],
dancers_array=[],
dancer_part_index_map={},
part_type_map={},
led_part_length_map={},
color_map={},
# effect_list
dancers_array=[],
dancer_part_index_map={},
# rpi_status
# shell_history
color_map_updates=ColorMapUpdates(added=[], updated=[], deleted=[]),
Expand Down
41 changes: 28 additions & 13 deletions editor-blender/core/utils/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
QueryEffectListItem,
QueryEffectListPositionFrame,
QueryLEDMapPayload,
QueryModelPayload,
QueryPosFrame,
QueryPosMapPayload,
QueryRevision,
Expand Down Expand Up @@ -41,6 +42,8 @@
LEDEffectID,
LEDMap,
Location,
ModelsArray,
ModelsArrayItem,
PartData,
PartType,
PosMap,
Expand All @@ -51,6 +54,14 @@
from ..states import state


def models_query_to_state(payload: QueryModelPayload) -> ModelsArray:
models_array = [
ModelsArrayItem(name=model.name, dancers=model.dancers) for model in payload
]

return models_array


def dancers_query_to_state(payload: QueryDancersPayload) -> DancersArray:
dancers_array: DancersArray = []

Expand Down Expand Up @@ -246,19 +257,23 @@ def color_map_query_to_state(payload: QueryColorMapPayload) -> ColorMap:
def led_map_query_to_state(payload: QueryLEDMapPayload) -> LEDMap:
led_map: LEDMap = {}

for part_name, effects in payload.items():
led_map[part_name] = {}
current_map = led_map[part_name]

for effect_name, effect in effects.items():
frame = effect.frames[0]
bulb_data = [
LEDBuldData(color_id=color_id, alpha=alpha)
for color_id, alpha in frame.LEDs
]
current_map[effect_name] = LEDEffect(
id=effect.id, name=effect_name, effect=bulb_data
)
for model_name, parts in payload.items():
led_map[model_name] = {}
model_map = led_map[model_name]

for part_name, effects in parts.items():
model_map[part_name] = {}
part_map = model_map[part_name]

for effect_name, effect in effects.items():
frame = effect.frames[0]
bulb_data = [
LEDBuldData(color_id=color_id, alpha=alpha)
for color_id, alpha in frame.LEDs
]
part_map[effect_name] = LEDEffect(
id=effect.id, name=effect_name, effect=bulb_data
)

return led_map

Expand Down
Loading

0 comments on commit 85d6e9a

Please sign in to comment.