「 プログラムをコピー 」に続いて「 プレイヤーを起動 」をクリックし、プレイヤー画面に貼り付けると、WEBブラウザ上でそのままプログラムを実行できます。

>> プレイヤーを起動できない場合はこちら

import Graphics ; 
import Graphics3D ; 
import GUI ; 
import Math ; 
import Time ; 
import Text ;


// import ここから


/* NUMERIC */

double o = 0.0, a = 1.0, d = 10.0 ;
double Slv = 2*cos( PI/4 ) , ISlv = cos( PI/4 ) ;
double Gld = 2*cos( PI/5 ) , IGld = Gld - 1.0 ;
double Plt = 2*cos( PI/6 ) , IPlt = tan( PI/6 ) ;
int O = newVector( o, o, o ) ; 

double l = 1.0 ; // 長さに用いる単位
int N ;

// symmetry
int S24 = 24, S12 = 12, S8 = 8, S6 = 6, S5 = 5, S4 = 4, S3 = 3, S2 = 2 ; 
int R3 = 3, R4 = 4, R5 = 5, R6 = 6, R8 = 8 ;


/* FUNCTIONS */

// unit step function
double Step( double x ) {

    double value;
    if ( x < 0.0 ) {
        value = 0.0 ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

double Slope( double x, double x0, double deltax ) {

    double value;
    if ( x < x0 ) {
        value = 0.0 ;
    } else if ( x < ( x0 + deltax ) ) {
        value = ( x - x0 ) / deltax ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

double VelvetySlope( double x, double x0, double deltax ) {

    double value;
    if ( x < x0 ) {
        value = 0.0 ;
    } else if ( x < ( x0 + deltax ) ) {
        double y = ( x - x0 ) / deltax ;
        value = ( 1.0 + sin( -PI/2 + PI*y ) ) / 2 ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

// eyeteeth ( teeth of saw )
double Eyeteeth( double x, double width ) {
// 0 <= x <=1
    double s = x ;
    if ( ( x < 0.0 ) || ( x > 1.0 ) ) {
        alert( "Error ( Eyeteeth ) " );
    } else {
        while ( s > width ) {
        s = s - width ;
        }
    }
    return s / width ;
}

// pulsar
double Pulsar( double x, double cycle, double upslope, double top, double downslope ) {
// 0 <= x <=1
    double value;
    double s = Eyeteeth( x, cycle ) ;
    double ups = upslope / cycle ;
    double tops = top / cycle ;
    double downs = downslope / cycle ;
    if ( s < ups ) {
        value = Bump( s / ups * 0.5 ) ; 

    } else if ( s < ups + tops ) {
        value = 1.0 ;
    } else if ( s < ups + tops + downs ) {
            value = Bump( 0.5 + ( ( s - ( ups + tops ) ) / downs ) * 0.5 ) ;
    } else {
        value = 0.0 ;
    }
    return value ;
}

// unit bump function
double Bump( double x ) {

    return ( sin( 2*PI * x - PI/2 ) + 1.0 ) / 2 ;
}

double TurnBump( double x ) {

    return 1.0 - Bump( x ) ;
}

double MSlope( double x ) {

    double y ;
    if ( x > 1.0 ) {
        y = x - (int)( x ) ;
    } else if ( x >= 0.0 ) {
        y = x ;
    } else {
        y = x + ( 1.0 - (int)( x ) ) ;
    }
    double value ;
    if ( y > 1.0/2 ) {
        y = 1.0 - y ;
    }
    if ( y > 1.0/3 ) {
        value = 0.0 ;
    } else if ( y > 1.0/6 ) {
        value = 2 - 6*y ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

int Parity( int i ) {

    int p;
    if ( i % 2 == 0 ) {
        p = 1 ;
    } else {
        p = -1 ;
    }
    return p ;
}


/* 3DGRAPHICS */

string TITLE ;
int TITLE_HEIGHT = 26 ;
int BORDER = 7 ;
int MAIN_GRAPHICS, MAIN_WINDOW, MAIN_DISPLAY_LABEL, RENDERER ;
int WIDTH = 0, HEIGHT = 0, WINDOW_POSITION_X = 0 ;

void Set3DGraphics( int w, int h, int x, int y, int bgcolor[ ] ) {

    WIDTH = w ;
    HEIGHT = h ;
    WINDOW_POSITION_X = x ;
    int bgred = bgcolor[0] ;
    int bggreen = bgcolor[1] ;
    int bgblue = bgcolor[2] ;
    int framewidth_x = 2*BORDER ;
    int framewidth_y = 2*BORDER + TITLE_HEIGHT ;
    int bgalpha = 255 ;
    MAIN_GRAPHICS = newGraphics()
    RENDERER = newGraphics3DRenderer( w, h, MAIN_GRAPHICS ) ;
    MAIN_WINDOW = newWindow( 
        WINDOW_POSITION_X, y, WIDTH + framewidth_x, HEIGHT + framewidth_y,
        " CG Window"
    ) ;
    MAIN_DISPLAY_LABEL = newGraphicsLabel( 
        0, 0, WIDTH, HEIGHT, MAIN_GRAPHICS 
    ) ;
    addComponent( MAIN_DISPLAY_LABEL, MAIN_WINDOW );
    setGraphics3DDefaultEventHandler( RENDERER, MAIN_DISPLAY_LABEL );
    setGraphics3DColor( RENDERER, bgred, bggreen, bgblue, bgalpha );
}

void PrepareStage() {

    int mds[ ] = getComponentSize( MAIN_DISPLAY_LABEL ) ;
    setGraphics3DCenter( RENDERER, mds[0] / 2, mds[1] / 2 );
    setGraphics3DDistance( RENDERER, GRAPHIC_DISTANCE );
    setGraphics3DMagnification( RENDERER, GRAPHIC_MAGNIFICATION );

    setGraphics3DClipFront( RENDERER, o );
    setGraphics3DClipBack( RENDERER, -1000.0 );

    int w = getWorldCoordinate( RENDERER ) ;
    setCoordinateOrigin( w, o, o, o )
    setCoordinateEulerAngle( w, o, o, o );
    setCameraOrigin( w, o, o, CAMERA_ORIGIN_Z );
    setCameraEulerAngle( w, o, o, o );
}


/* OUTPUT */

void PaintGraphics() {

    paintGraphics3D( RENDERER );
    paintComponent( MAIN_DISPLAY_LABEL );
}

void SaveImgPng() {
    int id = 10000 ;
    PICTURE_NUMBER = PICTURE_NUMBER + 1 ; 
    int filename = id + PICTURE_NUMBER ;
    exportGraphics(
        MAIN_GRAPHICS, "../../image/movie/" + filename + ".png", "PNG" 
    ) ;
}

int PICTURE_END_NUMBER = 5000 ;

void ExitLoopOverImageLimit() {
    alert( 
        "画像の保存が上限 ( " 
        + PICTURE_END_NUMBER 
        + " 枚 ) に達したため、CGアニメーションを終了します。"
    );
    KEEP_LOOP = false ;
}

void PrintBasicInfo() {

    print( lf()
        + " title                        " + TITLE + lf()
        + lf()
        + " movie " + lf()
        + " start time                =  " + START_T + " sec" + lf()
        + " start count               =  " + START_C + lf()
        + " end time                  =  " + END_T + " sec" + lf()
        + " end count                 =  " + END_C + lf()
        + " movie running time        =  " + ( END_T - START_T ) + " sec" + lf()
        + " movie running count       =  " + ( END_C - START_C + 1 ) + lf()
        + " added time                =  " + ( ADDED_T ) + " sec" + lf()
        + " 2*PI rotation             =  " + ( ROT_N ) + " times" + lf()
        + " number of frames          =  " + (int)( ( END_T - START_T ) / DEL_T / 

STEP + 1 ) + lf()
        + " frames / 1sec             =  " + FPS + lf()
        + " 1 / ( frames / 1sec )     =  " + a/2 / FPS + " sec(@ACCEL=0)" + lf()
        + "                           =  " + a / FPS + " sec(@ACCEL=1)" + lf()
        + "                           =  " + 2*a / FPS + " sec(@ACCEL=2)" + lf()
        + "                           =  " + 4*a / FPS + " sec(@ACCEL=3)" + lf()
        + "                           =  " + 8*a / FPS + " sec(@ACCEL=4)" + lf()
        + " number of indexed states  =  " + length( SX ) + lf()
        + lf()
        + " limit " + lf()
        + " of running time           =  " + LIMIT + " sec" + lf()
    ) ;
}

void SaveAnImage() { // override 用

}

bool ConfirmAboutSaving() {

    return confirm(
            "画像保存の上限に達しました",
            "保存上限を変更しますか?"
            ) ;
}


/* ROUTINE */

void PrintVectorln( int v, string s ) {
    println( "Vector " + s + " = "
        + getVectorX( v ) + ", "
        + getVectorY( v ) + ", "
        + getVectorZ( v )
    );
}

void SetPolygonSurface( int id, float x[ ] ) {

    setPolygonEmissive( id, x[0] );
    setPolygonDiffractive( id, x[1] );
    setPolygonDiffuse( id, x[2] );
    setPolygonAmbient( id, x[3] );
    setPolygonSpecular( id, x[4], x[5] );
}

void SetModelSurface( int id, float x[ ] ) {

    setModelEmissive( id, x[0] );
    setModelDiffractive( id, x[1] );
    setModelDiffuse( id, x[2] );
    setModelAmbient( id, x[3] );
    setModelSpecular( id, x[4], x[5] );
}

// polygonの光学性質をもとめて指定
void SetPolygonSurface( int polygon[ ][ ][ ], float option[ ] ) {

    for ( int i=0; i<length( polygon )[2]; i++ ) {
        for ( int j=0; j<length( polygon )[1]; j++ ) {
            for ( int k=0; k< length( polygon )[0]; k++ ) {
                SetPolygonSurface( polygon[i][j][k], option ) ;
            }
        }
    }
}
void SetPolygonSurface( int polygon[ ][ ], int ng, float option[ ] ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        SetPolygonSurface( polygon[ng][i], option ) ;
    }
}
void SetPolygonSurface( int polygon[ ][ ][ ], int ng, float option[ ] ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            SetPolygonSurface( polygon[ng][i][j], option ) ;
        }
    }
}

void SetPolygonColor( int id, int c[ ], int opc ) {

    setPolygonColor( id, c[0], c[1], c[2], opc );
}

// polygon色をまとめて指定
void SetPolygonColors( int polygon[ ][ ], int ng, int color[ ], int opacity ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        SetPolygonColor( polygon[ng][i], color, opacity ) ;
    }
}
void SetPolygonColors( int polygon[ ][ ][ ], int ng, int color[ ], int opacity ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            SetPolygonColor( polygon[ng][i][j], color, opacity ) ;
        }
    }
}
void SetPolygonColors( 
    int polygon[ ][ ], int ng, int color[ ][ ], int nc, int opacity 
) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        setPolygonColor( 
            polygon[ng][i], color[nc][0], color[nc][1], color[nc][2], opacity 
        ) ;
    }
}

// polygonのcullingをまとめて指定
void SetPolygonCull( int polygon[ ][ ][ ], bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[2]; i++ ) {
        for ( int j=0; j<length( polygon )[1]; j++ ) {
            for ( int k=0; k<length( polygon)[0]; k++) {
                setPolygonCull( polygon[i][j][k], cullout, cullin ) ;
            }
        }
    }
}
void SetPolygonCull( int polygon[ ][ ], int ng, bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        setPolygonCull( polygon[ng][i], cullout, cullin ) ;
    }
}
void SetPolygonCull( int polygon[ ][ ][ ], int ng, bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            setPolygonCull( polygon[ng][i][j], cullout, cullin ) ;
        }
    }
}

void SetModelColor( int id, int c[ ], int opc ) {

    setModelColor( id, c[0], c[1], c[2], opc );
}

void SetLightColor( int id, int c[ ], int opc ) {

    setLightColor( id, c[0], c[1], c[2], opc );
}

void PileCoordinate( int cd[ ] , int renderer ) {

    int n = length( cd ) ;
    for ( int i=0; i<n; i++ ) {
        if ( i == 0 ) {
            addCoordinate( cd[n-1-i], renderer );
        } else {
            addCoordinate( cd[n-1-i], renderer, cd[n-i] );
        }
    }
}

// vectorの和を返す
int GetVectorSum( int v1, int v2 ) {

    int v = newVector() ;
    double vx = getVectorX( v1 ) + getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) + getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) + getVectorZ( v2 ) ;
    setVector( v, vx, vy, vz );
    return v ;
}

// moveVectorの結果を返す
int GetMoveVector( int v, double x, double y, double z ) {

    int u = newVector( v );
    moveVector( u, x, y, z );
    return u ;
}

// vectorの差を求めて代入する
void VectorDifference( int v, int v1, int v2 ) {

    double vx = getVectorX( v1 ) - getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) - getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    setVector( v, vx, vy, vz );
}

// vectorの差を返す
int GetVectorDifference( int v1, int v2 ) {

    double vx = getVectorX( v1 ) - getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) - getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    int v = newVector( vx, vy, vz ) ;
    return v ;
}

// vectorの定数倍する
void ScaleVector( int v, double x ) {

    scaleVector( v, x, x, x ) ;
}

// vectorの定数倍を返す
int GetScaleVector( int v, double x ) {

    int u = newVector( v ) ;
    scaleVector( u, x, x, x ) ;
    return u ;
}

// vectorの回転を求めて返す
int GetRotXVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotXVector( u, angle );
    return u ;
}
int GetRotYVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotYVector( u, angle );
    return u ;
}
int GetRotZVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotZVector( u, angle );
    return u ;
}
int GetRotVector( int v, double angle, int ax, int rc ) {

    int u = newVector( v ) ;
    rotVector( u, angle, ax, rc );
    return u ;
}

// 内分点を求める。P1V ; VP2 = t : 1-t
int GetInternallyDividingVector(
    double x1, double y1, double z1,
    double x2, double y2, double z2,
    double t
) {

    double vx = ( 1.0 - t )*x1 + t*x2 ;
    double vy = ( 1.0 - t )*y1 + t*y2 ;
    double vz = ( 1.0 - t )*z1 + t*z2 ;
    int v = newVector ( vx, vy, vz ) ;
    return v ;
}

int GetInternallyDividingVector( int v1, int v2, double t ) {

    double vx = ( 1.0 - t )*getVectorX( v1 ) + t*getVectorX( v2 ) ;
    double vy = ( 1.0 - t )*getVectorY( v1 ) + t*getVectorY( v2 ) ;
    double vz = ( 1.0 - t )*getVectorZ( v1 ) + t*getVectorZ( v2 ) ;
    int v = newVector ( vx, vy, vz ) ;
    return v ;
}

int GetMiddlePointVector( int v1, int v2 ) {

    double x = ( getVectorX( v1 ) + getVectorX( v2 ) ) / 2 ;
    double y = ( getVectorY( v1 ) + getVectorY( v2 ) ) / 2 ;
    double z = ( getVectorZ( v1 ) + getVectorZ( v2 ) ) / 2 ;
    int mid = newVector( x, y, z ) ;
    return mid ;
}

// vをcdに配置してCDへ変換したものを求める
int GetTransformedVector( int v, int renderer, int cd, int CD ) {

    int u = newVector( v ) ;
    addVector( v, renderer, cd );
    transformVector( v, u, CD );
    removeVector( v, renderer, cd );
    return u ;
}

void TransformVector( int v, int renderer, int cd, int u, int CD ) {

    addVector( v, renderer, cd );
    transformVector( v, u, CD );
    removeVector( v, renderer, cd );
}

void SetCoordinateOrigin( int cd, double x[ ] ) {

    setCoordinateOrigin( cd, x[0], x[1], x[2] );
}

int GetVectorCoordinateOrigin( int cd ) {

    int v = newVector(
        getCoordinateOriginX( cd ),
        getCoordinateOriginY( cd ),
        getCoordinateOriginZ( cd )
    );
    return v ;
}

// 重心を返す
int GetVectorGravityCenter( int v[ ] ) {

    int g = newVector( v[0] ) ;
    for ( int i=1; i<length( v ); i++ ) {
        moveVector( g, v[i] );
    }
    double s = 1.0 / length( v ) ;
    scaleVector( g, s, s, s);
    return g ;
}

double[ ] getCenterOfGravity( int v[ ] ) {

    int g = newVector( v[0] ) ;
    int lenv = length( v ) ;
    for ( int i=1; i<lenv; i++ ) {
        moveVector( g, v[i] );
    }
    double s = 1.0 / lenv ;
    scaleVector( g, s, s, s);
    double x[ 3 ];
    x[0] = getVectorX( g ) ;
    x[1] = getVectorY( g ) ;
    x[2] = getVectorZ( g ) ;
    return x ;
}

