Skip to content

Commit 063181a

Browse files
committed
Added logging to export stage, fixed issue with exporter not being registered if not present in blender addons list
1 parent e414dd8 commit 063181a

File tree

6 files changed

+78
-28
lines changed

6 files changed

+78
-28
lines changed

blender_bevy_toolkit/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
import sys
33
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
44

5+
import logging
6+
from utils import jdict
7+
logger = logging.getLogger(__name__)
8+
59

610
import bpy
711
from bpy.app.handlers import persistent
@@ -22,6 +26,7 @@
2226

2327

2428

29+
2530
class BevyComponentsPanel(bpy.types.Panel):
2631
""" The panel in which buttons that add/remove components are shown """
2732
bl_idname = "OBJECT_PT_bevy_components_panel"
@@ -38,6 +43,7 @@ def draw(self, context):
3843

3944

4045
def register():
46+
logger.info({"event":"registering_bevy_addon", "state":"start"})
4147
bpy.utils.register_class(BevyComponentsPanel)
4248
bpy.utils.register_class(operators.RemoveBevyComponent)
4349
bpy.utils.register_class(operators.AddBevyComponent)
@@ -46,9 +52,11 @@ def register():
4652
bpy.app.handlers.load_post.append(load_handler)
4753

4854
bpy.types.TOPBAR_MT_file_export.append(menu_func)
55+
logger.info(jdict(event="registering_bevy_addon", state="end"))
4956

5057

5158
def unregister():
59+
logger.info(jdict(event="unregistering_bevy_addon", state="start"))
5260
bpy.utils.unregister_class(BevyComponentsPanel)
5361
bpy.utils.unregister_class(operators.RemoveBevyComponent)
5462
bpy.utils.unregister_class(operators.AddBevyComponent)
@@ -58,7 +66,9 @@ def unregister():
5866
bpy.app.handlers.load_post.remove(load_handler)
5967

6068
for component in component_base.COMPONENTS:
69+
logger.info(jdict(event="unregistering_component", component=str(component)))
6170
component.unregister()
71+
logger.info(jdict(event="unregistering_bevy_addon", state="end"))
6272

6373

6474
@persistent
@@ -71,6 +81,7 @@ def load_handler(dummy):
7181
operators.update_all_component_list()
7282

7383
for component in component_base.COMPONENTS:
84+
logger.info(jdict(event="registering_component", component=str(component)))
7485
component.register()
7586

7687

blender_bevy_toolkit/components.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
from . import json_components
77
from . import component_base
88

9+
import logging
10+
from utils import jdict
11+
logger = logging.getLogger(__name__)
12+
913

1014
def generate_component_list():
1115
""" Scans directories for components """
1216
component_base.COMPONENTS = []
1317
# Predefined json types
18+
19+
logger.info(jdict(event="generate_component_list", state="start"))
1420

1521
here = os.path.dirname(os.path.abspath(__file__))
1622

@@ -28,6 +34,8 @@ def generate_component_list():
2834
custom_component_folder = os.path.join(blend_path, "component_definitions")
2935
if os.path.isdir(custom_component_folder):
3036
load_folder(custom_component_folder)
37+
38+
logger.info(jdict(event="generate_component_list", state="complete"))
3139

3240

3341
def load_folder(folder):
@@ -36,12 +44,18 @@ def load_folder(folder):
3644

3745

3846
def load_python_components(folder):
47+
logger.info(jdict(event="scan_folder_for_python_components", folder=folder))
3948
import importlib.util
4049
for filename in os.listdir(folder):
4150
if filename.endswith(".py"):
4251
module_name = os.path.splitext(filename)[0]
4352
full_path = os.path.join(folder, filename)
53+
54+
logger.info(jdict(event="load_python_component", path=full_path, state="start"))
55+
4456
spec = importlib.util.spec_from_file_location(module_name, full_path)
4557
module = importlib.util.module_from_spec(spec)
4658
spec.loader.exec_module(module)
4759
sys.modules[module_name] = module
60+
61+
logger.info(jdict(event="load_python_component", path=full_path, state="end"))

blender_bevy_toolkit/core_definitions/mesh.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import os
55
from blender_bevy_toolkit.component_base import ComponentRepresentation, register_component
66

7+
import logging
8+
from blender_bevy_toolkit import jdict
9+
logger = logging.getLogger(__name__)
710

811
@register_component
912
class Mesh:
@@ -22,7 +25,7 @@ def encode(config, obj):
2225
hash_text,
2326
))
2427
if not os.path.exists(mesh_output_file):
25-
print("Writing Mesh {}".format(mesh_output_file))
28+
logger.info(jdict(event="writing_mesh", path=mesh_output_file))
2629
open(mesh_output_file, 'wb').write(mesh_data)
2730

2831
path = os.path.relpath(mesh_output_file, config["output_folder"])

