⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivp_physic_private.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 2 页
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.

#include <ivp_physics.hxx>

#ifndef WIN32
#	pragma implementation "ivp_physic_private.hxx"
#	pragma implementation "ivp_listener_object.hxx"
#	pragma implementation "ivp_listener_collision.hxx"
#	pragma implementation "ivp_controller.hxx"
#endif

#include <ivp_listener_object.hxx>
#include <ivp_listener_collision.hxx>
#include <ivp_physic_private.hxx>
#include <ivp_i_object_vhash.hxx>
#include <ivp_i_collision_vhash.hxx>
#include <ivp_mindist_intern.hxx> //because of Mindist
#include <ivp_friction.hxx>
#include <ivu_active_value.hxx>
#include <ivp_actuator.hxx>

#include <ivp_debug_manager.hxx> //because of debug psi_synchrone
#include <ivp_merge_core.hxx>
#include <ivp_debug.hxx>
#include <ivp_universe_manager.hxx>
#include <ivp_authenticity.hxx>


void IVP_Listener_Collision::event_pre_collision( IVP_Event_Collision *){;};   // the user app sould override this
void IVP_Listener_Collision::event_post_collision( IVP_Event_Collision *){;};   // the user app sould override this
void IVP_Listener_Collision::event_collision_object_deleted( IVP_Real_Object *){;};  // only object private callbacks are called	

	// friction
    // set the IVP_LISTENER_COLLISION_CALLBACK_FRICTION bit in the constructor if you want to use this
void IVP_Listener_Collision::event_friction_created(IVP_Event_Friction *){;};   // the user app sould override this
void IVP_Listener_Collision::event_friction_deleted(IVP_Event_Friction *){;};   // the user app sould override this

IVP_Cluster *IVP_Cluster_Manager::get_root_cluster()
{
    return root_cluster;
}

IVP_Cluster_Manager::IVP_Cluster_Manager(IVP_Environment *env)
{
	P_MEM_CLEAR(this);
	environment = env;
    root_cluster = new IVP_Cluster(env);
    this->obj_callback_hash = new IVP_Object_Callback_Table_Hash(16);
    this->collision_callback_hash = new IVP_Collision_Callback_Table_Hash(16);
}

void IVP_Cluster_Manager::fire_event_object_deleted(IVP_Event_Object *event_obj)
{
    IVP_Object_Callback_Table *obj_table;
    IVP_Real_Object *ro = event_obj->real_object;
    obj_table = this->obj_callback_hash->find_table(ro);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
	    lis->event_object_deleted(event_obj);
	    if (i>0 && !obj_callback_hash->find_table(ro)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_object_frozen(IVP_Event_Object *event_obj)
{
    IVP_Object_Callback_Table *obj_table;
    IVP_Real_Object *ro = event_obj->real_object;
    obj_table = this->obj_callback_hash->find_table(ro);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
	    lis->event_object_frozen(event_obj);
	    if (i>0 && !obj_callback_hash->find_table(ro)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_object_created(IVP_Event_Object *event_obj)
{
    IVP_Object_Callback_Table *obj_table;
    IVP_Real_Object *ro = event_obj->real_object;
    obj_table = this->obj_callback_hash->find_table(ro);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
	    lis->event_object_created(event_obj);
	    if (i>0 && !obj_callback_hash->find_table(ro)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_object_revived(IVP_Event_Object *event_obj)
{
    IVP_Object_Callback_Table *obj_table;
    IVP_Real_Object *ro = event_obj->real_object;
    obj_table = this->obj_callback_hash->find_table(ro);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
	    lis->event_object_revived(event_obj);
	    if (i>0 && !obj_callback_hash->find_table(ro)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_pre_collision(IVP_Real_Object *real_object, IVP_Event_Collision *event_obj)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
	    if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_PRE_COLLISION)) continue;

	    lis->event_pre_collision(event_obj);
	    if (i>0 && !collision_callback_hash->find_table(real_object)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_post_collision(IVP_Real_Object *real_object, IVP_Event_Collision *event_obj)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
	    if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_POST_COLLISION)) continue;

	    lis->event_post_collision(event_obj);
	    if (i>0 && !collision_callback_hash->find_table(real_object)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_collision_object_deleted(IVP_Real_Object *real_object)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
	    if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_OBJECT_DELETED)) continue;

	    lis->event_collision_object_deleted(real_object);
	    if (i>0 && !collision_callback_hash->find_table(real_object)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_friction_created(IVP_Real_Object *real_object, IVP_Event_Friction *event_friction)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
	    if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_FRICTION)) continue;
	    lis->event_friction_created(event_friction);
	    if (i>0 && !collision_callback_hash->find_table(real_object)) break;	// object deleted
	}
    }
}

