// KeySelectorC.cpp: implementation of the KeySelectorC class.
//
//////////////////////////////////////////////////////////////////////

#pragma warning( disable : 4786 )		// long names generated by STL

#include "demopajadoc.h"
#include "KeySelectorC.h"
#include "PajaTypes.h"
#include "DataBlockI.h"
#include "EditableI.h"
#include "LayerC.h"
#include "EffectI.h"
#include "GizmoI.h"
#include "SceneItemC.h"
#include "ControllerC.h"
#include "UndoC.h"
#include <assert.h>
#include <vector>
#include "FileIO.h"


using namespace Composition;
using namespace PajaTypes;
using namespace Edit;
using namespace FileIO;


KeySelectorC::KeySelectorC()
{
	// empty
}

KeySelectorC::KeySelectorC( EditableI* pOriginal ) :
	EditableI( pOriginal )
{
	// empty
}

KeySelectorC::~KeySelectorC()
{
	// empty
}


KeySelectorC*
KeySelectorC::create_new()
{
	return new KeySelectorC;
}

DataBlockI*
KeySelectorC::create()
{
	return new KeySelectorC;
}

DataBlockI*
KeySelectorC::create( EditableI* pOriginal )
{
	return new KeySelectorC( pOriginal );
}

void
KeySelectorC::copy( EditableI* pEditable )
{
	KeySelectorC*	pSel = (KeySelectorC*)pEditable;
	m_rSelItems = pSel->m_rSelItems;
}

void
KeySelectorC::restore( EditableI* pEditable )
{
	KeySelectorC*	pSel = (KeySelectorC*)pEditable;
	m_rSelItems = pSel->m_rSelItems;
}

void
KeySelectorC::select_key( SceneItemC* pItem, PajaTypes::int32 i32Time )
{
	uint32			i;

	if( pItem->get_type() == SCENEITEM_LAYER || pItem->get_type() == SCENEITEM_EFFECT ) {

		TimeSegmentC*	pSeg;

		if( pItem->get_type() == SCENEITEM_LAYER ) {
			LayerC*			pLayer = pItem->get_layer();
			if( !pLayer )
				return;
			pSeg = pLayer->get_timesegment();
		}
		else if( pItem->get_type() == SCENEITEM_EFFECT ) {
			EffectI*			pEffect = pItem->get_effect();
			if( !pEffect )
				return;
			pSeg = pEffect->get_timesegment();
		}

		for( i = 0; i < pSeg->get_key_count(); i++ ) {
			KeyC*	pKey = pSeg->get_key( i );
			if( pKey->get_time() == i32Time ) {
				pKey->add_flags( KEY_SELECTED );
				break;
			}
		}
	}
	else if( pItem->get_type() == SCENEITEM_PARAMETER ) {
		if( pItem->get_parameter() )
		{
			ControllerC*	pCont = pItem->get_parameter()->get_controller();
			for( i = 0; i < pCont->get_key_count(); i++ ) {
				KeyC*	pKey = pCont->get_key( i );
				if( pKey->get_time() == i32Time ) {
					pKey->add_flags( KEY_SELECTED );
					break;
				}
			}
		}
	}


	// find a match for the item from the list
	for( i = 0; i < m_rSelItems.size(); i++ ) {
		if( m_rSelItems[i] == *pItem ) {
			// found match
			return;
		}
	}	

	// not found. add new
	SceneItemC	rNewItem = *pItem;
	rNewItem.delete_controller_sampledata();
	m_rSelItems.push_back( rNewItem );
}