// normal vectorを返す
int GetNormalVectorQuadrangle( int v[ ] ) {

    int v1 = GetVectorDifference( v[2], v[0] ) ;
    int v2 = GetVectorDifference( v[3], v[1] ) ;
    int normalv = newVector() ;
    getVectorCrossProduct( v1, v2, normalv );
    double length = getVectorLength( normalv ) ;
    if ( !( length == o ) ) {
        setVectorLength( normalv, 1.0 );
    } else {
        alert( "error( GetNormalVectorQuadrangle )) ;
    }
    return normalv ;
}

// 2枚の面の作る角の余弦を返す
double GetAngleFaceFace ( int v1[ ], int v2[ ] ) {

    int n1 = GetNormalVectorQuadrangle( v1 ) ;
    int n2 = GetNormalVectorQuadrangle( v2 ) ;
    double costh = getVectorInnerProduct( n1, n2 ) ;
    return costh ;
}

void SetVectorsCoordinateLocationAttitude( int vo, int va, int cd ) {

    double x = getCoordinateOriginX( cd ) ;
    double y = getCoordinateOriginY( cd ) ;
    double z = getCoordinateOriginZ( cd ) ;
    double a = getCoordinateEulerAngleAlpha( cd ) ;
    double b = getCoordinateEulerAngleBeta( cd ) ;
    double g = getCoordinateEulerAngleGamma( cd ) ; 

    setVector( vo, x, y, z );
    setVector( va, a, b, g );
}

void SetVectorsCoordinateLocationAttitude( int so[ ], int sa[ ], int cd[ ] ) {

    double x, y, z, a, b, g ;
    for ( int i=0; i<length( cd ); i++ ) {
        x = getCoordinateOriginX( cd[i] ) ;
        y = getCoordinateOriginY( cd[i] ) ;
        z = getCoordinateOriginZ( cd[i] ) ;
        a = getCoordinateEulerAngleAlpha( cd[i] ) ;
        b = getCoordinateEulerAngleBeta( cd[i] ) ;
        g = getCoordinateEulerAngleGamma( cd[i] ) ;
        setVector( so[i], x, y, z ) ;
        setVector( sa[i], a, b, g ) ;
    }
}

void SetCoordinateLocationAttitude( int cd, int vo, int va ) {

    double x = getVectorX( vo ) ;
    double y = getVectorY( vo ) ;
    double z = getVectorZ( vo ) ;
    double a = getVectorX( va ) ;
    double b = getVectorY( va ) ;
    double g = getVectorZ( va ) ; 

    setCoordinateOrigin( cd, x, y, z );
    setCoordinateEulerAngle( cd, a, b, g );
}

void SetCoordinateEulerAngle( int cd, int v ) {

    setCoordinateEulerAngle( cd, 
        getVectorX( v ), getVectorY( v ), getVectorZ( v ) 
    );
}

double[ ] GetArryCoordinateEulerAngle( int cd ) {

    double ea[ 3 ];
    ea[0] = getCoordinateEulerAngleAlpha( cd ) ;
    ea[1] = getCoordinateEulerAngleBeta( cd ) ;
    ea[2] = getCoordinateEulerAngleGamma( cd ) ;
    return ea ;
}

int GetVectorCoordinateEulerAngle( int cd ) {

    double ea[ 3 ];
    ea[0] = getCoordinateEulerAngleAlpha( cd ) ;
    ea[1] = getCoordinateEulerAngleBeta( cd ) ;
    ea[2] = getCoordinateEulerAngleGamma( cd ) ;
    int v = newVector( ea ) ;
    return v ;
}

// リセットなしの回転
void RotateCoordinate( 
    int cd, int so, int sa, double angle, int ax, int rc, int renderer, int Cd 
) {

    int dummycd = newCoordinate() ;
    addCoordinate( dummycd, renderer, Cd ) ;
    SetCoordinateLocationAttitude( dummycd, so, sa ) ;
    rotCoordinate( dummycd, angle, ax, rc ) ;
    int sovalue = newVector() ;
    int savalue = newVector();
    SetVectorsCoordinateLocationAttitude( sovalue, savalue, dummycd ) ;
    SetCoordinateLocationAttitude( cd, sovalue, savalue ) ;
    removeCoordinate( dummycd, renderer, Cd ) ;
}

// O から dist 離れた地点へresetなしに移す, y-direction
void SetCoordinateLocationYdirection( int cd, double dist ) {

    int dummycd = newCoordinate() ;
    int v = newVector() ;
    CopyCoordinateAttitude( dummycd, cd ) ;
    walkCoordinate( dummycd, o, dist, o ) ;
    v = GetVectorCoordinateOrigin( dummycd ) ;
    setCoordinateOrigin( cd, v ) ;
}

// 座標系の姿勢をコピー(座標系原点はコピーせず O とする)
void CopyCoordinateAttitude( int cd, int originalcd ) {

    int sa = GetVectorCoordinateEulerAngle( originalcd ) ;
    SetCoordinateLocationAttitude( cd, O, sa ) ;
}

// y軸及びz軸が引数ベクトルと平行な姿勢にする
void SetCoordinateAttitudeYZ( int cd, int vy, int vz ) {

    int uy = newVector( vy ) ;
    int uz = newVector( vz ) ;
    setVectorLength( uy, 1.0 );
    setVectorLength( uz, 1.0 );
    int ux = newVector() ;
    getVectorCrossProduct( uy, uz, ux );
    setCoordinateBaseX( cd, ux );
    setCoordinateBaseY( cd, uy );
    setCoordinateBaseZ( cd, uz );
}

// 原点が v2, cylinder 端点が v1, v2 となるように cd を set する
void SetCoordinateCylinder( int cyl, double rad, int v1, int v2, int cd ) {

    double x[ 3 ];
    x[0] = getVectorX( v1 ) - getVectorX( v2 ) ; 
    x[1] = getVectorY( v1 ) - getVectorY( v2 ) ;
    x[2] = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    int v21 = newVector( x ) ;
    double length = getVectorLength( v21 ) ; // シリンダーの長さ

    if ( length != 0.0 ) {
        int xyprojection = newVector( x[0], x[1], 0.0 ) ;
        setVectorLength( xyprojection, 1.0 ) ;
        double cos1 = getVectorY( xyprojection ) ; // xy射影がy軸となす角の余弦
        double th1; // xy射影がy軸となす角度
        if ( x[1] == 0.0 ) {
            if ( x[0] >= 0.0 ) {
                th1 = PI/2 ;
            } else {
                th1 = -PI/2 ;
            }
        } else if( x[0] < 0.0 ) { 
            th1 = -acos( cos1 ) ; 
        } else {
            th1 = acos( cos1 ) ;
        }

        setVectorLength( v21, 1.0 );
        double sin2 = getVectorZ( v21 ); // 射影と元のベクトルのなす角の正弦
        double th2 = asin( sin2 ) ;

        double alpha = -th1 ;
        double beta = th2 - PI/2 ;
        double gamma = 0.0 ; if ( th1 < 0.0 ) { gamma = PI ; }
        setCoordinateOrigin( cd, v2 );
        setCoordinateEulerAngle( cd, alpha, beta, gamma );
         setModelSize( cyl, rad, rad, length );
    }
}

void SetSphereSize( int sp, double rad ) {

    setModelSize( sp, rad, rad, rad );
}

// n 番目の多面体のすべての面の頂点を vector で指定する
void SetTriangleVector( int p[ ][ ], int n, int v[ ][ ] ) {

    for ( int i=0; i<length( p ); i++ ) {
        setPolygonVector( p[n][i], v[i][0], v[i][1], v[i][2] ) ;
    }
}
void SetTriangleVector( int p[ ][ ][ ], int n, int v[ ][ ][ ] ) {

    for ( int i=0; i<length( p )[1]; i++ ) {
        for ( int j=0; j<length( p )[0]; j++ ) {
            setPolygonVector( p[n][i][j], v[i][j][0], v[i][j][1], v[i][j][2] ) 

;
        }
    }
}

// polygon をまとめて配置する
void AddPolygons( int p[ ][ ][ ], int renderer, int cd[ ] ) {

    for ( int i=0; i<length( p )[2]; i++ ) {
        for ( int j=0; j<length( p )[1]; j++ ) {
            for ( int k=0; k<length( p )[0]; k++ ) {
                addPolygon( p[i][j][k], renderer, cd[i] ) ;
            }
        }
    }
}
void AddPolygons( int p[ ][ ][ ], int ng, int renderer, int cd[ ] ) {

    for ( int i=0; i<length( p )[1]; i++ ) {
        for ( int j=0; j<length( p )[0]; j++ ) {
            addPolygon( p[ng][i][j], renderer, cd[ng] ) ;
        }
    }
}
void AddPolygons( int p[ ][ ], int m, int renderer, int cd[ ][ ], int n ) {

    for ( int i=0; i<length( p )[0]; i++ ) {
        addPolygon( p[m][i], renderer, cd[n][i] ) ;
    }
}
void AddPolygons( int p[ ][ ], int ng, int renderer, int cd ) {

    for ( int i=0; i<length( p )[0]; i++ ) {
        addPolygon( p[ng][i], renderer, cd ) ;
    }
}

int[ ] RV2_1( int v[ ][ ], int n ) { // ベクトルの2次元配列からベクトルの1次元配列を作る

    int m = length( v )[0] ;
    int u[ m ] ;
    for ( int i=0; i<m; i++ ) {
        u[i] = newVector( v[n][i] ) ;
    }
    return u ;
}
int[ ] RV2_0( int v[ ][ ], int n ) { // ベクトルの2次元配列からベクトルの1次元配列を作る

    int m = length( v )[1] ;
    int u[ m ] ;
    for ( int i=0; i<m; i++ ) {
        u[i] = newVector( v[i][n] ) ;
    }
    return u ;
}

int[ ] RA2_0( int arry[ ][ ], int n ) { // 整数型2次元配列から整数型1次元配列を作る

    int m = length( arry )[0] ;
    int rarry[ m ] ;
    for ( int i=0; i<m; i++ ) {
        rarry[i] = arry[n][i] ;
    }
    return rarry ;
}


/* MOTION */

void PrepareMovie() {

    double anglepf = 2*PI * RPM / 60 / FPS ;
    COUNT = 0 ;
    while ( COUNT <= END_C ) {
        Movie( anglepf, false ) ; // anglepf は終了時刻調節に必要
        if ( COUNT == 0 ) {
            NewStateVectors( LENGTH, NG ) ;
        }
        COUNT += STEP ;
    }
    COUNT = 0 ;
}

void NewStateVectors( int length1, int length2 ) {

    int dummy1[ length1 ], dummy2[ length1 ][ length2 ] ;
    SX [=] dummy1 ;
    SA [=] dummy1 ;
    X [=] dummy2 ;
    A [=] dummy2 ;
    for ( int i=0; i<length1; i++ ) {
        for ( int j=0; j<length2; j++ ) {
            X[i][j] = newVector() ;
            A[i][j] = newVector() ;
            if ( j == 0 ) {
                SX[i] = newVector() ;
                SA[i] = newVector() ;
            }
        }
    }
}

double Linear( int v ) {

    int c0 = getVectorZ( v ) * getVectorX( v ) ;
    int c1 = getVectorZ( v ) * getVectorY( v ) ;
    double t ;
    if ( COUNT < c0 ) {
        t = 0.0 ; println( "M0045", COUNT ) ;
    } else if ( COUNT <= c1 ) {
        t = a*( COUNT - c0 ) / ( c1 - c0 ) ;
    } else {
        t = 1.0 ; println( "M0049", COUNT ) ;
    }
    return t ;
}

double Sin( int v ) {

    double t = Linear( v ) ;
    double s = ( 1.0 + sin( PI*t - PI/2 ) ) / 2 ;
    return s ;
}

void SetRange( int v, int dn0, int dn1 ) {

    int n0 = (int)getVectorY( v ) + dn0 ;
    int n1 = n0 + dn1 ;
    int u = (int)getVectorZ( v ) ;
    setVector( v, (double)n0, (double)n1, (double)) ;
}

void SetRangeRight( int v, int u ) {
    int n0 = (int)getVectorX( v ) ;
    int n1 = (int)getVectorY( u ) ;
    int n2 = (int)getVectorZ( v ) ;
    setVector( v, (double)n0, (double)n1, (double)n2 ) ;
}

void SetRangeAbs( int v, int n0, int n1 ) {

    int u = getVectorZ( v ) ;
    setVector( v, (double)n0, (double)n1, (double)) ;
}

bool At( int v ) {

    return COUNT == (int)getVectorZ( v ) * (int)getVectorX( v ) ;
}

bool InRange( int v ) {

    int u = getVectorZ( v ) ;
    int c0 = u * (int)getVectorX( v ) ;
    int c1 = u * (int)getVectorY( v ) ;
    bool isin ;
    if ( INCREASE_COUNT ) {
        isin = COUNT > c0 && COUNT <= c1 ;
    } else {
        isin = COUNT >= c0 && COUNT < c1 ;
    }
    return isin ;
}

// spin
int ROT_COUNT1[ ] = { 0, 0, 0 } ;
int INITIAL_EA1[ 3 ] ; // initial Euler angle
for ( int i=0; i<length( INITIAL_EA1, 0 ); i++ ) {
    INITIAL_EA1[i] = newVector( O ) ;
}
bool ROT1_INI[ ] = { true, true ,true } ;

void Rot1Systems() {

    int rank, index, type ;
    for ( int i=0; i<length( ROTATE1 ); i++ ) {
        if ( ROTATE1[i] ) {
            ROT_COUNT1[i] = ROT_COUNT1[i] + 1 ;
            rank = COORD_RNK[ROT1_BT_INDEX[i] + 1 ] ;
            index = COORD_IDX[ROT1_BT_INDEX[i] + 1 ] ;
            type = ROTATION_TYPE[i] ;
            if ( rank == 0 ) {
                if ( ROT1_INI[i] ) {
                    double alp , bet, gam ;
                    string s = " が NaN です" 
                        + lf() + "値として 0.0 を与えます" ;
                    alp = getCoordinateEulerAngleAlpha( COORD[index] ) ;
                    if ( alp > d^16 ) {
                        alert( "getCoordinateEulerAngleAlpha" + s ) ;
                        alp = o ;
                    }
                    bet = getCoordinateEulerAngleBeta( COORD[index] ) ;
                    if ( bet > d^16 ) {
                        alert( "getCoordinateEulerAngleBeta" + s ) ;
                        bet = o ;
                    }
                    gam = getCoordinateEulerAngleGamma( COORD[index] ) ;
                    if ( gam > d^16 ) {
                        alert( "getCoordinateEulerAngleGamma" + s ) ;
                        gam = o ;
                    }
                    setVector( INITIAL_EA1[i] , alp, bet, gam ) ;
                    ROT1_INI[i] = false ;
                }
                if ( type == 0 ) {
                    rotXCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 1 ) {
                    rotYCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 2 ) {
                    rotZCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 3 ) {
                    spinXCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 4 ) {
                    spinYCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 5 ) {
                    spinZCoordinate( COORD[index], ANGLE1_PF[i] ) ;
                }
            } else ( rank == 1 ) {
                if ( ROT1_INI[i] ) {
                    double alp , bet, gam ;
                    string s = " が NaN です" 
                        + lf() + "値として 0.0 を与えます" ;
                    alp = getCoordinateEulerAngleAlpha( CD[index] ) ;
                    if ( alp > d^16 ) {
                        alert( "getCoordinateEulerAngleAlpha" + s ) ;
                        ) ;
                        alp = o ;
                    }
                    bet = getCoordinateEulerAngleBeta( CD[index] ) ;
                    if ( bet > d^16 ) {
                        alert( "getCoordinateEulerAngleBeta" + s ) ;
                        bet = o ;
                    }
                    gam = getCoordinateEulerAngleGamma( CD[index] ) ;
                    if ( gam > d^16 ) {
                        alert( "getCoordinateEulerAngleGamma" + s ) ;
                        gam = o ;
                    }
                    setVector( INITIAL_EA1[i] , alp, bet, gam ) ;
                    ROT1_INI[i] = false ;
                }
                if ( type == 0 ) {
                    rotXCoordinate( CD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 1 ) {
                    rotYCoordinate( CD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 2 ) {
                    rotZCoordinate( CD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 3 ) {
                    spinXCoordinate( CD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 4 ) {
                    spinYCoordinate( CD[index], ANGLE1_PF[i] ) ;
                } else if ( type == 5 ) {
                    spinZCoordinate( CD[index], ANGLE1_PF[i] ) ;
                }
            }
            if ( ROT_COUNT1[i] == 1 ) {
                setComponentText( ROT1_TLA[i], "" ) ;
            }
            if ( ROT_COUNT1[i] == END_ROT_COUNT1[i] ) {
                string s = "開始 " + ( i + 1 ) ;
                setComponentText( ROT1_BT[i], s ) ;
                setComponentText( ROT1_TLA[i], "done" ) ;
                ROTATE1[i] = false ;
                ROT_COUNT1[i] = 0 ;
            }
        }
    }
    ROTATE_SYSTEMS = ROTATE1[0] || ROTATE1[1] || ROTATE1[2] ;
    if ( ! ROTATE_SYSTEMS ) {
        setComponentText( ROT1_BT[3], "3つを同時に開始 t" ) ;
        for ( int i=0; i<length( ROT_COUNT1, 0 ); i++ ) {
            string s = "開始 " + ( i + 1 ) ;
            setComponentText( ROT1_BT[i], s ) ;
        }
    }
}

// override のため関数
bool F1_IN_MAIN = false ;
bool F1_IN_MOTION = false ;
void Dummyfunc1() {

    alert(
        "まだ override されていません",
        "override 内容を記述し、「上書きボタン」",
        "または「上書きして1回実行ボタン」を押して下さい"
    ) ;
    F1_IN_MAIN = false ;
    F1_IN_MOTION = false ;
    setComponentState( PCKB[0], false ) ;
    setComponentState( PCKB[1], false ) ;
}

void JumpTo( double tfin ) { // tfin はアニメーション中の時刻
alert("!");
}

void JumpTo( int c ) { // c はアニメーション中のcount

    bool motionstatechanged = false ;
    if ( KEEP_MOTION == true ) {
        while ( IN_MOVIE ) {
            KEEP_MOTION = false ;
        }
        KEEP_MOTION = false ;
        motionstatechanged = true ;
    }
    bool rewrite = false ;
    if ( c + START_C <= ( START_C + END_C ) / 2 ) {
        if ( ! INCREASE_COUNT ) {
            rewrite = true ;
            INCREASE_COUNT = true ;
        }
        COUNT = START_C - (int)( 2^ACCEL ) ;
        while ( COUNT < START_C + c ) {
            COUNT += (int)( 2^ACCEL ) ;
            Movie( o, true ) ;
        }
        if ( rewrite ) {
            INCREASE_COUNT = false ;
        }
    } else {
        COUNT = END_C + (int)( 2^ACCEL ) ;
        if ( INCREASE_COUNT ) {
            rewrite = true ;
            INCREASE_COUNT = false ;
        }
        while ( COUNT > START_C + c ) {
            COUNT -= (int)( 2^ACCEL ) ;
            Movie( o, true ) ;
        }
        if ( rewrite ) {
            INCREASE_COUNT = true ;
        }
    }
    PaintGraphics();
    if ( motionstatechanged ) {
        KEEP_MOTION = true ;
    }
}


/* COLORS */

int[ ] Color( int i, int j, int k ) {

    int c[ 3 ] ;
    if ( ( i < 0 ) || ( j < 0 ) || ( k < 0 ) 
            || ( i > 255 ) || ( j > 255 ) || ( k > 255 ) ) {
        c = 0 ;
        alert( "Error ( Color ) " );
    } else {
        c[0] = i ;
        c[1] = j ;
        c[2] = k ;
    }
    return c ;
}

int[ ] Color( float r, float g, float b ) {

    int c[ 3 ] ;
    if ( ( r < 0.0 ) || ( g < 0.0 ) || ( b < 0.0 ) 
            || ( r > 1.0 ) || ( g > 1.0 ) || ( b > 1.0 ) ) {
        c = 0 ;
        alert( "Error ( Color ) " );
    } else {
        c[0] = 255 * r ;
        c[1] = 255 * g ;
        c[2] = 255 * b ;
    }
    return c ;
}

int[ ] Color( float x ) {

    int c[ 3 ] ;
    if ( ( x < 0.0 ) || ( x > 1.0 ) ) {
        c = 0 ;
        alert( "Error ( Color ) " );
    } else {
        c = 255 * x ;
    }
    return c ;
}

int[ ] BiColor( float x ) {

    int c[ 3 ] ;
    c[0] = 255 * MSlope( x ) ;
    c[1] = 255 * MSlope( x - 1.0/3 ) ;
    c[2] = 255 * MSlope( x + 1.0/3 ) ;
    return c ;
}

int[ ] MixedColor( 
    float r1, float g1, float b1, 
    float r2, float g2, float b2, 
    double p 
) {

    int color[ 3 ] ;
    float c1[ ] = { r1, g1, b1 } ;
    float c2[ ] = { r2, g2, b2 } ;
    for ( int i=0; i<length( color ); i++ ) {
        color[i] = 255 * ( c1[i] * ( 1 - p ) + c2[i] * p ) ;
    }
    return color ;
}

int[ ] MixedColor( int color1[ ], int color2[ ], double p ){

    int color[ 3 ] ;
    for ( int i=0; i<length( color ); i++ ) {
        color[i] = color1[i] * ( 1 - p ) + color2[i] * p ;
    }
    return color ;
}


/* GEOMETRY */

double GetHeightAntiprismByConnectionName( 
    int nside, double rad, string polyhedronname 
) {

    double delta = rad * ( 1 - cos( PI/nside ) ) ;
    double antiprismdhangle ; // 底面と側面の normal vector の作る角
    if ( polyhedronname == "cube" ) {
        antiprismdhangle = 3*PI/4 ;
    } else if ( polyhedronname == "octahedron" ) {
        antiprismdhangle = PI/2 + acos( Slv*IPlt ) ;
    } else {
        alert( "error( GetHeightAntiprismByName )) ;
    }
    double antiprismheight = delta * tan( PI - antiprismdhangle ) ;
    return antiprismheight ;
}

int[ ] Get3Vectors4sideAntiprismCubeConnection( double baserad ) {

    int v[ 3 ] ;
    v[0] = newVector( o, o, baserad ) ;
    v[1] = GetRotYVector( v[0], PI/2 ) ;
    double h = GetHeightAntiprismByConnectionName( 4, baserad, "cube" ) ;
    v[2] = newVector( o, h, o ) ;
    return v ;
}

// dodecahedron の inradiusを返す
double GetInradiusDodecahedron( double prad ) {

    return prad * ( Gld + 1 ) / 2 ;
}

// 原点中心、zx平面内、regular n-gonのz軸上の点(z>0)とその反時計回り隣の点

int[ ] Get3VectorsNGon( int n, double rad ) {

    int u[ 3 ] ;
    u[0] = newVector( o, o, o ) ;
    u[1] = newVector( o, o, rad ) ;
    u[2] = GetRotYVector( u[1], 2*PI/n ) ;
    return u ;
}

// square cupola の頂点ベクトルを返す
int[ ] Get12VectorsSquareCupola( double baserad ) {

    int v[ 12 ] ;
    // 7 - 0 底面頂点
    v[0] = newVector( baserad*sin(PI/8), o, baserad*cos(PI/8) ) ; // 底面の edge は z軸に直交する
    for ( int i=1; i<=7; i++ ) {
        v[i] = GetRotYVector( v[0], PI/4 * i ) ;
    }
    // 11 - 8 天井
    double edge = 2 * baserad * sin( PI/8 ) ;
    double h = edge * ISlv ;
    v[8] = newVector( edge/2, h, edge/2 ) ;
    for( int i=9; i<=11; i++ ) {
        v[i] = GetRotYVector( v[8], PI/2 * i ) ;
    }
    return v ;
}
int[ ] Get2VectorsSquareCupola( double baserad ) {

    int v[ 2 ] ;
    v[0] = newVector( baserad*sin(PI/8), o, baserad*cos(PI/8) ) ; // 底面の edge は z軸に直交する
    double edge = 2 * baserad * sin( PI/8 ) ;
    double h = edge * ISlv ;
    v[1] = newVector( edge/2, h, edge/2 ) ; // 天井の edge はx軸に平行
    return v ;
}

// diamond space filler の頂点ベクトルを返す
int[ ][ ][ ] GetVectorsDiamondSpaceFiller( double x ) { // vertex ( x, 0, 0 )

    int v[ S4 ][ R3*2 ][ R3 ] ;
    v[0][0][0] = newVector( o, x, o ) ;
    v[0][0][1] = newVector( -x/2, x/2, x/2 ) ;
    v[0][0][2] = newVector( x/4, x/4, x/4 ) ;
    v[0][1][0] = newVector( v[0][0][1] ) ;
    v[0][1][1] = newVector( o, o, x ) ;
    v[0][1][2] = newVector( v[0][0][2] ) ;
    int ax0 = newVector( a, a, a ) ;
    int ax1 = newVector( a, o, a ) ;
    for ( int i=1; i<R3; i++ ) {
        for ( int j=0; j<R3; j++ ) {
            v[0][2*i][j] = GetRotVector( v[0][0][j], 2*PI/3 * i, ax0, O ) ;
            v[0][2*i+1][j] = GetRotVector( v[0][1][j], 2*PI/3 * i, ax0, O ) ;
        }
    }
    for ( int i=1; i<S4; i++ ) {
        for ( int j=0; j<R3*2; j++ ) {
            for ( int k=0; k<R3; k++ ) {
                v[i][j][k] = GetRotYVector( v[0][j][k], PI/2 * i ) ;
                if ( i%2 == 1 ) {
                    rotVector( v[i][j][k], PI, ax1 ) ;
                }
            }
        }
    }
    return v ;
}
void SetFacesDiamondSpaceFiller( int p[ ][ ][ ], int ng, double x ) {

    int u[ ][ ][ ] = GetVectorsDiamondSpaceFiller( x ) ;
    SetTriangleVector( p, ng, u ) ;
}

// octahedron の頂点ベクトルを返す
int[ ][ ] GetVectorsOctahedron( double x ) { // vertex ( x, 0, 0 )

    int v[ S8 ][ R3 ] ;
    v[0][0] = newVector( x, o, o ) ;
    v[0][1] = newVector( o, x, o ) ;
    v[0][2] = newVector( o, o, x ) ;
    for ( int i=1; i<S8; i++ ) {
        for ( int j=0; j<R3; j++ ) {
            if ( i <= 3 ) {
                v[i][j] = GetRotYVector( v[0][j], PI/2 * ( i%4 ) ) ;
            } else {
                v[i][j] = GetRotZVector( v[0][j], PI ) ;
                rotYVector( v[i][j], PI/2 * ( ( i - 3 ) % 4 ) ) ;
            }
        }
    }
    return v ;
}

int[ ] GetVectors4FacesSymmetry( double x ) { // ( x, x, x )

    int v[ 4 ] ;
    v[0] = newVector( x, x, x ) ;
    v[1] = GetRotYVector( v[0], PI ) ;
    v[2] = GetRotXVector( v[0], PI ) ;
    v[3] = GetRotZVector( v[0], PI ) ;
    return v ;
}

int[ ] GetVectors6FacesSymmetry( double x ) { // ( o, x, o )

    int v[ 6 ] ;
    v[0] = newVector( o, x, o ) ;
    v[1] = GetRotZVector( v[0], PI/2 ) ;
    for ( int i=2; i<=4; i++ ) {
        v[i] = GetRotYVector( v[1], PI/2 * ( i - 1 ) ) ;
    }
    v[5] = GetRotZVector( v[0], PI ) ;
    return v ;
}

int[ ] GetVectors8FacesSymmetry( double x ) { // ( x, x, x )

    int v[ 8 ] ;
    v[0] = newVector( x, x, x ) ;
    v[4] = newVector( x, -x, x ) ;
    for ( int i=1; i<4; i++ ) {
        v[i] = GetRotYVector( v[0], PI/2 * i ) ;
        v[4+i] = GetRotYVector( v[4], PI/2 * i ) ;
    }
    return v ;
}

int[ ] GetEulerAngleVectors8FacesSymmetry() { // y軸が normal vector

    int sa[8] ;
    int cd = newCoordinate() ;
    int ax = newVector( a, o, -a ) ;
    rotXCoordinate( cd, -atan( Slv ) ) ;
    rotYCoordinate( cd, -3*PI/4 ) ;
    sa[0] = GetVectorCoordinateEulerAngle( cd ) ;
    for ( int i=1; i<4; i++ ) {
        rotYCoordinate( cd, PI/2 ) ;
        sa[i] = GetVectorCoordinateEulerAngle( cd ) ;
    }
    setCoordinateEulerAngle( cd, o, o, o ) ;
    rotXCoordinate( cd, PI/2 + atan( ISlv ) ) ;
    rotYCoordinate( cd, PI/4 ) ;
    sa[4] = GetVectorCoordinateEulerAngle( cd ) ;
    for ( int i=5; i<8; i++ ) {
        rotYCoordinate( cd, PI/2 ) ;
        sa[i] = GetVectorCoordinateEulerAngle( cd ) ;
    }
    return sa ;
}

int[ ][ ] GetTransformedVectors6FacesSymmetry( 
    int v[ ], double y, double spiny 
) {

    int n = length( v ) ;
    int u[ 6 ][ n ] ;
    int dely = newVector( o, y, o ) ;
    for ( int i=0; i<=5; i++ ) {
        for ( int j=0; j<n; j++ ) {
            if ( i == 0 ) {
                u[i][j] = newVector( v[j] ) ;
                moveVector( u[i][j], dely ) ;
                rotYVector( u[i][j], spiny ) ;
            } else if ( i == 1 ) {
                u[i][j] = GetRotZVector( u[0][j], -PI/2 ) ;
            } else if ( i <= 4 ) {
                u[i][j] = GetRotYVector( u[1][j], PI/2 * ( i - 1 ) ) ;
            } else {
                u[i][j] = GetRotZVector( u[0][j], PI ) ;
            }
        }
    }
    return u ;
}


/* EVENTHANDLERS */

void onWindowClose( int id ) {

    if ( id == MAIN_WINDOW ) {
        KEEP_LOOP = false ;
    }
}

int ACCEL= 1 ; // accelerator
void onKeyDown( int id, string key ){

    if ( GUI_CREATED ) {
        if ( ! ( // text area, text field を除外
            // low panel
            id == LRTXL[0] 
            // side panel
            || id == ROT1_TF[0] || id == ROT1_TF[1] || id == ROT1_TF[2]
            // axis panel
            || id == AE_TXT[3][1] || id == AE_TXT[3][2] || id == AE_TXT[3][3]
            || id == AE_TXT[4][1] || id == AE_TXT[4][2] || id == AE_TXT[4][3]
            || id == AE_TXT[5][1] || id == AE_TXT[5][2] || id == AE_TXT[5][3]
            || id == AE_TXT[6][1] || id == AE_TXT[6][2] || id == AE_TXT[6][3]
            || id == AE_TXT[7][1] || id == AE_TXT[7][2] || id == AE_TXT[7][3]
            || id == AE_TXT[8][1] || id == AE_TXT[8][2] || id == AE_TXT[8][3]
            || id == AE_TXT[9][1] || id == AE_TXT[9][2] || id == AE_TXT[9][3]
            // comand window
            || id == CTXF[0] || id == CTXA[0] || id == CTXA[1]
            // program window
            || id == PTXT[0] || id == PTXT[1]
            // camera panel
            || id == CMPL_TF[0]
            // image save panel
            || id == ISPL_TF[0] || id == ISPL_TF[1] || id == ISPL_TF[2]
            || id == ISPL_TF[3] || id == ISPL_TF[4] || id == ISPL_TF[5]
            // frame panel
            || id == FMPL_TF[0] || id == FMPL_TF[1]
            || id == FMPL_TF[2] || id == FMPL_TF[3]
            || id == FMPL_TF[4] || id == FMPL_TF[5]
        ) ) {
            if ( key == "F1" ) {
            } else     if ( key == "ENTER" ) { // play
                ROT1_INI = true ; // Euler angle 初期値のリセット
                if ( KEEP_MOTION ) {
                    KEEP_MOTION = false ;
                    setComponentText( LBTN[0], LBTN_TX[0][0] ) ;
                    setComponentText( LTXL[0], 
                        (string)( (int)( DEL_T * ( COUNT - START_C ) ) ) 
                    ) ;
                } else {
                    KEEP_MOTION = true ;
                    setComponentText( LBTN[0], LBTN_TX[0][1] ) ;
                    if ( INCREASE_COUNT ) {
                        if ( COUNT == END_C ) {
                            COUNT = START_C ;
                        }
                    } else {
                        if ( COUNT == START_C ) {
                            COUNT = END_C ;
                        }
                    }
                }
            } else if ( key == "CONTROL" ) {
                int c[ ] = getComponentColor( MAIN_WINDOW ) ;
                if ( INCREASE_COUNT ) {
                    INCREASE_COUNT = false ;
                    setComponentColor( 
                        LTXL[0], 100, 100, 200, 255, c[4], c[5], c[6], c[7] 
                    ) ;
                } else {
                    INCREASE_COUNT = true ;
                    setComponentColor( 
                        LTXL[0], 200, 100, 100, 255, c[4], c[5], c[6], c[7] 
                    ) ;
                }
                RefreshIndicator() ;
            } else if ( key == "SHIFT" ) { // accel
                int formeri = ACCEL + 5 ;
                ACCEL++ ;
                if ( ACCEL >= 5 ) {
                    ACCEL = 0 ;
                }
                SPEED_CHANGED = true ;
                if ( PAUSE_MOTION ) {
                    SetPauseCount() ;
                }
                if ( getComponentVisible( FRAME_PNL ) ) {
                    JumpToFrame( FMPL_BT[3] ) ;
                }
                int n = ACCEL + 5 ;
                setComponentFontBold( LBTN[formeri], false ) ;
                setComponentFontSize( LBTN[formeri], 12 ) ;
                setComponentFontBold( LBTN[n], true ) ;
                setComponentFontSize( LBTN[n], 14 ) ;
                RefreshIndicator() ;
            } else if ( key == "C" ) {
                if ( CIRCULATIVE_MOTION ) {
                    CIRCULATIVE_MOTION = false ;
                } else {
                    CIRCULATIVE_MOTION = true ;
                    RECIPROCATIVE_MOTION = false ;
                    setComponentState( LCKB[1], false ) ;
                    PAUSE_MOTION = false ;
                    setComponentState( LCKB[3], false ) ;
                }
                setComponentState( LCKB[0], CIRCULATIVE_MOTION ) ;
            } else if ( key == "R" ) {
                if ( RECIPROCATIVE_MOTION ) {
                    RECIPROCATIVE_MOTION = false ;
                } else {
                    RECIPROCATIVE_MOTION = true ;
                    CIRCULATIVE_MOTION = false ;
                    setComponentState( LCKB[0], false ) ;
                    PAUSE_MOTION = false ;
                    setComponentState( LCKB[3], false ) ;
                }
                setComponentState( LCKB[1], RECIPROCATIVE_MOTION ) ;
            } else if ( key == "S" ) {
                if ( SPIN ) {
                    SPIN = false ;
                } else {
                    SPIN = true ;
                }
                setComponentState( LCKB[2], SPIN ) ;
            } else if ( key == "B" ) { // <<
                COUNT = START_C ;
                if ( !KEEP_MOTION ) {
                    InitializeIndicator() ;
                    RefreshIndicator() ;
                }
            } else if ( key == "E" ) { // >>
                COUNT = END_C ;
                if ( !KEEP_MOTION ) {
                    InitializeIndicator() ;
                    RefreshIndicator() ;
                }
            }
            // side panel
            else if ( key == "F8" ) {
                if ( SIDE_PANEL_OPENED ) {
                    setComponentText( LEXB[1], "パネル2 F8" ) ;
                } else {
                    setComponentText( LEXB[1], "パネル2 X" ) ;
                }
                SidePanel() ;
            } else if ( key == "F9" ) {
                if ( OPP01_CREATED ) {
                    if ( getComponentVisible( OPP01 ) ) {
                        CloseOptionPanel() ;
                    } else {
                        OpenOptionPanel() ;
                    }
                } else {
                    CreateOptionPanel() ;
                    OPP01_CREATED = true ;
                }
                if ( getComponentVisible( OPP01 ) ) {
                    setComponentText( LEXB[0], "パネル1 X" ) ;
                } else {
                    setComponentText( LEXB[0], "パネル1 F9" ) ;
                }
            } else if ( key == "F10" ) {
                if ( SETW01_CREATED ) {
                    setComponentVisible( SETW01, true ) ;
                } else {
                    CreateSETW01() ;
                    SETW01_CREATED = true ;
                }
            } else if ( key == "F11" ) {
                if ( CMW01_CREATED ) {
                    setComponentVisible( CMW01, true ) ;
                } else {
                    CreateCommadWindow() ;
                    CMW01_CREATED = true ;
                }
            } else if ( key == "F12" ) {
                if ( PRW01_CREATED ) {
                    setComponentVisible( PRW01, true ) ;
                } else {
                    CreateProgramWindow() ;
                    PRW01_CREATED = true ;
                }
            } else if ( // 回転
                ( key == "1" ) || ( key == "2" ) 
                || ( key == "3" ) || ( key == "T" ) 
            ) {
                int button ;
                if ( ROT1_USE_DFLT ) {
                    if ( key == "1" ) {
                        setComponentText( ROT1_SF[0], "回転1" ) ;
                        button = ROT1_BT[0] ;
                    } else if ( key == "2" ) {
                        setComponentText( ROT1_SF[1], "回転2" ) ;
                        button = ROT1_BT[1] ;
                    } else if ( key == "3" ) {
                        setComponentText( ROT1_SF[2], "回転3" ) ;
                        button = ROT1_BT[2] ;
                    } else if ( key == "T" ) {
                        setComponentText( ROT1_SF[0], "回転1" ) ;
                        setComponentText( ROT1_SF[1], "回転2" ) ;
                        setComponentText( ROT1_SF[2], "回転3" ) ;
                        button = ROT1_BT[3] ;
                    }
                }
                ControlRotation( button ) ;
            } else if ( key == "0" ) {
                if ( ! ROTATE_SYSTEMS ) {
                    for ( int i=0; i<length( ROT1_INI ); i++ ) {
                        if ( ROT1_INI[i] == false ) {
                            int rank = COORD_RNK[ROT1_BT_INDEX[i]+1] ;
                            int index = COORD_IDX[ROT1_BT_INDEX[i]+1] ;
                            if ( rank == 0 ) {
                                SetCoordinateEulerAngle( 
                                    COORD[index], INITIAL_EA1[i] 
                                ) ;
                            } else if ( rank == 1 ) {
                                SetCoordinateEulerAngle( 
                                    CD[index], INITIAL_EA1[i]
                                ) ;
                            }
                        }
                        setComponentText( 
                            ROT1_BT[3], "3つを同時に開始 t" 
                        ) ;
                        for ( int i=0; i<length( ROT_COUNT1, 0 ); i++ ) {
                            string s = "開始 " + ( i + 1 ) ;
                            setComponentText( ROT1_BT[i], s ) ;
                        }
                        setComponentText( ROT1_TLA[i], "" ) ;
                    }
                }
            } else if ( key == "I" ) {
                setCoordinateEulerAngle( 
                    getWorldCoordinate( RENDERER ), o, o, o 
                ) ;
                double q ;
                if ( P_INDEX == 0 ) {
                    q = a ;
                } else if ( P_INDEX == 1 ) {
                    q = a / 10 ;
                } else if ( P_INDEX == 2 ) {
                    q = a / 20 ;
                } else if ( P_INDEX == 3 ) {
                    q = a / 40 ;
                }
                setCoordinateOrigin(
                    getWorldCoordinate( RENDERER ), 
                    o, o, -CAMERA_ORIGIN_Z * q
                ) ;
                setGraphics3DMagnification( 
                        RENDERER, GRAPHIC_MAGNIFICATION * q
                );
                int mds[ ] = getComponentSize( MAIN_DISPLAY_LABEL ) ;
                int mdl[ ] = getComponentLocation( MAIN_DISPLAY_LABEL ) ;
                setGraphics3DCenter( 
                    RENDERER, mds[0] / 2, mds[1] / 2 + mdl[1] / 2  );
                setCoordinateEulerAngle(
                    COORD[TOP_COORD_INDEX], o, o, o
                );
            }
        }
    }
//            alert( key + "が押されました" ) ;
}

void onKeyType( int id, string key ) {

    if ( GUI_CREATED ) {
        if ( ! (
            // side panel
            id == ROT1_TF[0] || id == ROT1_TF[1] || id == ROT1_TF[2]
            // axis panel
            || id == AE_TXT[3][1] || id == AE_TXT[3][2] || id == AE_TXT[3][3]
            || id == AE_TXT[4][1] || id == AE_TXT[4][2] || id == AE_TXT[4][3]
            || id == AE_TXT[5][1] || id == AE_TXT[5][2] || id == AE_TXT[5][3]
            || id == AE_TXT[6][1] || id == AE_TXT[6][2] || id == AE_TXT[6][3]
            || id == AE_TXT[7][1] || id == AE_TXT[7][2] || id == AE_TXT[7][3]
            || id == AE_TXT[8][1] || id == AE_TXT[8][2] || id == AE_TXT[8][3]
            || id == AE_TXT[9][1] || id == AE_TXT[9][2] || id == AE_TXT[9][3]
            // comand window
            || id == CTXF[0] || id == CTXA[0] || id == CTXA[1]
            // program window
            || id == PTXT[0] || id == PTXT[1]
            // camera panel
            || id == CMPL_TF[0]
            // image save panel
            || id == ISPL_TF[0] || id == ISPL_TF[1] || id == ISPL_TF[2]
            || id == ISPL_TF[3] || id == ISPL_TF[4] || id == ISPL_TF[5]
            // frame panel
            || id == FMPL_TF[0] || id == FMPL_TF[1]
            || id == FMPL_TF[2] || id == FMPL_TF[3]
            || id == FMPL_TF[4] || id == FMPL_TF[5]
        ) ) {
            if ( id == LRTXL[0] ) {
                if ( PAUSE_MOTION ) {
                    PAUSE_MOTION = false ;
                    setComponentState( LCKB[3], false ) ;
                }
            }
        }
    }
}

void onButtonClick( int id ) {

    if ( GUI_CREATED ) {
        if ( id == LBTN[0] ) { // play
            ROT1_INI = true ; // Euler angle 初期値のリセット
            if ( KEEP_MOTION ) {
                KEEP_MOTION = false ;
                setComponentText( LBTN[0], LBTN_TX[0][0] ) ;
                setComponentText( LTXL[0], 
                    (string)( (int)( DEL_T * ( COUNT - START_C ) ) ) 
                ) ;
            } else {
                KEEP_MOTION = true ;
                setComponentText( LBTN[0], LBTN_TX[0][1] ) ;
                if ( INCREASE_COUNT ) {
                    if ( COUNT == END_C ) {
                        COUNT = START_C ;
                    }
                } else {
                    if ( COUNT == START_C ) {
                        COUNT = END_C ;
                    }
                }
            }
        } else if ( id == LBTN[1] ) { // <<
            COUNT = START_C ;
            if ( !KEEP_MOTION ) {
                InitializeIndicator() ;
                RefreshIndicator() ;
            }
        } else if ( id == LBTN[2] ) { // >>
            COUNT = END_C ;
            if ( !KEEP_MOTION ) {
                InitializeIndicator() ;
                RefreshIndicator() ;
            }
        } else if ( id == LBTN[3] ) { // reverse
            int c[ ] = getComponentColor( MAIN_WINDOW ) ;
            if ( INCREASE_COUNT ) {
                INCREASE_COUNT = false ;
                setComponentColor( 
                    LTXL[0], 100, 100, 200, 255, c[4], c[5], c[6], c[7] 
                ) ;
            } else {
                INCREASE_COUNT = true ;
                setComponentColor( 
                    LTXL[0], 200, 100, 100, 255, c[4], c[5], c[6], c[7] 
                ) ;
            }
            RefreshIndicator() ;
        } else if ( id == LBTN[4] ){ // accel
            int formeri = ACCEL + 5 ;
            ACCEL++ ;
            if ( ACCEL >= 5 ) {
                ACCEL = 0 ;
            }
            SPEED_CHANGED = true ;
            if ( PAUSE_MOTION ) {
                SetPauseCount() ;
            }
            if ( getComponentVisible( FRAME_PNL ) ) {
                JumpToFrame( FMPL_BT[3] ) ;
            }
            int n = ACCEL + 5 ;
            setComponentFontBold( LBTN[formeri], false ) ;
            setComponentFontSize( LBTN[formeri], 12 ) ;
            setComponentFontBold( LBTN[n], true ) ;
            setComponentFontSize( LBTN[n], 14 ) ;
        } else if ( 
            ( id == LBTN[5] ) || ( id == LBTN[6] ) || ( id == LBTN[7] )
            || ( id == LBTN[8] ) || ( id == LBTN[9] ) 
        ) { // accel 5 steps
            int formeri = ACCEL + 5, n = 5 ;
            while ( id != LBTN[n] ) {
                n++ ;
            }
            ACCEL = n - 5 ;
            SPEED_CHANGED = true ;
            if ( PAUSE_MOTION ) {
                SetPauseCount() ;
            }
            if ( getComponentVisible( FRAME_PNL ) ) {
                JumpToFrame( FMPL_BT[3] ) ;
            }
            setComponentFontBold( LBTN[formeri], false ) ;
            setComponentFontSize( LBTN[formeri], 12 ) ;
            setComponentFontBold( LBTN[n], true ) ;
            setComponentFontSize( LBTN[n], 14 ) ;
        } else if ( id == LEXB[1] || id == CLOSESIDEPNL_BTN ) {
            if ( SIDE_PANEL_OPENED ) {
                setComponentText( LEXB[1], "パネル2 F8" ) ;
            } else {
                setComponentText( LEXB[1], "パネル2 X" ) ;
            }
            SidePanel() ;
        }
        // side panel
        // button group
        else if ( id == PROGRAM_BTN ) { // program button
            if ( PRW01_CREATED ) {
                setComponentVisible( PRW01, true ) ;
            } else {
                CreateProgramWindow() ;
                PRW01_CREATED = true ;
            }
        } else if ( id == AXISSETTING_BTN ) { // 回転の設定などのウィンドウを開く
            if ( SETW01_CREATED ) {
                setComponentVisible( SETW01, true ) ;
            } else {
                CreateSETW01() ;
                SETW01_CREATED = true ;
            }
        } else if ( id == COMMAND_BTN ) { // command button
            if ( CMW01_CREATED ) {
                setComponentVisible( CMW01, true ) ;
            } else {
                CreateCommadWindow() ;
                CMW01_CREATED = true ;
            }
        } else if ( id == OPTION_BTN || id == LEXB[0] ) { // その他の設定
            if ( OPP01_CREATED ) {
                if ( getComponentVisible( OPP01 ) ) {
                    CloseOptionPanel() ;
                } else {
                    OpenOptionPanel() ;
                }
            } else {
                CreateOptionPanel() ;
                OPP01_CREATED = true ;
            }
            if ( getComponentVisible( OPP01 ) ) {
                setComponentText( LEXB[0], "パネル1 X" ) ;
            } else {
                setComponentText( LEXB[0], "パネル1 F9" ) ;
            }
        }
        // axis panel
        else if ( id == ABTN ) { // 座標軸の設定を開く
            if ( SETW01_CREATED ) {
                setComponentVisible( SETW01, true ) ;
                if ( ! OPEN_AEPNL ) {
                    OpenAxisEdit() ;
                    OPEN_AEPNL = true ;
                }
            } else {
                CreateSETW01() ;
                SETW01_CREATED = true ;
                OpenAxisEdit() ;
                OPEN_AEPNL = true ;
            }
        } 
        // rot1 panel
        // 回転などの設定を開き、簡略設定パネルを可視化する
        else if ( id == ROT1_ED_OPB[0] ) { 
            if ( SETW01_CREATED ) {
                setComponentVisible( SETW01, true ) ;
                if ( ! OPEN_REPNL ) {
                    OpenRotEdit1() ;
                    OPEN_REPNL = true ;
                }
            } else {
                CreateSETW01() ;
                SETW01_CREATED = true ;
                OpenRotEdit1() ;
                OPEN_REPNL = true ;
            }
        } 
        // 回転1〜3の「開始」button
        else if ( 
            ( id == ROT1_BT[0] ) || ( id == ROT1_BT[1] ) 
            || ( id == ROT1_BT[2] ) || ( id == ROT1_BT[3] ) 
        ) {
            if ( ROT1_USE_DFLT ) {
                string s ;
                for ( int i=0; i<length( ROT1_SF ); i++ ) {
                    if ( id == ROT1_BT[i] ) {
                        if ( i == 0 ) {
                            setComponentText( 
                                ROT1_SF[i], "回転1" 
                            ) ;
                        } else if ( i == 1 ) {
                            setComponentText( 
                                ROT1_SF[i], "回転2" 
                            ) ;
                        } else ( i == 2 ) {
                            setComponentText( 
                                ROT1_SF[i], "回転3" 
                            ) ;
                        }
                    } else {
                        setComponentText( ROT1_SF[0], "回転1" ) ;
                        setComponentText( ROT1_SF[1], "回転2" ) ;
                        setComponentText( ROT1_SF[2], "回転3" ) ;
                    }
                }
            }
            ControlRotation( id ) ;
        } 
        // cordinate attitude reset button
        else if ( id == ROT1_EULERANGLE_RESET_BT ) {
            if ( ! ROTATE_SYSTEMS ) {
                for ( int i=0; i<length( ROT1_INI ); i++ ) {
                    if ( ROT1_INI[i] == false ) {
                        int rank = COORD_RNK[ROT1_BT_INDEX[i]+1] ;
                        int index = COORD_IDX[ROT1_BT_INDEX[i]+1] ;
                        if ( rank == 0 ) {
                            SetCoordinateEulerAngle( 
                                COORD[index], INITIAL_EA1[i] 
                            ) ;
                        } else if ( rank == 1 ) {
                            SetCoordinateEulerAngle( 
                                CD[index], INITIAL_EA1[i]
                            ) ;
                        }
                        setComponentText( 
                            ROT1_BT[3], "3つを同時に開始 t" 
                        ) ;
                        for ( int i=0; i<length( ROT_COUNT1, 0 ); i++ ) {
                            string s = "開始 " + ( i + 1 ) ;
                            setComponentText( ROT1_BT[i], s ) ;
                        }
                        setComponentText( ROT1_TLA[i], "" ) ;
                    }
                }
            }
        }
        // camera reset button
        else if ( id == CAMERA_RESET_BT ) {
            setCoordinateEulerAngle( 
                getWorldCoordinate( RENDERER ), o, o, o 
            ) ;
            double q ;
            if ( P_INDEX == 0 ) {
                q = a ;
            } else if ( P_INDEX == 1 ) {
                q = a / 10 ;
            } else if ( P_INDEX == 2 ) {
                q = a / 20 ;
            } else if ( P_INDEX == 3 ) {
                q = a / 40 ;
            }
            setCoordinateOrigin(
                getWorldCoordinate( RENDERER ), o, o, -CAMERA_ORIGIN_Z * q
            ) ;
            setGraphics3DMagnification( 
                    RENDERER, GRAPHIC_MAGNIFICATION * q
            );
            int mds[ ] = getComponentSize( MAIN_DISPLAY_LABEL ) ;
            int mdl[ ] = getComponentLocation( MAIN_DISPLAY_LABEL ) ;
            setGraphics3DCenter( 
                RENDERER, mds[0] / 2, mds[1] / 2 + mdl[1] / 2  );
            setCoordinateEulerAngle(
                COORD[TOP_COORD_INDEX], o, o, o
            );
        }
        // comand window
        else if ( id == CBTN[0] ) {
            ShowBasicInfo() ;
        } else if ( id == CBTN[1] ) {
            ShowNow() ;
        } else if ( id == CBTN[2] ) {
            string text = getComponentText( CSLF[0] ) ;
            ShowCoordinateEulerAngle( text ) ;
        } else if ( id == CBTN[3] ) {
            string text = getComponentText( CSLF[0] ) ;
            ShowCoordinateOrigin( text ) ;
        } else if ( id == CBTN[4] ) {
            ShowEval( CTXF[0] ) ;
        } else if ( id == CBTN[5] ) {
            show() ;
        } else if ( id == CBTN[6] ) {
            print( getComponentText( CTXA[0] ) ) ;
        }
        // setting window
        // axix edit button
        else if ( id == AXIS_SETTING_BTN ) {
            if ( OPEN_AEPNL ) {
                CloseAxisEdit() ;
                OPEN_AEPNL = false ;
            } else {
                OpenAxisEdit() ;
                OPEN_AEPNL = true ;
            }
        }
        // axsis setting apply button
        else if ( id == A_AP_BT ) {
            ApplyAxisSetting() ;
        }
        // rotation edit button
        else if ( id == ROTATION_EDIT_BTN1 ) {
            if ( OPEN_REPNL ) {
                CloseRotEdit1() ;
                OPEN_REPNL = false ;
            } else {
                OpenRotEdit1() ;
                OPEN_REPNL = true ;
            }
        } else if ( id == REEX_BT[0] ) { // 回転設定の説明表示ボタン
            if ( ! ADD_REETX ) {
                AddPanelREEX() ;
                ADD_REETX = true ;
            } else {
                RemovePanelREEX() ;
                ADD_REETX = false ;
            }
        } else if ( id == RSET_BT1 ) { // 簡略設定の反映を行う
            if ( ! ROT1_USE_WRITTEN_VALUE ) {
                string s, s1 ;
                for ( int i=0; i<length( ROT1_SF ); i++ ) {
                    s = getComponentText( ROT1_SF[i] ) ;
                    if ( s == "回転1" ) {
                        s1 = getComponentText( RE_SF12[0] ) ;
                    } else if ( s == "回転2" ) {
                        s1 = getComponentText( RE_SF12[1] ) ;
                    } else if ( s == "回転3" ) {
                        s1 = getComponentText( RE_SF12[2] ) ;
                    } else if ( s == "回転4" ) {
                        s1 = getComponentText( RE_SF12[3] ) ;
                    } else if ( s == "回転5" ) {
                        s1 = getComponentText( RE_SF12[4] ) ;
                    } else if ( s == "回転6" ) {
                        s1 = getComponentText( RE_SF12[5] ) ;
                    }
                    s1 = replace( s1, "°", "" ) ;
                    setComponentText( ROT1_TF[i], s1 ) ;
                }
            }
            if ( ROT1_USE_DFLT ) {
                ROT1_USE_DFLT = false ;
                setComponentState( ROT1_CB[0], ROT1_USE_DFLT ) ;
            }
        }
        // program window
        else if ( id == PBTN[0] ) { // 上書きボタン
            string s = getComponentText( PTXT[0] ) ;
            Override1( s ) ;
            CopyComponentText( PTXT[0], PTXT[1] ) ;
        } else if ( id == PBTN[1] ) { // 上書き+1回実行
            string s = getComponentText( PTXT[0] ) ;
            Override1( s ) ;
            Dummyfunc1() ;
            CopyComponentText( PTXT[0], PTXT[1] ) ;
        }
        // option panel
        // button group
        else if ( id == CAMERA_SETTING_BTN ) { // camera settig
            setComponentVisible( CAMERA_PNL, true ) ;
            setComponentVisible( IMGSV_PNL, false ) ;
            setComponentVisible( IMGSV_PNL2, false ) ;
            setComponentVisible( FRAME_PNL, false ) ;
        } else if ( id == IMAGE_SAVE_BTN ) { // image save setting
            setComponentVisible( IMGSV_PNL, true ) ;
            setComponentVisible( CAMERA_PNL, false ) ;
            setComponentVisible( IMGSV_PNL2, false ) ;
            setComponentVisible( FRAME_PNL, false ) ;
        } else if ( id == FRAME_SETTING_BTN ) { // frame setting
            setComponentVisible( FRAME_PNL, true ) ;
            setComponentVisible( CAMERA_PNL, false ) ;
            setComponentVisible( IMGSV_PNL, false ) ;
            setComponentVisible( IMGSV_PNL2, false ) ;
        } else if ( id == CLOSE_OPTION_BTN ) { // close panel
            CloseOptionPanel() ;
            if ( getComponentVisible( OPP01 ) ) {
                setComponentText( LEXB[0], "パネル1 X" ) ;
            } else {
                setComponentText( LEXB[0], "パネル1 F9" ) ;
            }
        }
        // camera panel
        else if ( id == CMPL_BT[0] ) {
            string s = getComponentText( CMPL_TF[0] ) ;
            if ( s != "" ) {
                double camz = feval( s ) ;
                double q ;
                if ( P_INDEX == 0 ) {
                    q = a ;
                } else if ( P_INDEX == 1 ) {
                    q = a / 10 ;
                } else if ( P_INDEX == 2 ) {
                    q = a / 20 ;
                } else if ( P_INDEX == 3 ) {
                    q = a / 40 ;
                }
                CAMERA_ORIGIN_Z = camz ;
                setCoordinateOrigin( getWorldCoordinate( RENDERER ), 
                    o, o, -CAMERA_ORIGIN_Z * q
                ) ;
            }
        }
        // save image panel
        else if ( id == ISPL_BT[0] ) { // 次へ
            setComponentVisible( IMGSV_PNL2, true ) ;
            setComponentVisible( CAMERA_PNL, false ) ;
            setComponentVisible( IMGSV_PNL, false ) ;
            setComponentVisible( FRAME_PNL, false ) ;
            string tx1 = "現在の設定:" 
                + getComponentText( ISPL_TF[0] ) + " 秒("
                + getComponentText( ISPL_TF[1] ) + ")〜 "
                + getComponentText( ISPL_TF[2] ) + " 秒("
                + getComponentText( ISPL_TF[3] ) + ")"
            ;
            setComponentText( ISP2_TX[1], tx1 ) ;
            string tx2 = "合計 " 
                + getComponentText( ISPL_TF[4] ) + " 秒間("
                + getComponentText( ISPL_TF[5] ) + " フレーム)"
            ;
            setComponentText( ISP2_TX[2], tx2 ) ;
        } else if ( id == ISP2_BT[0] ) { // 戻る
            setComponentVisible( IMGSV_PNL, true ) ;
            setComponentVisible( IMGSV_PNL2, false ) ;
            setComponentVisible( CAMERA_PNL, false ) ;
            setComponentVisible( FRAME_PNL, false ) ;
        } else if ( id == ISP2_BT[1] ) { // 区間の再生
            int start_f = (int)( getComponentText( ISPL_TF[1] ) ) - 1 ;
            int end_f = (int)( getComponentText( ISPL_TF[3] ) ) - 1 ;
            int start_c = start_f * 2^ACCEL ;
            int end_c = end_f * 2^ACCEL ;
            bool save = false ;
            PlayFromTo( start_c, end_c, save ) ;
        } else if ( id == ISP2_BT[2] ) { // 区間の画像保存
            int start_f = (int)( getComponentText( ISPL_TF[1] ) ) - 1 ;
            int end_f = (int)( getComponentText( ISPL_TF[3] ) ) - 1 ;
            int start_c = start_f * 2^ACCEL ;
            int end_c = end_f * 2^ACCEL ;
            bool save = true ;
            PlayFromTo( start_c, end_c, save ) ;
        } else if ( id == ISP2_BT[4] ) { // 1枚撮影
            SaveImgPng() ;
        }
        // frame panel
        else if ( 
            id == FMPL_BT[0] || id == FMPL_BT[1] ||id == FMPL_BT[2]
            ||id == FMPL_BT[3]
        ) {
            JumpToFrame( id ) ;
        } else if ( id == FMPL_BT[4] || id == FMPL_BT[5] ) {
            GetTime( id ) ;
        }
    }
}

void onMouseLeftClick( int id, int x, int y, int count ){

    if ( GUI_CREATED ) {
        int n = length( INDICATOR ) - 1, i = 0 ;
        bool loop = true ;
        while ( loop ) {
            loop = ( id != INDICATOR[i] ) ;
            if ( i == n ) {
                if ( loop ) { // インジケーター以外をクリックした場合
                    i = -1 ;
                    loop = false ;
                }
            }
            i ++ ;
        }
        i -= 1 ;
        if ( i >= 0 ) { // インジケーターに限定
            int c = STEP * ( ( END_C - START_C ) * i / n / STEP ) ;
            JumpTo( c ) ;
            setComponentText( LTXL[0], (string)( (int)( DEL_T * c ) ) ) ;
            RefreshIndicator() ;
        }
    }
}

void onMouseRightClick( int id, intx, int y, int cout ) {

    alert( "右クリックされたコンポーネントの id は " + id ) ;
}

void onMouseLeftDrag( int id, int x, int y, int count ){

    if ( GUI_CREATED ) {
        int n = length( INDICATOR ) - 1, i = 0, nx ;
        double u ;
        bool loop = true ;
        while ( loop ) {
            loop = ( id != INDICATOR[i] ) ;
            if ( i == n ) {
                if ( loop ) { // インジケーター以外をドラッグした場合
                    i = -1 ;
                    loop = false ;
                }
            }
            i ++ ;
        }
        i -= 1 ;
        if ( i >= 0 ) { // インジケーターに限定
            nx = INDIW * i + x ; // MAIN_WINDOW 左基準の座標値
            u = a*nx / ( ( n + 1 ) * INDIW ) ; // 規格化
            if ( u < o ) {
                u = o ;
            } else if ( u > a ) {
                u = a ;
            }
            COUNT = START_C + ( END_C - START_C ) * u ;
            setComponentText( 
                LTXL[0], (string)( (int)( DEL_T * ( COUNT - START_C ) ) ) 
            ) ;
            if ( !KEEP_MOTION ) {
                Movie( o, true ) ;
            }
            RefreshIndicator() ;
        }
    }
}

void onCheckBoxClick( int id, bool state ) {

    // low panel
    if ( id == LCKB[0] ) {
        CIRCULATIVE_MOTION = state ;
        if ( CIRCULATIVE_MOTION ) {
            RECIPROCATIVE_MOTION = false ;
            setComponentState( LCKB[1], false ) ;
            PAUSE_MOTION = false ;
            setComponentState( LCKB[3], false ) ;
        }
    } else if ( id == LCKB[1] ) {
        RECIPROCATIVE_MOTION = state ;
        if ( RECIPROCATIVE_MOTION ) {
            CIRCULATIVE_MOTION = false ;
            setComponentState( LCKB[0], false ) ;
            PAUSE_MOTION = false ;
            setComponentState( LCKB[3], false ) ;
        }
    } else if ( id == LCKB[2] ) {
        SPIN = state ;
    } else if ( id == LCKB[3] ) {
        PAUSE_MOTION = state ;
        if ( PAUSE_MOTION ) {
            SetPauseCount() ;
        }
    }
    // control panel
    // axis 表示
    else if ( 
        ( id == ACKB[0] ) 
        || ( id == ACKB[1] ) ||( id == ACKB[2] ) || ( id == ACKB[3] )
        || ( id == ACKB[4] ) ||( id == ACKB[5] ) || ( id == ACKB[6] )
    ) {
        for ( int i=0; i<length( ACKB ); i++ ) {
            if ( id == ACKB[i] ) {
                if ( COORD_RNK[i] == -1 ) {
                    if ( state == true ) {
                        addModel( AXIS[i], RENDERER ) ;
                    } else {
                        removeModel( AXIS[i], RENDERER) ;
                    }
                } else if ( COORD_RNK[i] == 0 ) {
                    if ( state == true ) {
                        addModel( 
                            AXIS[i], RENDERER, COORD[COORD_IDX[i]] 
                        ) ;
                    } else {
                        removeModel( 
                            AXIS[i], RENDERER, COORD[COORD_IDX[i]] 
                        ) ;
                    }
                } else if ( COORD_RNK[i] == 1 ) {
                    if ( state == true ) {
                        addModel( 
                            AXIS[i], RENDERER, CD[COORD_IDX[i]] 
                        ) ;
                    } else {
                        removeModel( 
                            AXIS[i], RENDERER, CD[COORD_IDX[i]] 
                        ) ;
                    }
                }
            }
        }
    }
    // 座標系と回転軸に default を使うかどうか
    else if ( id == ROT1_CB[0] ) {
        ROT1_USE_DFLT = state ;
        if ( ROT1_USE_DFLT ) {
            setComponentText( ROT1_SF[0], "回転1" ) ;
            setComponentText( ROT1_SF[1], "回転2" ) ;
            setComponentText( ROT1_SF[2], "回転3" ) ;
            if ( ! ROT1_USE_WRITTEN_VALUE ) {
                setComponentText( ROT1_TF[0], "360" ) ;
                setComponentText( ROT1_TF[1], "360" ) ;
                setComponentText( ROT1_TF[2], "360" ) ;
            }
            // SETW01_CREATED, OPEN_REPNL は必ず true
            // 簡略設定パネルの回転1〜3のみが既定値に戻るようにする
            string s1[ ] = { "座標系1", "座標系2", "座標系3" } ;
            string s2[ ] = { 
                "親座標系のx軸", "親座標系のy軸", "親座標系のz軸"
            } ;
            string s3 = "360°" ;
            for ( int i=0; i<3; i++ ) {
                setComponentText( RE_SF10[i], s1[i] ) ;
                setComponentText( RE_SF11[i], s2[i] ) ;
                setComponentText( RE_SF12[i], s3 ) ;
            }
        } else {
            if ( SETW01_CREATED ) {
                setComponentVisible( SETW01, true ) ;
                if ( ! OPEN_REPNL ) {
                    OpenRotEdit1() ;
                    OPEN_REPNL = true ;
                }
            } else {
                CreateSETW01() ;
                SETW01_CREATED = true ;
                OpenRotEdit1() ;
                OPEN_REPNL = true ;
                setComponentText( ROT1_TF[0], "360" ) ;
                setComponentText( ROT1_TF[1], "360" ) ;
                setComponentText( ROT1_TF[2], "360" ) ;
            }
        }
    } 
    // 入力フィールドの数値を使うかどうか
    else if ( id == ROT1_CB[1] ) {
        ROT1_USE_WRITTEN_VALUE = state ;
        if ( ! ROT1_USE_WRITTEN_VALUE ) { // 簡略設定を使う
            if ( SETW01_CREATED ) {
                setComponentVisible( SETW01, true ) ;
                if ( ! OPEN_REPNL ) {
                    OpenRotEdit1() ;
                    OPEN_REPNL = true ;
                }
            } else {
                CreateSETW01() ;
                SETW01_CREATED = true ;
                OpenRotEdit1() ;
                OPEN_REPNL = true ;
            }
            string s1, s2 ;
            int n ;
            for ( int i=0; i<length( ROT1_SF ); i++ ) {
                string s1 = getComponentText( ROT1_SF[i] ) ;
                if ( s1 == "回転1" ) {
                    n = 0 ;
                } else if ( s1 == "回転2" ) {
                    n = 1 ;
                } else if ( s1 == "回転3" ) {
                    n = 2 ;
                } else if ( s1 == "回転4" ) {
                    n = 3 ;
                } else if ( s1 == "回転5" ) {
                    n = 4 ;
                } else if ( s1 == "回転6" ) {
                    n = 5 ;
                }
                s2 = getComponentText( RE_SF12[n] ) ;
                s2 = replace( s2, "°", "" ) ;
                setComponentText( ROT1_TF[i], s2 ) ;
            }
        }
    }
    // program window
    else if ( id == PCKB[0] ) {
        F1_IN_MOTION = state ;
        if ( F1_IN_MOTION ) {
            F1_IN_MAIN = false ;
            setComponentState( PCKB[1], false ) ;
        }
    } else if ( id == PCKB[1] ) {
        F1_IN_MAIN = state ;
        if ( F1_IN_MAIN ) {
            F1_IN_MOTION = false ;
            setComponentState( PCKB[0], false ) ;
        }
    }
}

void onSelectFieldClick( int id, string text ) {

    // control panel
    // 回転の種類を選択し直した場合
    if ( 
        ( id == ROT1_SF[0] ) || ( id == ROT1_SF[1] ) || ( id == ROT1_SF[2] ) 
    ) {
        for ( int i=0; i< length( ROT1_SF ); i++ ) {
            if ( id == ROT1_SF[i] ) {
                if ( ! ROT1_USE_WRITTEN_VALUE ) {
                    string s ;
                    if ( text == "回転1" ) {
                        s = getComponentText( RE_SF12[0] ) ;
                    } else if ( text == "回転2" ) {
                        s = getComponentText( RE_SF12[1] ) ;
                    } else if ( text == "回転3" ) {
                        s = getComponentText( RE_SF12[2] ) ;
                    } else if ( text == "回転4" ) {
                        s = getComponentText( RE_SF12[3] ) ;
                    } else if ( text == "回転5" ) {
                        s = getComponentText( RE_SF12[4] ) ;
                    } else if ( text == "回転6" ) {
                        s = getComponentText( RE_SF12[5] ) ;
                    }
                    s = replace( s, "°", "" ) ;
                    setComponentText( ROT1_TF[i], s ) ;
                }
            }
        }
    }
    // option panel
    // camera
    else if ( id == CMPL_SF[0] ) { // 遠近法
        PERSPECTIVE_CHANGED = true ;
    }
    // image save
    else if ( id == ISPL_SF[0] ) { // 諸量自動補填
        PrepareSavingImg( text ) ;
    }
}


/* PLAYER */

int LOW_PNL ;
int LR_PNL ;

int INDI_PNL ; // indicator panel
int INDICATOR[ 1 ] ; // text label 要素数は後で変更
int INDIW ; // onMouseLeftDrag() needs this

int LEXB[ 2 ] ;
N = 1 + 2 + 1 + 1 + 5 ; // play + to start, end + reverse + accel + 5steps
int LBTN[ N ] ; 
string LBTN_TX[ N ][ 2 ] ;
int LTXL[ 4 ] ; // num + sec + mum + sec, stop time + sec
int LRTXL[ 2 ] ;
int LCKB[ 4 ] ; // circulate + reciprocate + spin + pause

bool CIRCULATIVE_MOTION = false, RECIPROCATIVE_MOTION = false ; // repat

void CreateLowPanel( int buttonh ) {

    int c[ ] = { 51, 51, 51, 255, 250, 250, 250, 255 } ;

    int mws[ ] = getComponentSize( MAIN_WINDOW ) ;
    SetComponentColor( MAIN_WINDOW, c ) ;

    int comps = 6, s = 4 ;

    // LOW_PNL
    int mdls[ ] = getComponentSize( MAIN_DISPLAY_LABEL ) ;
    int lpy = GetComponentLocationLow( MAIN_DISPLAY_LABEL ) ;
    LOW_PNL = newPanel( comps, lpy, mdls[0] - 2*comps, 0, "low panel" ) ;
    SetComponentColor( LOW_PNL, MAIN_WINDOW ) ;
    addComponent( LOW_PNL, MAIN_WINDOW ) ;

    // indicator
    int indix = 0 ;
    int indiw = 14, indih = 12 ;
    INDI_PNL = newPanel( 
        0, 0, getComponentSize( LOW_PNL )[0], indih, 
        "indicator panel"
    ) ;
    SetComponentColor( INDI_PNL, LOW_PNL ) ;
    INDIW = indiw ;
    int len = ( getComponentSize( INDI_PNL )[0] - indix * 2 ) / indiw ;
    int dummyindi[ len ] ;
    INDICATOR [=] dummyindi ; // WIDTH と indiw で計算した length に合わす
    for ( int i=0; i<length( INDICATOR ); i++ ) {
        INDICATOR[i] = newTextLabel(
            indix + indiw * i, 0, indiw, indih, "=="
        ) ;
    }

    int x = 0, y = 0, w = 12 * 9, h = buttonh ;

    // LBTN[0], play button
    y = GetComponentLocationLow( INDI_PNL ) ;
    h = 2*h ;
    LBTN_TX[0][0] = "CG進行" ;
    LBTN_TX[0][1] = "CG停止" ;
    LBTN[0] = newButton( x, y, w, h, LBTN_TX[0][0] ) ;

    // LBTN[1,2], to edge
    x = GetComponentLocationRight( LBTN[0] ) ;
    w = w/2 ;
    h = h/2 ;
    LBTN_TX[1][0] = "|<" ;
    LBTN[1] = newButton( x, y, w, h, LBTN_TX[1][0] ) ;
    x = GetComponentLocationRight( LBTN[1] ) ;
    LBTN_TX[2][0] = ">|" ;
    LBTN[2] = newButton( x, y, w, h, LBTN_TX[2][0] ) ;

    // LBTN[3], reverse
    x = GetComponentLocationRight( LBTN[0] ) ;
    y = GetComponentLocationLow( LBTN[2] ) ;
    w = 2*w ;
    LBTN_TX[3][0] = "時間反転" ;
    LBTN[3] = newButton( x, y, w, h, LBTN_TX[3][0] ) ;

    // LBTN[4], 進行速度
    x = GetComponentLocationRight( LBTN[2] ) ;
    y = getComponentLocation( LBTN[2] )[1] ;
    LBTN_TX[4][0] = "進行速度" ;
    LBTN[4] = newButton( x, y, w, h, LBTN_TX[4][0] ) ;

    // LBTN[5-9], accel
    x = GetComponentLocationRight( LBTN[2] ) ;
    y = GetComponentLocationLow( LBTN[2] ) ;
    w = w/2 ;
    string accel[ ] = { "0.5", "1.0", "2.0", "4.0", "8.0" } ;
    for ( int i=5; i<=9; i++ ) {
        LBTN_TX[i][0] = accel[i-5] ;
        LBTN[i] = newButton( 
            x + w * ( i - 5 ), y, w, h, LBTN_TX[i][0] 
        ) ;
    }

    // 時間表示
    x = GetComponentLocationRight( LBTN[4] )  + w ;
    y = getComponentLocation( LBTN[4] )[1] ;
    w = 26 ;
    LTXL[0] = newTextLabel( x, y, w, h, "  0 " ) ;
    setComponentColor( LTXL[0], 200    , 100, 100, 255, c[4], c[5], c[6], c[7] ) ;
    setComponentFontItalic( LTXL[0], true ) ;
    x += w ;
    w = 12 ;
    LTXL[1] = newTextLabel( x, y, w, h, "秒" ) ;
    setComponentFontBold( LTXL[1], false) ;
    x += w + 24 ;
    w = getComponentSize( LTXL[0] )[1] ;
    string totaltime = (string)( (int)( END_T - START_T ) ) ;
    LTXL[2] = newTextLabel( x, y, w, h, totaltime ) ;
    setComponentFontBold( LTXL[2], false ) ;
    setComponentFontItalic( LTXL[2], true ) ;
    x += getComponentSize( LTXL[0] )[0] ;
    w = getComponentSize( LTXL[1] )[0] ;
    LTXL[3] = newTextLabel( x, y, w, h, "秒" ) ;
    setComponentFontBold( LTXL[3], false) ;

    // LEXB[0], open option panel
    w = 12*9 ;
    x = GetComponentLocationRight( LOW_PNL ) - w - 6 ;
    y = getComponentLocation( LBTN[0] )[1] ;
    LEXB[0] = newButton( x, y, w, h, "パネル1 F9" ) ;

    //LEXB[1], open side panel
    y = GetComponentLocationLow( LEXB[0] ) ;
    LEXB[1] = newButton( x, y, w, h, "パネル2 F8" ) ;

    // 残りは生成配置後透明化
    x = 0 ; y = 0 ; w = 0 ; h = 0 ;
    LR_PNL = newPanel( x, y, w, h, "low right panel" ) ;
    SetComponentColor( LR_PNL, MAIN_WINDOW ) ;
    addComponent( LR_PNL, MAIN_WINDOW ) ;
    setComponentVisible( LR_PNL, false ) ;
    x = 4 ; y = -3 ; w = 200 ; h = 18 ;
    LCKB[2] = newCheckBox( 
        x, y, w, h, "CG進行中の定角速度回転 s" , false
    ) ;
    y += h ; w = 100 - 16 ; 
    LCKB[0] = newCheckBox( x, y, w, h, "循環 c", false ) ;
    x += w ; w = 120 ;
    LCKB[1] = newCheckBox( x, y, w, h, "往復を続ける r", false ) ;
    x = 8 ;
    y += h ; w = 54 ;
    LRTXL[0] = newTextField( x, y, w, h, "          0.0" ) ;
    setComponentFontBold( LRTXL[0], false ) ;
    setComponentFontSize( LRTXL[0], 12 ) ;
    x += w + 2 ; w = 24 ;
    LRTXL[1] = newTextLabel( x, y, w, h, "秒で" ) ;
    setComponentFontBold( LRTXL[1], false ) ;
    x += w ; w = 100 ;
    LCKB[3] = newCheckBox( x, y, w, h, "一時停止", false ) ;

    addComponent( INDI_PNL, LOW_PNL ) ;
    AddComponent( INDICATOR, INDI_PNL ) ;

    SetComponentFontBold( LEXB, false ) ;
    AddComponent( LEXB, LOW_PNL ) ;

    SetComponentFontBold( LBTN, false ) ;
    AddComponent( LBTN, LOW_PNL ) ;

    AddComponent( LTXL, LOW_PNL ) ;
    SetComponentFontBold( LRTXL, false ) ;
    SetComponentColor( LRTXL, LR_PNL ) ;
    AddComponent( LRTXL, LR_PNL ) ;

    SetComponentFontBold( LCKB, false ) ;
    SetComponentColor( LCKB, LR_PNL ) ;
    AddComponent( LCKB, LR_PNL ) ;

    SetComponentSizeY( LOW_PNL, GetComponentLocationLow( LBTN[3] ) + s ) ;
    SetComponentSizeY( MAIN_WINDOW, 
        GetComponentLocationLow( LOW_PNL ) + TITLE_HEIGHT + 2 * BORDER 
    ) ;

    RefreshIndicator() ;
}

void CompactLowPanel( int delx ) {

    ShiftComponentLocationX( LOW_PNL, delx ) ;
    setComponentVisible ( LR_PNL, false ) ;
}

void EnlargeLowPanel( int delx ) {

    int x = 4 ;
    int y = getComponentLocation( LOW_PNL )[1] 
            + getComponentLocation( LBTN[0] )[1] -2 ;
    int w = getComponentSize( SIDESCRL_PNL )[0] + 4 ;
    int h = getComponentSize( LBTN[0] )[1] + 2 ;
    SetComponent( LR_PNL, x, y, w, h ) ;
    ShiftComponentLocationX( LOW_PNL, delx ) ;
    setComponentVisible ( LR_PNL, true ) ;
}


void InitializeIndicator() {

    int n = length( INDICATOR ) - 1 ;
    int dispT = DEL_T * ( COUNT - START_C ) ;
    int c[ ] = getComponentColor( MAIN_WINDOW ) ;
    int cinc[ 8 ] = { 200, 100, 100, 255, c[4], c[5], c[6], c[7] } ;
    int cdec[ 8 ] = { 100, 100, 200, 255, c[4], c[5], c[6], c[7] } ;
    int cind[ 8 ] = { 180, 180, 180, 255, c[4], c[5], c[6], c[7] } ;
    for ( int i=0; i<n; i++ ) {
        SetComponentColor( INDICATOR[i], cind ) ;
        setComponentText( INDICATOR[i], "==" ) ;
    }
    if ( INCREASE_COUNT ) {
        SetComponentColor( LTXL[0], cinc ) ;
        if ( COUNT == START_C ) {
            SetComponentColor( INDICATOR[0], cinc ) ;
        }
        if ( COUNT == END_C ) {
            SetComponentColor( INDICATOR[n], cinc ) ;
        }
        setComponentText( LTXL[0], (string)( dispT ) ) ;
        setComponentText( LBTN[0], LBTN_TX[0][0] ) ;
        if ( COUNT == START_C ) {
            setComponentText( INDICATOR[0], ">" ) ;
        } else if ( COUNT == END_C ) {
            setComponentText( INDICATOR[n], ">" ) ;
        }
        if ( KEEP_MOTION ) {
            setComponentText( LBTN[0], LBTN_TX[0][1] ) ;
        }
        if ( !KEEP_MOTION ) {
            Movie( o, true ) ;
        }
    } else {
        SetComponentColor( LTXL[0], cdec ) ;
        if ( COUNT == START_C ) {
            SetComponentColor( INDICATOR[0], cdec ) ;
        }
        if ( COUNT == END_C ) {
            SetComponentColor( INDICATOR[n], cdec ) ;
        }
        setComponentText( LTXL[0], (string)( dispT ) ) ;
        setComponentText( LBTN[0], LBTN_TX[0][0] ) ;
        if ( COUNT == START_C ) {
            setComponentText( INDICATOR[0], "<" ) ;
        } else if ( COUNT == END_C ) {
            setComponentText( INDICATOR[n], "<" ) ;
        }
        if ( KEEP_MOTION ) {
            setComponentText( LBTN[0], LBTN_TX[0][1] ) ;
        }
        if ( !KEEP_MOTION ) {
            Movie( o, true ) ;
        }
    }
}

void RefreshIndicator() {

    double t = a*( COUNT - START_C ) / ( END_C - START_C ) ;
    if ( t < o ) {
        t = o ;
    } else if ( t > a ) {
        t = a ;
    }
    int n = length( INDICATOR ) - 1 ;
    int index = n * t ;
    int c[ ] = getComponentColor( MAIN_WINDOW ) ;
    for ( int i=0; i<=n; i++ ) {
        if ( i == index ) {
            if ( INCREASE_COUNT ) {
                setComponentColor( INDICATOR[i],
                    200, 100, 100, 255, c[4], c[5], c[6], c[7]
                ) ;
                setComponentText( INDICATOR[i], ">" ) ;
            } else {
                setComponentColor( INDICATOR[i],
                    100, 100, 200, 255, c[4], c[5], c[6], c[7]
                ) ;
                setComponentText( INDICATOR[i], "<" ) ;
            }
        } else {
            setComponentColor( INDICATOR[i],
                180, 180, 180, 255, c[4], c[5], c[6], c[7]
            ) ;
            setComponentText( INDICATOR[i], "==" ) ;
        }
    }
}

void SetPauseCount() {

    string s_t = getComponentText( LRTXL[0] ) ;
    double pt = feval( s_t ) ;
    int c = 2 * pt * FPS ;
    c = ( c / (int)( 2^ACCEL ) ) * (int)( 2^ACCEL ) ;
    PAUSE_C = START_C + c ;
    pt = c * DEL_T ;
    string s = pt ;
    if ( lengthOf( s ) > 8 ) {
        s = substring( s , 0, 8 ) ;
    }
    setComponentText( LRTXL[0], s ) ;
    CIRCULATIVE_MOTION = false ;
    setComponentState( LCKB[0], false ) ;
    RECIPROCATIVE_MOTION = false ;
    setComponentState( LCKB[1], false ) ;
}


/* CONTROLPANEL */

bool SIDE_PANEL_OPENED = false ;

void UnvisualizeSidePanel() {

    int delx = getComponentSize( MAIN_DISPLAY_LABEL )[0]
                - getComponentSize( MAIN_WINDOW )[0] + 2*BORDER ;
    ShiftComponentSizeX( MAIN_WINDOW, delx ) ;
    SetComponentLocationX( MAIN_DISPLAY_LABEL, 0 ) ;
    ShiftComponentLocationX( MAIN_WINDOW, -delx ) ;
    setComponentVisible( SBTN_G1, false ) ;
    setComponentVisible( SIDESCRL_PNL, false ) ;
    CompactLowPanel( delx ) ;
    if ( OPP01_CREATED ) {
        SetComponentLocationX( OPP01, 4 ) ;
    }
}

void VisualizeSidePanel( int pw ) {

    ShiftComponentLocationX( MAIN_WINDOW, -pw ) ;
    SetComponentLocationX( MAIN_DISPLAY_LABEL, pw ) ;
    ShiftComponentSizeX( MAIN_WINDOW, pw ) ;
    setComponentVisible( SBTN_G1, true ) ;
    setComponentVisible( SIDESCRL_PNL, true ) ;
    if ( OPP01_CREATED ) {
        SetComponentLocationX( OPP01, pw ) ;
    }

    int comps = 6, s = 4 ;

    int x = 0, y = 0, w = pw - 2*s, h = 30 ;
    x = 0 ; y = 0 ;
    SetComponent( PROGRAM_BTN, x, y, w, h ) ;
    y += h ;
    SetComponent( COMMAND_BTN, x, y, w, h ) ;
    y += h ;
    SetComponent( AXISSETTING_BTN, x, y, w, h ) ;
    y += h ;
    SetComponent( OPTION_BTN, x, y, w, h ) ;
    w = 12*9 + 34 ; y += h ;
    SetComponent( ABOUTPROGRAM_BTN, x, y, w, h ) ;
    x += w ;
    w = pw - 2*s - w ;
    SetComponent( CLOSESIDEPNL_BTN, x, y, w, h ) ;
    w = pw - 2*s ;
    SetComponent( 
        SBTN_G1, s, s, w, GetComponentLocationLow( ABOUTPROGRAM_BTN ) + s 
    ) ;

    x = s ; y = s ; w = w - 4*s ; h = 20 ;
    SetComponent( ATXL[0], x, y, w/2, h ) ;
    x += w/2 ;
    SetComponent( ABTN, x, y, 58, h ) ;
    x = s ;
    y += h + s ;
    SetComponent( ACKB[0], x, y, w, h ) ;
    y += h + s ;
    int ck1w = w / 2 ;
    SetComponent( ACKB[1], x, y, ck1w, h ) ;
    SetComponent( ACKB[2], x + ck1w, y, ck1w, h ) ;
    y += h + s ;
    SetComponent( ACKB[3], x, y, ck1w, h ) ;
    SetComponent( ACKB[4], x + ck1w, y, ck1w, h ) ;
    y += h + s ;
    SetComponent( ACKB[5], x, y, ck1w, h ) ;
    SetComponent( ACKB[6], x + ck1w, y, ck1w, h ) ;
    SetComponent( 
        AXS_PNL, 0, 0, pw, GetComponentLocationLow( ACKB[6] ) + s
    ) ;

    x = s ; y = s ;
    SetComponent( ROT1_TL[0], x, y, w, h ) ;
    x += s ; y += h + s ; w = 82 ;
    SetComponent( ROT1_ED_OPB[0], x, y, w, h ) ;
    x += w + 2 ; 
    SetComponent( ROT1_TL[1], x, y, w, h ) ;
    x = 2*s ; y += h + s ; w = pw - 2*s ;
    SetComponent( ROT1_CB[0], x, y, w, h ) ;
    x = 2*s ; y += h ;
    SetComponent( ROT1_CB[1], x, y, w, h ) ;

    y += h + 2*s ; w = 60 + s ; h = 18 ;
    SetComponent( ROT1_SF[0], x, y, w, h ) ;
    x += w + 6*s ; w = pw - x - 8*s ; h = 30 ;
    SetComponent( ROT1_BT[0], x, y, w, h ) ;
    h = 18 ; x = 2*s ; y += h + 2*s ; w = 60 + s - 6 ; h += 2 ;
    SetComponent( ROT1_TF[0], x, y, w, h ) ;
    x += w ; w = 12 ; h = 18 ;
    SetComponent( ROT1_TLD[0], x, y, w, h ) ;
    x = getComponentLocation( ROT1_BT[0] )[0] ;
    y += s ; w = 84 ; h = 16 ;
    SetComponent( ROT1_TLA[0], x, y, w, h ) ;

    x = 2*s ; w = 60 + s ; h = 18 ;
    y = GetComponentLocationLow( ROT1_TF[0] ) + 2*s ;
    SetComponent( ROT1_SF[1], x, y, w, h ) ;
    x += w + 6*s ; w = pw - x - 8*s ; h = 30 ;
    SetComponent( ROT1_BT[1], x, y, w, h ) ;
    h = 18 ; x = 2*s ; y += h + 2*s ; w = 60 + s - 6 ; h += 2 ;
    SetComponent( ROT1_TF[1], x, y, w, h ) ;
    x += w ; w = 12 ; h = 18 ;
    SetComponent( ROT1_TLD[1], x, y, w, h ) ;
    x = getComponentLocation( ROT1_BT[0] )[0] ;
    y += s ; w = 84 ; h = 16 ;
    SetComponent( ROT1_TLA[1], x, y, w, h ) ;

    x = 2*s ; w = 60 + s ; h = 18 ;
    y = GetComponentLocationLow( ROT1_TF[1] ) + 2*s ;
    SetComponent( ROT1_SF[2], x, y, w, h ) ;
    x += w + 6*s ; w = pw - x - 8*s ; h = 30 ;
    SetComponent( ROT1_BT[2], x, y, w, h ) ;
    h = 18 ; x = 2*s ; y += h + 2*s ; w = 60 + s - 6 ; h += 2 ;
    SetComponent( ROT1_TF[2], x, y, w, h ) ;
    x += w ; w = 12 ; h = 18 ;
    SetComponent( ROT1_TLD[2], x, y, w, h ) ;
    x = getComponentLocation( ROT1_BT[0] )[0] ;
    y += s ; w = 84 ; h = 16 ;
    SetComponent( ROT1_TLA[2], x, y, w, h ) ;

    h = 18 ; x = 2*s ; h = 30 ;
    y = GetComponentLocationLow( ROT1_TF[2] ) + 2*s ;
    w = GetComponentLocationRight( ROT1_BT[2] ) 
            - getComponentLocation( ROT1_SF[2] )[0] ;
    SetComponent( ROT1_BT[3], x, y, w, h ) ;

    y += h ;
    SetComponent( ROT1_EULERANGLE_RESET_BT, x, y, w, h ) ;

    y += h ;
    SetComponent( CAMERA_RESET_BT, x, y, w, h ) ;


    SetComponent( ROT_CTRL_PNL, 
        0, GetComponentLocationLow( AXS_PNL ), 
        getComponentSize( AXS_PNL )[0], 
        GetComponentLocationLow( CAMERA_RESET_BT ) + s
    ) ;

    SetComponent( 
        SIDESCRLAREA_PNL, 0, 0, pw - 22, 
        GetComponentLocationLow( ROT_CTRL_PNL )
    ) ;

    SetComponent( SIDESCRL_PNL,
        s, GetComponentLocationLow( SBTN_G1 ),
        getComponentSize( PROGRAM_BTN )[0],
        getComponentSize( MAIN_WINDOW )[1] - ( TITLE_HEIGHT + 2*BORDER )
            - GetComponentLocationLow( SBTN_G1 )
            - getComponentSize( LOW_PNL )[1]
            + getComponentSize( INDI_PNL )[1] / 2
    ) ;

    EnlargeLowPanel( pw ) ;
}

void CreateSidePanel( int panelw ) {

    int y, compareaspace = 6, compspace = 4 ;

    // CommandPanel y
    CreateSideButtonGroup1( 0, 0, 0, 0 ) ;

    y = getComponentLocation( SBTN_G1 )[1]
        + getComponentSize( SBTN_G1 )[1] ; // + compareaspace ; // Side scroll y
    CreateSideScrollPanel( 0, 0, 0, 0 ) ;

    y = getComponentLocation( SIDESCRL_PNL )[1]
        + getComponentSize( SIDESCRL_PNL )[1] + compareaspace ; // AxixPanel y
    CreateAxisPanel( 0, 0, compareaspace, compspace/2 ) ;

    y = getComponentLocation( AXS_PNL )[1]
        + getComponentSize( AXS_PNL )[1] + compareaspace ; // RotationPanel y
    CreateRotationPanel( 0, y, compareaspace, compspace ) ;
}

int SBTN_G1 ; // command, setting button等の group
int PROGRAM_BTN ; // program window を開くボタン
int COMMAND_BTN ; // command window を開くボタン
int AXISSETTING_BTN ; // axis setting window を開くボタン
int OPTION_BTN ; // ライト、背景色などの設定を開くボタン
int ABOUTPROGRAM_BTN ; // このプログラムについてを開くボタン
int CLOSESIDEPNL_BTN ;

void CreateSideButtonGroup1( int pw, int py, int compas, int s ) {

    int x = 0, y = 0, w = 0, h = 0 ;
    SBTN_G1 = newPanel( x, y, w, h, "side button group1" ) ;
    addComponent( SBTN_G1, MAIN_WINDOW ) ;
    PROGRAM_BTN = newButton(
        x, y, w, h, "プログラムの記述と実行 F12"
    ) ;
    COMMAND_BTN = newButton(
        x, y, w, h, "式、変数、関数の計算 F11"
    ) ;
    AXISSETTING_BTN = newButton(
        x, y, w, h, "座標系関連の設定 F10"
    ) ;
    OPTION_BTN = newButton(
        x, y, w, h, "その他(パネル1) F9"
    ) ;
    ABOUTPROGRAM_BTN = newButton(
        x, y, w, h, "このCGについて"
    ) ;
    CLOSESIDEPNL_BTN = newButton(
        x, y, w, h, "X"
    ) ;
    setComponentFontBold( PROGRAM_BTN, false ) ;
    addComponent( PROGRAM_BTN, SBTN_G1 ) ;
    setComponentFontBold( COMMAND_BTN, false ) ;
    addComponent( COMMAND_BTN, SBTN_G1 ) ;
    setComponentFontBold( OPTION_BTN, false ) ;
    addComponent( OPTION_BTN, SBTN_G1 ) ;
    setComponentFontBold( AXISSETTING_BTN, false ) ;
    addComponent( AXISSETTING_BTN, SBTN_G1 ) ;
    setComponentFontBold( ABOUTPROGRAM_BTN, false ) ;
    addComponent( ABOUTPROGRAM_BTN, SBTN_G1 ) ;
    addComponent( CLOSESIDEPNL_BTN, SBTN_G1 ) ;
}

int SIDESCRL_PNL ; // scroll panel
int SIDESCRLAREA_PNL ;

void CreateSideScrollPanel( int pw, int py, int comps, int s ) {

    int x = 0, y = 0, w = 0, h = 0 ;
    SIDESCRL_PNL =  newScrollPanel( x, y, w, h, "side scroll panel" ) ;
    addComponent( SIDESCRL_PNL, MAIN_WINDOW ) ;
    SIDESCRLAREA_PNL = newPanel( x, y, w, h, "side scroll area panel" ) ;
    setComponentColor( SIDESCRLAREA_PNL,
        51, 51, 51, 255, 255, 255, 255, 255
    ) ;
    addComponent( SIDESCRLAREA_PNL, SIDESCRL_PNL) ;
}

int AXS_PNL ;
int ACKB[ 7 ], ATXL[ 1 ], ABTN ;

void CreateAxisPanel( int pw, int axispanely, int compareas, int comps ) {

    int c[ ] = { 51, 51, 51, 255, 230, 230, 250, 255 } ;
    int x = 0, y = 0, w = 0, h = 0 ;
    AXS_PNL = newPanel( x, y, w, h, "axis_panel" ) ;
    addComponent( AXS_PNL, SIDESCRLAREA_PNL ) ;
    SetComponentColor( AXS_PNL, c ) ;

    ATXL[0] = newTextLabel(
        x, y, w, h, "座標軸の表示"
    ) ;
    ABTN = newButton( x, y, 58, h, "設定" ) ;
    ACKB[0] = newCheckBox(
        x, y, w, h, "ワールド座標系", false
    ) ;
    ACKB[1] = newCheckBox(
        x, y, w, h, "座標系1", false
    ) ;
    ACKB[2] = newCheckBox(
        x, y, w, h, "座標系2", false
    ) ;
    ACKB[3] = newCheckBox(
        x, y, w, h, "座標系3", false
    ) ;
    ACKB[4] = newCheckBox(
        x, y, w, h, "座標系A", false
    ) ;
    ACKB[5] = newCheckBox(
        x, y, w, h, "座標系B", false
    ) ;
    ACKB[6] = newCheckBox(
        x, y, w, h, "座標系C", false
    ) ;
    SetComponentFontBold( ACKB, false ) ;
    SetComponentColor( ACKB, c ) ;
    AddComponent( ACKB, AXS_PNL ) ;
    SetComponentFontBold( ATXL, false ) ;
    SetComponentColor( ATXL, c ) ;
    AddComponent( ATXL, AXS_PNL ) ;
    setComponentFontBold( ABTN, false ) ;
    addComponent( ABTN, AXS_PNL ) ;
}

int ROT_CTRL_PNL ; // rotation control panel
int CAMERA_RESET_BT ; // カメラリセットボタン
int ROT1_SF[ 3 ] ; // 簡略回転設定セレクトフィールド
int ROT1_TF[ 3 ] ; // 簡略角度設定フィールド
int ROT1_TLD[ 3 ] ; // deg 表示
int ROT1_TLA[ 3 ] ; // 現在 deg 表示
int ROT1_BT[ 4 ] ; // 簡略回転開始ボタン
int ROT1_ED_OPB[ 1 ] ; // 簡略設定を開くボタン
int ROT1_TL[ 2 ] ; // その他のラベル
int ROT1_CB[ 2 ] ; // default の適用、角度指定の仕方
int ROT1_EULERANGLE_RESET_BT ; // 座標系姿勢リセット
bool ROT1_USE_DFLT = true ;
bool ROT1_USE_WRITTEN_VALUE = true ;

void CreateRotationPanel( int pw, int py, int compas, int s ) {

    int c[ ] = { 51, 51, 51, 255, 245, 230, 245, 255 } ;
    int x = 0, y = 0, w = 0, h = 0 ;

    ROT_CTRL_PNL = newPanel( x, y, w, h, "rot control panel" ) ;
    SetComponentColor( ROT_CTRL_PNL, c ) ;
    addComponent( ROT_CTRL_PNL, SIDESCRLAREA_PNL ) ;

    ROT1_TL[0] = newTextLabel( x, y, w, h, 
        "座標系の回転" 
    ) ;
    ROT1_ED_OPB[0] = newButton( x, y, w, h,
        "簡略設定"
    ) ;
    ROT1_TL[1] = newTextLabel( x, y, w, h, 
        "に基づく操作" 
    ) ;
    ROT1_CB[0] = newCheckBox( x, y, w, h,
        "座標系と回転軸は既定値", ROT1_USE_DFLT
    ) ;
    ROT1_CB[1] = newCheckBox( x, y, w, h,
        "回転角は入力値優先", ROT1_USE_WRITTEN_VALUE
    ) ;
    string s1[ ] = { "回転1", "回転2", "回転3", 
        "回転4", "回転5", "回転6" } ;
    ROT1_SF[0] = newSelectField( x+100, y, w, h, s1 ) ;
    string sstart = "開始 1" ;
    ROT1_BT[0] = newButton( x, y, w, h, sstart ) ;
    string sang = "360" ;
    ROT1_TF[0] = newTextField( x, y, w, h, sang ) ;
    string sdeg = "°" ;
    ROT1_TLD[0] = newTextLabel( x, y, w, h, sdeg ) ;
    ROT1_TLA[0] = newTextLabel( x, y, w, h, "" ) ;
    ROT1_SF[1] = newSelectField( x, y, w, h, s1 ) ;
    setComponentText( ROT1_SF[1], "回転2" ) ;
    sstart = "開始 2" ;
    ROT1_BT[1] = newButton( x, y, w, h, sstart ) ;
    ROT1_TF[1] = newTextField( x, y, w, h, sang ) ;
    ROT1_TLD[1] = newTextLabel( x, y, w, h, sdeg ) ;
    ROT1_TLA[1] = newTextLabel( x, y, w, h, "" ) ;
    ROT1_SF[2] = newSelectField( x, y, w, h, s1 ) ;
    setComponentText( ROT1_SF[2], "回転3" ) ;
    sstart = "開始 3" ;
    ROT1_BT[2] = newButton( x, y, w, h, sstart ) ;
    ROT1_TF[2] = newTextField( x, y, w, h, sang ) ;
    ROT1_TLD[2] = newTextLabel( x, y, w, h, sdeg ) ;
    ROT1_TLA[2] = newTextLabel( x, y, w, h, "" ) ;
    sstart = "3つを同時に開始 t" ;
    ROT1_BT[3] = newButton( x, y, w, h, sstart ) ;
    string eareset = "回転操作前へ戻す 0" ;
    ROT1_EULERANGLE_RESET_BT = newButton( x, y, w, h, eareset ) ;
    setComponentFontSize( ROT1_EULERANGLE_RESET_BT, 12 ) ;
    string rset = "他の状態を初期化 i" ;
    CAMERA_RESET_BT = newButton( x, y, w, h, rset ) ;

    SetComponentFont( ROT1_BT, 14, false ) ;
    AddComponent( ROT1_BT, ROT_CTRL_PNL ) ;
    setComponentFontSize( ROT1_BT[3], 12 ) ;

    AddComponent( ROT1_SF, ROT_CTRL_PNL ) ;

    SetComponentFont( ROT1_TF, 16, false ) ;
    AddComponent( ROT1_TF, ROT_CTRL_PNL ) ;

    SetComponentFont( ROT1_TLD, 16, false ) ;
    AddComponent( ROT1_TLD, ROT_CTRL_PNL ) ;

    SetComponentFont( ROT1_TLA, 11, false ) ;
    SetComponentFontItalic( ROT1_TLA, true ) ;
    AddComponent( ROT1_TLA, ROT_CTRL_PNL ) ;

    SetComponentColor( ROT1_CB, c ) ;
    SetComponentFontBold( ROT1_CB, false ) ;
    AddComponent( ROT1_CB, ROT_CTRL_PNL ) ;

    SetComponentFontBold( ROT1_TL, false ) ;
    AddComponent( ROT1_TL, ROT_CTRL_PNL ) ;

    SetComponentFontBold( ROT1_ED_OPB, false ) ;
    AddComponent( ROT1_ED_OPB, ROT_CTRL_PNL ) ;

    setComponentFontBold( ROT1_EULERANGLE_RESET_BT, false ) ;
    addComponent( ROT1_EULERANGLE_RESET_BT, ROT_CTRL_PNL ) ;
    setComponentFontBold( CAMERA_RESET_BT, false ) ;
    addComponent( CAMERA_RESET_BT, ROT_CTRL_PNL ) ;
}

bool ROTATE_SYSTEMS = false ;
bool ROTATE1[ ] = { false, false, false } ;
int END_ROT_COUNT1[ ] = { 0, 0, 0 } ;
int ROTATION_TYPE[ ] = { 0, 0, 0 } ; // rotX, rotY, rotZ, spnX, spinY, spinZ
int ROT1_BT_INDEX[ ] = { 0, 0, 0 } ; // ROT1_BT[x]がどのAXISが配置さている座標系に回転をほどこすか
double ANGLE1_PF[ ] = { o, o, o } ;
double DEG[ ] = { o, o, o } ;

void ControlRotation( int buttonid ) { // 回転ボタンが押されたときに呼び出される関数

    string s_rkind[ 3 ], s_system[ 3 ], s_ax[ 3 ], s_deg[ 3 ] ;
    int i = 0, j = 0, k = 0 ;
    while ( buttonid != ROT1_BT[i] ) {
        i ++ ;
        if ( i >= length( ROT1_BT, 0 ) ) {
            exit() ;
        } 
    }
    string s1[ ] = { 
        "回転1", "回転2", "回転3",
        "回転4", "回転5", "回転6"
     } ;
    string s2[ ] = { 
        "親座標系のx軸", "親座標系のy軸", "親座標系のz軸" 
    } ;

    if ( i < 3 ) {
        if ( ROT1_USE_DFLT ) {
            setComponentText( ROT1_SF[i], s1[i] ) ;
            s_ax[i] = s2[i] ;
            ROT1_BT_INDEX[i] = i ;
        } else {
            s_rkind[i] = getComponentText( ROT1_SF[i] ) ;
            while ( s_rkind[i] != s1[j] ) {
                j ++ ; // 回転(j+1)
                if ( j >= length( s1, 0 ) ) {
                    exit() ;
                } 
            }
            s_system[i] = getComponentText( RE_SF10[j] ) ;
            s_ax[i] = getComponentText( RE_SF11[j] ) ;
            string s[ ] = {
                "座標系1", "座標系2", "座標系3",
                "座標系A", "座標系B", "座標系C"
            } ;
            while ( s_system[i] != s[k] ) {
                k++ ;
                if ( k >= length( s, 0 ) ) {
                    exit() ;
                } 
            }
            ROT1_BT_INDEX[i] = k ; // ボタンiがどの座標系を回すか
        }
        if ( ROT1_USE_WRITTEN_VALUE ) {
            s_deg[i] = getComponentText( ROT1_TF[i] ) ;
        } else {
            s_deg[i] = replace( 
                getComponentText( RE_SF12[j] ), "°", "" 
            ) ;
        }
        string ch = charAt( s_ax[i], 5 ) ;
        bool parent = startsWith( s_ax[i], "親" ) ;
        if ( parent ) {
            if ( ch == "x" ) {
                ROTATION_TYPE[i] = 0 ;
            } else if ( ch == "y" ) {
                ROTATION_TYPE[i] = 1 ;
            } else if ( ch == "z" ) {
                ROTATION_TYPE[i] = 2 ;
            }
        } else {
            if ( ch == "x" ) {
                ROTATION_TYPE[i] = 3 ;
            } else if ( ch == "y" ) {
                ROTATION_TYPE[i] = 4 ;
            } else if ( ch == "z" ) {
                ROTATION_TYPE[i] = 5 ;
            }
        }
        if ( ROT_COUNT1[i] == 0 ) {
            DEG[i] = feval( s_deg[i] ) ;
            double x = DEG[i] / 360 ;
            if ( x < o ) {
                x = -x ;
            }
            if ( x > 1 ) {
                alert( 
                    "角度の絶対値は360°まで",
                    "同一回転3つの重ね合わせで最大1080°" 
                ) ;
            } else if ( x == o ) {
            } else {
                double y = ( x * ( 2 - x ) )^(a/2) ;
                END_ROT_COUNT1[i] = (int)( FPS * 4 * y * 2^( 1 - ACCEL ) ) ;
                ANGLE1_PF[i] = ( DEG[i] / END_ROT_COUNT1[i] ) * PI/180 ;
                ROTATE1[i] = true ;
                ROTATE_SYSTEMS = true ;
                setComponentText( ROT1_TF[i], (string)( DEG[i] ) ) ;
                string s = "停止 " + ( i + 1 ) ;
                setComponentText( ROT1_BT[i], s ) ;
                setComponentText( ROT1_BT[3], "待機中・・・" ) ;
            }
        } else if ( ROT_COUNT1[i] > 0 ) {
            if( ROTATE1[i] ) {
                ROTATE1[i] = false ;
                ROTATE_SYSTEMS = ROTATE1[0] || ROTATE1[1] || ROTATE1[2] ;
                string s = "再開 " + ( i + 1 ) ;
                setComponentText( ROT1_BT[i], s ) ;
                string ang 
                    =(string)( ROT_COUNT1[i] * ANGLE1_PF[i] * 180 / PI ) ;
                setComponentText( ROT1_TLA[i], "@" + ang ) ;
            } else if ( ! ROTATE1[i] ) {
                setComponentText( ROT1_TF[i], (string)( DEG[i] ) ) ;
                string s = "停止 " + ( i + 1 ) ;
                setComponentText( ROT1_BT[i], s ) ;
                ROTATE1[i] = true ;
                ROTATE_SYSTEMS = true ;
            }
        }
    } else if ( i == 3 ) { // 3つ同時
        if ( ! ROTATE_SYSTEMS ) {
            string st ;
            for ( int n=0; n<length( ROT1_BT, 0 ); n++ ) {
                if ( n < 3 ) {
                    st = "停止 " + ( n + 1 ) ;
                    if ( ROT1_USE_DFLT ) {
                        setComponentText( ROT1_SF[n], s1[n] ) ;
                        s_ax[n] = s2[n] ;
                        ROT1_BT_INDEX[n] = n ;
                    } else {
                        s_rkind[n] = getComponentText( ROT1_SF[n] ) ;
                        j = 0 ;
                        while ( s_rkind[n] != s1[j] ) {
                            j ++ ; // 回転(j+1)
                            if ( j >= length( s1, 0 ) ) {
                                exit() ;
                            } 
                        }
                        s_system[n] = getComponentText( RE_SF10[j] ) ;
                        s_ax[n] = getComponentText( RE_SF11[j] ) ;
                        string s[ ] = {
                            "座標系1", "座標系2", "座標系3",
                            "座標系A", "座標系B", "座標系C"
                        } ;
                        k = 0 ;
                        while ( s_system[n] != s[k] ) {
                            k++ ;
                            if ( k >= length( s, 0 ) ) {
                                exit() ;
                            } 
                        }
                        ROT1_BT_INDEX[n] = k ; // ボタンiがどの座標系を回すか
                    }
                    if ( ROT1_USE_WRITTEN_VALUE ) {
                        s_deg[n] = getComponentText( ROT1_TF[n] ) ;
                    } else {
                        s_deg[n] = replace( 
                            getComponentText( RE_SF12[j] ), "°", "" 
                        ) ;
                    }
                    string ch = charAt( s_ax[n], 5 ) ;
                    bool parent = startsWith( s_ax[n], "親" ) ;
                    if ( parent ) {
                        if ( ch == "x" ) {
                            ROTATION_TYPE[n] = 0 ;
                        } else if ( ch == "y" ) {
                            ROTATION_TYPE[n] = 1 ;
                        } else if ( ch == "z" ) {
                            ROTATION_TYPE[n] = 2 ;
                        }
                    } else {
                        if ( ch == "x" ) {
                            ROTATION_TYPE[n] = 3 ;
                        } else if ( ch == "y" ) {
                            ROTATION_TYPE[n] = 4 ;
                        } else if ( ch == "z" ) {
                            ROTATION_TYPE[n] = 5 ;
                        }
                    }
                    if ( ROT_COUNT1[n] == 0 ) {
                        DEG[n] = feval( s_deg[n] ) ;
                        double x = DEG[n] / 360 ;
                        if ( x < o ) {
                            x = -x ;
                        }
                        if ( x > 1 ) {
                            alert( 
                                "角度の絶対値は360°まで",
                                "同一回転3つの重ね合わせで最大1080°" 
                            ) ;
                        } else if ( x == o ) {
                            st = "待機中" ;
                        } else {
                            double y = ( x * ( 2 - x ) )^(a/2) ;
                            END_ROT_COUNT1[n] 
                                = (int)( FPS * 4 * y * 2^( 1 - ACCEL ) ) ;
                            ANGLE1_PF[n] 
                                = ( DEG[n] / END_ROT_COUNT1[n] ) * PI/180 ;
                            setComponentText( ROT1_TF[n], (string)( DEG[n] ) ) ;
                            ROTATE1[n] = true ;
                        }
                    }
                } else {
                    st = "待機中・・・" ;
                }
                setComponentText( ROT1_BT[n], st ) ;
            }
            ROTATE_SYSTEMS = true ;
        }
    }
}

void SidePanel() {
    if ( OTHER_ACTIONS ) {
        alert( "待機中" ) ;
    } else {
        string args[ 0 ] ;
        string program ;
        if ( SIDE_PANEL_OPENED ) {
            program 
                = "UnvisualizeSidePanel() ;"
                + "OTHER_ACTIONS = false ;"
                + "SIDE_PANEL_OPENED = false ;"
            ;
        } else {
            program 
                = "VisualizeSidePanel( 206 ) ;"
                + "OTHER_ACTIONS = false ;"
                + "SIDE_PANEL_OPENED = true ;"
            ;
        }
        override( "Action1", args, program ) ;
        OTHER_ACTIONS = true ;
    }
}


/* COMMANDWINDOW */

int CMW01 ;
int CTXA[ 2 ] ;
int CTAL[ 2 ] ; // text area 用のテキストラベル
int CSLF[ 1 ] ;
string CSFTX0[ ] = { 
    "座標系1", "座標系2", "座標系3", "座標系A", "座標系B", "座標系C"
} ;
int CTXF[ 1 ] ;
int CTXL[ 4 ] ;
int CBTN[ 7 ] ;
int CCKB[ 2 ] ;
int LFB ; // lf() button
int COPYB, MOVEB, CPADB, MVADB ;
bool KEEP_TXA0 = true ;
bool CMW01_CREATED = false ;

void CreateCommadWindow() {

    int mwx[ ] = getComponentLocation( MAIN_WINDOW ) ;
    int mws[ ] = getComponentSize( MAIN_WINDOW ) ;
    int cww = 600 ;
    int cwx[ ] = { mwx[0] + ( mws[0] - cww ) + 2*30, mwx[1] + 2*30 } ;
    int cws[ ] = { 600, mws[1] - 50 - 220 } ;
    int width = 250 ;
    int height = 30 ;
    int space = 12 ;
    int s = 4 ;
    int btnw = ( cws[0]-15 ) / 2 - 2*space - 5 ;
    int cwh = cws[1] - 36 ;
    CMW01 = newWindow( cwx[0], cwx[1], cws[0], cws[1], "コマンドウィンドウ" ) ;
    // CTAL[0]
    int tlx = ( cws[0]-15 ) / 2 -space, tly = space ;
    int tlw = 200, tlh = 20 ;
    CTAL[0] = newTextLabel(
        tlx, tly, tlw, tlh, "取得内容"
    ) ;
    // CTXA[0]
    int txa0w = ( cws[0]-15 ) / 2 , txa0h = 3*cwh / 5 ; 
    CTXA[0] = newTextArea( 
        tlx, tly + tlh , 
        txa0w, txa0h, ""
    ) ;
    // CTAL[1]
    CTAL[1] = newTextLabel(
        tlx, tly + tlh + txa0h + space, tlw, tlh, "メモ"
    ) ;
    // CTXA[1]
    int yr = year(), mt = month(), dy = day(), hr = hour(), mn = minute(), sd = second() ;
    string text = "vcssl  "
        + yr + "-" + mt + "-" + dy + "-" + hr + ":" + mn + ":" + sd ;
    CTXA[1] = newTextArea( 
        tlx, tly + 2*tlh + txa0h + space, 
        txa0w, cwh - 3 * space - 2*tlh - txa0h, text
    ) ;
    // CTXL, BTN
    int y = tly - 5 ;
    CTXL[0] = newTextLabel( space, y, width, height, 
        "以下の情報や値を取得して表示します" 
    ) ;
    y += height ;
    CBTN[0] = newButton( space, y, btnw, height, 
        "アニメーション情報、変数初期値" 
    ) ;
    y += height ;
    CBTN[1] = newButton( space, y, btnw, height, 
        "アニメーション現在情報" 
    ) ;
    y += height + space ;
    int txl2h = height + space ;
    int txl2w = 72 + s ;
    CSLF[0] = newSelectField( space, y, txl2w, txl2h, 
        CSFTX0 
    ) ;
    CTXL[1] = newTextLabel( space + txl2w + 4, y, width - txl2w, height, 
        "に関して、親座標系から見た" 
    ) ;
    y += height - 5 ;
    CBTN[2] = newButton( space, y, btnw, height, 
        "Euler 角 α, β, γ" 
    ) ;
    y += height ;
    CBTN[3] = newButton( space, y, btnw, height, 
        "原点座標 ( x, y, z )
    ) ;
    y += height + space ;
    CTXL[2] = newTextLabel( space, y, width, height, 
        "式の計算結果や変数値、関数値を求めます" 
    ) ;
    y += height ;
    CTXF[0] = newTextField( space, y, btnw, height, 
        "ここへ変数、数式、関数式を記述" 
    ) ;
    y += height + space/2 ;
    CBTN[4] = newButton( space, y, btnw, height, "計算実行" ) ;
    y += height + space ;
    CTXL[3] = newTextLabel( space, y, width, height, 
        "その他のコマンドの実行" 
    ) ;
    y += height ;
    CBTN[5] = newButton( space, y, btnw, height, "VCSSLコンソールを開く" ) ;
    y += height ;
    CBTN[6] = newButton( space, y, btnw, height, "VCSSLコンソールへ取得内容を表示" ) ;

    for ( int i=0; i<length( CTAL ); i ++ ) {
        setComponentFontBold( CTAL[i], false ) ;
        addComponent( CTAL[i], CMW01 ) ;
    }
    for ( int i=0; i<length( CTXA ); i++ ) {
        setComponentFontSize( CTXA[i], 16 ) ;
        setComponentFontBold( CTXA[i], false ) ;
        addComponent( CTXA[i], CMW01 ) ;
    }
    for ( int i=0; i<length( CTXF ); i++ ) {
        setComponentFontSize( CTXF[i], 14 ) ;
        setComponentFontBold( CTXF[i], false ) ;
        addComponent( CTXF[i], CMW01 ) ;
    }
    for ( int i=0; i<length( CSLF ); i++ ) {
        addComponent( CSLF[i], CMW01 ) ;
    }
    for ( int i=0; i<length( CBTN ); i++ ) {
        setComponentFontBold( CBTN[i], false ) ;
        addComponent( CBTN[i], CMW01 ) ;
    }
    for ( int i=0; i<length( CTXL ); i++ ) {
        setComponentFontBold( CTXL[i], false ) ;
        addComponent( CTXL[i], CMW01 ) ;
    }
}

void OpenCommandWindow() {

    int mwx[ ] = getComponentLocation( MAIN_WINDOW ) ;
    int mws[ ] = getComponentSize( MAIN_WINDOW ) ;
    int cwx[ ] = { mwx[0] -50, mwx[1] + 50 } ;
    int cws[ ] = { 600, mws[1]*2/3 } ;
    setComponentSize( CMW01, cws[0], cws[1] ) ;
    setComponentVisible( CMW01, true ) ;
}

void ShowBasicInfo() {

    int frames = ( END_C - START_C ) ;
    int size[ ] = getComponentSize( MAIN_DISPLAY_LABEL ) ;
    double omgps = 2*PI * RPM / 60, omgpf = omgps / FPS ;
    omgps = omgps*180/PI ;
    omgpf = omgpf*180/PI ;
    string camz ;
    string disp = "アニメーションに関する基本情報" + lf()
        + "    タイトル" + lf()
        + "        " + TITLE + lf()
        + "    CG表示領域の寸法" + lf()
        + "        " + WIDTH + " ピクセル x " + HEIGHT + " ピクセル " + lf()
        + "    総時間" + lf()
        + "        " + ( END_T - START_T ) + " 秒" + lf()
        + "    フレーム数" + lf()
        + "        " + FPS + " フレーム/秒" + lf()
        + "        " + "総計 " + ( frames/2 + 1 ) + " フレーム" + lf()
        + "    スピン座標系のインデックス" + lf()
        + "        " + (string)( TOP_COORD_INDEX ) + lf()
        + "    スピン座標系の一定角速度" + lf()
        + "        " + omgps/180 + " PI/秒" + lf()
        + "        " + "(" + omgps + " °/秒)" + lf()
        + "        " + "(" + omgpf + " °/フレーム)" + lf()
        + "    座標系階層数" + lf()
        + "        " + (string)( length( COORD, 0 ) ) + lf()
        + "    最上階層に並列配置された座標系総数" + lf()
        + "        " + (string)( length( CD, 0 ) ) + lf()
    ;
    if ( KEEP_TXA0 ) {
        string txa0 = getComponentText( CTXA[0] ) ;
         disp = txa0 + disp ;
    }
    setComponentText( CTXA[0], disp ) ;
}

void ShowNow() {

    int c = COUNT - START_C ;
    double t = c * DEL_T ;
    int f  = c / (int)( 2^ACCEL ) + 1 ;
    double runtime = second( time() ) ;
    string disp = "現在時刻,フレーム,カウント" + lf()
        + "    =  " + t + " 秒," + lf()
        + "        " + f 
            + " フレーム目 ( @ 倍速 " + ( 2^( ACCEL - 1 ) )
            + " ) " + lf() 
        + "        " + c 
            + " カウント" + lf() 
        +"起動してからの時間" + lf()
        + "    =  " + runtime + " 秒," + lf()
    ;
    if ( KEEP_TXA0 ) {
        string txa0 = getComponentText( CTXA[0] ) ;
        disp = txa0 + disp ;
    }
    setComponentText( CTXA[0], disp ) ;
}

void ShowCoordinateEulerAngle( string text ) {

    int index, i = -1 ;
    int sa ;
    bool loop = true ;
    while ( loop ) {
        i ++ ;
        loop = ( text != CSFTX0[i] ) ;
        if ( i == 5 ) {
            loop = false ;
        }
    }
    index = COORD_IDX[i+1] ;
    int rnk = COORD_RNK[i+1] ;
    if ( rnk == 0 ) {
        sa = GetVectorCoordinateEulerAngle( COORD[index] ) ;
        text = text + " ( COORD [ " + index + " ] ) " ;
    } else if ( rnk == 1 ) {
        sa = GetVectorCoordinateEulerAngle( CD[index] ) ;
        text = text + " ( CD [ " + index + " ] ) " ;
    }
    double al = getVectorX( sa ) / PI ;
    if ( abs( al ) < d^-6 ) {
        al = o ;
    }
    double bt = getVectorY( sa ) / PI ;
    if ( abs( bt ) < d^-6 ) {
        bt = o ;
    }
    double gm = getVectorZ( sa ) / PI ;
    if ( abs( gm ) < d^-6 ) {
        gm = o ;
    }
    string disp
        = text + "の Euler 角" + lf()
        + " α =  " + al + " PI" + lf() 
        + "        ( " + al*180 + "° )" + lf()
        + " β =  " + bt + " PI" + lf() 
        + "        ( " + bt*180 + "° )" + lf()
        + " γ =  " + gm + " PI" + lf() 
        + "        ( " + gm*180 + "° )" + lf()
    ;
    if ( KEEP_TXA0 ) {
        string txa0 = getComponentText( CTXA[0] ) ;
        disp = txa0 + disp ;
    }
    setComponentText( CTXA[0], disp ) ;
}

void ShowEval( int id ) {

string exp = getComponentText( id ) ;
string s[ ] = eval( exp ) ;
string val = s[0] ;
    for ( int i=1; i<length( s, 0 ); i++ ) {
        val = val + "," + lf() + "        " + s[i] ;
    }
    string disp = exp + lf() +  "    =  " + val + lf() ;
    if ( KEEP_TXA0 ) {
        string txa0 = getComponentText( CTXA[0] ) ;
        disp = txa0 + disp ;
    }
    setComponentText( CTXA[0], disp ) ;
}

void ShowCoordinateOrigin( string text ) {

    int index, i = -1 ;
    int origin ;
    bool loop = true ;
    while ( loop ) {
        i ++ ;
        loop = ( text != CSFTX0[i] ) ;
        if ( i == 5 ) {
            loop = false ;
        }
    }
    index = COORD_IDX[i+1] ;
    int rnk = COORD_RNK[i+1] ;
    if ( rnk == 0 ) {
        origin = GetVectorCoordinateOrigin( COORD[index] ) ;
        text = text + " ( COORD [ " + index + " ] ) " ;
    } else if ( rnk == 1 ) {
        origin = GetVectorCoordinateOrigin( CD[index] ) ;
        text = text + " ( CD [ " + index + " ] ) " ;
    }
    double x = getVectorX( origin ) ;
    if ( abs( x