From 08446cc3a39bbc98f809ecafbb14c1c489bf7861 Mon Sep 17 00:00:00 2001
From: Darryl Pogue <darryl@dpogue.ca>
Date: Sat, 12 Jun 2021 16:07:01 -0700
Subject: [PATCH 1/3] Add support for waveset buoys

---
 korman/properties/modifiers/water.py | 33 ++++++++++++++++++++++++++++
 korman/ui/modifiers/water.py         | 16 ++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/korman/properties/modifiers/water.py b/korman/properties/modifiers/water.py
index 806883b..4e2bc4f 100644
--- a/korman/properties/modifiers/water.py
+++ b/korman/properties/modifiers/water.py
@@ -471,3 +471,36 @@ class PlasmaWaveTexState(PlasmaWaveState, PlasmaModifierProperties):
     def export(self, exporter, bo, so):
         waveset = exporter.mgr.find_create_object(plWaveSet7, name=bo.name, so=so)
         self.convert_wavestate(waveset.state.texState)
+
+
+class PlasmaBuoyObject(idprops.IDPropObjectMixin, bpy.types.PropertyGroup):
+    display_name = StringProperty(name="Display Name")
+    buoy_object = PointerProperty(name="Buoy Object",
+                                  description="Object that float on water",
+                                  type=bpy.types.Object,
+                                  poll=idprops.poll_mesh_objects)
+
+    @classmethod
+    def _idprop_mapping(cls):
+        return {"buoy_object": "object_name"}
+
+
+class PlasmaWaterBuoyModifier(PlasmaModifierProperties):
+    pl_depends = {"water_basic"}
+    pl_id = "water_buoy"
+
+    bl_category = "Water"
+    bl_label = "Water Buoys"
+    bl_description = ""
+
+    buoys = CollectionProperty(type=PlasmaBuoyObject)
+    active_buoy_index = IntProperty(options={"HIDDEN"})
+
+    def export(self, exporter, bo, so):
+        waveset = exporter.mgr.find_create_object(plWaveSet7, name=bo.name, so=so)
+        waveset.setFlag(plWaveSet7.kHasBuoys, True)
+
+        for i in self.buoys:
+            if i.buoy_object is None:
+                raise ExportError("'{}': Buoy Object for '{}' is invalid".format(self.key_name, i.display_name))
+            waveset.addBuoy(exporter.mgr.find_create_key(plSceneObject, bl=i.buoy_object))
diff --git a/korman/ui/modifiers/water.py b/korman/ui/modifiers/water.py
index 08313b9..203e8bb 100644
--- a/korman/ui/modifiers/water.py
+++ b/korman/ui/modifiers/water.py
@@ -135,3 +135,19 @@ def water_shore(modifier, layout, context):
     col.prop(modifier, "finger")
     col.prop(modifier, "edge_opacity")
     col.prop(modifier, "edge_radius")
+
+
+class BuoyListUI(bpy.types.UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
+        layout.prop(item, "display_name", emboss=False, text="", icon="MOD_CAST")
+
+
+def water_buoy(modifier, layout, context):
+    ui_list.draw_modifier_list(layout, "BuoyListUI", modifier, "buoys",
+                               "active_buoy_index", name_prefix="Buoy",
+                               name_prop="display_name", rows=2, maxrows=3)
+
+    # Display the active buoy
+    if modifier.buoys:
+        buoy = modifier.buoys[modifier.active_buoy_index]
+        layout.prop(buoy, "buoy_object", icon="MESH_DATA")

From adbdf31507bc4eaa5d8abfc12688f31558452e39 Mon Sep 17 00:00:00 2001
From: Darryl Pogue <darryl@dpogue.ca>
Date: Sat, 12 Jun 2021 21:21:23 -0700
Subject: [PATCH 2/3] Apply suggestions from code review

Co-authored-by: Adam Johnson <AdamJohnso@gmail.com>
---
 korman/properties/modifiers/water.py | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/korman/properties/modifiers/water.py b/korman/properties/modifiers/water.py
index 4e2bc4f..510f131 100644
--- a/korman/properties/modifiers/water.py
+++ b/korman/properties/modifiers/water.py
@@ -480,10 +480,6 @@ class PlasmaBuoyObject(idprops.IDPropObjectMixin, bpy.types.PropertyGroup):
                                   type=bpy.types.Object,
                                   poll=idprops.poll_mesh_objects)
 
-    @classmethod
-    def _idprop_mapping(cls):
-        return {"buoy_object": "object_name"}
-
 
 class PlasmaWaterBuoyModifier(PlasmaModifierProperties):
     pl_depends = {"water_basic"}
@@ -502,5 +498,5 @@ class PlasmaWaterBuoyModifier(PlasmaModifierProperties):
 
         for i in self.buoys:
             if i.buoy_object is None:
-                raise ExportError("'{}': Buoy Object for '{}' is invalid".format(self.key_name, i.display_name))
+                raise ExportError("'{}': Buoy Object for '{}' is invalid", self.key_name, i.display_name)
             waveset.addBuoy(exporter.mgr.find_create_key(plSceneObject, bl=i.buoy_object))

