Jump to content

[SOLVED] ComponentSystem Array of Structs


photo

Recommended Posts

Hello,

are there examples available of:

  • how to declare a struct
  • how to create a single parameter of that struct
  • how to create an array of that struct

within a header file of custom component in C++?

I.e. what would the C++ .h file look like for a Component, which creates the following property file:

<property name="MyComponent">
	<struct name="MyStruct">
		<parameter name="someInt" type="int">0</parameter>
		<parameter name="someFile" type="file" flags="asset"/>
	</struct>
	<parameter name="someArray" type="array" array_type="MyStruct" array_dim="1"/>
</property>

Many thanks,

Helmut

 

 

Link to comment

Hi Helmut,

It's very simple:

#pragma once
#include "ComponentSystem/ComponentSystem.h"

class MyComponent : public ComponentBase
{
public:
	COMPONENT(MyComponent, ComponentBase);
	PROP_NAME("MyComponent");

	struct MyStruct : public ComponentStruct
	{
		PROP_PARAM(Int, someInt);
		PROP_PARAM(File, someFile);
	};
	PROP_ARRAY_STRUCT(MyStruct, someArray);
};

Best regards,
Alexander

Link to comment
  • morbid changed the title to [SOLVED] ComponentSystem Array of Structs

Just one additional observation (for the implementation in 2.7.3):

someArray.size()

always returns zero, when I add structs through the editor. Likewise the [ ] operator crashs when I try to access array elments.

I can access the array elements by using the getNumChildren() and getChild() methods from the Property and the PropertyParameterPtr class.

I don't know if that is a bug or if I'm using the API in a wrong way, just want to mention it here.

Cheers

Helmut

 

Link to comment

Yes, this is a bug. It was fixed in the SDK v2.7.3.1.
To fix it change the ComponentVariableArray class in the ComponentSystem.h file with the following code:

template <class C>
class ComponentVariableArray : public ComponentVariable
{
public:
	ComponentVariableArray(): struct_reference(nullptr) {}
	ComponentVariableArray(PropertyWrapper *component, const char *name, const char *type_name,
		const char *title = nullptr, const char *tooltip = nullptr, const char *group = nullptr)
		: ComponentVariable(component, name, Unigine::Property::PARAMETER_ARRAY, title, tooltip, group)
		, struct_reference(nullptr)
	{
		is_basic_type = is_type_name(type_name);

		// all basic types ("int", "float") have lower characters instead of structs ("MyStruct")
		// so, we modify the name if we got "Int" or "Float" string in type_name
		value_type = type_name;
		if (is_basic_type)
			value_type.lower();

		// add new struct to the Component
		if (!is_basic_type)
		{
			int index = component->findStructIndex(value_type.get());
			if (index == -1)
			{
				struct_reference = new C { component, type_name };
				ComponentVariableStructBase *struct_reference_base = dynamic_cast<ComponentVariableStructBase*>(struct_reference);
				component->structs.append({ value_type, struct_reference_base->getBase() });
			}
		}
	}

	virtual ~ComponentVariableArray()
	{
		delete struct_reference;
	}

	UNIGINE_INLINE void resize(int size)
	{
		int prev_size = value.size();
		
		// destroy old values
		for (int i = size; i < prev_size; i++)
			delete value[i];

		// resize
		value.resize(size);
		if (parameter)
			parameter->setArraySize(size);

		// initialize new values
		for (int i = prev_size; i < size; i++)
		{
			if (is_basic_type)
				value[i] = new C { holder, "" };
			else
				value[i] = new C { holder, value_type.get() };
		}

		// set actual PropertyParameter to children
		if (parameter)
			for (int i = 0; i < size; i++)
				value[i]->setParameter(parameter->getChild(i));
	}

	UNIGINE_INLINE int size() { refresh(); return (int)value.size(); }
	UNIGINE_INLINE C &get(int index) { refresh(); return *value[index]; }
	UNIGINE_INLINE C &operator[](int index) { refresh(); return *value[index]; }

	UNIGINE_INLINE void save(const Unigine::XmlPtr &xml) override
	{
		ComponentVariable::save(xml);
		xml->setArg("array_type", value_type.get());
	}

protected:
	Unigine::String value_type;
	int is_basic_type;
	Unigine::Vector<C*> value;
	C *struct_reference;

private:
	// refresh links from Property to Vector<C> value variable
	void refresh()
	{
		if (parameter && parameter->getArraySize() != value.size())
			resize(parameter->getArraySize());
	}
};


Best regards,
Alexander

Link to comment
×
×
  • Create New...