void IVP_Cluster_Manager::fire_event_friction_deleted(IVP_Real_Object *real_object, IVP_Event_Friction *event_friction)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	int i;
	for (i=obj_table->listeners.len()-1; i>=0; i--) {
	    IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
	    if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_FRICTION)) continue;
	    lis->event_friction_deleted(event_friction);
	    if (i>0 && !collision_callback_hash->find_table(real_object)) break;	// object deleted
	}
    }
}





IVP_Real_Object *IVP_Cluster_Manager::get_next_real_object_in_cluster_tree(IVP_Object *object){

    IVP_Object *next_object;
    if (number_of_real_objects == 0) return NULL;
    if (object == NULL){
    	IVP_Cluster *root = get_root_cluster();
	object = root->get_first_object_of_cluster();
	next_object = object; // no object supplied: we get the root cluster and we want the first object in root cluster!
	if (!object) return NULL;
    }
    else {
	next_object = object->next_in_cluster; // object supplied: just get the next object in cluster
    }


    IVP_OBJECT_TYPE type = object->get_type();    
    // try to go down as deep as possible
    if(type == IVP_CLUSTER){
	IVP_Cluster *cluster = object->to_cluster();
	while(1){
	    object = cluster->get_first_object_of_cluster();
	    if (object){
		type = object->get_type();
		if (type != IVP_CLUSTER) return object->to_real();
		cluster = object->to_cluster();
		continue;
	    }else{
		break; // just get next_in_cluster
	    }
	}
    }

    IVP_Object *next;
    // go up until a next pointer is found

    for (next=next_object; !next; next=object->next_in_cluster) {
	IVP_Object *old_father = object;
	object = object->father_cluster;
	if (!object){
    	    IVP_Cluster *root = get_root_cluster();
	    if ( root == old_father ) return(NULL); /* necessary to avoid endless loop caused by the last object
						    *	(ball's father is cluster; cluster has no father,
						    *   therefore we would "get_root_cluster()" which is the same as
						    *   the old cluster and whose first object is the "static ball" 
						    *    --> perfect endless loop :-) [SF, 25 nov 1999]
						    */
	    object = root->get_first_object_of_cluster();
	    if (!object) return NULL;
	}
    }

    // now a next is found
    object = next;
    type = object->get_type();

    if (type == IVP_CLUSTER){
	return get_next_real_object_in_cluster_tree(object);
    }

    return object->to_real();
}

void IVP_Cluster_Manager::check_for_unused_objects(IVP_Universe_Manager *um){
    const IVP_Universe_Manager_Settings *ums = um->provide_universe_settings();

    if (number_of_real_objects < ums->num_objects_in_environment_threshold_0) return;
    {
	int i = int( ums->check_objects_per_second_threshold_0 * environment->get_delta_PSI_time());
	for ( ; i>=0; i-- ){
	    IVP_Real_Object *an_object = this->an_object_to_be_checked;
	    this->an_object_to_be_checked = get_next_real_object_in_cluster_tree(this->an_object_to_be_checked);
	    if (!an_object) return; // no objects available
	    if (an_object->get_collision_check_reference_count() != 0) continue;
	    um->object_no_longer_needed(an_object);
	    if (number_of_real_objects < ums->num_objects_in_environment_threshold_0)	    return;
	}
    }

    if (number_of_real_objects < ums->num_objects_in_environment_threshold_1) return;
    {
	int i = int( ums->check_objects_per_second_threshold_1 * environment->get_delta_PSI_time());
	for ( ; i>=0; i-- ){
	    IVP_Real_Object *an_object = this->an_object_to_be_checked;
	    if (!an_object) return; // no objects available
	    this->an_object_to_be_checked = get_next_real_object_in_cluster_tree(this->an_object_to_be_checked);
	    if (an_object->get_collision_check_reference_count() != 1) continue;
	    um->object_no_longer_needed(an_object);
	    if (number_of_real_objects < ums->num_objects_in_environment_threshold_1)	    return;
	}
    }

    return;
}