From 532b712ca642881ddc4d33c65911aa7795741325 Mon Sep 17 00:00:00 2001
From: Darryl Pogue <darryl@dpogue.ca>
Date: Sat, 12 Jun 2021 21:48:14 -0700
Subject: [PATCH 3/3] Improve buoy UI & export checks

---
 korman/idprops.py                    |  3 +++
 korman/properties/modifiers/water.py | 16 +++++++++++-----
 korman/ui/modifiers/water.py         | 15 +++++++++++----
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/korman/idprops.py b/korman/idprops.py
index 40cc474..4d62310 100644
--- a/korman/idprops.py
+++ b/korman/idprops.py
@@ -127,6 +127,9 @@ def poll_camera_objects(self, value):
 def poll_drawable_objects(self, value):
     return value.type == "MESH" and any(value.data.materials)
 
+def poll_dynamic_objects(self, value):
+    return value.plasma_modifiers.collision.enabled and value.plasma_modifiers.collision.dynamic
+
 def poll_empty_objects(self, value):
     return value.type == "EMPTY"
 
diff --git a/korman/properties/modifiers/water.py b/korman/properties/modifiers/water.py
index 510f131..aef5fcc 100644
--- a/korman/properties/modifiers/water.py
+++ b/korman/properties/modifiers/water.py
@@ -125,7 +125,7 @@ class PlasmaSwimRegion(idprops.IDPropObjectMixin, PlasmaModifierProperties, bpy.
         # Detector region bounds
         if self.region is not None:
             region_so = exporter.mgr.find_create_object(plSceneObject, bl=self.region)
-    
+
             # Good news: if this phys has already been exported, this is basically a noop
             member_group = "kGroupDetector" if exporter.mgr.getVer() == "pvMoul" else "kGroupLOSOnly"
             exporter.physics.generate_physical(self.region, region_so,
@@ -473,12 +473,12 @@ class PlasmaWaveTexState(PlasmaWaveState, PlasmaModifierProperties):
         self.convert_wavestate(waveset.state.texState)
 
 
-class PlasmaBuoyObject(idprops.IDPropObjectMixin, bpy.types.PropertyGroup):
-    display_name = StringProperty(name="Display Name")
+class PlasmaBuoyObject(bpy.types.PropertyGroup):
     buoy_object = PointerProperty(name="Buoy Object",
                                   description="Object that float on water",
+                                  options=set(),
                                   type=bpy.types.Object,
-                                  poll=idprops.poll_mesh_objects)
+                                  poll=idprops.poll_dynamic_objects)
 
 
 class PlasmaWaterBuoyModifier(PlasmaModifierProperties):
@@ -493,10 +493,16 @@ class PlasmaWaterBuoyModifier(PlasmaModifierProperties):
     active_buoy_index = IntProperty(options={"HIDDEN"})
 
     def export(self, exporter, bo, so):
+        if exporter.mgr.getVer() != pvMoul:
+            exporter.report.warning("Not supported on this version of Plasma", indent=3)
+            return
+        else:
+            exporter.report.port("This will only function on MOUL", indent=3)
+
         waveset = exporter.mgr.find_create_object(plWaveSet7, name=bo.name, so=so)
         waveset.setFlag(plWaveSet7.kHasBuoys, True)
 
         for i in self.buoys:
             if i.buoy_object is None:
-                raise ExportError("'{}': Buoy Object for '{}' is invalid", self.key_name, i.display_name)
+                raise ExportError("'{}': Buoy Object for '{}' is invalid", self.key_name, i.buoy_object.name)
             waveset.addBuoy(exporter.mgr.find_create_key(plSceneObject, bl=i.buoy_object))
diff --git a/korman/ui/modifiers/water.py b/korman/ui/modifiers/water.py
index 203e8bb..5ce74fd 100644
--- a/korman/ui/modifiers/water.py
+++ b/korman/ui/modifiers/water.py
@@ -139,7 +139,10 @@ def water_shore(modifier, layout, context):
 
 class BuoyListUI(bpy.types.UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
-        layout.prop(item, "display_name", emboss=False, text="", icon="MOD_CAST")
+        if item.buoy_object is None:
+            layout.label("[No Object Specified]", icon="ERROR")
+        else:
+            layout.label(item.buoy_object.name, icon="MOD_CAST")
 
 
 def water_buoy(modifier, layout, context):
@@ -148,6 +151,10 @@ def water_buoy(modifier, layout, context):
                                name_prop="display_name", rows=2, maxrows=3)
 
     # Display the active buoy
-    if modifier.buoys:
-        buoy = modifier.buoys[modifier.active_buoy_index]
-        layout.prop(buoy, "buoy_object", icon="MESH_DATA")
+    try:
+        buoy_ref = modifier.buoys[modifier.active_buoy_index]
+    except:
+        pass
+    else:
+        layout.alert = buoy_ref.buoy_object is None
+        layout.prop(buoy_ref, "buoy_object")