// Filename: physical.cxx
// Created by:  charles (16Jun00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include <pointerTo.h>

#include "physical.h"
#include "physicsManager.h"

TypeHandle Physical::_type_handle;

// the idea here is that most physicals will NOT be collections of
// sets (i.e. particle systems and whatever else).  Because of this,
// the default constructor, unless otherwise specified, will
// automatically allocate and initialize one PhysicalObject.
// this makes it easier for high-level work.

// pre-alloc is ONLY for multiple-object physicals, and if true,
// fills the physics_object vector with dead nodes, pre-allocating
// for the speed end of the speed-vs-overhead deal.

////////////////////////////////////////////////////////////////////
//     Function : Physical
//       Access : Public
//  Description : Default Constructor
////////////////////////////////////////////////////////////////////
Physical::
Physical(int ttl_objects, bool pre_alloc) {
  _physical_node = (PhysicalNode *) NULL;
  _physics_manager = (PhysicsManager *) NULL;

  if (ttl_objects == 1) {
    _phys_body = new PhysicsObject;
    add_physics_object(_phys_body);
  }
  else {
    int i;
    _phys_body = (PhysicsObject *) NULL;

    // allocate each object.
    if (pre_alloc == true) {
      PhysicsObject *po;

      for (i = 0; i < ttl_objects; i++) {
        po = new PhysicsObject;
        add_physics_object(po);
      }
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function : Physical
//       Access : Public
//  Description : copy constructor (note- does deep copy of pn's)
//                but does NOT attach itself to its template's
//                physicsmanager.
////////////////////////////////////////////////////////////////////
Physical::
Physical(const Physical& copy) {
  _physics_manager = (PhysicsManager *) NULL;

  // copy the forces.
  pvector< PT(LinearForce) >::const_iterator lf_cur;
  pvector< PT(LinearForce) >::const_iterator lf_end = copy._linear_forces.end();

  for (lf_cur = copy._linear_forces.begin(); lf_cur != lf_end; lf_cur++) {
    _linear_forces.push_back((*lf_cur)->make_copy());
  }

  pvector< PT(AngularForce) >::const_iterator af_cur;
  pvector< PT(AngularForce) >::const_iterator af_end = copy._angular_forces.end();

  for (af_cur = copy._angular_forces.begin(); af_cur != af_end; af_cur++) {
    _angular_forces.push_back((*af_cur)->make_copy());
  }

  // copy the physics objects
  pvector< PT(PhysicsObject) >::const_iterator p_cur;
  pvector< PT(PhysicsObject) >::const_iterator p_end = copy._physics_objects.end();

  for (p_cur = copy._physics_objects.begin(); p_cur != p_end; p_cur++) {
    // oooh so polymorphic.
    _physics_objects.push_back((*p_cur)->make_copy());
  }

  // now set the one-element-quick-access pointer
  if (_physics_objects.size() == 1)
    _phys_body = _physics_objects[0];
  else
    _phys_body = (PhysicsObject *) NULL;
}

////////////////////////////////////////////////////////////////////
//     Function : ~Physical
//       Access : Public
//  Description : destructor
////////////////////////////////////////////////////////////////////
Physical::
~Physical(void) {
  // note that this removes a physical from a physics manager.
  // this is safe because the physics manager doesn't keep PT's to
  // physicals, simply *'s, and also means that we don't have to tell
  // the physics manager ourselves when one of our physicals is dead.
  if (_physics_manager != (PhysicsManager *) NULL) {
    _physics_manager->remove_physical(this);
  }
}