blender_bevy_toolkit/json_components.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
from .component_base import ComponentRepresentation, register_component
2020
import utils
2121

22+
import logging
23+
from utils import jdict
24+
logger = logging.getLogger(__name__)
25+
26+
2227
FieldDefinition = collections.namedtuple("FieldDefinition", ["field", "type", "default", "description"])
2328
ComponentDefininition = collections.namedtuple("ComponentDefinition", ["name", "description", "id", "struct", "fields"])
2429

@@ -59,10 +64,12 @@ def get_component_files(folder):
5964

6065
def construct_component_classes(component_filepath):
6166
# Parse the file from JSON into some python namedtuples
67+
logging.info(jdict(event="construct_json_classes", path=component_filepath, state="start"))
68+
6269
try:
6370
component = json.load(open(component_filepath))
6471
except json.decoder.JSONDecodeError as err:
65-
print("Failed to construct class for {}: {}".format(component_filepath, err))
72+
logging.exception(jdict(event="construct_json_component_parse_error", path=component_filepath, error=err, exc_info=err))
6673
return None
6774

6875
def parse_field(field):
@@ -80,6 +87,7 @@ def parse_field(field):
8087
struct=component["struct"],
8188
fields=[parse_field(f) for f in component["fields"]]
8289
)
90+
logging.debug(jdict(event="construct_json_classes", path=component_filepath, state="parse_complete"))
8391

8492

8593
# component becomes bpy.types.Object.<<<obj_key>>>
@@ -116,6 +124,7 @@ def parse_field(field):
116124
fields["present"] = bpy.props.BoolProperty(name="Present", default=False)
117125
properties.__annotations__ = fields
118126

127+
logging.debug(jdict(event="construct_json_classes", path=component_filepath, state="fields_completed"))
119128

120129

121130
# Create a class to store the data about this component inside the
@@ -157,6 +166,8 @@ def draw(self, context):
157166
row.prop(getattr(context.object, obj_key), field)
158167
panel.draw = draw
159168

169+
logging.debug(jdict(event="construct_json_classes", path=component_filepath, state="panel_created"))
170+
160171

161172

162173
# These functions all get put inside the component_class
@@ -194,13 +205,16 @@ def fix_types(field_name, value):
194205
component_class.remove = staticmethod(remove)
195206
component_class.encode = staticmethod(encode)
196207

197-
208+
logging.debug(jdict(event="construct_json_classes", path=component_filepath, state="end"))
198209
return component_class
199210

200211

201212

202213
def load_folder(folder):
214+
logger.info(jdict(event="scan_folder_for_json_components", folder=folder))
215+
203216
json_files = get_component_files(folder)
217+
logger.info(jdict(event="scan_folder_for_json_components", folder=folder, json_files=json_files))
204218
classes = [construct_component_classes(c) for c in json_files]
205219
for cls in classes:
206220
register_component(cls)

blender_bevy_toolkit/rapier_definitions/collider_description.py

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
# has a name (displayed in teh enum), a function
99
# that turns an object into bytes
1010
# and draw_type defines how bounds are drawn in the viewport.
11-
BoundsType = collections.namedtuple("BoundsType", ["name", "encoder", "draw_type"])
11+
BoundsType = collections.namedtuple(
12+
"BoundsType", ["name", "encoder", "draw_type"])
1213

1314

1415
def encode_sphere_collider_data(obj):
@@ -23,7 +24,6 @@ def encode_sphere_collider_data(obj):
2324
else:
2425
print("Unable to figure out radius for {}", obj.name)
2526
radius = 1.0
26-
2727

2828
return struct.pack("<f", radius)
2929

@@ -41,20 +41,20 @@ def encode_capsule_collider_data(obj):
4141

4242
def encode_box_collider_data(obj):
4343
if obj.type == "MESH":
44-
dims = [obj.dimensions.x/2.0, obj.dimensions.y/2.0, obj.dimensions.z/2.0]
44+
dims = [obj.dimensions.x/2.0,
45+
obj.dimensions.y/2.0, obj.dimensions.z/2.0]
4546
else:
4647
print("Unable to figure out box dimensions for {}", obj.name)
4748
dims = [1.0, 1.0, 1.0]
4849
return struct.pack("<fff", *dims)
4950

5051

51-
5252
# Physics shapes and a function to encode that shape provided an object
53-
# Be cautious about inserting to the beginning/middle of this list or
53+
# Be cautious about inserting to the beginning/middle of this list or
5454
# removing an item as it will break existing blend files.
5555
COLLIDER_SHAPES = [
5656
BoundsType(
57-
name="Sphere",
57+
name="Sphere",
5858
encoder=encode_sphere_collider_data,
5959
draw_type="SPHERE"
6060
),
@@ -69,7 +69,7 @@ def encode_box_collider_data(obj):
6969
draw_type="BOX"
7070
),
7171
]
72-
72+
7373

