Войти
Уголок tool-программСтатьи

Загрузка, Редактирование, Сохранение - Универсальный подход

Автор:

Введение
Описание шаблона
Интерфейс к редактируемому объекту
Интерфейс пользователю
Пара слов о загрузке
Заключение

Введение

Наверняка в вашем движке имеется множество объектов-ресурсов, они грузятся, все работает, но со временем приходит желание пользоваться более удобным инструментом для редактирования чем Блокнот, и мы хотим редактировать объект, и сразу видеть изменения. Быть может, редактор будет не скоро, но обязательно стоит взглянуть вперед и представить, как же будут редактироваться все ваши объекты, все эти источники звука, света, материалы, свойства физических тел, водные поверхности, настройки параметров неба, и т.д. Конечно, можно сказать что не проблема, каждому объекту по окошку для редактирования, как доберемся до редактора так и подумаем.

После того, как я представил, сколько нужно будет написать однотипного кода, причем абсолютно не переиспользуемого, стало совсем нехорошо. А если представить, что код объекта немножечко поменялся, значит, лезь в код редактора и переписывай.

Раз уж все объекты можно и удобно описывать в XML формате, то почему бы ни сделать единообразный интерфейс, порожденный от стиля XML, и этим интерфейсом и ковыряться в каждом объекте. При таком подходе мы напишем одно окошко в редакторе, и с помощью этого окошка сможем редактировать все и вся, и неважно, если кто-то поменяет объекты или добавить новый.

Описание шаблона

Для начала опишем наш объект, который будет представлен деревом Tag’ов, каждый тег имеет набор значений Value. Нам потребуются два типа TExplorerTagDescr & TExplorerValueDescr.

typedef enum{
  VALUETYPE_BOOL = 0,
  VALUETYPE_INT,
  VALUETYPE_FLOAT,
  VALUETYPE_VECTOR2,
  VALUETYPE_VECTOR3,
  VALUETYPE_VECTOR4,
  VALUETYPE_MATRIX_3x3,
  VALUETYPE_MATRIX_3x4,
  VALUETYPE_MATRIX_4x4,
  VALUETYPE_STRING,
  VALUETYPE_UNKNOW
}VALUETYPE;

typedef enum{
VALUESPECIFIC_NONE = 0,         //все как обычно
VALUESPECIFIC_ENUM,             //имеется соответствие между int значением и строкой
VALUESPECIFIC_FILENAME,         //для такой переменной в редакторы открывать окошко выбора файла
VALUESPECIFIC_PERCENT,          //[0..1] для такого значения лучше отобразить ползунок
VALUESPECIFIC_SIGNEDIDENTITY,   //[-1..1] для такого значения лучше отобразить ползунок
VALUESPECIFIC_COLOR,            //цвет хорошо бы отобразить окошко выбора цвета
VALUESPECIFIC_POSITIVE,         //неотрицательное число
VALUESPECIFIC_POSITION,         //значит можно потаскать за это переменную в редакторе,
                                // будь то вектор или матрица
VALUESPECIFIC_UNKNOW
}VALUESPECIFIC;

class TExplorerValueDescr
{
public:
  const char * czName;            //имя переменной
  VALUETYPE eType;                //тип переменной
  VALUESPECIFIC eSpecific;        //специфика переменной
  bool bStatic;                   //является ли переменная неудаляемой из тега
  uint nMaxArraySize;             //максимально возможный размер массива этой переменной, обычно 1
  const char * czDescriptionInfo; //маленький хелп

  //эти значения нужны только при eSpecific == VALUESPECIFIC_ENUM
  const char ** aczEnumName;      //имена перечисления
  const int * anEnumInt;          //значения соответствующие именам
  uint nEnumCount;                //число перечислений
};

typedef struct TExplorerTagDescr
{
  const char * czName;               //имя тега
  bool bStatic;                      //является ли тег неудаляемой из родительского тега
  uint nMaxArraySize;                //максимально возможный размер массива  тега
  const char * czDescriptionInfo;    //маленький хелп

  //переменные тега
  const TExplorerValueDescr ** apValue;    
  uint nValueCount;  
    
  //дочерние теги
  const TExplorerTagDescr ** apTag;  
  uint nTagCount;
}

