NodeDeclPtr XmlSceneParser::Impl::PrepareNode (const ParseNode& decl)
{
  try
  {
      //попытка найти параметры в кеше
      
    if (NodeDeclPtr* node_decl_ptr = cache.FindValue<NodeDeclPtr> (decl))
      return *node_decl_ptr;

    NodeDeclPtr node_decl (new NodeDecl, false);

      //парсинг базовых свойств
    
    node_decl->name = get<const char*> (decl, "id", "");

      //парсинг точки поворота

    if (decl.First ("pivot"))      
    {
      stl::auto_ptr<NodeDecl::Pivot> pivot (new NodeDecl::Pivot);

      ParseAttribute (decl, "pivot", pivot->position);

      pivot->has_orientation_pivot = strcmp (get<const char*> (decl, "orientation_pivot", "true"), "true") == 0;
      pivot->has_scale_pivot       = strcmp (get<const char*> (decl, "scale_pivot", "true"), "true") == 0;

      node_decl->pivot = pivot;
    }

      //парсинг трансформаций

    node_decl->is_world_transform = strcmp (get<const char*> (decl, "bind_space", "local"), "world") == 0;

    if (ParseNode tm_node = decl.First ("transform"))
    {
      math::mat4f tm;        
      
      ParseAttribute (tm_node, "", tm);
      
      affine_decompose (tm, node_decl->position, node_decl->orientation, node_decl->scale);
    }
    else
    {
      ParseAttribute (decl, "position", node_decl->position);
      ParseAttribute (decl, "scale", node_decl->scale);        
      
      if (ParseNode rotation_node = decl.First ("rotation"))
      {
        float rotation [3] = {0.0f, 0.0f, 0.0f};
        
        ParseAttribute (rotation_node, "", 3, &rotation [0]);
        
        node_decl->orientation = to_quat (degree (rotation [0]), degree (rotation [1]), degree (rotation [2]));
      }
      else
      {
        ParseAttribute (decl, "orientation", node_decl->orientation);
      }
    }
    
    node_decl->orientation_inherit = strcmp (get<const char*> (decl, "orientation_inherit", "true"), "true") == 0;
    node_decl->scale_inherit       = strcmp (get<const char*> (decl, "scale_inherit", "true"), "true") == 0;

      //парсинг пользовательских свойств

    PropertyMap* properties = 0;
    
    if (decl.First ("property"))
      node_decl->properties.reset (properties = new PropertyMap);

    for (Parser::NamesakeIterator iter = decl.First ("property"); iter; ++iter)
    {
      ParseNode property_decl = *iter;

      const char*  name  = get<const char*> (property_decl, "name");
      PropertyType type  = get_property_type (property_decl.First ("type"));

      size_t property_index = properties->AddProperty (name, type, 1);
      
      stl::string value = get<const char*> (property_decl, "value");
      
      properties->SetProperty (property_index, value.c_str ());
    }

      //парсинг after node
      
    if (ParseNode before_node_decl = decl.First ("before_node"))
    {
      node_decl->before_node.reset (new stl::string);
      
      *node_decl->before_node = get<const char*> (before_node_decl, "");
    }
            
      //парсинг привязки к родителю
      
    if (ParseNode parent_name_decl = decl.First ("parent"))
    {
      node_decl->parent_name.reset (new stl::string);
      
      *node_decl->parent_name = get<const char*> (parent_name_decl, "");
    }

      //регистрация дескриптора узла
      
    cache.SetValue (decl, node_decl);
    
    return node_decl;
  }
  catch (xtl::exception& e)
  {
    e.touch ("scene_graph::XmlSceneParser::Impl::PrepareNode");
    throw;
  }
}