void
PlayerSceneCreate::configureNode(SceneNodePtr node, const PlayerItemPtr item, const TimeRange &time_range)
{
    // Set screen rectangle for node
    const ScreenRect &rect = item->getScreenRect();
    if (rect.isFullScreen())
        node->setFullScreenRect();
    else {
        float x1,y1,x2,y2;
        rect.getExtents(x1, y1, x2, y2);
        node->setScreenRect(x1, y1, x2, y2);
    }

    // Pivot point is center of rotation and scaling
    float pivotX = 0, pivotY = 0, pivotZ = 0;
    compute_pivot(item, pivotX, pivotY, pivotZ);
    node->setPivot(pivotX, pivotY, pivotZ);

    // Static Transformation
    float sx = 1, sy = 1, sz = 1;
    item->getScale(sx, sy, sz);
    node->setScale(sx, sy, sz);
    float posx = 0, posy = 0, posz = 0;
    item->getPosition(posx, posy, posz);
    node->setPosition(posx, posy, posz);

    // Switching to euler angles for 3d rotation
    //node->setRotationInDegrees(item->getRotationInDegrees());
    float rx = 0, ry = 0, rz = 0;
    item->getEulerAnglesInDegrees(rx, ry, rz);
    node->setEulerAnglesInDegrees(rx, ry, rz);

    // Set rule for how to fit image into aspect ratio of screen
    ContentMode contentMode = item->getContentMode();
    set_node_resize_fit(node.get(), contentMode);

    // And set the gravity enumeration
    Gravity gravity = item->getGravity();
    set_node_gravity(node.get(), gravity);

    // Cropping region, default of "no crop" is (0,0,1,1)
    float cx = 0, cy = 0, cw = 1, ch = 1;
    item->getCroppingRegion(cx, cy, cw, ch);
    node->setCroppingRegion(cx, cy, cw, ch);

    // Focus of subregion when aspect fitting subregions
    float fx = 0.5f, fy = 0.3333f;
    item->getFocusCenter(fx, fy);
    node->setFocusCenter(fx, fy);

    // Frame preserves size when image resizes
    const FrameInfo &framing = item->getFraming();
    if (framing.hasFraming()) {
        BorderWidths frame_size, frame_uvs;
        framing.getFrameSize(frame_size.left, frame_size.right, frame_size.top, frame_size.bottom);
        framing.getFrameUVs(frame_uvs.left, frame_uvs.right, frame_uvs.top, frame_uvs.bottom);
        node->setFrameBorder(frame_size, frame_uvs);
    }

    // Blend mode enumeration
    BlendMode blendMode = item->getBlendMode();
    set_node_blend_mode(node.get(), blendMode);

    // Set zorder, when static
    node->setZOrder(item->getZOrder());

    // Set static opacity
    node->setOpacity(item->getOpacity());

    // This controls when videos start playing.
    // NOTE: if the transition expands the visible time, should the
    // video be playing during this time? Right now, it is set
    // so that the video holds the first or last frame during the
    // extra transition time.
    //
    mf::Time playbackStartOffset = time_range.getItemStartTime()+Time::Seconds(item->getPlaybackStart());
    node->setLocalTimeOffset(playbackStartOffset);

    //NOTE This isn't the way I want to keep track of local time. I want it to
    // be handled by the Preloader later.
    if (node->getAsset() != NULL)
        node->getAsset()->setLocalTimeOffset(playbackStartOffset);

    // Create keys for the animation for this item, if it exists
    const AnimationPtr animation = item->getAnimation();
    if (animation) {
        Time anim_begin, anim_end;
        switch(animation->getTiming()) {
        default:
        case Animation::INNER_TIME_RANGE:
            // Internal time range is the time when the item is visible and
            // is not running part of the transition animation.
            anim_begin = time_range.getInternalStartTime();
            anim_end = time_range.getInternalEndTime();
            break;
        case Animation::ITEM_TIMING:
            anim_begin = time_range.getItemStartTime();
            anim_end = time_range.getItemEndTime();
            break;
        case Animation::OUTER_TIME_RANGE:
            anim_begin = time_range.getVisibleStartTime();
            anim_end = time_range.getVisibleEndTime();
            break;
        }

        // Make sure there is really time between the transitions in order to play an animation
        if (anim_begin < anim_end) {
            animation->addKeysToNode(node.get(), anim_begin, anim_end);
        }
    }

    // Add in the filter effects based on the transitions
    applyTransitionEffects(node, item, time_range);

    // Transfer camera
    if (item->getCamera()) {
        CameraViewPtr camera_view = item->getCamera();
        CameraObjectPtr camera_object;

        const auto it = _cameraShareMap.find(camera_view);
        if (it != _cameraShareMap.end()) {
            camera_object = it->second;
        } else {
            camera_object.reset(new CameraNode());
            _cameraShareMap[camera_view] = camera_object;  // store for sharing

            // Transfer properties
            camera_view->setProperties(camera_object.get());

            // Add animation to camera
            camera_view->addKeysToNode(camera_object.get(), time_range.getItemStartTime(), time_range.getItemEndTime());
        }

        // Give camera to node
        node->setCamera(camera_object);
    }

}
void
PlayerSceneCreate::applyTransitionEffects(SceneNodePtr node, const PlayerItemPtr item, const TimeRange &time_range)
{
    Time beginTime = time_range.getVisibleStartTime();
    Time endTime = time_range.getVisibleEndTime();

    const TransitionPtr trans = item->getStartTransition();
    // Add in the animations based on the begin transition
    if (trans) {

        const Time end = beginTime + Time::Seconds(trans->getDuration());
        FilterEffectPtr filter = trans->getFilterForNextItem();
        if (filter) {
            EffectNodeCreateInfo createInfo;
            createInfo.sourceAsset = node->getAsset();
            // reversing end and start times, effect time goes from 1->0
            createInfo.animBegin = end - time_range.getItemStartTime();
            createInfo.animEnd = beginTime - time_range.getItemStartTime();
            createInfo.shareNonStatic = false;
            createInfo.nodeCreator = std::bind(&PlayerSceneCreate::
                                               createOrShareNodeNetwork,
                                               this,
                                               std::placeholders::_1,
                                               std::placeholders::_2);

            // Create effect network for the transition filter
            ShaderNodePtr shader;
            EffectNodeNetworkPtr network = createOrShareNodeNetwork(filter, createInfo);
            if (network->getNetworkType() == IMAGE) {
                // Connect the shader to the output of this network
                ImageAsset *filterNetworkOutput = network->getImage();
                shader = node->addRendererKey(beginTime, filter->getRendererId());
                shader->setSourceImage(filterNetworkOutput);
            }
            else if (network->getNetworkType() == SHADER) {
                shader = ShaderNodePtr(network->getShader());
                // Start transition filter's shader at begin time
                node->addRendererKey(beginTime, shader);
            }

            // After transition, go back to regular renderer (id ==0)
            node->addDefaultRendererKey(end);

            // Animate the transition
            node->addEffectTimeKey(beginTime, 1.0f);
            node->addEffectTimeKey(end, 0.0f);
        }
    }

    const TransitionPtr endTrans = item->getEndTransition();
    // Add in the animations based on the end transition
    if (endTrans)  {

        Time start = endTime - Time::Seconds(endTrans->getDuration());

        FilterEffectPtr filter = endTrans->getFilterForPreviousItem();
        if (filter) {
            EffectNodeCreateInfo createInfo;
            createInfo.sourceAsset = node->getAsset();
            createInfo.animBegin = start - time_range.getItemStartTime();
            createInfo.animEnd = endTime - time_range.getItemStartTime();
            createInfo.shareNonStatic = false;
            createInfo.nodeCreator = std::bind(&PlayerSceneCreate::createOrShareNodeNetwork,
                                               this,
                                               std::placeholders::_1,
                                               std::placeholders::_2);

            // Create effect network for the transition filter
            ShaderNodePtr shader;
            EffectNodeNetworkPtr network = createOrShareNodeNetwork(filter, createInfo);
            if (network->getNetworkType() == IMAGE) {
                // Connect the shader to the output of this network
                ImageAsset *filterNetworkOutput = network->getImage();
                shader = node->addRendererKey(start, filter->getRendererId());
                shader->setSourceImage(filterNetworkOutput);
            }
            else if (network->getNetworkType() == SHADER) {
                shader = ShaderNodePtr(network->getShader());
                // Start transition filter's shader at start time
                node->addRendererKey(start, shader);
            }

            // Animate the transition
            node->addEffectTimeKey(start, 0.0f);
            node->addEffectTimeKey(endTime, 1.0f);
        }

    }

}