|
1 | 1 | import math |
2 | 2 | import re |
3 | 3 | from copy import deepcopy |
4 | | -from itertools import takewhile, tee, zip_longest |
| 4 | +from dataclasses import dataclass, field |
| 5 | +from itertools import chain, takewhile, tee, zip_longest |
5 | 6 | from typing import Dict, List, Optional, Tuple, Union |
6 | 7 |
|
7 | 8 | import bpy |
|
17 | 18 | from ..xplane_helpers import floatToStr, logger, vec_b_to_x, vec_x_to_b |
18 | 19 |
|
19 | 20 |
|
| 21 | +@dataclass |
| 22 | +class _LightSpillCustomParams: |
| 23 | + r: float |
| 24 | + g: float |
| 25 | + b: float |
| 26 | + |
| 27 | + @property |
| 28 | + def a(self): |
| 29 | + return 1 |
| 30 | + |
| 31 | + size: float |
| 32 | + dx: float |
| 33 | + dy: float |
| 34 | + dz: float |
| 35 | + width: float |
| 36 | + dataref: str |
| 37 | + |
| 38 | + def __str__(self): |
| 39 | + return " ".join( |
| 40 | + chain( |
| 41 | + map( |
| 42 | + floatToStr, |
| 43 | + ( |
| 44 | + self.r, |
| 45 | + self.g, |
| 46 | + self.b, |
| 47 | + self.a, |
| 48 | + self.size, |
| 49 | + self.dx, |
| 50 | + self.dy, |
| 51 | + self.dz, |
| 52 | + self.width, |
| 53 | + ), |
| 54 | + ), |
| 55 | + (self.dataref,), |
| 56 | + ) |
| 57 | + ) |
| 58 | + |
| 59 | + |
20 | 60 | class XPlaneLight(xplane_object.XPlaneObject): |
21 | 61 | def __init__(self, blenderObject: bpy.types.Object): |
22 | 62 | super().__init__(blenderObject) |
@@ -63,6 +103,8 @@ def __init__(self, blenderObject: bpy.types.Object): |
63 | 103 | self.params = {} |
64 | 104 | elif self.lightType == LIGHT_PARAM: |
65 | 105 | self.params = blenderObject.data.xplane.params |
| 106 | + elif self.lightType == LIGHT_SPILL_CUSTOM: |
| 107 | + self.params = _LightSpillCustomParams(*([0] * 8), "") |
66 | 108 | else: |
67 | 109 | self.params = None |
68 | 110 |
|
@@ -379,7 +421,50 @@ def convert_table(param: str) -> float: |
379 | 421 | logger.warn(unknown_light_name_warning) |
380 | 422 | # X-Plane Light Type | Light Type | parsed_light | light_param_defs | Result |
381 | 423 | # -------------------|------------|--------------|------------------|------- |
382 | | - # LIGHT_ old | * | N/A | N/A | Write |
| 424 | + # LIGHT_SPILL_CUSTOM |"POINT/SPOT"| N/A | N/A | Fillout params, write |
| 425 | + # LIGHT_SPILL_CUSTOM | Any others | N/A | N/A | Error |
| 426 | + elif self.lightType == LIGHT_SPILL_CUSTOM and light_data.type not in { |
| 427 | + "POINT", |
| 428 | + "SPOT", |
| 429 | + }: |
| 430 | + logger.error( |
| 431 | + f"Custom Spill lights must be a Point or Spot light, change {self.blenderObject.name}'s type or change it's X-Plane Light Type" |
| 432 | + ) |
| 433 | + return |
| 434 | + elif self.lightType == LIGHT_SPILL_CUSTOM and light_data.type in { |
| 435 | + "POINT", |
| 436 | + "SPOT", |
| 437 | + }: |
| 438 | + p = self.params |
| 439 | + p.r, self.params.g, self.params.b = self.color |
| 440 | + p.size = self.size |
| 441 | + |
| 442 | + def width_param_new_value() -> float: |
| 443 | + if light_data.type == "POINT": |
| 444 | + return 1 |
| 445 | + elif light_data.type == "SPOT": |
| 446 | + # cos(half the cone angle) |
| 447 | + return XPlaneLight.WIDTH_for_spill(light_data.spot_size) |
| 448 | + |
| 449 | + def new_dxyz_vec_x() -> Vector: |
| 450 | + """ |
| 451 | + Returns (potentially scaled) light direction |
| 452 | + or (0, 0, 0) for omni lights in X-Plane coords |
| 453 | + """ |
| 454 | + |
| 455 | + if light_data.type == "POINT": |
| 456 | + return Vector((0, 0, 0)) |
| 457 | + elif light_data.type == "SPOT": |
| 458 | + return vec_b_to_x(self.get_light_direction_b()) |
| 459 | + else: |
| 460 | + assert False, f"What is this light_data.type {light_data.type}" |
| 461 | + |
| 462 | + p.dx, p.dy, p.dz = new_dxyz_vec_x() |
| 463 | + p.width = width_param_new_value() |
| 464 | + p.dataref = self.dataref |
| 465 | + # X-Plane Light Type | Light Type | parsed_light | light_param_defs | Result |
| 466 | + # -------------------|------------|--------------|------------------|------- |
| 467 | + # LIGHT_{OLD_TYPES} | * | N/A | N/A | Write |
383 | 468 | elif self.lightType in LIGHTS_OLD_TYPES: |
384 | 469 | pass |
385 | 470 | else: |
@@ -587,6 +672,8 @@ def should_autocorrect_automatic() -> bool: |
587 | 672 | f" {' '.join(map(floatToStr,self.uv))}" |
588 | 673 | f" {self.dataref}\n" |
589 | 674 | ) |
| 675 | + elif self.lightType == LIGHT_SPILL_CUSTOM: |
| 676 | + o += f"{indent}LIGHT_SPILL_CUSTOM {translation_xp_str} {self.params}\n" |
590 | 677 | # do not render lights with no indices |
591 | 678 | elif self.indices[1] > self.indices[0]: |
592 | 679 | offset = self.indices[0] |
|
0 commit comments