void
KeySelectorC::deselect_key( SceneItemC* pItem, PajaTypes::int32 i32Time )
{
	int32			i32SelCount = 0;
	uint32			i;
	
	if( pItem->get_type() == SCENEITEM_LAYER || pItem->get_type() == SCENEITEM_EFFECT ) {

		TimeSegmentC*	pSeg;

		if( pItem->get_type() == SCENEITEM_LAYER ) {
			LayerC*			pLayer = pItem->get_layer();
			if( !pLayer )
				return;
			pSeg = pLayer->get_timesegment();
		}
		else if( pItem->get_type() == SCENEITEM_EFFECT ) {
			EffectI*			pEffect = pItem->get_effect();
			if( !pEffect )
				return;
			pSeg = pEffect->get_timesegment();
		}

		for( i = 0; i < pSeg->get_key_count(); i++ ) {
			KeyC*	pKey = pSeg->get_key( i );
			if( pKey->get_time() == i32Time ) {
				pKey->del_flags( KEY_SELECTED );
			}
			else if( pKey->get_flags() & KEY_SELECTED )
				i32SelCount++;
		}
	}
	else if( pItem->get_type() == SCENEITEM_PARAMETER ) {
		if( pItem->get_parameter() )
		{
			ControllerC*	pCont = pItem->get_parameter()->get_controller();
			for( i = 0; i < pCont->get_key_count(); i++ ) {
				KeyC*	pKey = pCont->get_key( i );
				if( pKey->get_time() == i32Time ) {
					pKey->del_flags( KEY_SELECTED );
				}
				else if( pKey->get_flags() & KEY_SELECTED )
					i32SelCount++;
			}
		}
	}

	// if theres still selected keys in this item return ...
	if( i32SelCount >= 0 )
		return;

	// ... otherwise remove the item.
	// find a match for the item from the list
	for( i = 0; i < m_rSelItems.size(); i++ ) {
		SceneItemC& rCurItem = m_rSelItems[i];
		if( m_rSelItems[i] == *pItem ) {
			// found match, remove it
			m_rSelItems.erase( m_rSelItems.begin() + i );
			return;
		}
	}	
}


void
KeySelectorC::update_selected_keys( SceneItemC* pItem )
{
	uint32			i;

	// find a match for the item from the list
	for( i = 0; i < m_rSelItems.size(); i++ ) {
		if( m_rSelItems[i] == *pItem ) {
			return;
		}
	}	

	// not found. add new
	SceneItemC	rNewItem = *pItem;
	rNewItem.delete_controller_sampledata();
	m_rSelItems.push_back( rNewItem );
}


void
KeySelectorC::deselect_all()
{
	uint32			i, j;

	for( i = 0; i < m_rSelItems.size(); i++ ) {
		SceneItemC& rItem = m_rSelItems[i];

		if( rItem.get_type() == SCENEITEM_LAYER || rItem.get_type() == SCENEITEM_EFFECT ) {

			TimeSegmentC*	pSeg;

			if( rItem.get_type() == SCENEITEM_LAYER ) {
				LayerC*			pLayer = rItem.get_layer();
				if( !pLayer )
					return;
				pSeg = pLayer->get_timesegment();
			}
			else if( rItem.get_type() == SCENEITEM_EFFECT ) {
				EffectI*			pEffect = rItem.get_effect();
				if( !pEffect )
					return;
				pSeg = pEffect->get_timesegment();
			}

			for( j = 0; j < pSeg->get_key_count(); j++ ) {
				KeyC*	pKey = pSeg->get_key( j );
				pKey->del_flags( KEY_SELECTED );
			}
		}
		else if( rItem.get_type() == SCENEITEM_PARAMETER ) {
			if( !rItem.get_parameter() )
				return;
			ControllerC*	pCont = rItem.get_parameter()->get_controller();
			for( j = 0; j < pCont->get_key_count(); j++ ) {
				KeyC*	pKey = pCont->get_key( j );
				pKey->del_flags( KEY_SELECTED );
			}
		}
	}

	m_rSelItems.clear();
}


