Skip to content

Commit

Permalink
Closes #312! This is the code for the LIGHT_SPILL_CUSTOM feature
Browse files Browse the repository at this point in the history
  • Loading branch information
tngreene committed Sep 24, 2020
1 parent d364731 commit c1fbbf5
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 2 deletions.
81 changes: 79 additions & 2 deletions io_xplane2blender/xplane_types/xplane_light.py
@@ -1,7 +1,7 @@
import math
import re
from copy import deepcopy
from itertools import takewhile, tee, zip_longest
from itertools import chain, takewhile, tee, zip_longest
from typing import Dict, List, Optional, Tuple, Union

import bpy
Expand All @@ -17,6 +17,44 @@
from ..xplane_helpers import (floatToStr, logger, vec_b_to_x,
vec_x_to_b)

from dataclasses import dataclass, field

@dataclass
class _LightSpillCustomParams:
r:float
g:float
b:float
@property
def a(self):
return 1

size:float
dx:float
dy:float
dz:float
width:float
dataref:str

def __str__(self):
return " ".join(
chain(
map(
floatToStr,
(
self.r,
self.g,
self.b,
self.a,
self.size,
self.dx,
self.dy,
self.dz,
self.width,
),
),
(self.dataref,),
)
)

class XPlaneLight(xplane_object.XPlaneObject):
def __init__(self, blenderObject:bpy.types.Object):
Expand Down Expand Up @@ -64,6 +102,8 @@ def __init__(self, blenderObject:bpy.types.Object):
self.params = {}
elif self.lightType == LIGHT_PARAM:
self.params = blenderObject.data.xplane.params
elif self.lightType == LIGHT_SPILL_CUSTOM:
self.params = _LightSpillCustomParams(*([0]*8),"")
else:
self.params = None

Expand Down Expand Up @@ -302,7 +342,42 @@ def convert_table(param:str)->float:
logger.warn(unknown_light_name_warning)
# X-Plane Light Type | Light Type | parsed_light | light_param_defs | Result
# -------------------|------------|--------------|------------------|-------
# LIGHT_ old | * | N/A | N/A | Write
# LIGHT_SPILL_CUSTOM |"POINT/SPOT"| N/A | N/A | Fillout params, write
# LIGHT_SPILL_CUSTOM | Any others | N/A | N/A | Error
elif self.lightType == LIGHT_SPILL_CUSTOM and light_data.type not in {"POINT", "SPOT"}:
logger.error(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")
return
elif self.lightType == LIGHT_SPILL_CUSTOM and light_data.type in {"POINT", "SPOT"}:
p = self.params
p.r, self.params.g, self.params.b = self.color
p.size = self.size

def width_param_new_value()->float:
if light_data.type == "POINT":
return 1
elif light_data.type == "SPOT":
# cos(half the cone angle)
return XPlaneLight.WIDTH_for_spill(light_data.spot_size)

def new_dxyz_vec_x()->Vector:
"""
Returns (potentially scaled) light direction
or (0, 0, 0) for omni lights in X-Plane coords
"""

if light_data.type == "POINT":
return Vector((0, 0, 0))
elif light_data.type == "SPOT":
return vec_b_to_x(self.get_light_direction_b())
else:
assert False, f"What is this light_data.type {light_data.type}"

p.dx, p.dy, p.dz = new_dxyz_vec_x()
p.width = width_param_new_value()
p.dataref = self.dataref
# X-Plane Light Type | Light Type | parsed_light | light_param_defs | Result
# -------------------|------------|--------------|------------------|-------
# LIGHT_{OLD_TYPES} | * | N/A | N/A | Write
elif self.lightType in LIGHTS_OLD_TYPES:
pass
else:
Expand Down Expand Up @@ -467,6 +542,8 @@ def should_autocorrect_automatic()->bool:
f" {' '.join(map(floatToStr,[self.energy, self.size]))}"
f" {' '.join(map(floatToStr,self.uv))}"
f" {self.dataref}\n")
elif self.lightType == LIGHT_SPILL_CUSTOM:
o += f"{indent}LIGHT_SPILL_CUSTOM {translation_xp_str} {self.params}\n"
# do not render lights with no indices
elif self.indices[1] > self.indices[0]:
offset = self.indices[0]
Expand Down
@@ -0,0 +1,18 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Spot_blank
# LIGHT: Spot_blank weight: 10000
LIGHT_SPILL_CUSTOM 0 1 -0 1 1 1 1 15 0 1 -0.00000015 0.92387953
# 1 Light: Spot_none
# LIGHT: Spot_none weight: 10000
LIGHT_SPILL_CUSTOM 10 1 -0 1 1 1 1 15 0 1 -0.00000015 0.92387953 none
# 1 Light: Spot_traffic_light
# LIGHT: Spot_traffic_light weight: 10000
LIGHT_SPILL_CUSTOM 20 1 -0 1 1 1 1 15 0 1 -0.00000015 0.92387953 sim/graphics/animation/lights/traffic_light

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,21 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Spot_aa_backish_68.5_-.907_0,087_-.413_pink
# LIGHT: Spot_aa_backish_68.5_-.907_0,087_-.413_pink weight: 10000
LIGHT_SPILL_CUSTOM 0 10 5 1 0 1 1 35 -0.54601967 0.35867152 0.75711119 0.92387953
# 1 Light: Spot_down_0_0_0_red
# LIGHT: Spot_down_0_0_0_red weight: 10000
LIGHT_SPILL_CUSTOM -20 10 -0 1 0 0 1 35 0 -1 -0 0.92387953
# 1 Light: Spot_forward_90_0_0_blue
# LIGHT: Spot_forward_90_0_0_blue weight: 10000
LIGHT_SPILL_CUSTOM -10 10 -0 0 0 1 1 35 0 0.00000004 -1 0.92387953
# 1 Light: Spot_right_90_0_-90_green
# LIGHT: Spot_right_90_0_-90_green weight: 10000
LIGHT_SPILL_CUSTOM 0 10 -0 0 1 0 1 35 1 0.00000004 0.00000004 0.92387953

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,15 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Point_pink
# LIGHT: Point_pink weight: 10000
LIGHT_SPILL_CUSTOM 5 5 -5 1 0.1 0.80000001 1 35 0 0 0 1
# 1 Light: Spot_green
# LIGHT: Spot_green weight: 10000
LIGHT_SPILL_CUSTOM -4 5 4 0 1 0.25 1 35 0 -1 -0 0.92387953

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,24 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Point_1
# LIGHT: Point_1 weight: 10000
LIGHT_SPILL_CUSTOM -20 14 -0 1 1 1 1 35 0 0 0 1
# 1 Light: Point_180
# LIGHT: Point_180 weight: 10000
LIGHT_SPILL_CUSTOM 20 14 -0 1 1 1 1 35 0 0 0 1
# 1 Light: Point_35
# LIGHT: Point_35 weight: 10000
LIGHT_SPILL_CUSTOM -10 14 -0 1 1 1 1 35 0 0 0 1
# 1 Light: Point_45
# LIGHT: Point_45 weight: 10000
LIGHT_SPILL_CUSTOM 0 14 -0 1 1 1 1 35 0 0 0 1
# 1 Light: Pointt_120
# LIGHT: Pointt_120 weight: 10000
LIGHT_SPILL_CUSTOM 10 14 -0 1 1 1 1 35 0 0 0 1

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,24 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Spot_1
# LIGHT: Spot_1 weight: 10000
LIGHT_SPILL_CUSTOM -20 14 -0 1 1 1 1 35 0 -1 -0 0.99996192
# 1 Light: Spot_120
# LIGHT: Spot_120 weight: 10000
LIGHT_SPILL_CUSTOM 10 14 -0 1 1 1 1 35 0 -1 -0 0.49999997
# 1 Light: Spot_180
# LIGHT: Spot_180 weight: 10000
LIGHT_SPILL_CUSTOM 20 14 -0 1 1 1 1 35 0 -1 -0 -0.00000004
# 1 Light: Spot_35
# LIGHT: Spot_35 weight: 10000
LIGHT_SPILL_CUSTOM -10 14 -0 1 1 1 1 35 0 -1 -0 0.95371695
# 1 Light: Spot_45
# LIGHT: Spot_45 weight: 10000
LIGHT_SPILL_CUSTOM 0 14 -0 1 1 1 1 35 0 -1 -0 0.92387953

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,15 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Light: Point_size_67.58
# LIGHT: Point_size_67.58 weight: 10000
LIGHT_SPILL_CUSTOM 5 5 -5 1 0.1 0.80000001 1 67.580002 0 0 0 1
# 1 Light: Spot_size_40
# LIGHT: Spot_size_40 weight: 10000
LIGHT_SPILL_CUSTOM -4 5 4 0 1 0.25 1 40 0 -1 -0 0.92387953

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
@@ -0,0 +1,19 @@
I
800
OBJ

