Ry_Mik Posted April 24 Share Posted April 24 Добрый день! Пожалуйста, помогите разобраться со свойствами. Пытался реализовать два класса: 1) Обработчик данных от внешнего трекера - получает от устройства 4 double, превращает в кватернион и назначает указанной ноде. 2) Элемент графического интерфейса, который бы выводил полученные от трекера цифровые значения. Подумал реализовать их с помощью "наблюдателя" // Наблюдатель, получет какие-то данные от информатора // Например поле с текстом обновляется при изменении координат class GUIObserver { public: virtual ~GUIObserver() = default; // Получить обновленые данные virtual void ObserverUpdate() = 0; }; class GUITrackerObserver : public GUIObserver { public: inline void ObserverUpdate() override { throw std::runtime_error("GUITrackerObserver::Update()::BaseMethod is not allowed"); } virtual void ObserverUpdate(const RRZ::TrackerData& data) = 0; }; // Информатор, подписывает на свою рассылку наблюдателей // Например обработчик данных с трекера, чтобы быстро обновлять поля гуя class GUIInformer { public: virtual ~GUIInformer() = default; // Выполняет обновление состояния наблюдателей virtual void UpdateObservers() = 0; // Подписать наблюдателя на обновления virtual void Subscribe(GUIObserver *observer) = 0; // Отписать наблюдателя от получения обновлений virtual void Renounce(GUIObserver *observer) = 0; }; // Соответственно наблюдатель (он в своём неймспейсе, так что коллизии с Unigine::WidgetEditText нет) // WidgetBase также наследуется от ComponentBase class WidgetEditText : public WidgetBase, public GUITrackerObserver // Обработчик данных с трекера class TrackerHandler : public ComponentBase, public GUIInformer У трекера есть поле PROP_ARRAY(Node, observers) С помощью которого я планировал "собирать подписоту", закинув нужные мне узлы в поле свойства И метод инициализации списка подписчиков с которым никак не могу совладать void TrackerHandler::InitObservers() { for (int i = 0; i != observers.size(); ++i) { for (int y = 0; y != observers[i]->getNumProperties(); ++y) { Unigine::Log::message(observers[i]->getPropertyName(y)); Unigine::Log::message("\n"); } // Не ошибка, я знаю, что в редакторе нужное свойство идёт именно под индексом 1 Unigine::PropertyPtr prop = observers[i]->getProperty(1); auto pr = prop.get(); Ry::WidgetEditText* observer = prop.getInternalObject<Unigine::UnigineBaseObject>()->getInterface<Ry::WidgetEditText>(); // auto raw = prop.get(); // Ry::WidgetEditText* observer = dynamic_cast<Ry::WidgetEditText*>(raw); Subscribe(observer); // Unigine::Ptr<GUIObserver> observ = dynamic_ptr_cast(prop.getInternalObject()); // Subscribe((GUIObserver*)prop.get()); } _obs_init = true; } Закомментированное - это всё "и так, и эдак". Самый крайний вариант - приведение в C-стиле работает, проект компилится и в момент первого же обновления подписчика вываливается с исключением segmentation fault... Все остальные варианты каста не работают. Подскажите, как правильно, корректно получить указатель на экземпляр компонента? Я уверен что компонент не nullptr, он 100% уже существует, инициализирован и в первом кадре уже отрисовал себя собственным методом init(). Еще вопрос - в шарпе, можно сделать публичное поле с собственным классом и вставить туда прямо экземпляр класса с произвольной ноды. Можно ли такое сделать в C++? Есть компонент PROP_PARAM(Property ...) но, я не могу туда "вставить" из уже созданной ноды, предлагается вариант только создать новый элемент. Спасибо! Link to comment
cash-metall Posted April 25 Share Posted April 25 Привет! в метод ComponentSystem::get()->getComponent<ComponentClass>(node) можно подавать не только непосредственно компоненту, но и ее родителей void TrackerHandler::InitObservers() { for (int i = 0; i != observers.size(); ++i) { NodePtr observer_node = observers[i]; if (!observer_node) // проверяем что ноду вообще указали в массиве. там может быть пусто или битая ссылка { Log::error("TrackerHandler::InitObservers: wrong observer node index %d\n", i); continue; } GUIObserver * observer = ComponentSystem::get()->getComponent<GUIObserver>(observers[i]); if (observer) // проверяем что обсервер существует. { Subscribe(observer); } else { Log::error("TrackerHandler::InitObservers: node %d(%s) doesn't have any observers\n", observers[i]->getID(), observers[i]->getName()); } } _obs_init = true; } так же вам может пригодится событие на изменение проперти, чтобы не проверять каждый раз состояние наблюдателя информацию об этом можно найти тут https://developer.unigine.com/en/docs/2.18.1/api/library/common/class.property?rlang=cpp#add_property (чуть ниже, раздел Handling Events) Link to comment
Ry_Mik Posted April 25 Author Share Posted April 25 1 hour ago, cash-metall said: Привет! в метод ComponentSystem::get()->getComponent<ComponentClass>(node) можно подавать не только непосредственно компоненту, но и ее родителей void TrackerHandler::InitObservers() { for (int i = 0; i != observers.size(); ++i) { NodePtr observer_node = observers[i]; if (!observer_node) // проверяем что ноду вообще указали в массиве. там может быть пусто или битая ссылка { Log::error("TrackerHandler::InitObservers: wrong observer node index %d\n", i); continue; } GUIObserver * observer = ComponentSystem::get()->getComponent<GUIObserver>(observers[i]); if (observer) // проверяем что обсервер существует. { Subscribe(observer); } else { Log::error("TrackerHandler::InitObservers: node %d(%s) doesn't have any observers\n", observers[i]->getID(), observers[i]->getName()); } } _obs_init = true; } так же вам может пригодится событие на изменение проперти, чтобы не проверять каждый раз состояние наблюдателя информацию об этом можно найти тут https://developer.unigine.com/en/docs/2.18.1/api/library/common/class.property?rlang=cpp#add_property (чуть ниже, раздел Handling Events) Вельми понежа! От меня как-то ускользнула мысль попробовать взять компонент из ComponentSystem. Отлично работает. Также изучу EventSystem. Спасибо за помощь, наводки и оперативность! 1 Link to comment
Recommended Posts