Example #1
0
UndoCommandPtr Curve::CenterTransform()
{
    BatchUndoCommandPtr batch = new BatchUndoCommand();

    batch->Push( Base::CenterTransform() );

    if ( GetNumberControlPoints() == 0 )
    {
        return batch;
    }


    //
    // We are going to move all control points, so just snap shot
    //

    batch->Push( SnapShot() );


    //
    // Compute the centered position
    //

    Vector3 position = Vector3::Zero;

    {
        uint32_t controlPointCount = 0;
        OS_HierarchyNodeDumbPtr::Iterator childItr = GetChildren().Begin();
        OS_HierarchyNodeDumbPtr::Iterator childEnd = GetChildren().End();
        for ( ; childItr != childEnd; ++childItr )
        {
            CurveControlPoint* point = Reflect::SafeCast< CurveControlPoint >( *childItr );
            if ( point )
            {
                ++controlPointCount;
                position += point->GetPosition();
            }
        }
        position /= (float32_t)controlPointCount;
    }

    m_GlobalTransform.TransformVertex( position );


    //
    // Offset the control points
    //

    Matrix4 m = m_GlobalTransform;

    m.t = position;

    m = m_GlobalTransform * m.Inverted();

    {
        OS_HierarchyNodeDumbPtr::Iterator childItr = GetChildren().Begin();
        OS_HierarchyNodeDumbPtr::Iterator childEnd = GetChildren().End();
        for ( ; childItr != childEnd; ++childItr )
        {
            CurveControlPoint* point = Reflect::SafeCast< CurveControlPoint >( *childItr );
            if ( point )
            {
                Vector3 p = point->GetPosition();

                m.TransformVertex( p );

                batch->Push( new PropertyUndoCommand< Vector3 >( new Helium::MemberProperty< CurveControlPoint, Vector3 >( point, &CurveControlPoint::GetPosition, &CurveControlPoint::SetPosition ), p ) );
            }
        }
    }


    //
    // Recompute global transform
    //

    // our new global transform is just translated to the new position
    m_GlobalTransform.t = position;

    // this will recompute the local components
    SetGlobalTransform( m_GlobalTransform );

    // update the transform object
    Evaluate( GraphDirections::Downstream );

    // update each child's local transform to stay in the same global position
    for ( OS_HierarchyNodeDumbPtr::Iterator itr = m_Children.Begin(), end = m_Children.End(); itr != end; ++itr )
    {
        HierarchyNode* n = *itr;

        Transform* t = Reflect::SafeCast<Transform>( n );

        if ( !t )
        {
            continue;
        }

        batch->Push( t->ComputeObjectComponents() );
    }

    Dirty();

    return batch;
}