POINT_COUNTS 0 0 0 0

# 0 ROOT
# 1 Armature: Armature
# ARMATURE: Armature weight: 0
# 2 Bone: Bone
# 3 Bone: Bone.001
# 4 Light: Point_5_5_5
# LIGHT: Point_5_5_5 weight: 10000
LIGHT_SPILL_CUSTOM 1.3570218 14.714046 -5.7140455 1 0.82163 0.0033541408 1 35 0 0 0 1
# 4 Light: Spot_-4_-4_5
# LIGHT: Spot_-4_-4_5 weight: 10000
LIGHT_SPILL_CUSTOM -2.8856175 6.2287636 2.7712367 1 0.018346181 0.028602321 1 35 -0.66666675 -0.33333337 -0.66666663 0.92387953

# Build with Blender 2.80 (sub 75) (build b'f6cb5f54494e'). Exported with XPlane2Blender 4.0.0-dev.0+90.NO_BUILD_NUMBR
Binary file not shown.
39 changes: 39 additions & 0 deletions tests/lights/light_spill_custom_attributes.test.py
@@ -0,0 +1,39 @@
import inspect

from typing import Tuple
import os
import sys

import bpy
from io_xplane2blender import xplane_config
from io_xplane2blender.tests import *
from io_xplane2blender.tests import test_creation_helpers

__dirname__ = os.path.dirname(__file__)

class TestLightSpillCustomAttributes(XPlaneTestCase):
def test_light_attributes(self)->None:
filenames = ["test_light_spill_custom_xyz",
"test_light_spill_custom_rgb",
"test_light_spill_custom_dxyz",
"test_light_spill_custom_size",
"test_light_spill_custom_semi_spot",
"test_light_spill_custom_semi_point",
"test_light_spill_custom_dref",]

for filename in filenames:
with self.subTest(filename=filename):
self.assertExportableRootExportEqualsFixture(
filename[5:],
os.path.join(__dirname__, "fixtures", "light_spill_custom", f"{filename}.obj"),
{"LIGHT_SPILL_CUSTOM"},
filename,
)

def test_incompatible_light_types(self):
filename = inspect.stack()[0].function
out = self.exportExportableRoot(filename[5:])
self.assertLoggerErrors(2)


runTestCases([TestLightSpillCustomAttributes])
Binary file added tests/lights/white.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c1fbbf5

Please sign in to comment.