void SetParameters( void* obj, const ClassAccessors& accessors, const ParameterBox& paramBox) { // we can choose to iterate through the parameters in either way: // either by iterating through the accessors in "accessors" and pulling // values from the parameter box... // or by iterating through the parameters in "paramBox" and pushing those // values in. // We have to consider array cases -- perhaps it easier to go through the // parameters in the parameter box for (auto i=paramBox.Begin(); !i.IsEnd(); ++i) { const auto nameStart = i.Name(); const auto nameEnd = XlStringEnd(nameStart); auto arrayBracket = std::find(nameStart, nameEnd, '['); if (arrayBracket == nameEnd) { accessors.TryOpaqueSet( obj, Hash64(nameStart, nameEnd), i.RawValue(), i.Type(), false); } else { auto arrayIndex = XlAtoUI32((const char*)(arrayBracket+1)); accessors.TryOpaqueSet( obj, Hash64(nameStart, arrayBracket), arrayIndex, i.RawValue(), i.Type(), false); } } }
template<> const ClassAccessors& GetAccessors<SceneEngine::VegetationSpawnConfig>() { using Obj = SceneEngine::VegetationSpawnConfig; static ClassAccessors props(typeid(Obj).hash_code()); static bool init = false; if (!init) { props.Add(u("BaseGridSpacing"), DefaultGet(Obj, _baseGridSpacing), DefaultSet(Obj, _baseGridSpacing)); props.Add(u("JitterAmount"), DefaultGet(Obj, _jitterAmount), DefaultSet(Obj, _jitterAmount)); props.AddChildList<Obj::Material>( u("Material"), DefaultCreate(Obj, _materials), DefaultGetCount(Obj, _materials), DefaultGetChildByIndex(Obj, _materials), DefaultGetChildByKey(Obj, _materials)); props.AddChildList<Obj::ObjectType>( u("ObjectType"), DefaultCreate(Obj, _objectTypes), DefaultGetCount(Obj, _objectTypes), DefaultGetChildByIndex(Obj, _objectTypes), DefaultGetChildByKey(Obj, _objectTypes)); init = true; } return props; }
template<> const ClassAccessors& GetAccessors<SceneEngine::VegetationSpawnConfig::ObjectType>() { using Obj = SceneEngine::VegetationSpawnConfig::ObjectType; static ClassAccessors props(typeid(Obj).hash_code()); static bool init = false; if (!init) { props.Add(u("Model"), DefaultGet(Obj, _modelName), DefaultSet(Obj, _modelName)); props.Add(u("Material"), DefaultGet(Obj, _materialName), DefaultSet(Obj, _materialName)); init = true; } return props; }
template<> const ClassAccessors& GetAccessors<SceneEngine::VegetationSpawnConfig::Bucket>() { using Obj = SceneEngine::VegetationSpawnConfig::Bucket; static ClassAccessors props(typeid(Obj).hash_code()); static bool init = false; if (!init) { props.Add(u("ObjectType"), DefaultGet(Obj, _objectType), DefaultSet(Obj, _objectType)); props.Add(u("MaxDrawDistance"), DefaultGet(Obj, _maxDrawDistance), DefaultSet(Obj, _maxDrawDistance)); props.Add(u("FrequencyWeight"), DefaultGet(Obj, _frequencyWeight), DefaultSet(Obj, _frequencyWeight)); init = true; } return props; }
void AccessorSerialize( OutputStreamFormatter& formatter, const void* obj, const ClassAccessors& props) { using CharType = utf8; auto charTypeCat = ImpliedTyping::TypeOf<CharType>()._type; CharType buffer[ParsingBufferSize]; for (size_t i=0; i<props.GetPropertyCount(); ++i) { const auto& p = props.GetPropertyByIndex(i); if (p._castTo) { p._castTo( obj, buffer, sizeof(buffer), ImpliedTyping::TypeDesc(charTypeCat, dimof(buffer)), true); formatter.WriteAttribute( AsPointer(p._name.cbegin()), AsPointer(p._name.cend()), buffer, XlStringEnd(buffer)); } if (p._castToArray) { for (size_t e=0; e<p._fixedArrayLength; ++e) { p._castToArray( obj, e, buffer, sizeof(buffer), ImpliedTyping::TypeDesc(charTypeCat, dimof(buffer)), true); StringMeld<256, CharType> name; name << p._name.c_str() << "[" << e << "]"; formatter.WriteAttribute(name.get(), buffer); } } } for (size_t i=0; i<props.GetChildListCount(); ++i) { const auto& childList = props.GetChildListByIndex(i); auto count = childList._getCount(obj); for (size_t e=0; e<count; ++e) { const auto* child = childList._getByIndex(obj, e); auto eleId = formatter.BeginElement(childList._name); AccessorSerialize(formatter, child, *childList._childProps); formatter.EndElement(eleId); } } }
template<> const ClassAccessors& GetAccessors<SceneEngine::VegetationSpawnConfig::Material>() { using Obj = SceneEngine::VegetationSpawnConfig::Material; static ClassAccessors props(typeid(Obj).hash_code()); static bool init = false; if (!init) { props.Add(u("NoSpawnWeight"), DefaultGet(Obj, _noSpawnWeight), DefaultSet(Obj, _noSpawnWeight)); props.Add(u("SuppressionThreshold"), DefaultGet(Obj, _suppressionThreshold), DefaultSet(Obj, _suppressionThreshold)); props.Add(u("SuppressionNoise"), DefaultGet(Obj, _suppressionNoise), DefaultSet(Obj, _suppressionNoise)); props.Add(u("SuppressionGain"), DefaultGet(Obj, _suppressionGain), DefaultSet(Obj, _suppressionGain)); props.Add(u("SuppressionLacunarity"), DefaultGet(Obj, _suppressionLacunarity), DefaultSet(Obj, _suppressionLacunarity)); props.Add(u("MaterialId"), DefaultGet(Obj, _materialId), DefaultSet(Obj, _materialId)); props.AddChildList<SceneEngine::VegetationSpawnConfig::Bucket>( u("Bucket"), DefaultCreate(Obj, _buckets), DefaultGetCount(Obj, _buckets), DefaultGetChildByIndex(Obj, _buckets), DefaultGetChildByKey(Obj, _buckets)); init = true; } return props; }
template<> const ClassAccessors& GetAccessors<PlatformRig::DefaultShadowFrustumSettings>() { using Obj = PlatformRig::DefaultShadowFrustumSettings; static ClassAccessors props(typeid(Obj).hash_code()); static bool init = false; if (!init) { props.Add(u("FrustumCount"), DefaultGet(Obj, _frustumCount), [](Obj& obj, unsigned value) { obj._frustumCount = Clamp(value, 1u, SceneEngine::MaxShadowTexturesPerLight); }); props.Add(u("MaxDistanceFromCamera"), DefaultGet(Obj, _maxDistanceFromCamera), DefaultSet(Obj, _maxDistanceFromCamera)); props.Add(u("FrustumSizeFactor"), DefaultGet(Obj, _frustumSizeFactor), DefaultSet(Obj, _frustumSizeFactor)); props.Add(u("FocusDistance"), DefaultGet(Obj, _focusDistance), DefaultSet(Obj, _focusDistance)); props.Add(u("Flags"), DefaultGet(Obj, _flags), DefaultSet(Obj, _flags)); props.Add(u("TextureSize"), DefaultGet(Obj, _textureSize), [](Obj& obj, unsigned value) { obj._textureSize = 1<<(IntegerLog2(value-1)+1); }); // ceil to a power of two props.Add(u("SingleSidedSlopeScaledBias"), DefaultGet(Obj, _slopeScaledBias), DefaultSet(Obj, _slopeScaledBias)); props.Add(u("SingleSidedDepthBiasClamp"), DefaultGet(Obj, _depthBiasClamp), DefaultSet(Obj, _depthBiasClamp)); props.Add(u("SingleSidedRasterDepthBias"), DefaultGet(Obj, _rasterDepthBias), DefaultSet(Obj, _rasterDepthBias)); props.Add(u("DoubleSidedSlopeScaledBias"), DefaultGet(Obj, _dsSlopeScaledBias), DefaultSet(Obj, _dsSlopeScaledBias)); props.Add(u("DoubleSidedDepthBiasClamp"), DefaultGet(Obj, _dsDepthBiasClamp), DefaultSet(Obj, _dsDepthBiasClamp)); props.Add(u("DoubleSidedRasterDepthBias"), DefaultGet(Obj, _dsRasterDepthBias), DefaultSet(Obj, _dsRasterDepthBias)); props.Add(u("WorldSpaceResolveBias"), DefaultGet(Obj, _worldSpaceResolveBias), DefaultSet(Obj, _worldSpaceResolveBias)); props.Add(u("BlurAngleDegrees"), [](const Obj& obj) { return Rad2Deg(XlATan(obj._tanBlurAngle)); }, [](Obj& obj, float value) { obj._tanBlurAngle = XlTan(Deg2Rad(value)); } ); props.Add(u("MinBlurSearch"), DefaultGet(Obj, _minBlurSearch), DefaultSet(Obj, _minBlurSearch)); props.Add(u("MaxBlurSearch"), DefaultGet(Obj, _maxBlurSearch), DefaultSet(Obj, _maxBlurSearch)); init = true; } return props; }
void AccessorDeserialize( Formatter& formatter, void* obj, const ClassAccessors& props) { using Blob = Formatter::Blob; using CharType = Formatter::value_type; auto charTypeCat = ImpliedTyping::TypeOf<CharType>()._type; for (;;) { switch (formatter.PeekNext()) { case Blob::AttributeName: { typename Formatter::InteriorSection name, value; if (!formatter.TryAttribute(name, value)) Throw(FormatException("Error in begin element", formatter.GetLocation())); auto arrayBracket = std::find(name._start, name._end, '['); if (arrayBracket == name._end) { if (!props.TryOpaqueSet( obj, Hash64(name._start, name._end), value._start, ImpliedTyping::TypeDesc(charTypeCat, uint16(value._end - value._start)), true)) { LogWarning << "Failure while assigning property during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(name._start, name._end)); } } else { auto arrayIndex = XlAtoUI32((const char*)(arrayBracket+1)); if (!props.TryOpaqueSet( obj, Hash64(name._start, arrayBracket), arrayIndex, value._start, ImpliedTyping::TypeDesc(charTypeCat, uint16(value._end - value._start)), true)) { LogWarning << "Failure while assigning array property during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(name._start, name._end)); } } } break; case Blob::EndElement: case Blob::None: return; case Blob::BeginElement: { typename Formatter::InteriorSection eleName; if (!formatter.TryBeginElement(eleName)) Throw(FormatException("Error in begin element", formatter.GetLocation())); auto created = props.TryCreateChild(obj, Hash64(eleName._start, eleName._end)); if (created.first) { AccessorDeserialize(formatter, created.first, *created.second); } else { LogWarning << "Couldn't find a match for element name during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(eleName._start, eleName._end)); formatter.SkipElement(); } if (!formatter.TryEndElement()) Throw(FormatException("Expecting end element", formatter.GetLocation())); break; } } } }