From f684a6058c322e8aadca45a86767c2620af098bc Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 23 Jun 2025 18:13:03 +0500 Subject: [PATCH] Light UI - quickly select current time/pick location from Google Maps Location - https://files.catbox.moe/ew9tgd.png ("Now" and "Pick" buttons) --- .../bonsai/bim/module/light/__init__.py | 2 + .../bonsai/bim/module/light/operator.py | 50 ++++++++++++++++++- src/bonsai/bonsai/bim/module/light/prop.py | 34 ++++++++++--- src/bonsai/bonsai/bim/module/light/ui.py | 10 +++- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/light/__init__.py b/src/bonsai/bonsai/bim/module/light/__init__.py index 8530b145d9..5c3c25ae58 100644 --- a/src/bonsai/bonsai/bim/module/light/__init__.py +++ b/src/bonsai/bonsai/bim/module/light/__init__.py @@ -38,6 +38,8 @@ classes = ( operator.MoveSunPathTo3DCursor, operator.RadianceRender, operator.ViewFromSun, + operator.LightPickCoordinates, + operator.LightSetTimeToNow, operator.RefreshIFCMaterials, operator.UnmapMaterial, operator.RADIANCE_OT_select_camera, diff --git a/src/bonsai/bonsai/bim/module/light/operator.py b/src/bonsai/bonsai/bim/module/light/operator.py index 6eb3e2a09c..2dc0834ea2 100644 --- a/src/bonsai/bonsai/bim/module/light/operator.py +++ b/src/bonsai/bonsai/bim/module/light/operator.py @@ -28,8 +28,7 @@ from datetime import datetime import bpy import bonsai.tool as tool from pathlib import Path -from typing import Union, Optional -from collections.abc import Sequence +from typing import Union, TYPE_CHECKING import json import math import time @@ -38,6 +37,7 @@ import ifcopenshell.util.geolocation import webbrowser import ifcopenshell.geom import multiprocessing +import requests from mathutils import Vector from bonsai.bim.module.light.data import SolarData from bpy_extras.io_utils import ExportHelper @@ -565,6 +565,52 @@ class ViewFromSun(bpy.types.Operator): return {"FINISHED"} +class LightPickCoordinates(bpy.types.Operator): + bl_idname = "bim.light_pick_coordinates" + bl_label = "Pick Coordinates" + bl_description = ( + "Open web browser with Google Maps to pick coordinates (Right Mouse Click in maps to copy selected location).\n\n" + "ALT+Click to insert current location based on the current IP-address (using ip-api.com)." + ) + bl_options = {"REGISTER", "UNDO"} + + use_current_location: bpy.props.BoolProperty(options={"SKIP_SAVE"}) # pyright: ignore[reportRedeclaration] + + if TYPE_CHECKING: + use_current_location: bool + + def invoke(self, context, event): + if event.alt: + self.use_current_location = True + return self.execute(context) + + def execute(self, context): + props = tool.Blender.get_solar_props() + if not self.use_current_location: + zoom = 13.5 + url = f"https://www.google.com/maps/@{props.latitude},{props.longitude},{zoom}z" + webbrowser.open(url) + return {"FINISHED"} + + response = requests.get("http://ip-api.com/json/") + data = response.json() + props.latitude = data["lat"] + props.longitude = data["lon"] + return {"FINISHED"} + + +class LightSetTimeToNow(bpy.types.Operator): + bl_idname = "bim.light_set_time_to_now" + bl_label = "Now" + bl_description = "Set time to current local time." + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + props = tool.Blender.get_solar_props() + props.set_from_datetime(datetime.now()) + return {"FINISHED"} + + class RefreshIFCMaterials(bpy.types.Operator): bl_idname = "bim.refresh_ifc_materials" bl_label = "Refresh IFC Materials" diff --git a/src/bonsai/bonsai/bim/module/light/prop.py b/src/bonsai/bonsai/bim/module/light/prop.py index 3e659ea811..91a7d6b522 100644 --- a/src/bonsai/bonsai/bim/module/light/prop.py +++ b/src/bonsai/bonsai/bim/module/light/prop.py @@ -41,6 +41,7 @@ from bonsai.bim.module.light.data import SolarData from bonsai.bim.module.light.decorator import SolarDecorator sun_position = tool.Blender.get_sun_position_addon() +now = datetime.datetime.now() with open(os.path.join(os.path.dirname(__file__), "spectraldb.json"), "r") as f: spectraldb: dict[str, dict[str, str]] = json.load(f) @@ -441,15 +442,27 @@ class RadianceExporterProperties(PropertyGroup): class BIMSolarProperties(PropertyGroup): sites: EnumProperty(items=get_sites, name="Sites") - latitude: FloatProperty(name="Latitude", min=-90, max=90, update=update_latlong) - longitude: FloatProperty(name="Longitude", min=-180, max=180, update=update_latlong) + latitude: FloatProperty( + name="Latitude", + min=-90, + max=90, + update=update_latlong, + default=-33.865143, + ) + longitude: FloatProperty( + name="Longitude", + min=-180, + max=180, + update=update_latlong, + default=151.209900, + ) timezone: StringProperty(name="Timezone", default="Etc/GMT") true_north: FloatProperty(name="True North", min=-180, max=180, update=update_true_north) - year: IntProperty(name="Year", min=1, max=9999, default=2025, update=update_date) - month: IntProperty(name="Month", min=1, max=12, default=1, update=update_date) - day: IntProperty(name="Date", min=1, max=31, default=1, update=update_date) - hour: IntProperty(name="Hour", min=0, max=23, default=12, update=update_hourminute) - minute: IntProperty(name="Minute", min=0, max=59, update=update_hourminute) + year: IntProperty(name="Year", min=1, max=9999, default=now.year, update=update_date) + month: IntProperty(name="Month", min=1, max=12, default=now.month, update=update_date) + day: IntProperty(name="Date", min=1, max=31, default=now.day, update=update_date) + hour: IntProperty(name="Hour", min=0, max=23, default=now.hour, update=update_hourminute) + minute: IntProperty(name="Minute", min=0, max=59, default=now.minute, update=update_hourminute) sun_position: FloatVectorProperty(name="Sun Position", subtype="XYZ", default=(0, 0, 0)) sun_path_origin: FloatVectorProperty(name="Sun Path Origin", subtype="XYZ", default=(0, 0, 0)) sun_path_size: FloatProperty(name="Sun Path Size", min=0.1, default=50, update=update_sun_path_size) @@ -504,3 +517,10 @@ class BIMSolarProperties(PropertyGroup): UTC_zone: float shadow_mode: Literal["NONE", "SHADING", "RENDERING"] display_sun_path: bool + + def set_from_datetime(self, dt: datetime.datetime) -> None: + self.year = dt.year + self.month = dt.month + self.day = dt.day + self.hour = dt.hour + self.minute = dt.minute diff --git a/src/bonsai/bonsai/bim/module/light/ui.py b/src/bonsai/bonsai/bim/module/light/ui.py index d3068823da..fb62ad5bab 100644 --- a/src/bonsai/bonsai/bim/module/light/ui.py +++ b/src/bonsai/bonsai/bim/module/light/ui.py @@ -165,7 +165,11 @@ class BIM_PT_solar(bpy.types.Panel): sun_props = tool.Blender.get_sun_props() - row = self.layout.row() + row = self.layout.row(align=True) + row.alignment = "RIGHT" + row.operator("bim.light_pick_coordinates", icon="URL", text="Pick") + + row = self.layout.row(align=True) row.prop(sun_props, "coordinates", icon="URL") row = self.layout.row(align=True) row.prop(props, "latitude") @@ -176,6 +180,10 @@ class BIM_PT_solar(bpy.types.Panel): if SolarData.data["true_north"] is not None: row.operator("bim.import_true_north", icon="IMPORT", text="") + row = self.layout.row() + row.alignment = "RIGHT" + row.operator("bim.light_set_time_to_now", icon="TIME", text="Now") + row = self.layout.row() row.prop(props, "year") row = self.layout.row(align=True)