/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_SERIALIZATION_CALLBACK_H #define CRYINCLUDE_CRYCOMMON_SERIALIZATION_CALLBACK_H #pragma once #include namespace Serialization { struct ICallback { virtual bool SerializeValue(IArchive& ar, const char* name, const char* value) = 0; virtual ICallback* Clone() = 0; virtual void Release() = 0; virtual TypeID Type() const = 0; typedef AZStd::function ApplyFunction; virtual void Call(const ApplyFunction&) = 0; }; template struct CallbackSimple : ICallback { typedef AZStd::function CallbackFunction; T* value; T oldValue; CallbackFunction callback; CallbackSimple(T* value, const T& oldValue, const AZStd::function& callback) : value(value) , oldValue(oldValue) , callback(callback) { } ICallback* Clone() { return new CallbackSimple(0, oldValue, callback); } void Release() { delete this; } bool SerializeValue(IArchive& ar, const char* name, const char* label) { return ar(*value, name, label); } TypeID Type() const{ return TypeID::get(); } void Call(const ApplyFunction& applyFunction) { T newValue; applyFunction((void*)&newValue, TypeID::get()); if (oldValue != newValue) { callback(newValue); oldValue = newValue; } } }; template struct CallbackWithDecorator : ICallback { typedef AZStd::function CallbackFunction; typedef AZStd::function DecoratorFunction; T oldValue; T* value; CallbackFunction callback; DecoratorFunction decorator; CallbackWithDecorator(T* value, const T& oldValue, const CallbackFunction& callback, const DecoratorFunction& decorator) : value(value) , oldValue(oldValue) , callback(callback) , decorator(decorator) { } ICallback* Clone() { return new CallbackWithDecorator(0, oldValue, callback, decorator); } void Release() { delete this; } bool SerializeValue(IArchive& ar, const char* name, const char* label) { return ar(decorator(*value), name, label); } TypeID Type() const{ return TypeID::get(); } void Call(const ApplyFunction& applyFunction) { T newValue; Decorator dec = decorator(newValue); applyFunction((void*)&dec, TypeID::get()); if (oldValue != newValue) { callback(newValue); oldValue = newValue; } } }; namespace Detail { template struct MethodReturnType { typedef void type; }; template struct MethodReturnType { typedef ReturnType type; }; template struct OperatorBracketsReturnType { typedef typename MethodReturnType::type Type; }; } template CallbackSimple Callback(T& value, const CallbackFunc& callback) { return CallbackSimple(&value, value, AZStd::function(callback)); } template CallbackWithDecorator::Type> Callback(T& value, const CallbackFunc& callback, const DecoratorFunc& decorator) { typedef typename Detail::OperatorBracketsReturnType::Type Decorator; return CallbackWithDecorator(&value, value, AZStd::function(callback), AZStd::function(decorator)); } template bool Serialize(IArchive& ar, CallbackSimple& callback, const char* name, const char* label) { if (ar.IsEdit()) { return ar(static_cast(callback), name, label); } else { if (!ar(*callback.value, name, label)) { return false; } return true; } } template bool Serialize(IArchive& ar, CallbackWithDecorator& callback, const char* name, const char* label) { if (ar.IsEdit()) { return ar(static_cast(callback), name, label); } else { if (!ar(*callback.value, name, label)) { return false; } return true; } } } #endif // CRYINCLUDE_CRYCOMMON_SERIALIZATION_CALLBACK_H