Skip to content

Commit 798f0ea

Browse files
Rework how vehicles work
1 parent b5e0478 commit 798f0ea

File tree

6 files changed

+290
-163
lines changed

6 files changed

+290
-163
lines changed

loco-graphics-helper/loco_object_helper_panel.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ def draw_bogie_panel(self, context, layout):
6060

6161
vehicle_properties = context.object.loco_graphics_helper_vehicle_properties
6262

63-
row.prop(vehicle_properties, "is_clone_bogie")
63+
row.prop(vehicle_properties, "is_clone")
6464
row = layout.row()
6565

66-
if vehicle_properties.is_clone_bogie:
66+
row.prop(vehicle_properties, "is_inverted")
67+
row = layout.row()
68+
69+
if vehicle_properties.is_clone:
6770
row.prop(vehicle_properties, "index",text="Clone of bogie index:")
6871
row = layout.row()
6972
return
@@ -109,6 +112,17 @@ def draw_body_panel(self, context, layout):
109112

110113
vehicle_properties = context.object.loco_graphics_helper_vehicle_properties
111114

115+
row.prop(vehicle_properties, "is_clone")
116+
row = layout.row()
117+
118+
row.prop(vehicle_properties, "is_inverted")
119+
row = layout.row()
120+
121+
if vehicle_properties.is_clone:
122+
row.prop(vehicle_properties, "index",text="Clone of body index:")
123+
row = layout.row()
124+
return
125+
112126
box = layout.box()
113127

114128
row = box.row()

loco-graphics-helper/operators/vehicle_render_operator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def create_task(self, context):
3636
self.task_builder.set_palette(self.palette_manager.get_base_palette(
3737
general_props.palette, general_props.number_of_recolorables, "FULL"))
3838

39-
bodies = [x for x in context.scene.objects if x.loco_graphics_helper_object_properties.object_type == "BODY"]
39+
bodies = [x for x in context.scene.objects if x.loco_graphics_helper_object_properties.object_type == "BODY" and not x.loco_graphics_helper_vehicle_properties.is_clone]
4040
bodies = sorted(bodies, key=lambda x: x.loco_graphics_helper_vehicle_properties.index)
4141
for body_object in bodies:
4242
self.add_render_angles(body_object)
@@ -47,7 +47,7 @@ def create_task(self, context):
4747
self.task_builder.set_palette(self.palette_manager.get_shadow_palette())
4848
self.add_airplane_shadow_render_angles(bodies[0])
4949
else:
50-
bogies = [x for x in context.scene.objects if x.loco_graphics_helper_object_properties.object_type == "BOGIE" and not x.loco_graphics_helper_vehicle_properties.is_clone_bogie]
50+
bogies = [x for x in context.scene.objects if x.loco_graphics_helper_object_properties.object_type == "BOGIE" and not x.loco_graphics_helper_vehicle_properties.is_clone]
5151
bogies = sorted(bogies, key=lambda x: x.loco_graphics_helper_vehicle_properties.index)
5252
for bogie_object in bogies:
5353
self.add_render_angles(bogie_object)

loco-graphics-helper/properties/object_properties.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class ObjectProperties(bpy.types.PropertyGroup):
3737
("BOGIE", "Bogie", "", 2),
3838
("CARGO", "Cargo", "", 3),
3939
("CAR", "Car", "", 4),
40+
("ANIMATION", "Animation position", "", 5),
4041
),
4142
default="NONE",
4243
update=object_type_update_func

loco-graphics-helper/properties/vehicle_properties.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,15 @@ class VehicleProperties(bpy.types.PropertyGroup):
116116
default=False
117117
)
118118