void
KeySelectorC::select_all_keys( SceneItemC* pItem )
{
	TimeSegmentC*	pSeg;
	uint32			i;

	if( pItem->get_type() == SCENEITEM_LAYER || pItem->get_type() == SCENEITEM_EFFECT ) {

		if( pItem->get_type() == SCENEITEM_LAYER ) {
			LayerC*			pLayer = pItem->get_layer();
			if( !pLayer )
				return;
			pSeg = pLayer->get_timesegment();
		}
		else if( pItem->get_type() == SCENEITEM_EFFECT ) {
			EffectI*			pEffect = pItem->get_effect();
			if( !pEffect )
				return;
			pSeg = pEffect->get_timesegment();
		}

		for( i = 0; i < pSeg->get_key_count(); i++ ) {
			KeyC*	pKey = pSeg->get_key( i );
			pKey->add_flags( KEY_SELECTED );
		}
	}
	else if( pItem->get_type() == SCENEITEM_PARAMETER ) {
		if( !pItem->get_parameter() )
			return;
		ControllerC*	pCont = pItem->get_parameter()->get_controller();

		for( i = 0; i < pCont->get_key_count(); i++ ) {
			KeyC*	pKey = pCont->get_key( i );
			pKey->add_flags( KEY_SELECTED );
		}
	}

	// find a match for the item from the list
	for( i = 0; i < m_rSelItems.size(); i++ ) {
		if( m_rSelItems[i] == *pItem ) {
			// found match
			return;
		}
	}	

	// not found. add new
	SceneItemC	rNewItem = *pItem;
	rNewItem.delete_controller_sampledata();
	m_rSelItems.push_back( rNewItem );
}


void
KeySelectorC::save_state_selected()
{
	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {
		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_LAYER || rItem.get_type() == SCENEITEM_EFFECT ) {

			TimeSegmentC*	pSeg;

			if( rItem.get_type() == SCENEITEM_LAYER ) {
				LayerC*			pLayer = rItem.get_layer();
				if( !pLayer )
					return;
				pSeg = pLayer->get_timesegment();
			}
			else if( rItem.get_type() == SCENEITEM_EFFECT ) {
				EffectI*			pEffect = rItem.get_effect();
				if( !pEffect )
					return;
				pSeg = pEffect->get_timesegment();
			}

			UndoC*	pOldUndo = pSeg->begin_editing( get_undo() );

			for( uint32 i = 0; i < pSeg->get_key_count(); i++ ) {
				KeyC*	pKey = pSeg->get_key( i );
				if( pKey->get_flags() & KEY_SELECTED ) {
					UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
					pKey->end_editing( pOldKeyUndo );
				}
			}

			pSeg->end_editing( pOldUndo );
		}
		else if( rItem.get_type() == SCENEITEM_PARAMETER ) {
			if( !rItem.get_parameter() )
				return;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			UndoC*	pOldUndo = pCont->begin_editing( get_undo() );

			// Save all keys. Calling "prepare" will change their values too.
			for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
				KeyC*	pKey = pCont->get_key( i );
				UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
				pKey->end_editing( pOldKeyUndo );
			}

			pCont->end_editing( pOldUndo );
		}
	}
}

void
KeySelectorC::move_keys( PajaTypes::int32 i32DeltaTime )
{
	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {
		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_LAYER || rItem.get_type() == SCENEITEM_EFFECT ) {

			TimeSegmentC*	pSeg;

			if( rItem.get_type() == SCENEITEM_LAYER ) {
				LayerC*			pLayer = rItem.get_layer();
				if( !pLayer )
					return;
				pSeg = pLayer->get_timesegment();
			}
			else if( rItem.get_type() == SCENEITEM_EFFECT ) {
				EffectI*			pEffect = rItem.get_effect();
				if( !pEffect )
					return;
				pSeg = pEffect->get_timesegment();
			}

			UndoC*	pOldUndo = pSeg->begin_editing( get_undo() );

			for( uint32 i = 0; i < pSeg->get_key_count(); i++ ) {
				KeyC*	pKey = pSeg->get_key( i );
				if( pKey->get_flags() & KEY_SELECTED ) {
					UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
					pKey->set_time( pKey->get_time() + i32DeltaTime );
					pKey->end_editing( pOldKeyUndo );
				}
			}

			pSeg->sort_keys();
			pSeg->end_editing( pOldUndo );
		}
		else if( rItem.get_type() == SCENEITEM_PARAMETER ) {
			if( !rItem.get_parameter() )
				return;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			UndoC*	pOldUndo = pCont->begin_editing( get_undo() );

			for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
				KeyC*	pKey = pCont->get_key( i );
				if( pKey->get_flags() & KEY_SELECTED ) {
					UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
					pKey->set_time( pKey->get_time() + i32DeltaTime );
					pKey->end_editing( pOldKeyUndo );
				}
			}

			pCont->sort_keys();
			pCont->prepare();

			pCont->end_editing( pOldUndo );
		}
	}
}

