Jump to content

[SOLVED] Вопрос по работе со свойствами


photo

Recommended Posts

Добрый день!
Пожалуйста, помогите разобраться со свойствами.
Пытался реализовать два класса:
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

Привет! 
в метод 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
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.
Спасибо за помощь, наводки и оперативность!

  • Like 1
Link to comment
  • silent changed the title to [SOLVED] Вопрос по работе со свойствами
×
×
  • Create New...