С помощью этих типов можно набить описание шаблона любого типа ресурса. Описание шаблона говорит из каких тегов и переменных состоит данный тип ресурса, но оно ничего не знает о конкретном экземпляре данного ресурса. То есть, например, в описании существа записано, что у существа могут быть руки, ноги, глаза, которые имеют размеры и цвет, но сколько их у конкретного существа и какой они длинны и цвета знает лишь само существо.  Поэтому описание, это чисто статическая вещь.

Набьем описание простенькой структурки данных.

class TRSurfaceDescr
{
public:
  uint width,height;
  R_FORMAT format;
  bool bMipMap;
};

// это описание перечисления, обычно оно располагается после перечисления,
// здесь оно приводится для наглядности
static const char * gvalue_R_FORMAT_aEnumName[] = {"A8R8G8B8","A2B10G10R10",
    "A16B16G16R16","A16B16G16R16F","A32B32G32R32F”};
static const int gvalue_R_FORMAT_aEnumInt[] = {R_FORMAT_A8R8G8B8,R_FORMAT_A2B10G10R10,
    R_FORMAT_A16B16G16R16,R_FORMAT_A16B16G16R16F,R_FORMAT_A32B32G32R32F};
static const TExplorerValueDescr gvalue_R_FORMAT = 
{
  "format",VALUETYPE_INT,VALUESPECIFIC_ENUM,
  gvalue_R_FORMAT_aEnumName,gvalue_R_FORMAT_aEnumInt,6
};

//VALUES//
static const TExplorerValueDescr gvalue_RSurfaceDescr_width = {
  "width",VALUETYPE_INT,VALUESPECIFIC_POSITIVE,NULL,NULL,0,true,1,"pixel width"
};
static const TExplorerValueDescr gvalue_RSurfaceDescr_height = {
  "height",VALUETYPE_INT,VALUESPECIFIC_POSITIVE,NULL,NULL,0,true,1,"pixel height"
};
static const TExplorerValueDescr gvalue_RSurfaceDescr_format = {
  "format",VALUETYPE_INT,VALUESPECIFIC_ENUM,
  gvalue_R_FORMAT.aczEnumName,gvalue_R_FORMAT.anEnumInt,gvalue_R_FORMAT.nEnumCount,
  true,1,"format type"
};
static const TExplorerValueDescr gvalue_RSurfaceDescr_bmipmap = {
  "bmipmap",VALUETYPE_BOOL,VALUESPECIFIC_NONE,NULL,NULL,0,true,1,"mip map"
};
static const TExplorerValueDescr * gtag_RSurfaceDescr_aValue[] =
{
&gvalue_RSurfaceDescr_width,&gvalue_RSurfaceDescr_height,
&gvalue_RSurfaceDescr_format,&gvalue_RSurfaceDescr_bmipmap
};
//для удобства в будущем запомним номера переменных
static const uint gvalue_N_RSurfaceDescr_widtht = 0;
static const uint gvalue_N_RSurfaceDescr_height = 1;
static const uint gvalue_N_RSurfaceDescr_format = 2;
static const uint gvalue_N_RSurfaceDescr_bmipmap = 3;
//TAGS//
// дочерних тегов нет
//DESCRIPTION//
static const TExplorerTagDescr gtag_RSurfaceDescr = 
{
  "SurfaceDescr",true,1,
  "surface description",
  gtag_RSurfaceDescr_aValue,4,  //подключаем ранее объявленные описания переменных
  NULL,0                        //здесь аналогично подключение описаний дочерних тегов
};

Однако описание, это только начало, и самое легкое и приятное, кстати. Надо, ведь, иметь интерфейс, который будет, используя  это описание, редактировать объект.

Страницы: 1 2 3 4 Следующая »

24 сентября 2007 (Обновление: 27 сен. 2007)

Комментарии [6]