void
KeySelectorC::delete_selected()
{
	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {

		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_LAYER || rItem.get_type() == SCENEITEM_EFFECT ) {

			TimeSegmentC*	pSeg;

			if( rItem.get_type() == SCENEITEM_LAYER ) {
				LayerC*			pLayer = rItem.get_layer();
				if( !pLayer )
					return;
				pSeg = pLayer->get_timesegment();
			}
			else if( rItem.get_type() == SCENEITEM_EFFECT ) {
				EffectI*			pEffect = rItem.get_effect();
				if( !pEffect )
					return;
				pSeg = pEffect->get_timesegment();
			}

			UndoC*	pOldUndo = pSeg->begin_editing( get_undo() );

			for( int32 i = (int32)pSeg->get_key_count() - 1; i >= 0 ; i-- )
				if( pSeg->get_key( i )->get_flags() & KEY_SELECTED )
					pSeg->del_key( i );

			pSeg->sort_keys();
			pSeg->end_editing( pOldUndo );
		}
		else if( rItem.get_type() == SCENEITEM_PARAMETER ) {
			if( !rItem.get_parameter() )
				return;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			UndoC*	pOldUndo = pCont->begin_editing( get_undo() );

			for( int32 i = (int32)pCont->get_key_count() - 1; i >= 0 ; i-- ) {
				KeyC*	pKey = pCont->get_key( i );
				if( pKey->get_flags() & KEY_SELECTED )
					pCont->del_key( i );
			}

			pCont->prepare();
			pCont->end_editing( pOldUndo );
		}
	}
}

void
KeySelectorC::gather_common_values( CommonKeyValuesS* pCommon )
{
	float32	f32Tens = 0;
	float32	f32Cont = 0;
	float32	f32Bias = 0;
	float32	f32EaseIn = 0;
	float32	f32EaseOut = 0;

	int32	i32SameTensCount = 0;
	int32	i32SameContCount = 0;
	int32	i32SameBiasCount = 0;
	int32	i32SameEaseInCount = 0;
	int32	i32SameEaseOutCount = 0;

	// Initialise
	pCommon->m_i32SelCount = 0;
	pCommon->m_i32SmoothCount = 0;
	pCommon->m_i32LinCount = 0;
	pCommon->m_i32HoldCount = 0;
	pCommon->m_i32Interpolation = 0;

	pCommon->m_i32Tens = -1;
	pCommon->m_i32Cont = -1;
	pCommon->m_i32Bias = -1;
	pCommon->m_i32EaseIn = -1;
	pCommon->m_i32EaseOut = -1;


	// loop thru all selected parameters and selecte keys
	// gather all common values for all keys.

	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {
		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_PARAMETER ) {

			if( !rItem.get_parameter() )
				continue;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			if( pCont->get_type() != CONT_TYPE_FILE ) {
				for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
					FloatKeyC*	pKey = (FloatKeyC*)pCont->get_key( i );
					if( pKey && (pKey->get_flags() & KEY_SELECTED) ) {
						if( pKey->get_flags() & KEY_SMOOTH ) pCommon->m_i32SmoothCount++;
						if( pKey->get_flags() & KEY_LINEAR ) pCommon->m_i32LinCount++;
						if( pKey->get_flags() & KEY_HOLD ) pCommon->m_i32HoldCount++;

						if( i32SameTensCount && f32Tens == pKey->get_tens() ) i32SameTensCount++;
						else if( !i32SameTensCount ) { f32Tens = pKey->get_tens(); i32SameTensCount++; };

						if( i32SameContCount && f32Cont == pKey->get_cont() ) i32SameContCount++;
						else if( !i32SameContCount ) { f32Cont = pKey->get_cont(); i32SameContCount++; };

						if( i32SameBiasCount && f32Bias == pKey->get_bias() ) i32SameBiasCount++;
						else if( !i32SameBiasCount ) { f32Bias = pKey->get_bias(); i32SameBiasCount++; };

						if( i32SameEaseInCount && f32EaseIn == pKey->get_ease_in() ) i32SameEaseInCount++;
						else if( !i32SameEaseInCount ) { f32EaseIn = pKey->get_ease_in(); i32SameEaseInCount++; };

						if( i32SameEaseOutCount && f32EaseOut == pKey->get_ease_out() ) i32SameEaseOutCount++;
						else if( !i32SameEaseOutCount ) { f32EaseOut = pKey->get_ease_out(); i32SameEaseOutCount++; };

						pCommon->m_i32SelCount++;
					}
				}
			}
		}
	}

	// check common values for TCB and ease in/out
	if( i32SameTensCount == pCommon->m_i32SelCount )
		pCommon->m_i32Tens = (int32)((f32Tens + 1.0f) * 5.0f);
	
	if( i32SameContCount == pCommon->m_i32SelCount )
		pCommon->m_i32Cont = (int32)((f32Cont + 1.0f) * 5.0f);
	
	if( i32SameBiasCount == pCommon->m_i32SelCount )
		pCommon->m_i32Bias = (int32)((f32Bias + 1.0f) * 5.0f);
	
	if( i32SameEaseInCount == pCommon->m_i32SelCount )
		pCommon->m_i32EaseIn = (int32)(f32EaseIn * 10.0f);
	
	if( i32SameEaseOutCount == pCommon->m_i32SelCount )
		pCommon->m_i32EaseOut = (int32)(f32EaseOut * 10.0f);

	// check common interpolation method
	if( pCommon->m_i32SmoothCount == pCommon->m_i32SelCount )
		pCommon->m_i32Interpolation = KEY_SMOOTH;
	
	if( pCommon->m_i32LinCount == pCommon->m_i32SelCount )
		pCommon->m_i32Interpolation = KEY_LINEAR;

	if( pCommon->m_i32HoldCount == pCommon->m_i32SelCount )
		pCommon->m_i32Interpolation = KEY_HOLD;
}

