require 'sketchup.rb'

dir = File.dirname(__FILE__)
$LOAD_PATH.insert(0, dir)

# List of all global variables in SP
$spExperimentalFeatures = true
$bSPDoRecord = false
$spReplayCamera = false
$spMovieMode = false
$spObjectInspector = nil
$sketchyPhysicsToolInstance = nil
$curPhysicsSimulation = nil
$curEvalGroup = nil
$curEvalTouchingGroup = nil

# Version variable for compatibility.
$sketchyphysics_version_loaded = MSketchyPhysics3::VERSION.to_f

begin
  require 'class_extensions.rb'
  require 'newton.rb'
  require 'virtual_key_codes.rb'
  require 'input.rb'
  require 'midi.rb'
  require 'sound.rb'
  require 'controller_commands.rb'
  require 'sp_util.rb'
  require 'control_panel.rb'
  require 'settings_ui.rb'
  require 'prims_tool.rb'
  require 'box_prim_tool.rb'
  require 'joint_tool.rb'
  require 'joint_connection_tool.rb'
  require 'attach_tool.rb'
  require 'sketchy_replay.rb'
  require 'sp_tool.rb'
rescue Exception => e
  err = RUBY_VERSION =~ /1.8/ ? "#{e}\n\n#{e.backtrace.join("\n")}" : e
  raise err
ensure
  $LOAD_PATH.delete_at(0)
end

