Russian Qt Forum
Апрель 24, 2024, 20:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Запись "изменений"  (Прочитано 4091 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Август 26, 2015, 12:13 »

Добрый день

В задаче "запись данных анимации" (недавно обсуждалось) удалось обойтись без этого,  но необходимость возникла в смежной задаче.

Есть (большая) структура в памяти. В какой-то момент приходит ключ (или неск ключей). Если значение ключа ненулевое, то нужно сделать копию текущей структуры и в ней изменить значение полей по этому ключу. Псевдокод
Код
C++ (Qt)
struct CData {
float mAmount;  
int  mSomeVal;
// .. еще 100 таких
};  
 
void SetupData( const CData & src, CData & dst, int key )
{
dst = src;  // копируем
dst.mAmount = ???  // какие-то поля меняем
}
Нужно как-то идентифицировать какое поле менять и знать на что менять. В момент записи это известно, т.е. мы знаем что mAmount должно меняться, и мы имеем контейнер подставляемых значений из которых по ключу будет выбрано нужное.

Как должна выглядеть реализация с точки зрения читающего (подставляющего)?

Спасибо
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #1 : Август 26, 2015, 14:09 »

Цитировать
Как должна выглядеть реализация с точки зрения читающего (подставляющего)?

Например так:

Код
C++ (Qt)
struct CData
{
   float mAmount;
   int  mSomeVal;
};
 
 
enum keys
{
   key0,
   key1
};
 
 
class setter
{
public:
   typedef boost::variant<int, float> variant_t;
   typedef int key_t;
   typedef std::map<key_t, std::function<void (setter*, const variant_t &)>> map_t;
 
   setter(CData & data) : m_data(data)
   {
       m_map[keys::key0] = std::function<void (setter*,  const variant_t &)>(&setter::set_amount);
       m_map[keys::key1] = std::function<void (setter*,  const variant_t &)>(&setter::set_some_val);
   }
 
   template <class T>
   void set(key_t key, const T & val, const CData & src)
   {
       m_data = src;
       m_map[key](this, val);
   }
 
private:
   CData & m_data;
   map_t m_map;
 
   void set_amount(const variant_t & val) { m_data.mAmount = boost::get<decltype(m_data.mAmount)>(val); }
   void set_some_val(const variant_t & val) { m_data.mSomeVal = boost::get<decltype(m_data.mSomeVal)>(val); }
};
 
 
 
int main()
{
 
   CData dst;
   CData src;
 
   setter mysetter(dst);
 
   mysetter.set(keys::key0, 12.9f, src);
 
   std::cout << dst.mAmount << std::endl;
 
   mysetter.set(keys::key1, 100500, src);
 
   std::cout << dst.mSomeVal << std::endl;
 
 
 
   return 0;
}
 
« Последнее редактирование: Август 26, 2015, 14:11 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Август 27, 2015, 11:29 »

Пример, см аттач. Есть 3 кубика которые представлены как одна модель и используют один зкземпляр CData. Пусть mAmount - прозрачность текстуры которая должна быть разной для разных кубиков. Ясно что мы должны как-то отличать кубики друг от друга. Заметим что они могут рендеоиться в любом порядке, напр сначала точка 2-го (нужна одна прозрачность), потом точка первого (другая), потом опять второго. Поэтому вписываем ключи  - (уникальные ID). В полигоны 1-го запишем 1, второго 2  и.т.д. Эта операция делается 1 раз на старте

Теперь нам надо превратить ID ключа в конкретные значения изменяемых параметров. Для этого в объекте есть такие данные

1) Что менять. Идентифицируется строкой (напр "Amount") один раз на старте. То есть mAmount меняется или всегда или никогда.

2) Массив данных для изменения, индивидуальный для каждого меняемого параметра. Загружается на старте и никогда не меняется. Напр там записано 2 значения 0.0f и 1.0f. Или 3 (1, 0,5, 0, 1)

3) Как менять, это число - номер метода или "способ замены". Напр число 1 значит "выбросить случайное число" (конечно используя ключ ID) и по нему выбрать значение из массива данных, возможно интерполируя

С этой точки зрения зачем мне нужна мапа? На всякий случай напомню "в чем проблема" - параметров много (сотни) и любой(ые) из них может быть назначен "мутирующим", т.е. механизм изменений должен быть в общем виде
« Последнее редактирование: Август 27, 2015, 11:31 от Igors » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #3 : Август 28, 2015, 14:31 »

Цитировать
Теперь нам надо превратить ID ключа в конкретные значения изменяемых параметров.

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

 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Август 30, 2015, 10:23 »

Тогда напрашивается написать свой класс ключа, который знает что и как менять в том объекте к которому он приставлен..
Это уже даже и не ключ, а скорее набор харрактеристик и действий..
Для примера выше: ключ - идентификатор кубика (одного из многих), это просто число, без всякого интеллекта. Класс (выполняющий изменения) конечно есть, и конечно ключ он получает как аргумент. На основании этого ключа он вычислит "измененное значение", но нужен общий механизм куда это значение поместить (т.е. собственно поменять)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #5 : Август 30, 2015, 12:42 »

m_ax говорит о чем-то типа этого:
Код
C++ (Qt)
class Mutabler
{
   ....
private:
   Key    m_key;    // Тот самый ключ
   map<string, variant>    m_values;    // Коллекция с измененными значениями (название параметра : значение )
};
 
У нас есть ключ и значения которые нужно изменить у этплонного объекта.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #6 : Август 30, 2015, 12:55 »

Цитировать
m_ax говорит о чем-то типа этого:

Да, именно так  Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Август 30, 2015, 13:58 »

Да, именно так  Улыбающийся
Не так Улыбающийся Ключ - для генерации измененного значения, это не селектор изменяемого поля. С полем сделал так
Цитировать
{ "Amount", offsetof(struct MyClass, mAmount) },
{ "SomeVal", offsetof(struct MyClass, mSomeVal) }
... еще 100 таких
Жесткая макруха (Саня Грей Непонимающий) - но лучшего не видно
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.106 секунд. Запросов: 22.