void
KeySelectorC::set_interpolation( PajaTypes::uint32 ui32Type )
{
	// loop thru all selected parameters and selected keys
	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {
		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_PARAMETER ) {

			if( !rItem.get_parameter() )
				return;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			KeyC*			pKey;
			UndoC*			pOldUndo = pCont->begin_editing( get_undo() );

			for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
				pKey = pCont->get_key( i );
				if( pKey && (pKey->get_flags() & KEY_SELECTED) ) {
					UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );

					pKey->del_flags( KEY_SMOOTH );
					pKey->del_flags( KEY_LINEAR );
					pKey->del_flags( KEY_HOLD );

					if( ui32Type == KEY_SMOOTH )
						pKey->add_flags( KEY_SMOOTH );
					else if( ui32Type == KEY_LINEAR )
						pKey->add_flags( KEY_LINEAR );
					else if( ui32Type == KEY_HOLD )
						pKey->add_flags( KEY_HOLD );

					pKey->end_editing( pOldKeyUndo );
				}
			}
			pCont->prepare();
			pCont->end_editing( pOldUndo );
		}
	}
}

void
KeySelectorC::set_interpolation_property( PajaTypes::uint32 ui32Type, PajaTypes::float32 f32Val )
{
	// loop thru all selected parameters and selected keys
	for( uint32 j = 0; j < m_rSelItems.size(); j++ ) {
		SceneItemC&		rItem = m_rSelItems[j];

		if( rItem.get_type() == SCENEITEM_PARAMETER ) {

			if( !rItem.get_parameter() )
				return;

			ControllerC*	pCont = rItem.get_parameter()->get_controller();

			if( pCont->get_type() != CONT_TYPE_FILE ) {
				FloatKeyC*		pKey;
				UndoC*			pOldUndo = pCont->begin_editing( get_undo() );

				for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
					pKey = (FloatKeyC*)pCont->get_key( i );
					if( pKey && (pKey->get_flags() & KEY_SELECTED) ) {
						UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
						
						if( ui32Type == PROPERTY_TENS )
							pKey->set_tens( f32Val );
						if( ui32Type == PROPERTY_CONT )
							pKey->set_cont( f32Val );
						if( ui32Type == PROPERTY_BIAS )
							pKey->set_bias( f32Val );
						if( ui32Type == PROPERTY_EASE_IN )
							pKey->set_ease_in( f32Val );
						if( ui32Type == PROPERTY_EASE_OUT )
							pKey->set_ease_out( f32Val );

						pKey->end_editing( pOldKeyUndo );
					}
				}
				pCont->prepare();
				pCont->end_editing( pOldUndo );
			}
		}
	}
}

