# AC3D
# (C) Copyright 2003 Inivis


proc hier_mark_selections {} {
global oblist
global obnum

   .hier.listbox selection clear 0 $obnum
   for {set n 0} {$n < $obnum} {incr n} {
       if { [ac3d object_is_selected $oblist($n) ] } {
            .hier.listbox selection set $n $n 
       } else {
            .hier.listbox selection clear $n $n 
       }
   }
}


proc poo { object level } {
global oblist
global obnum

    set oblist($obnum) $object
    incr obnum

    set name [ac3d object_get_name $object]
    set str ""
    for { set n 0 } { $n < $level} {incr n} {
        set str "$str      "
    }

	set kids [ac3d object_get_children $object]

	if {$kids > 0} {
		if { $level == 0 } {
			set type "World "
		} else {
			set type "Group "
		}
	} else {
	    set type "Object"
	}

	set str "$str - $type "

	if { $name == "" } {
		set str "$str $name"
	} else {
		set str "$str '$name'";
	}

    if { [ac3d object_is_visible $object]} {
        set str "$str \[hidden/locked]"
    }
    .hier.listbox insert end $str

    if { [ac3d object_is_selected $object ] } {
        .hier.listbox selection set $obnum $obnum
    }

    if {$kids != ""} {
        foreach k $kids {
           poo $k [expr $level+1]
        }
    }
}


proc hier_click {win pos} {
global oblist
global obnum

    if { [$win selection include $pos] } {
        ac3d object_select $oblist([$win index $pos])
    } else {
        ac3d object_deselect $oblist([$win index $pos])
    }
    ac3d redraw_all
    sync_ui
}


proc hier_make_list {} {
global oblist
global obnum

    set obnum 0
    set world [ac3d get_world]

    set top [.hier.listbox yview]
   .hier.listbox delete 0 end
    poo $world 0

    .hier.listbox yview moveto [lindex $top 0]
    hier_mark_selections

}



proc hier_view_prop {} {
global hier_current
global oblist

    set ob $oblist($hier_current)
    set w .hier$hier_current

    if [winfo exists $w] { destroy $w}

    toplevel $w
    wm title $w "Object Properties"
    wm transient $w [winfo toplevel [winfo parent $w]]

    set str "Name:"
    set name [ac3d object_get_name $ob]
    set str "$str $name"

    set children [ac3d object_get_children $ob]
    set numkids [llength $children]
    set str "$str\nChildren: $numkids"

    set surfaces [ac3d object_get_surfaces $ob]
    set numsurf [llength $surfaces]
    set str "$str\nSurfaces: $numsurf"

    set vertices [ac3d object_get_vertices $ob]
    set numvert [llength $vertices]
    set str "$str\nVertices: $numvert"

    set cen [ac3d object_get_centre $ob]
    set str "$str\nT: $cen"

    set url [ac3d object_get_url $ob]
    set str "$str\nURL: $url"

    set data [ac3d object_get_data $ob]
    set str "$str\nData: $data"

    label $w.lab -text $str -justify left
    pack  $w.lab -side top 
    button $w.close -text "Close" -command "destroy $w"
    pack $w.close -side bottom
    centre_window_on_screen $w

}


proc hier_hide_object {} {
global hier_current
global oblist

    set ob $oblist($hier_current)
    ac3d object_hide $ob
    ac3d redraw_all
    hier_make_list
    sync_ui

}

proc hier_unhide_object {} {
global hier_current
global oblist

    set ob $oblist($hier_current)
    ac3d object_unhide $ob
    ac3d redraw_all
    hier_make_list
    sync_ui

}

proc hier_move_to_head {} {
global hier_current
global oblist

    set ob $oblist($hier_current)
    ac3d object_move_to_head $ob
    ac3d redraw_all
    hier_make_list
    sync_ui
}



proc menu_hier {} {
global oblist
global obnum
global hier_current

    set obnum 0

  if ![winfo exists .hier] {

    toplevel .hier
    wm title .hier "Object Hierarchy"
    wm transient .hier [winfo toplevel [winfo parent .hier]]

    label .hier.selinfo -textvariable select_info -justify left
    pack .hier.selinfo -side top


    listbox .hier.listbox -selectmode multiple -yscrollcommand {.hier.yscroll set }
    scrollbar .hier.yscroll -orient vertical \
		-command { .hier.listbox yview }

    bind .hier.listbox <ButtonRelease-1> { hier_click %W @%x,%y }
    frame .hier.buttons
    button .hier.buttons.close -text "Close" -command { wm withdraw .hier }
    button .hier.buttons.refresh -text "Refresh" -command { hier_make_list }
    pack .hier.buttons.close .hier.buttons.refresh -side left
    pack .hier.buttons -side bottom


    frame .hier.functions
    pack .hier.functions -side bottom
    button .hier.functions.b1 -text "Select all" -command { ac3d select_all ; hier_make_list }
    button .hier.functions.b2 -text "Select none" -command { ac3d clear_selection ; hier_make_list }
    button .hier.functions.group -text "Group" -command { ac3d group ; hier_make_list }
    button .hier.functions.ungroup -text "Ungroup" -command { ac3d ungroup ; hier_make_list }
    pack .hier.functions.b1 .hier.functions.b2 .hier.functions.group .hier.functions.ungroup \
         -side left
    pack .hier.yscroll  -side left -fill y
    pack .hier.listbox  -side left -fill both -expand 1
#    pack .hier.listbox -expand 1 -fill y

    if ![winfo exists .hiermenu] {
        menu .hiermenu -tearoff false 
        .hiermenu add command -label "View properties..." -command "hier_view_prop"

        .hiermenu add command -label "Hide" -command "hier_hide_object"
        .hiermenu add command -label "Unhide" -command "hier_unhide_object"
		.hiermenu add command -label "Move to head" -command "hier_move_to_head"
        .hiermenu add command -label "Edit object data..." -command "hier_edit_object_data"

    }

    bind .hier.listbox <3> { set hier_current  [.hier.listbox index @%x,%y ]; tk_popup .hiermenu %X %Y }

    # call the trace function to grey out the group/ungroup buttons if needed
    hier_trace_select_mode 0 0 0
  } else {
    
    wm deiconify .hier
    raise .hier
  }
    centre_window_on_screen .hier

    hier_make_list
}

proc hier_trace_select_mode { name1 name2 op } {
global select_mode

  if ![winfo exists .hier] return

   if { $select_mode == "tree"} {
       set_sensitive true .hier.functions.group .hier.functions.ungroup
   } else {
       set_sensitive false .hier.functions.group .hier.functions.ungroup
   }

}


proc hier_trace_select_info { name1 name2 op } {
global select_mode

  if ![winfo exists .hier] return
    hier_make_list

}

proc hier_update { } {

  if ![winfo exists .hier] return
    hier_make_list

}


#could probably add hier_make_list in sync_ui proc but do this instead:
trace variable select_mode w hier_trace_select_mode
trace variable select_info w hier_trace_select_info
