// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.library;

import static net.cellcomputing.himawari.library.CqStats.STATS_INC;
import static net.cellcomputing.himawari.library.EqIntIndex.GPR_created;
import static net.cellcomputing.himawari.library.EqModeBlock.Motion;
import static net.cellcomputing.himawari.library.RiGlobal.QGetRenderContext;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.util.HimawariLogger;

/**
 * 
 * Define the context that exists between calls to RiMotionBegin/RiMotionEnd.
 *  RiMotionBegin/RiMotionEndが呼ばれている間に存在する、コンテキストを定義する。
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqMotionModeBlock extends CqModeBlock
{
	
	/**
	 * コンストラクタ。　初期値の設定。
	 * @param N	times[]のサイズ。
	 * @param times	モーションの指定時間。
	 * @param pconParent	前のコンテキスト。
	 */
	public CqMotionModeBlock( int N, float times[], final CqModeBlock pconParent )
	{
		super( pconParent, Motion );
	    
		// Copy the parents attributes, as this state change doesn't save attributes.
		//　状態の変化で変わるアトリビュートは保存されないため、親のアトリビュートをコピー
	    if ( pconParent != null)
	        m_pattrCurrent = pconParent.m_pattrCurrent;
	    else
	    { //pconParent　== nullの場合は仕様上起こらない。。と思われる。
	        m_pattrCurrent = new CqAttributes();
	        m_pattrCurrent.AddRef(); //ADD するなら　Relese　する？
	    }

	    if ( pconParent != null)
	    {
			m_ptransCurrent = new CqTransform(pconParent.m_ptransCurrent );
	
			// Set the default 'new time slot' matrix to the current 0 time matrix, this
	        // takes care of the case of moving from non-Motion to Motion.
			// 現在のマトリクスにデフォルト値'new time slot'を設定。 非モーションからモーションまでの動きを管理する。
		    
			//m_ptransCurrent->SetDefaultObject( m_ptransCurrent->GetMotionObject( m_ptransCurrent->Time( 0 ) ) );
			SqTransformation ct = new SqTransformation();
			ct.m_matTransform.assignment( m_ptransCurrent.matObjectToWorld( m_ptransCurrent.Time( 0 ) ) );
			ct.m_Handedness = m_ptransCurrent.GetHandedness( m_ptransCurrent.Time( 0 ) );
			m_ptransCurrent.SetDefaultObject( new SqTransformation(ct) );
	    }
	    else
	    {
	        m_ptransCurrent = new CqTransform();
	    }


	    // Store the array of times.
	    int i;
	    for ( i = 0; i < N; i++ )
	        m_aTimes.add( times[ i ] );

	    m_iTime = 0;
	}
	
	
	/** 
	 * デストラクタ。　実装なし。
	 * @see net.cellcomputing.himawari.library.CqModeBlock#destruct()
	 */
	@Override
	public void destruct()
	{}

	
    /**
     * Create a main context.<br>
     * 	メインのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     */
	@Override
    public CqModeBlock BeginMainModeBlock()
    {
        return 	null;	// Error
    }		
    
    
    /** 
     * Create a frame context.<br>
     * フレームのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     */
    @Override
    public CqModeBlock BeginFrameModeBlock()
    {
        return	null;	// Error
    }		
    
    
    /** 
     * Create a world context.<br>
     * 	ワールドのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     */
    @Override
    public CqModeBlock BeginWorldModeBlock()
    {
        return 	null;	// Error
    }		
    
    
    /** 
     * Create a attribute context.<br>
     * 	アトリビュートのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     */
    @Override
    public CqModeBlock BeginAttributeModeBlock()
    {
        return	null;	// Error
    }		
    
    
    /**
     * Create a transform context.<br>
     * 	トランスフォームのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     * @see net.cellcomputing.himawari.library.CqModeBlock#BeginTransformModeBlock()
     */
    @Override
    public CqModeBlock BeginTransformModeBlock()
    {
        return	null;	// Error
    }	
    
    
    /**
     * Create a solid context.<br>
     * 	ソリッドのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     * @see net.cellcomputing.himawari.library.CqModeBlock#BeginSolidModeBlock(java.lang.String)
     */
    @Override
    public CqModeBlock	BeginSolidModeBlock( String type )
    {
        return	null;	// Error
    }	
    
    
    /**
     * Create a object context.<br>
     * 	オブジェクトのコンテキストを作成する。
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     * @see net.cellcomputing.himawari.library.CqModeBlock#BeginObjectModeBlock()
     */
    @Override
    public CqModeBlock BeginObjectModeBlock()
    {
        return	null;	// Error
    }	
    
    
    /**
     * Create a motion context.<br>
     * 	モーションのコンテキストを作成する。	// Error
     * 
     * @warning モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     * @see net.cellcomputing.himawari.library.CqModeBlock#BeginMotionModeBlock(int, float[])
     */
    @Override
    public CqModeBlock BeginMotionModeBlock( int N, float times[] )
    {
        return	null;	// Error
    }		

   
    /**
     * Delete the object context.<br>
     * 	オブジェクトのコンテキストを消去する。
     * 
     * @attention 	モーションコンテキストの中で、このメソッドが呼ばれた場合エラーとなる。
     * @see net.cellcomputing.himawari.library.CqModeBlock#EndMotionModeBlock()
     */
    @Override
    public void EndMotionModeBlock()
    {
        if( m_pDeformingSurface != null )
        {
        	//check motion object size
        	if( m_pDeformingSurface.m_aObjects.size() < 2 ) {
        		HimawariLogger.getLogger().error( "Motion Objects is more 2 necessary.\n " );
        		if( m_pDeformingSurface.m_aObjects.size()==1 )QGetRenderContext().pImage().PostSurface( m_pDeformingSurface.m_aObjects.get(0) );
        	}
        	else{
        		QGetRenderContext().pImage().PostSurface( m_pDeformingSurface );
        	}
            STATS_INC( GPR_created );
        }
    }
    
   
    /**
     * Get a reference to the options at the parent context, <br>
     * 	as motion context doesn't store options.<br>
     * 	オプションのゲッタ。<br>
     * 	モーションコンテキストはオプションを保存しないため、親のオプションを返す。	
     * 
     * @return	親のオプション
     * @see net.cellcomputing.himawari.library.CqModeBlock#optCurrent()
     */
    @Override
    public CqOptions optCurrent()
    {
        return ( pconParent().optCurrent() );
    }

    
    /**
     * Get the current time,<br> 
     * as specified at initialisation of the block.<br>
     * 	ブロックの初期化で指定された時間を取得。
     * 
     * @return 現在の時。　指定時間を越えている場合は0を返す。
     * @see net.cellcomputing.himawari.library.CqModeBlock#Time()
     */
    @Override
    public float Time()
    {
        if ( m_iTime < m_aTimes.size() )
            return ( m_aTimes.get( m_iTime ).floatValue() );
        else
            return ( 0.0f );
    }
    
   
    /**
     * Advance the current time to the next specified time.<br>
     *  現在の時間を指定された次の時間に進める。
     *  
     * @see net.cellcomputing.himawari.library.CqModeBlock#AdvanceTime()
     */
    @Override
    public void	AdvanceTime()
    {
        m_iTime++;
    }
    
    
    /**
     * Get the current frame index if in a motion block.<br>
     * 現在のフレームインデックスのゲッタ。<br>
     *  モーションブロックの中なら、現在のフレームのインデックスを取得。
     *  
     * @see net.cellcomputing.himawari.library.CqModeBlock#TimeIndex()
     */
    @Override
    public int	TimeIndex()
    {
		return( m_iTime );
	}
    
    
    /** 
     * Indicate that this is a motion block.<br>
     * 	モーションブロックの中であれば、trueを返す。
     * 
     * @return 　true
     */
    @Override
    public boolean	fMotionBlock()
    {
        return ( true );
    }
    
    
    /**
     * Get the CqDeformingSurface,<br> 
     * if generating a deformation motion blur sequence.<br>
     * 	CqDeformingSurfaceのゲッタ。<br>
     * 	変形モーションブラー系列を発生させる場合に使用。
     * 
     * @return	m_pDeformingSurface	現在のm_pDeformingSurface
     */
    public CqDeformingSurface GetDeformingSurface()
    {
        return( m_pDeformingSurface );
    }
    
    
    /**
     * Set the CqDeformingSurface, <br>
     * if generating a deformation motion blur sequence.<br>
     * CqDeformingSurfaceのセッタ。<br>
     * 	変形モーションブラー系列を発生場合に使用。
     * 変形モーションブラー系列を発生させるなら、CqDeformingSurfaceを設定してください。
     * 
     * @param pDeformingSurface	セットオブジェクト
     */
    public void SetDeformingSurface( final CqDeformingSurface pDeformingSurface)
    {
        m_pDeformingSurface = pDeformingSurface;
    }
    
    private int					m_iTime;		///< フレーム時間のインデックス。 < The index of the current frame time.
    private STLVector<Float>		m_aTimes = new STLVector<Float>( Float.class );		///< An array of specified frame times.
    private CqDeformingSurface	m_pDeformingSurface;
}