uint32
KeySelectorC::selected_items_count()
{
	return m_rSelItems.size();
}

SceneItemC*
KeySelectorC::get_selected_item( uint32 ui32Index )
{
	assert( ui32Index < m_rSelItems.size() );
	return &m_rSelItems[ui32Index];
}

bool
KeySelectorC::select_keys_in_range( SceneItemC* pItem, int32 i32StartTime, int32 i32EndTime )
{
	int32	i32SelCount = 0;
	int32	i32TimeOffset = 0;

	if( !pItem->get_layer() )
		return false;

	TimeSegmentC*	pLayerSegment = pItem->get_layer()->get_timesegment();

	if( pItem->get_type() == SCENEITEM_LAYER || pItem->get_type() == SCENEITEM_EFFECT ) {

		TimeSegmentC*	pSegment = 0;

		if( pItem->get_type() == SCENEITEM_LAYER ) {
			LayerC*			pLayer = pItem->get_layer();
			if( !pLayer )
				return false;
			pSegment = pLayer->get_timesegment();
			i32TimeOffset = pLayerSegment->get_segment_start();
		}
		else if( pItem->get_type() == SCENEITEM_EFFECT ) {
			EffectI*			pEffect = pItem->get_effect();
			if( !pEffect )
				return false;
			pSegment = pEffect->get_timesegment();
			i32TimeOffset = pLayerSegment->get_segment_start();
			i32TimeOffset += pSegment->get_segment_start();
		}

		// test keys
		for( uint32 i = 0; i < pSegment->get_key_count(); i++ ) {
			KeyC*	pKey = pSegment->get_key( i );
			if( (pKey->get_time() + i32TimeOffset) >= i32StartTime && (pKey->get_time() + i32TimeOffset) <= i32EndTime ) {
				pKey->add_flags( KEY_SELECTED );
				i32SelCount++;
			}
		}
	}
	else if( pItem->get_type() == SCENEITEM_PARAMETER ) {
		ParamI*			pParam = pItem->get_parameter();
		EffectI*		pEffect = pItem->get_effect();

		if( !pEffect || !pParam )
			return false;

		TimeSegmentC*	pEffectSegment = pEffect->get_timesegment();

		if( !pLayerSegment || !pEffectSegment )
			return false;

		ControllerC*	pCont = pParam->get_controller();

		if( !pCont )
			return false;

		i32TimeOffset = pLayerSegment->get_segment_start();
		i32TimeOffset += pEffectSegment->get_segment_start();

		UndoC*	pOldUndo = pCont->begin_editing( get_undo() );

		for( uint32 i = 0; i < pCont->get_key_count(); i++ ) {
			KeyC*	pKey = pCont->get_key( i );
			if( (pKey->get_time() + i32TimeOffset) >= i32StartTime && (pKey->get_time() + i32TimeOffset) <= i32EndTime ) {
				UndoC*	pOldKeyUndo = pKey->begin_editing( get_undo() );
				pKey->add_flags( KEY_SELECTED );
				pKey->end_editing( pOldKeyUndo );
				i32SelCount++;
			}
		}

		pCont->end_editing( pOldUndo );
	}

	if( i32SelCount ) {

		// find a match for the item from the list
		for( uint32 i = 0; i < m_rSelItems.size(); i++ ) {
			if( m_rSelItems[i] == *pItem ) {
				// found match
				return true;
			}
		}	

		// not found. add new
		SceneItemC	rNewItem = *pItem;
		rNewItem.delete_controller_sampledata();
		m_rSelItems.push_back( rNewItem );

		return true;
	}

	return false;
}

uint32
KeySelectorC::save( SaveC* pSave )
{
	return IO_OK;
}

uint32
KeySelectorC::load( LoadC* pLoad )
{
	return IO_OK;
}