IVP_Universe_Manager_Settings::IVP_Universe_Manager_Settings(){
	num_objects_in_environment_threshold_0 = 1;
	check_objects_per_second_threshold_0 = 1;

	num_objects_in_environment_threshold_1 = 1000000;
	check_objects_per_second_threshold_1 = 10;
};

IVP_Object_Callback_Table::~IVP_Object_Callback_Table()
{
    return;
}

IVP_Collision_Callback_Table::~IVP_Collision_Callback_Table()
{
    return;
}


IVP_Cluster_Manager::~IVP_Cluster_Manager() 
{ 
    P_DELETE( root_cluster );
    P_DELETE(this->obj_callback_hash);
    P_DELETE(this->collision_callback_hash);
}

void IVP_Cluster_Manager::add_listener_object(IVP_Real_Object *real_object, IVP_Listener_Object *listener)
{
    IVP_Object_Callback_Table *obj_table;
    obj_table = this->obj_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	obj_table->listeners.add(listener);
    }
    else {
	obj_table = new IVP_Object_Callback_Table();
	obj_table->real_object = real_object;
	obj_table->listeners.add(listener);
	this->obj_callback_hash->add_table(obj_table);        
	real_object->flags.object_listener_exists = 1;
    }
    return;
}

void IVP_Cluster_Manager::add_listener_collision(IVP_Real_Object *real_object, IVP_Listener_Collision *listener)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	obj_table->listeners.add(listener);
    }
    else {
	obj_table = new IVP_Collision_Callback_Table();
	obj_table->real_object = real_object;
	obj_table->listeners.add(listener);
	this->collision_callback_hash->add_table(obj_table);        
	real_object->flags.collision_listener_exists = 1;
    }
    return;
}

void IVP_Cluster_Manager::remove_listener_object(IVP_Real_Object *real_object, IVP_Listener_Object *listener)
{
    IVP_Object_Callback_Table *obj_table;
    obj_table = this->obj_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	obj_table->listeners.remove(listener);
	if ( obj_table->listeners.len() == 0 ) {
	    this->obj_callback_hash->remove_table(real_object);
	    delete obj_table;
	    real_object->flags.object_listener_exists = 0;
	}
    }
    return;
}

void IVP_Cluster_Manager::remove_listener_collision(IVP_Real_Object *real_object, IVP_Listener_Collision *listener)
{
    IVP_Collision_Callback_Table *obj_table;
    obj_table = this->collision_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	obj_table->listeners.remove(listener);
	if ( obj_table->listeners.len() == 0 ) {
	    this->collision_callback_hash->remove_table(real_object);
	    delete obj_table;
	    real_object->flags.collision_listener_exists = 0;
	}
    }
    return;
}

void IVP_Cluster_Manager::add_object(IVP_Real_Object * /*real_object*/ ){
    this->number_of_real_objects++;
}


void IVP_Cluster_Manager::remove_object(IVP_Real_Object *real_object)
{
    this->number_of_real_objects--;
    IVP_Object_Callback_Table *obj_table;
    obj_table = this->obj_callback_hash->find_table(real_object);
    if ( obj_table != NULL ) {
	this->obj_callback_hash->remove_table(real_object);
	delete obj_table;
    }

    IVP_Collision_Callback_Table *coll_table;
    coll_table = this->collision_callback_hash->find_table(real_object);
    if ( coll_table != NULL ) {
	this->collision_callback_hash->remove_table(real_object);
	delete coll_table;
    }

    if (real_object == an_object_to_be_checked){
        an_object_to_be_checked = get_next_real_object_in_cluster_tree(an_object_to_be_checked);
		if (real_object == an_object_to_be_checked){
			an_object_to_be_checked = NULL;
		}
    }

    IVP_Universe_Manager *um = environment->get_universe_manager();
    if (um){
	    um->event_object_deleted(real_object);
    }

    return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -