######################################
###  DM2_w25 # AGruber@tugraz.at   ###
### hu_08 Mary Poppins Regenschirm ###
######################################

import rhinoscriptsyntax as rs
import random, time, sys, math
sys.path.append("P:/")
sys.path.append("P:/WWW/dx6419/dm2/")
import DM_lib as dm
import scriptcontext as sc

rs.UnitSystem(4)  # Meter
rs.ShowGrid(None, False)
rs.ShowGridAxes(None, False)
rs.ViewDisplayMode(rs.CurrentView(), "wireframe")
rs.Command("cplane w t enter", False)  # World Top

dm.PointRadius(displayModeX=0, rad=3, styl=3)
dm.PointRadius(displayModeX=1, rad=4, styl=1)
dm.PointRadius(displayModeX=2, rad=2, styl=0)
dm.printDisplay(state=False)

rs.EnableRedraw(False)

# -------------------------
# Funktion zum Erzeugen des Schirms
# -------------------------
def create_umbrella_safe(position=[0,0,0], radius=0.5, pole_height=20, num_ribs=8, circle_drop=0.8, rib_drop=0.1, pole_length=0.6):
    pos3d = rs.coerce3dpoint(position)
    pos3d = rs.PointAdd(pos3d, [0,0,-pole_height])
    top = rs.VectorAdd(pos3d, [0,0,pole_height])

    # Schirmkreis Punkte
    circle_z = pole_height * circle_drop
    circle_points = []
    for i in range(num_ribs):
        angle = 2*math.pi*i/num_ribs
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        z = circle_z
        cor = [x,y,z]
        cor = rs.VectorAdd(cor, pos3d)
        circle_points.append(cor)

    # Streben
    for pt_coords in circle_points:
        mid = dm.pntInbetween(top, pt_coords)
        mid[2] += pole_height * rib_drop
        rs.AddCurve([top, mid, pt_coords], degree=2)

    # Schirmkante
    circle_points.append(circle_points[0])
    rs.AddCurve(circle_points, 1)

    # Stab
    bottom = rs.PointAdd(top, [0,0,-pole_length])
    rs.AddLine(top, bottom)

    return bottom  # unteres Ende des Stabs

# -------------------------
# Flugbahn und Parameter
# -------------------------
flugbahn = rs.ObjectsByName("flugbahn")[0]
anzahl = 200
positions = rs.DivideCurve(flugbahn, anzahl, 1)

dm.newEmptyLayer("PROJECT::umbrellas", [0,100,200])
rs.Redraw()

delta_circle_drop = dC = (0.9 - 0.1)/anzahl
delta_rib_drop    = dR = (0.6 - 0.2)/anzahl
delta_radius      = dRad = (20.0 - 0.1)/anzahl
pole_start = 0.8
pole_end   = 20.0
delta_pole = (pole_end - pole_start) / anzahl


# Blockinstanz und Punkt auf Layer "Mary popins"
layer_name = "Mary popins"
objs_on_layer = rs.ObjectsByLayer(layer_name)

block_instance = None

# Blockinstanz suchen
for obj in objs_on_layer:
    if rs.IsBlockInstance(obj):
        block_instance = obj
        break

if not block_instance:
    raise Exception("Keine Blockinstanz auf Layer '{}' gefunden.".format(layer_name))

# Punkt innerhalb der Blockdefinition abfragen
block_def_name = rs.BlockInstanceName(block_instance)
block_def_objs = rs.BlockObjects(block_def_name)

block_def_point = None
for obj in block_def_objs:
    if rs.IsPoint(obj):
        block_def_point = rs.PointCoordinates(obj)
        break

if not block_def_point:
    raise Exception("Kein Punkt innerhalb der Blockdefinition gefunden!")

# Transformation der Instanz abrufen, um Punkt in Instanz-Koordinaten zu bekommen
xform = rs.BlockInstanceXform(block_instance)
block_point_inst = rs.PointTransform(block_def_point, xform)


stop_distance = 200  # Block bleibt 185 Einheiten vor letztem Schirm stehen
end_pos = positions[-1]

# Animation: immer nur aktueller Schirm + Block
last_umbrella_objs = []
last_block = None
block_stop = False

for i, pos in enumerate(positions):


    if sc.escape_test():
        print("Animation abgebrochen!")
        break
        

    if last_umbrella_objs:
        rs.DeleteObjects(last_umbrella_objs)
        last_umbrella_objs = []

    # Vorherigen Block nur loeschen, wenn Stop noch nicht erreicht
    if last_block and not block_stop:
        rs.DeleteObject(last_block)
        last_block = None

    # Schirm erzeugen
    objs_before = set(rs.AllObjects())  
    bottom = create_umbrella_safe(
        position=pos,
        radius=0.1 + dRad*i,
        num_ribs=8 + i,
        circle_drop=0.9 - dC*i,
        rib_drop=0.2 + dR*i,
        pole_length=pole_start + delta_pole*i
    )
    objs_after = set(rs.AllObjects())
    last_umbrella_objs = list(objs_after - objs_before)  

    # Block erzeugen und bewegen
    dist_to_end = rs.Distance(bottom, end_pos)
    if not block_stop:
        if dist_to_end > stop_distance:
            # Block fliegt mit
            target_point_on_stab = bottom
            new_block = rs.CopyObject(block_instance)
            translation = rs.VectorCreate(target_point_on_stab, block_point_inst)
            rs.MoveObject(new_block, translation)
            last_block = new_block
        else:
            # Stop-Abstand erreicht Block wird einmal erzeugt und bleibt stehen
            target_point_on_stab = bottom
            new_block = rs.CopyObject(block_instance)
            translation = rs.VectorCreate(target_point_on_stab, block_point_inst)
            rs.MoveObject(new_block, translation)
            last_block = new_block
            block_stop = True  

    # Animationseffekt
    rs.Redraw()
    rs.Sleep(100)



rs.EnableRedraw(True)
dm.printDisplay(state=True, scale=1000)
dm.newEmptyLayer("Default")
print("done")