7474
@register_component
7575
class ColliderDescription:
@@ -86,17 +86,17 @@ def encode(config, obj):
8686

8787
field_dict = {}
8888
for field_name, converter in field_converters:
89-
field_dict[field_name] = converter(getattr(obj.rapier_collider_description, field_name))
89+
field_dict[field_name] = converter(
90+
getattr(obj.rapier_collider_description, field_name))
9091

9192
# The collider_data field is dependant on the collider_shape, so we have to do some
9293
# derivation here
9394
collider_shape = int(obj.rapier_collider_description.collider_shape)
9495

9596
encode_function = COLLIDER_SHAPES[collider_shape].encoder
9697
raw_data = encode_function(obj)
97-
98-
data = list(raw_data)
9998

99+
data = list(raw_data)
100100

101101
field_dict["collider_shape"] = collider_shape
102102
field_dict["collider_shape_data"] = {
@@ -108,11 +108,11 @@ def encode(config, obj):
108108
"blender_bevy_toolkit::rapier_physics::ColliderDescription",
109109
field_dict
110110
)
111-
111+
112112
def is_present(obj):
113113
""" Returns true if the supplied object has this component """
114114
return obj.rapier_collider_description.present
115-
115+
116116
def can_add(obj):
117117
return True
118118

@@ -125,13 +125,13 @@ def add(obj):
125125
def remove(obj):
126126
obj.rapier_collider_description.present = False
127127
update_draw_bounds(obj)
128-
128+
129129
@staticmethod
130130
def register():
131131
bpy.utils.register_class(ColliderDescriptionPanel)
132132
bpy.utils.register_class(ColliderDescriptionProperties)
133-
bpy.types.Object.rapier_collider_description = bpy.props.PointerProperty(type=ColliderDescriptionProperties)
134-
133+
bpy.types.Object.rapier_collider_description = bpy.props.PointerProperty(
134+
type=ColliderDescriptionProperties)
135135

136136
@staticmethod
137137
def unregister():
@@ -150,50 +150,53 @@ class ColliderDescriptionPanel(bpy.types.Panel):
150150
@classmethod
151151
def poll(cls, context):
152152
return ColliderDescription.is_present(context.object)
153-
153+
154154
def draw(self, context):
155155
row = self.layout.row()
156-
row.label(text="A collider so this object can collide with things (when coupled with a rigidbody somewhere)")
156+
row.label(
157+
text="A collider so this object can collide with things (when coupled with a rigidbody somewhere)")
157158

158-
fields = ["friction", "restitution", "is_sensor", "density", "collider_shape"]
159+
fields = ["friction", "restitution",
160+
"is_sensor", "density", "collider_shape"]
159161

160162
for field in fields:
161163
row = self.layout.row()
162164
row.prop(context.object.rapier_collider_description, field)
163165

164166

165-
166167
def update_draw_bounds(obj):
167168
""" Changes how the object is shown in the viewport in order to
168169
display the bounds to the user """
169170
if ColliderDescription.is_present(obj):
170171
collider_type_id = int(obj.rapier_collider_description.collider_shape)
171172
collider_type_data = COLLIDER_SHAPES[collider_type_id].draw_type
172-
173+
173174
obj.show_bounds = True
174175
obj.display_bounds_type = collider_type_data
175-
176+
176177
else:
177178
obj.show_bounds = False
178179

180+
179181
def collider_shape_changed(_, context):
180182
""" Runs when the enum selecting the shape is changed """
181183
update_draw_bounds(context.object)
182184

185+
183186
class ColliderDescriptionProperties(bpy.types.PropertyGroup):
184187
present: bpy.props.BoolProperty(name="Present", default=False)
185188

186189
friction: bpy.props.FloatProperty(name="friction", default=0.5)
187190
restitution: bpy.props.FloatProperty(name="restitution", default=0.5)
188191
is_sensor: bpy.props.BoolProperty(name="is_sensor", default=False)
189-
192+
190193
density: bpy.props.FloatProperty(name="density", default=0.5)
191194

192195
shape_items = [(str(i), s.name, "") for i, s in enumerate(COLLIDER_SHAPES)]
193196

194197
collider_shape: bpy.props.EnumProperty(
195-
name="collider_shape",
196-
default=0,
198+
name="collider_shape",
199+
default=0,
197200
items=shape_items,
198201
update=collider_shape_changed
199-
)
202+
)

blender_bevy_toolkit/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import mathutils
22
import bpy
3+
import json
4+
5+
def jdict(**kwargs):
6+
return json.dumps(dict(**kwargs))
7+
38

49
def iterable_to_string(data, start="[", end="]", joiner=","):
510
return start + joiner.join(encode(d) for d in data) + end

0 commit comments

Comments
 (0)