1 # SPDX-License-Identifier: GPL-2.0-or-later
4 from bpy
.types
import Operator
, Menu
5 from bl_operators
.presets
import AddPresetBase
7 from math
import degrees
9 from .sun_calc
import (format_lat_long
, format_time
, format_hms
, sun
)
12 # -------------------------------------------------------------------
13 # Choice list of places, month and day at 12:00 noon
14 # -------------------------------------------------------------------
17 class SUNPOS_MT_Presets(Menu
):
18 bl_label
= "Sun Position Presets"
19 preset_subdir
= "operator/sun_position"
20 preset_operator
= "script.execute_preset"
21 draw
= Menu
.draw_preset
24 class SUNPOS_OT_AddPreset(AddPresetBase
, Operator
):
25 '''Add Sun Position preset'''
26 bl_idname
= "world.sunpos_add_preset"
27 bl_label
= "Add Sun Position preset"
28 preset_menu
= "SUNPOS_MT_Presets"
30 # variable used for all preset values
32 "sun_props = bpy.context.scene.sun_pos_properties"
35 # properties to store in the preset
42 "sun_props.use_daylight_savings",
44 "sun_props.longitude",
47 # where to store the preset
48 preset_subdir
= "operator/sun_position"
51 # -------------------------------------------------------------------
53 # Draw the Sun Panel, sliders, et. al.
55 # -------------------------------------------------------------------
57 class SUNPOS_PT_Panel(bpy
.types
.Panel
):
58 bl_space_type
= "PROPERTIES"
59 bl_region_type
= "WINDOW"
61 bl_label
= "Sun Position"
62 bl_options
= {'DEFAULT_CLOSED'}
64 def draw(self
, context
):
65 sp
= context
.scene
.sun_pos_properties
66 p
= context
.preferences
.addons
[__package__
].preferences
68 self
.draw_panel(context
, sp
, p
, layout
)
70 def draw_panel(self
, context
, sp
, p
, layout
):
71 col
= self
.layout
.column(align
=True)
72 col
.label(text
="Usage Mode")
74 row
.prop(sp
, "usage_mode", expand
=True)
76 if sp
.usage_mode
== "HDR":
77 self
.draw_environ_mode_panel(context
, sp
, p
, layout
)
79 self
.draw_normal_mode_panel(context
, sp
, p
, layout
)
81 def draw_environ_mode_panel(self
, context
, sp
, p
, layout
):
82 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=True,
83 even_rows
=False, align
=False)
85 col
= flow
.column(align
=True)
86 col
.label(text
="Environment Texture")
88 if context
.scene
.world
is not None:
89 if context
.scene
.world
.node_tree
is not None:
90 col
.prop_search(sp
, "hdr_texture",
91 context
.scene
.world
.node_tree
, "nodes", text
="")
93 col
.label(text
="Please activate Use Nodes in the World panel.",
96 col
.label(text
="Please select World in the World panel.",
101 col
= flow
.column(align
=True)
102 col
.label(text
="Sun Object")
103 col
.prop_search(sp
, "sun_object",
104 context
.view_layer
, "objects", text
="")
107 col
= flow
.column(align
=True)
108 col
.prop(sp
, "sun_distance")
109 if not sp
.bind_to_sun
:
110 col
.prop(sp
, "hdr_elevation")
111 col
.prop(sp
, "hdr_azimuth")
114 col
= flow
.column(align
=True)
116 col
.prop(sp
, "bind_to_sun", toggle
=True, icon
="CONSTRAINT",
117 text
="Release binding")
119 col
.prop(sp
, "bind_to_sun", toggle
=True, icon
="CONSTRAINT",
120 text
="Bind Texture to Sun")
122 row
= col
.row(align
=True)
123 row
.enabled
= not sp
.bind_to_sun
124 row
.operator("world.sunpos_show_hdr", icon
='LIGHT_SUN')
126 def draw_normal_mode_panel(self
, context
, sp
, p
, layout
):
127 if p
.show_time_place
:
128 row
= layout
.row(align
=True)
129 row
.menu(SUNPOS_MT_Presets
.__name
__, text
=SUNPOS_MT_Presets
.bl_label
)
130 row
.operator(SUNPOS_OT_AddPreset
.bl_idname
, text
="", icon
='ADD')
131 row
.operator(SUNPOS_OT_AddPreset
.bl_idname
, text
="", icon
='REMOVE').remove_active
= True
133 col
= layout
.column(align
=True)
134 col
.use_property_split
= True
135 col
.use_property_decorate
= False
136 col
.prop(sp
, "sun_object")
139 col
.prop(sp
, "object_collection")
140 if sp
.object_collection
:
141 col
.prop(sp
, "object_collection_type")
142 if sp
.object_collection_type
== 'DIURNAL':
143 col
.prop(sp
, "time_spread")
146 if context
.scene
.world
is not None:
147 if context
.scene
.world
.node_tree
is not None:
148 col
.prop_search(sp
, "sky_texture",
149 context
.scene
.world
.node_tree
, "nodes")
151 col
.label(text
="Please activate Use Nodes in the World panel.",
154 col
.label(text
="Please select World in the World panel.",
158 class SUNPOS_PT_Location(bpy
.types
.Panel
):
159 bl_space_type
= "PROPERTIES"
160 bl_region_type
= "WINDOW"
162 bl_label
= "Location"
163 bl_parent_id
= "SUNPOS_PT_Panel"
166 def poll(self
, context
):
167 sp
= context
.scene
.sun_pos_properties
168 return sp
.usage_mode
!= "HDR"
170 def draw(self
, context
):
172 sp
= context
.scene
.sun_pos_properties
173 p
= context
.preferences
.addons
[__package__
].preferences
175 col
= layout
.column(align
=True)
176 col
.label(text
="Enter Coordinates")
177 col
.prop(sp
, "co_parser", text
='', icon
='URL')
181 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=True, even_rows
=False, align
=False)
183 col
= flow
.column(align
=True)
184 col
.prop(sp
, "latitude")
187 row
.alignment
= 'RIGHT'
188 row
.label(text
=format_lat_long(sp
.latitude
, True))
190 col
= flow
.column(align
=True)
191 col
.prop(sp
, "longitude")
194 row
.alignment
= 'RIGHT'
195 row
.label(text
=format_lat_long(sp
.longitude
, False))
199 col
= flow
.column(align
=True)
200 col
.prop(sp
, "show_north", toggle
=True)
201 col
.prop(sp
, "north_offset")
204 if p
.show_surface
or p
.show_analemmas
:
205 col
= flow
.column(align
=True)
207 col
.prop(sp
, "show_surface", toggle
=True)
209 col
.prop(sp
, "show_analemmas", toggle
=True)
213 col
= flow
.column(align
=True)
214 split
= col
.split(factor
=0.4, align
=True)
215 split
.label(text
="Azimuth:")
216 split
.label(text
=str(round(degrees(sun
.azimuth
), 3)) + "°")
217 split
= col
.split(factor
=0.4, align
=True)
218 split
.label(text
="Elevation:")
219 split
.label(text
=str(round(degrees(sun
.elevation
), 3)) + "°")
222 if p
.show_refraction
:
224 col
.prop(sp
, "use_refraction")
228 col
.prop(sp
, "sun_distance")
232 class SUNPOS_PT_Time(bpy
.types
.Panel
):
233 bl_space_type
= "PROPERTIES"
234 bl_region_type
= "WINDOW"
237 bl_parent_id
= "SUNPOS_PT_Panel"
240 def poll(self
, context
):
241 sp
= context
.scene
.sun_pos_properties
242 return sp
.usage_mode
!= "HDR"
244 def draw(self
, context
):
246 sp
= context
.scene
.sun_pos_properties
247 p
= context
.preferences
.addons
[__package__
].preferences
249 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=True, even_rows
=False, align
=False)
251 col
= flow
.column(align
=True)
252 col
.prop(sp
, "use_day_of_year",
254 if sp
.use_day_of_year
:
255 col
.prop(sp
, "day_of_year")
258 col
.prop(sp
, "month")
262 col
= flow
.column(align
=True)
264 col
.prop(sp
, "UTC_zone")
265 if p
.show_daylight_savings
:
266 col
.prop(sp
, "use_daylight_savings")
269 col
= flow
.column(align
=True)
270 lt
= format_time(sp
.time
,
271 p
.show_daylight_savings
and sp
.use_daylight_savings
,
273 ut
= format_time(sp
.time
,
274 p
.show_daylight_savings
and sp
.use_daylight_savings
,
277 col
.alignment
= 'CENTER'
279 split
= col
.split(factor
=0.5, align
=True)
280 split
.label(text
="Local:", icon
='TIME')
282 split
= col
.split(factor
=0.5, align
=True)
283 split
.label(text
="UTC:", icon
='PREVIEW_RANGE')
287 col
= flow
.column(align
=True)
288 col
.alignment
= 'CENTER'
290 sr
= format_hms(sun
.sunrise
)
291 ss
= format_hms(sun
.sunset
)
293 split
= col
.split(factor
=0.5, align
=True)
294 split
.label(text
="Sunrise:", icon
='LIGHT_SUN')
296 split
= col
.split(factor
=0.5, align
=True)
297 split
.label(text
="Sunset:", icon
='SOLO_ON')