unless file_loaded?(__FILE__)

  menu = UI.menu('Plugins').add_submenu('SketchyPhysics')
  help_menu = UI.menu('Help')

  menu.add_item('Physics Settings'){
    MSketchyPhysics3.editPhysicsSettings
  }

  menu.add_item('Buoyancy Settings'){
    MSketchyPhysics3.setupBuoyancy
  }

  menu.add_item('Edit Joint Scale'){
    MSketchyPhysics3.editJointScale
  }

  menu.add_item('Erase All Attributes'){
    msg = "This option removes all SP attributes including saved body script.\n"
    msg << "Are you sure you want to continue?"
    next if UI.messagebox(msg, MB_YESNO) == IDNO
    model = Sketchup.active_model
    if Sketchup.version.to_i > 6
      model.start_operation('Remove SP Atrributes', true)
    else
      model.start_operation('Remove SP Atrributes')
    end
    model.definitions.each { |cd|
      cd.instances.each { |inst|
        atr = inst.attribute_dictionaries
        next unless atr
        atr.delete('SPOBJ')
        atr.delete('SPTAKE')
        inst.layer = 'Layer0' if (inst.is_a?(Sketchup::Text) && atr['SketchyPhysics'])
        atr.delete('SketchyPhysics')
      }
    }
    model.entities.grep(Sketchup::Text).each { |ent|
      atr = ent.attribute_dictionaries
      next unless atr
      ent.layer = 'Layer0' if atr['SketchyPhysics']
      atr.delete('SketchyPhysics')
    }
    model.attribute_dictionaries.delete('SPRECORD')
    model.attribute_dictionaries.delete('SPSETTINGS')
    model.attribute_dictionaries.delete('sketchyphysics')
    model.attribute_dictionaries.delete('SketchyPhysics')
    msg = "Would you like to erase all SP joints as well?"
    to_remove = []
    if UI.messagebox(msg, MB_YESNO) == IDYES
      model.definitions.each { |cd|
        cd.instances.each { |inst|
          if inst.attribute_dictionaries && inst.attribute_dictionaries['SPJOINT']
            to_remove << inst
          end
        }
      }
    end
    to_remove.each { |e| e.erase! if e.valid? }
    to_remove.clear
    model.definitions.purge_unused
    model.materials.purge_unused
    model.layers.purge_unused
    model.styles.purge_unused
    model.commit_operation
  }

  menu.add_separator

  menu.add_item("Check for new version..."){
    #dir = File.dirname(__FILE__)
    #path = File.join(dir, 'html/sp.html')
    #UI.openURL path
    UI.openURL('http://5mp.eu/fajlok2/sp3/sphysics_www.5mp.eu_.html')
  }

  about_msg = "SketchyPhysics #{MSketchyPhysics3::VERSION} -- #{MSketchyPhysics3::RELEASE_DATE}\n"
  about_msg << "Powered by the Newton Dynamics #{MSketchyPhysics3.getNewtonVersion} Physics SDK.\n"
  about_msg << "Copyright © 2007, Chris Phillips\n\n"
  menu.add_item('About'){ UI.messagebox(about_msg) }
  toolbar = UI::Toolbar.new 'SketchyPhysics'

  # Toolbar icons size
  if Sketchup.version.to_i < 16
    small = 'images/small_6_15/'
    large = 'images/large_6_15/'
  else
    small = 'images/icons_16+/'
    large = 'images/icons_16+/'
  end

  cmd = UI::Command.new('Play'){
    MSketchyPhysics3::SketchyPhysicsClient.physicsTogglePlay
  }
  cmd.set_validation_proc {
    MSketchyPhysics3::SketchyPhysicsClient.active? ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.menu_text = cmd.tooltip = 'Play/Pause'
  cmd.status_bar_text = 'Play/Pause physics simulation.'
  cmd.small_icon = small + 'toggle_play.png'
  cmd.large_icon = large + 'toggle_play.png'
  toolbar.add_item(cmd)


  cmd = UI::Command.new('Stop'){
    MSketchyPhysics3::SketchyPhysicsClient.physicsReset
  }
  cmd.set_validation_proc {
    MF_GRAYED unless MSketchyPhysics3::SketchyPhysicsClient.active?
  }
  cmd.menu_text = cmd.tooltip = 'Stop'
  cmd.status_bar_text = 'Reset physics simulation.'
  cmd.small_icon = small + 'rewind.png'
  cmd.large_icon = large + 'rewind.png'
  toolbar.add_item(cmd)


  cmd = UI::Command.new('JointConnectionTool'){
    model = Sketchup.active_model
    if MSketchyPhysics3::JointConnectionTool.active?
      model.select_tool nil
      model.selection.clear
    else
      model.select_tool MSketchyPhysics3::JointConnectionTool.new
    end
  }
  cmd.set_validation_proc {
    if MSketchyPhysics3::SketchyPhysicsClient.active?
      MF_GRAYED
    else
      MSketchyPhysics3::JointConnectionTool.active? ? MF_CHECKED : MF_UNCHECKED
    end
  }
  cmd.menu_text = cmd.tooltip = 'Joint Connector'
  cmd.status_bar_text = 'Activate / Deactivate joint connection tool.
L-Ctrl:   Add joints.
L-shift:  Remove joints.'
  cmd.small_icon = small + 'joint_connector.png'
  cmd.large_icon = large + 'joint_connector.png'
  toolbar.add_item(cmd)

  cmd = UI::Command.new('ShowUI'){
    $spObjectInspector.toggleDialog
  }
  cmd.set_validation_proc {
    if MSketchyPhysics3::SketchyPhysicsClient.active?
      MF_GRAYED
    else
      $spObjectInspector.dialogVisible? ? MF_CHECKED : MF_UNCHECKED
    end
  }
  cmd.menu_text = cmd.tooltip = 'Settings'
  cmd.status_bar_text = 'Show/Hide Settings dialog.
This dialog is free scalable.'
  cmd.small_icon = small + 'ui.png'
  cmd.large_icon = large + 'ui.png'
  toolbar.add_item(cmd)

  toolbar.show


  # ----------------------------------------------------------------------------
  # Create sketchy replay toolbar
  # ----------------------------------------------------------------------------


  toolbar = UI::Toolbar.new('SketchyReplay')
  $bSPDoRecord = false
  $spMovieMode = false
  replayAnimation = nil

  cmd = UI::Command.new('Record'){ $bSPDoRecord = !$bSPDoRecord }
  cmd.set_validation_proc {
    $bSPDoRecord ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'replay_record.png'
  cmd.large_icon = large + 'replay_record.png'
  cmd.menu_text = cmd.tooltip = 'Record'
  cmd.status_bar_text = 'Check to record simulation.'
  toolbar.add_item cmd


  cmd = UI::Command.new('RepalyCamera'){ $spReplayCamera = !$spReplayCamera }
  cmd.set_validation_proc {
    $spReplayCamera ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'replay_camera.png'
  cmd.large_icon = large + 'replay_camera.png'
  cmd.menu_text = cmd.tooltip = 'Replay Camera'
  cmd.status_bar_text = 'Check to replay camera.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Play'){
    unless replayAnimation
      replayAnimation = SketchyReplay::SketchyReplay.new
    end
    replayAnimation.play
  }
  cmd.set_validation_proc {
    if MSketchyPhysics3::SketchyPhysicsClient.active?
      MF_GRAYED
    else
      next MF_UNCHECKED unless replayAnimation
      replayAnimation.paused? ? MF_UNCHECKED : MF_CHECKED
    end
  }
  cmd.small_icon = small + 'replay_toggle_play.png'
  cmd.large_icon = large + 'replay_toggle_play.png'
  cmd.menu_text = cmd.tooltip = 'Replay'
  cmd.status_bar_text = 'Play/Pause animation.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Rewind'){
    replayAnimation.rewind if replayAnimation
  }
  cmd.set_validation_proc {
    MF_GRAYED if MSketchyPhysics3::SketchyPhysicsClient.active?
  }
  cmd.small_icon = small + 'replay_rewind.png'
  cmd.large_icon = large + 'replay_rewind.png'
  cmd.menu_text = cmd.tooltip = 'Rewind'
  cmd.status_bar_text = 'Reset animation, set objects to original placement.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Reverse'){
    replayAnimation.reverse if replayAnimation
  }
  cmd.set_validation_proc {
    MF_GRAYED if MSketchyPhysics3::SketchyPhysicsClient.active?
  }
  cmd.small_icon = small + 'replay_reverse.png'
  cmd.large_icon = large + 'replay_reverse.png'
  cmd.menu_text = cmd.tooltip = 'Reverse'
  cmd.status_bar_text = 'Reverse animation.'
  toolbar.add_item cmd


  cmd = UI::Command.new('RecordMovie'){
    $spMovieMode = !$spMovieMode
  }
  cmd.set_validation_proc {
    if MSketchyPhysics3::SketchyPhysicsClient.active?
      MF_GRAYED
    else
      $spMovieMode ? MF_CHECKED : MF_UNCHECKED
    end
  }
  cmd.small_icon = small + 'replay_movie.png'
  cmd.large_icon = large + 'replay_movie.png'
  cmd.menu_text = cmd.tooltip = 'Movie Mode'
  cmd.status_bar_text = 'Toggle movie mode.'
  #~ toolbar.add_item cmd


  submenu = UI.menu('Plugins').add_submenu('SketchyReplay')
  submenu.add_item('Export to KerkyThea'){
    SketchyReplay.export_to_kerkythea
  }
  submenu.add_item('Export Animation'){
    sr = SketchyReplay::SketchyReplay.new
    sr.export
  }
  submenu.add_item('Erase Record'){
    model = Sketchup.active_model
    if Sketchup.version.to_i > 6
      model.start_operation('Export SP to Kerkythea', true)
    else
      model.start_operation('Export SP to Kerkythea')
    end
    model.definitions.each { |cd|
      cd.instances.each { |ci|
        ci.delete_attribute('SPTAKE', 'samples')
      }
    }
    model.attribute_dictionaries.delete('SPRECORD')
    model.commit_operation
  }
  submenu.add_separator
  submenu.add_item('About'){
    UI.messagebox("Version 1.6.0\nWritten by Chris Phillips.")
  }

  toolbar.show


  # ----------------------------------------------------------------------------
  # Create joints toolbar
  # ----------------------------------------------------------------------------


  toolbar = UI::Toolbar.new 'SketchyPhysics Joints'

  %w(hinge piston servo slider motor gyro fixed).each do |joint|
    cmd = UI::Command.new(joint.capitalize){
      Sketchup.active_model.select_tool(MSketchyPhysics3::CreateJointTool.new(joint))
    }
    cmd.set_validation_proc {
      $selectedJoint == joint ? MF_CHECKED : MF_UNCHECKED
    }
    cmd.menu_text = cmd.tooltip = joint.capitalize
    cmd.status_bar_text = "Create a #{joint} joint."
    cmd.small_icon = small + "#{joint}.png"
    cmd.large_icon = large + "#{joint}.png"
    toolbar.add_item(cmd)
  end

  toolbar.add_separator

  %w(corkscrew spring ball universal).each do |joint|
    cmd = UI::Command.new(joint.capitalize){
      Sketchup.active_model.select_tool(MSketchyPhysics3::CreateJointTool.new(joint))
    }
    cmd.set_validation_proc {
      $selectedJoint == joint ? MF_CHECKED : MF_UNCHECKED
    }
    cmd.menu_text = cmd.tooltip = joint.capitalize
    cmd.status_bar_text = "Create a #{joint} joint."
    cmd.small_icon = small + "#{joint}.png"
    cmd.large_icon = large + "#{joint}.png"
    toolbar.add_item(cmd)
  end

  toolbar.add_separator

  cmd = UI::Command.new('jointscale'){
    MSketchyPhysics3.editJointScale
  }
  cmd.small_icon = small + 'jointscale.png'
  cmd.large_icon = large + 'jointscale.png'
  cmd.menu_text = cmd.tooltip = 'Edit Joint Scale'
  cmd.status_bar_text = 'Edit size of all Joints.'
  toolbar.add_item cmd

  toolbar.restore

  # ----------------------------------------------------------------------------
  # Create prisms toolbar
  # ----------------------------------------------------------------------------


  toolbar = UI::Toolbar.new('Sketchy Solids')

  cmd = UI::Command.new('Floor'){ MSketchyPhysics3.createPhysicsFloor }
  cmd.small_icon = small + 'floor.png'
  cmd.large_icon = large + 'floor.png'
  cmd.menu_text = cmd.tooltip = 'Create floor'
  cmd.status_bar_text = 'Create a static-mesh floor.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Box'){ MSketchyPhysics3.createPrim('box') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'box' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'box.png'
  cmd.large_icon = large + 'box.png'
  cmd.menu_text = cmd.tooltip = 'Create box'
  cmd.status_bar_text = 'Create a rectangular prism.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Sphere'){ MSketchyPhysics3.createPrim('sphere') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'sphere' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'sphere.png'
  cmd.large_icon = large + 'sphere.png'
  cmd.menu_text = cmd.tooltip = 'Create sphere'
  cmd.status_bar_text = 'Create a sphere.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Cylinder'){ MSketchyPhysics3.createPrim('cylinder') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'cylinder' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'cylinder.png'
  cmd.large_icon = large + 'cylinder.png'
  cmd.menu_text = cmd.tooltip = 'Create cylinder'
  cmd.status_bar_text = 'Create a cylinder.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Cone'){ MSketchyPhysics3.createPrim('cone') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'cone' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'cone.png'
  cmd.large_icon = large + 'cone.png'
  cmd.menu_text = cmd.tooltip = 'Create cone'
  cmd.status_bar_text = 'Create a cone.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Capsule'){ MSketchyPhysics3.createPrim('capsule') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'capsule' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'capsule.png'
  cmd.large_icon = large + 'capsule.png'
  cmd.menu_text = cmd.tooltip = 'Create a capsule or chamfer'
  cmd.status_bar_text = 'Create a capsule or chamfer.'
  toolbar.add_item cmd

  toolbar.add_separator

  cmd = UI::Command.new('Wheel'){ MSketchyPhysics3.createPrim('wheel') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'wheel' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'wheel.png'
  cmd.large_icon = large + 'wheel.png'
  cmd.menu_text = cmd.tooltip = 'Create wheel'
  cmd.status_bar_text = 'Create wheel, a capsule with a hinge or servo (press CTRL) at center.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Door'){ MSketchyPhysics3.createPrim('door') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'door' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'door.png'
  cmd.large_icon = large + 'door.png'
  cmd.menu_text = cmd.tooltip = 'Create door'
  cmd.status_bar_text = 'Create door, a box with a hinge or servo (press CTRL) at the first corner.'
  toolbar.add_item cmd


  cmd = UI::Command.new('Lift'){ MSketchyPhysics3.createPrim('lift') }
  cmd.set_validation_proc {
    MSketchyPhysics3.selectedPrim == 'lift' ? MF_CHECKED : MF_UNCHECKED
  }
  cmd.small_icon = small + 'lift.png'
  cmd.large_icon = large + 'lift.png'
  cmd.menu_text = cmd.tooltip = 'Create lift'
  cmd.status_bar_text = 'Create lift, a capsule with a built in slider or piston (press CTRL) at center.'
  toolbar.add_item cmd

  toolbar.show

  file_loaded(__FILE__)
end