119-
is_clone_bogie = bpy.props.BoolProperty(
120-
name="Is a clone of another bogie",
121-
description="If a bogie clone will not be rendered and here just for show/location data",
119+
is_clone = bpy.props.BoolProperty(
120+
name="Is a clone of another bogie/body",
121+
description="Clones will not be rendered and here just for show/location/meta data",
122+
default=False
123+
)
124+
125+
is_inverted = bpy.props.BoolProperty(
126+
name="Direction is inverted",
127+
description="Useful for clones to mark an inverted clone",
122128
default=False
123129
)
124130

loco-graphics-helper/rct_graphics_helper_panel.py

Lines changed: 111 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
from .models.palette import palette_colors, palette_colors_details
2626

27+
from .vehicle import get_car_components, VehicleComponent, SubComponent
28+
2729
class RepairConfirmOperator(bpy.types.Operator):
2830
"""This action will clear out the default camera and light. Changes made to the rig object, compositor nodes and recolorable materials will be lost."""
2931
bl_idname = "loco_graphics_helper.repair_confirm"
@@ -212,108 +214,6 @@ def draw_track_panel(self, scene, layout):
212214
# if general_properties.rendering:
213215
# text = "Failed"
214216
# row.operator("render.loco_track", text=text)
215-
@staticmethod
216-
def get_number_of_sprites(object):
217-
is_bogie = object.loco_graphics_helper_object_properties.object_type == "BOGIE"
218-
props = object.loco_graphics_helper_vehicle_properties
219-
220-
multiplier = props.number_of_animation_frames
221-
if props.roll_angle != 0:
222-
multiplier = 3
223-
elif props.braking_lights:
224-
multiplier = multiplier + 1
225-
if props.rotational_symmetry:
226-
multiplier = multiplier / 2
227-
228-
num_transition_sprites = 0 if is_bogie else 4 + 4
229-
num_sprites = 0
230-
if props.sprite_track_flags[0]:
231-
num_sprites = int(props.flat_viewing_angles) * multiplier
232-
if props.sprite_track_flags[1]:
233-
num_sprites = num_sprites + (int(props.sloped_viewing_angles) * 2 + num_transition_sprites) * multiplier
234-
if props.sprite_track_flags[2]:
235-
num_sprites = num_sprites + (int(props.sloped_viewing_angles) * 2 + num_transition_sprites) * multiplier
236-
237-
if props.is_airplane:
238-
num_sprites = num_sprites + int(props.flat_viewing_angles) * multiplier / 2
239-
return int(num_sprites)
240-
241-
@staticmethod
242-
def get_min_max_x_bound_box_corners_with_children(object):
243-
mins = []
244-
maxs = []
245-
min_x, max_x = GraphicsHelperPanel.get_min_max_x_bound_box_corners(object)
246-
# This can happen if there are no dimensions to this object (or if its 0 width)
247-
if min_x != max_x:
248-
mins.append(min_x)
249-
maxs.append(max_x)
250-
251-
for c in object.children:
252-
min_x, max_x = GraphicsHelperPanel.get_min_max_x_bound_box_corners_with_children(c)
253-
if min_x != max_x:
254-
mins.append(min_x)
255-
maxs.append(max_x)
256-
if len(mins) == 0 or len(maxs) == 0:
257-
return (0, 0)
258-
return (min(mins), max(maxs))
259-
260-
@staticmethod
261-
def get_min_max_x_bound_box_corners(object):
262-
bbox_corners = [object.matrix_world * Vector(corner) for corner in object.bound_box]
263-
min_x = min([x[0] for x in bbox_corners])
264-
max_x = max([x[0] for x in bbox_corners])
265-
return (min_x, max_x)
266-
267-
@staticmethod
268-
def get_longest_component_edge(front, back, body):
269-
mins = []
270-
maxs = []
271-
if not front is None:
272-
min_x, max_x = GraphicsHelperPanel.get_min_max_x_bound_box_corners_with_children(front)
273-
if min_x != max_x:
274-
mins.append(min_x)
275-
maxs.append(max_x)
276-
277-
if not back is None:
278-
min_x, max_x = GraphicsHelperPanel.get_min_max_x_bound_box_corners_with_children(back)
279-
if min_x != max_x:
280-
mins.append(min_x)
281-
maxs.append(max_x)
282-
283-
body_min_x, body_max_x = GraphicsHelperPanel.get_min_max_x_bound_box_corners_with_children(body)
284-
mins.append(body_min_x)
285-
maxs.append(body_max_x)
286-
min_x = body.location[0] - min(mins)
287-
max_x = max(maxs) - body.location[0]
288-
return max(min_x, max_x)
289-
290-
@staticmethod
291-
def get_bogie_position_from_component(bogie, body, half_width):
292-
body_x = body.location[0]
293-
bogie_x = bogie.location[0]
294-
position_from_centre = max(body_x, bogie_x) - min(body_x, bogie_x)
295-
return half_width - position_from_centre
296-
297-
@staticmethod
298-
def get_car_components(cars):
299-
components = []
300-
for car in cars:
301-
component_bogies = [x for x in car.children if x.loco_graphics_helper_object_properties.object_type == 'BOGIE']
302-
component_bodies = [x for x in car.children if x.loco_graphics_helper_object_properties.object_type == 'BODY']
303-
304-
if len(component_bodies) != 1:
305-
print("Malformed car {}".format(car.name))
306-
continue
307-
308-
if len(component_bogies) != 2:
309-
components.append((None, None, component_bodies[0]))
310-
continue
311-
312-
front_bogie = component_bogies[0] if component_bogies[0].location[0] > component_bogies[1].location[0] else component_bogies[1]
313-
back_bogie = component_bogies[1] if component_bogies[0].location[0] > component_bogies[1].location[0] else component_bogies[0]
314-
315-
components.append((front_bogie, back_bogie, component_bodies[0]))
316-
return components
317217

318218
@staticmethod
319219
def blender_to_loco_dist(dist):
@@ -327,67 +227,122 @@ def draw_vehicle_panel(self, scene, layout):
327227

328228
total_number_of_sprites = 0
329229

330-
components = self.get_car_components(cars)
331-
if len(components) > 0:
332-
row = layout.row()
333-
row.label("Car(s) details:")
334-
335-
for component in components:
336-
front, back, body = component
337-
idx = body.loco_graphics_helper_vehicle_properties.index
338-
print("Car {}".format(idx))
339-
half_width = self.get_longest_component_edge(front, back, body)
340-
341-
front_position = 0
342-
back_position = 0
343-
front_idx = 255
344-
back_idx = 255
345-
warning = None
346-
if not front is None:
347-
front_position = self.get_bogie_position_from_component(front, body, half_width)
348-
back_position = self.get_bogie_position_from_component(back, body, half_width)
349-
230+
components = get_car_components(cars)
231+
if len(components) == 0:
232+
return
233+
row = layout.row()
234+
row.label("Car(s) details:")
235+
236+
for component in components:
237+
front = component.get_object(SubComponent.FRONT)
238+
back = component.get_object(SubComponent.BACK)
239+
body = component.get_object(SubComponent.BODY)
240+
idx = body.loco_graphics_helper_vehicle_properties.index
241+
242+
front_position = 0
243+
back_position = 0
244+
body_idx = idx - 1 + 180 if body.loco_graphics_helper_vehicle_properties.is_inverted else idx - 1
245+
front_idx = 255
246+
back_idx = 255
247+
warning = None
248+
anim_location = 0
249+
front_name = '' if front is None else front.name
250+
back_name = '' if back is None else back.name
251+
if not front is None:
252+
front_position = component.get_bogie_position(SubComponent.FRONT)
253+
back_position = component.get_bogie_position(SubComponent.BACK)
254+
255+
if component.get_number_of_sprites(SubComponent.FRONT) != 0:
350256
front_idx = front.loco_graphics_helper_vehicle_properties.index - 1
351-
back_idx = back.loco_graphics_helper_vehicle_properties.index - 1
352-
mid_point_x = (front.location[0] - back.location[0]) / 2 + back.location[0]
353-
if not math.isclose(body.location[0], mid_point_x, rel_tol=1e-4):
354-
warning = "BODY LOCATION IS NOT AT MID X POINT BETWEEN BOGIES! {}".format(mid_point_x)
355-
elif body.loco_graphics_helper_vehicle_properties.is_airplane:
356-
front_idx = 0
357-
358-
row = layout.row()
359-
row.label(" {}. {}, Half-Width: {}, Front Position: {}, Back Position: {}".format(idx, body.name, self.blender_to_loco_dist(half_width), self.blender_to_loco_dist(front_position), self.blender_to_loco_dist(back_position)))
360-
row = layout.row()
361-
row.label(" Body Sprite Index: {}, Front Bogie Sprite Index: {}, Back Bogie Sprite Index: {},".format(idx - 1, front_idx, back_idx))
362-
if not warning is None:
363-
row = layout.row()
364-
row.label(" WARNING: {},".format(warning))
365-
366-
bodies = [x for x in scene.objects if x.loco_graphics_helper_object_properties.object_type == "BODY"]
367-
bodies = sorted(bodies, key=lambda x: x.loco_graphics_helper_vehicle_properties.index)
368-
bogies = [x for x in scene.objects if x.loco_graphics_helper_object_properties.object_type == "BOGIE"]
369-
bogies = sorted(bogies, key=lambda x: x.loco_graphics_helper_vehicle_properties.index)
257+
front_idx = front_idx + 180 if front.loco_graphics_helper_vehicle_properties.is_inverted else front_idx
370258

371-
if len(bodies) > 0:
259+
if component.get_number_of_sprites(SubComponent.BACK) != 0:
260+
back_idx = back.loco_graphics_helper_vehicle_properties.index - 1
261+
back_idx = back_idx + 180 if front.loco_graphics_helper_vehicle_properties.is_inverted else back_idx
262+
mid_point_x = (front.location[0] - back.location[0]) / 2 + back.location[0]
263+
if not math.isclose(body.location[0], mid_point_x, rel_tol=1e-4):
264+
warning = "BODY LOCATION IS NOT AT MID X POINT BETWEEN BOGIES! {}".format(mid_point_x)
265+
anim_location = component.get_animation_location()
266+
if anim_location > 255 or anim_location < 0:
267+
warning = "Animation is too far from bogies"
268+
anim_location = 255
269+
elif body.loco_graphics_helper_vehicle_properties.is_airplane:
270+
front_idx = 0
271+
372272
row = layout.row()
373-
row.label("Body(s) details:")
374-
for idx, body in enumerate(bodies):
273+
row.label("{}. {}, {}, {}, {}".format(component.car.loco_graphics_helper_vehicle_properties.index - 1, component.car.name, body.name, front_name, back_name))
274+
row = layout.row()
275+
row.label(" Front Position: {}".format(self.blender_to_loco_dist(front_position)))
276+
row = layout.row()
277+
row.label(" Back Position: {}".format(self.blender_to_loco_dist(back_position)))
278+
row = layout.row()
279+
row.label(" Front Bogie Sprite Index: {}".format(front_idx))
280+
row = layout.row()
281+
row.label(" Back Bogie Sprite Index: {}".format(back_idx))
282+
row = layout.row()
283+
row.label(" Body Sprite Index: {}".format(body_idx))
284+
row = layout.row()
285+
row.label(" Animation Position: {}".format(anim_location))
286+
287+
if not warning is None:
375288
row = layout.row()
376-
number_of_sprites = self.get_number_of_sprites(body)
377-
row.label(" {}. {}, Number of sprites: {}".format(idx + 1, body.name, number_of_sprites))
378-
total_number_of_sprites = total_number_of_sprites + number_of_sprites
289+
row.label(" WARNING: {},".format(warning))
379290

380-
if len(bogies) > 0:
291+
row = layout.row()
292+
row.label("Body(s) details:")
293+
components = sorted(components, key=lambda x: x.body.loco_graphics_helper_vehicle_properties.index)
294+
for component in components:
295+
body = component.body
296+
if body is None:
297+
continue
298+
if body.loco_graphics_helper_vehicle_properties.is_clone:
299+
continue
300+
number_of_sprites = component.get_number_of_sprites(SubComponent.BODY)
301+
total_number_of_sprites = total_number_of_sprites + number_of_sprites
302+
303+
if number_of_sprites == 0:
304+
continue
305+
306+
half_width = component.get_half_width()
381307
row = layout.row()
382-
row.label("Bogie(s) details:")
383-
for idx, bogie in enumerate(bogies):
384-
row = layout.row()
385-
number_of_sprites = 0
386-
if not bogie.loco_graphics_helper_vehicle_properties.is_clone_bogie:
387-
number_of_sprites = self.get_number_of_sprites(bogie)
388-
total_number_of_sprites = total_number_of_sprites + number_of_sprites
389-
row.label(" {}. {}, Number of sprites: {}".format(idx + 1, bogie.name, number_of_sprites))
308+
row.label("{}. {}".format(body.loco_graphics_helper_vehicle_properties.index, body.name))
309+
row = layout.row()
310+
row.label(" Half-Width: {}".format(self.blender_to_loco_dist(half_width)))
311+
row = layout.row()
312+
row.label(" Number of sprites: {}".format(number_of_sprites))
313+
314+
bogies = [x for x in scene.objects if x.loco_graphics_helper_object_properties.object_type == "BOGIE" and not x.loco_graphics_helper_vehicle_properties.is_clone]
315+
bogies = sorted(bogies, key=lambda x: x.loco_graphics_helper_vehicle_properties.index)
316+
317+
row = layout.row()
318+
row.label("Bogie(s) details:")
319+
for bogie in bogies:
320+
car = None
321+
sub_component = None
322+
for component in components:
323+
if component.front == bogie:
324+
car = component
325+
sub_component = SubComponent.FRONT
326+
break
327+
if component.back == bogie:
328+
car = component
329+
sub_component = SubComponent.BACK
330+
break
331+
if car is None:
332+
continue
333+
334+
number_of_sprites = car.get_number_of_sprites(sub_component)
335+
total_number_of_sprites = total_number_of_sprites + number_of_sprites
336+
337+
if number_of_sprites == 0:
338+
continue
390339

340+
half_width = component.get_half_width()
341+
row = layout.row()
342+
row.label("{}. {}".format(bogie.loco_graphics_helper_vehicle_properties.index, bogie.name))
343+
row = layout.row()
344+
row.label(" Number of sprites: {}".format(number_of_sprites))
345+
391346
row = layout.row()
392347
row.label("Total number of sprites: {}".format(total_number_of_sprites))
393348

0 commit comments

Comments
 (0)