/* * 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. // Description : Helper classes for implementing serialization in script #include "CryLegacy_precompiled.h" #include "ScriptSerialize.h" // // CScriptSerializeAny // CScriptSerializeAny::CScriptSerializeAny(EScriptSerializeType type) : m_type(type) { switch (m_type) { case eSST_StringTable: case eSST_String: new (Ptr())string(); break; } } CScriptSerializeAny::CScriptSerializeAny(const CScriptSerializeAny& other) { m_type = other.m_type; switch (m_type) { case eSST_StringTable: case eSST_String: new (Ptr())string(*other.Ptr()); break; default: memcpy(m_buffer, other.m_buffer, BUFFER_SIZE); } } CScriptSerializeAny::~CScriptSerializeAny() { switch (m_type) { case eSST_StringTable: case eSST_String: Ptr()->~string(); break; } } CScriptSerializeAny& CScriptSerializeAny::operator =(const CScriptSerializeAny& other) { // this isn't general enough to be used in every place... but for what // we have for now it should be fine if (&other == this) { return *this; } this->~CScriptSerializeAny(); new (this)CScriptSerializeAny(other); return *this; } bool CScriptSerializeAny::SetFromFunction( IFunctionHandler* pFH, int param) { switch (m_type) { case eSST_Bool: if (!pFH->GetParam(param, *Ptr())) { return false; } break; case eSST_Float: if (!pFH->GetParam(param, *Ptr())) { return false; } break; case eSST_Int8: { int temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = temp; } break; case eSST_Int16: { int temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = temp; } break; case eSST_Int32: { int temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = temp; } break; case eSST_StringTable: case eSST_String: { const char* temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = temp; } break; case eSST_EntityId: { ScriptHandle temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = (EntityId)temp.n; } break; case eSST_Vec3: { Vec3 temp; if (!pFH->GetParam(param, temp)) { return false; } *Ptr() = temp; } case eSST_Void: break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } return true; } void CScriptSerializeAny::PushFuncParam(IScriptSystem* pSS) const { switch (m_type) { case eSST_Bool: pSS->PushFuncParam(*Ptr()); break; case eSST_Float: pSS->PushFuncParam(*Ptr()); break; case eSST_Int8: pSS->PushFuncParam((int)*Ptr()); break; case eSST_Int16: pSS->PushFuncParam((int)*Ptr()); break; case eSST_Int32: pSS->PushFuncParam((int)*Ptr()); break; case eSST_StringTable: case eSST_String: pSS->PushFuncParam(Ptr()->c_str()); break; case eSST_EntityId: { ScriptHandle temp; temp.n = *Ptr(); pSS->PushFuncParam(temp); } break; case eSST_Vec3: pSS->PushFuncParam(*Ptr()); break; case eSST_Void: pSS->PushFuncParam(0); break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } } void CScriptSerializeAny::SerializeWith(TSerialize ser, const char* name) { #define SER_NAME(n) (name ? name : n) switch (m_type) { case eSST_Bool: ser.Value(SER_NAME("bool"), *Ptr()); break; case eSST_Float: ser.Value(SER_NAME("float"), *Ptr()); break; case eSST_Int8: ser.Value(SER_NAME("int8"), *Ptr()); break; case eSST_Int16: ser.Value(SER_NAME("int16"), *Ptr()); break; case eSST_Int32: ser.Value(SER_NAME("int32"), *Ptr()); break; case eSST_String: ser.Value(SER_NAME("string"), *Ptr()); break; case eSST_StringTable: ser.Value(SER_NAME("string"), *Ptr(), 'stab'); break; case eSST_EntityId: ser.Value(SER_NAME("entityid"), *Ptr(), 'eid'); break; case eSST_Vec3: ser.Value(SER_NAME("vec3"), *Ptr()); break; case eSST_Void: break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } #undef SER_NAME } bool CScriptSerializeAny::CopyFromTable(SmartScriptTable& tbl, const char* name) { bool ok = false; switch (m_type) { case eSST_Bool: ok = tbl->GetValue(name, *Ptr()); break; case eSST_Float: ok = tbl->GetValue(name, *Ptr()); break; case eSST_Int8: { int temp; ok = tbl->GetValue(name, temp); *Ptr() = temp; } break; case eSST_Int16: { int temp; ok = tbl->GetValue(name, temp); *Ptr() = temp; } break; case eSST_Int32: { int temp; ok = tbl->GetValue(name, temp); *Ptr() = temp; } break; case eSST_StringTable: case eSST_String: { const char* temp; ok = tbl->GetValue(name, temp); *Ptr() = temp; } break; case eSST_EntityId: { ScriptHandle temp; ok = tbl->GetValue(name, temp); *Ptr() = (EntityId)temp.n; } break; case eSST_Vec3: { Vec3 temp; ok = tbl->GetValue(name, temp); *Ptr() = temp; } break; case eSST_Void: ok = true; break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } if (!ok) { GameWarning("Unable to read property %s of type %c", name, (char)m_type); } return ok; } void CScriptSerializeAny::CopyToTable(SmartScriptTable& tbl, const char* name) { switch (m_type) { case eSST_Bool: tbl->SetValue(name, *Ptr()); break; case eSST_Float: tbl->SetValue(name, *Ptr()); break; case eSST_Int8: tbl->SetValue(name, (int)*Ptr()); break; case eSST_Int16: tbl->SetValue(name, (int)*Ptr()); break; case eSST_Int32: tbl->SetValue(name, (int)*Ptr()); break; case eSST_StringTable: case eSST_String: tbl->SetValue(name, Ptr()->c_str()); break; case eSST_EntityId: { ScriptHandle temp; temp.n = *Ptr(); tbl->SetValue(name, temp); } break; case eSST_Vec3: tbl->SetValue(name, *Ptr()); break; case eSST_Void: tbl->SetToNull(name); break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } } string CScriptSerializeAny::DebugInfo() const { string output; switch (m_type) { case eSST_Bool: output = *Ptr() ? "true" : "false"; break; case eSST_Float: output.Format("%f", *Ptr()); break; case eSST_Int8: output.Format("%i", (int)*Ptr()); break; case eSST_Int16: output.Format("%i", (int)*Ptr()); break; case eSST_Int32: output.Format("%i", (int)*Ptr()); break; case eSST_StringTable: case eSST_String: output = *Ptr(); break; case eSST_EntityId: { EntityId id = *Ptr(); IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id); const char* name = pEntity ? pEntity->GetName() : ""; output.Format("entity[%d]:%s", id, name); } break; case eSST_Vec3: { Vec3 temp = *Ptr(); output.Format("%f,%f,%f", temp.x, temp.y, temp.z); } break; case eSST_Void: output = "void"; break; default: CRY_ASSERT(!"need to add the type enum to this switch"); } return output; } // // CScriptRMISerialize // CScriptRMISerialize::CScriptRMISerialize(const char* format) { SetFormat(format); } void CScriptRMISerialize::SetFormat(const char* format) { m_values.clear(); while (format && *format) { m_values.push_back((EScriptSerializeType) * format); format++; } } void CScriptRMISerialize::SerializeWith(TSerialize ser) { for (TValueVec::iterator i = m_values.begin(); i != m_values.end(); ++i) { i->SerializeWith(ser); } } bool CScriptRMISerialize::SetFromFunction( IFunctionHandler* pFH, int firstParam) { for (size_t i = 0; i < m_values.size(); i++) { if (!m_values[i].SetFromFunction(pFH, firstParam + i)) { return false; } } return true; } void CScriptRMISerialize::PushFunctionParams(IScriptSystem* pSS) { for (TValueVec::iterator i = m_values.begin(); i != m_values.end(); ++i) { i->PushFuncParam(pSS); } } string CScriptRMISerialize::DebugInfo() { bool first = true; string out; for (TValueVec::iterator i = m_values.begin(); i != m_values.end(); ++i) { if (!first) { out += ", "; } out += i->DebugInfo(); first = false; } return out; } // // CScriptSerialize // bool CScriptSerialize::ReadValue(const char* name, EScriptSerializeType type, TSerialize ser, IScriptTable* pTable) { AZ_Error("CScriptSerialize",ser.IsReading(),"Serializer is in wrong state for ReadValue."); switch (type) { case eSST_Bool: { bool temp; ser.Value(name, temp /*, 'bool'*/); pTable->SetValue(name, temp); } break; case eSST_Float: { float temp; ser.Value(name, temp); pTable->SetValue(name, temp); } break; case eSST_Int8: { int8 temp; ser.Value(name, temp, 'i8'); pTable->SetValue(name, (int)temp); } break; case eSST_Int16: { int16 temp; ser.Value(name, temp, 'i16'); pTable->SetValue(name, (int)temp); } break; case eSST_Int32: { int32 temp; ser.Value(name, temp, 'i32'); pTable->SetValue(name, (int)temp); } break; case eSST_String: { ser.Value(name, m_tempString); pTable->SetValue(name, m_tempString.c_str()); } break; case eSST_StringTable: { ser.Value(name, m_tempString, 'stab'); pTable->SetValue(name, m_tempString.c_str()); } break; case eSST_EntityId: { EntityId id = INVALID_ENTITYID; ScriptHandle hdl; ser.Value(name, id, 'eid'); hdl.n = id; pTable->SetValue(name, hdl); } break; case eSST_Vec3: { Vec3 temp; ser.Value(name, temp); pTable->SetValue(name, temp); } break; default: CRY_ASSERT(!"type not added to ReadValue"); return false; } return true; } bool CScriptSerialize::WriteValue(const char* name, EScriptSerializeType type, TSerialize ser, IScriptTable* pTable) { AZ_Error("CScriptSerialize",ser.IsWriting(),"Serializer is in wrong state for WriteValue."); bool ok = false; switch (type) { case eSST_Bool: { bool temp = false; if (ok = pTable->GetValue(name, temp)) { ser.Value(name, temp /*, 'bool'*/); } else if (!pTable->HaveValue(name)) { ser.Value(name, temp); ok = true; } } break; case eSST_Float: { float temp = 0; if (ok = pTable->GetValue(name, temp)) { ser.Value(name, temp); } else if (!pTable->HaveValue(name)) { ser.Value(name, temp); ok = true; } } break; case eSST_Int8: { int temp1; int8 temp2 = 0; if (ok = pTable->GetValue(name, temp1)) { if (temp1 < -128 || temp1 > 127) { ok = false; } else { temp2 = temp1; ser.Value(name, temp2, 'i8'); } } else if (!pTable->HaveValue(name)) { ser.Value(name, temp2, 'i8'); ok = true; } } break; case eSST_Int16: { int temp1; int16 temp2 = 0; if (ok = pTable->GetValue(name, temp1)) { if (temp1 < -32768 || temp1 > 32767) { ok = false; } else { temp2 = temp1; ser.Value(name, temp2, 'i16'); } } else if (!pTable->HaveValue(name)) { ser.Value(name, temp2, 'i16'); ok = true; } } break; case eSST_Int32: { int32 temp1; int temp2 = 0; if (ok = pTable->GetValue(name, temp1)) { temp2 = temp1; ser.Value(name, temp2, 'i32'); } else if (!pTable->HaveValue(name)) { ser.Value(name, temp2, 'i32'); ok = true; } } break; case eSST_StringTable: case eSST_String: { const char* temp; if (ok = pTable->GetValue(name, temp)) { m_tempString = temp; ser.Value(name, m_tempString); } else if (!pTable->HaveValue(name)) { m_tempString = string(); ser.Value(name, m_tempString); ok = true; } } break; case eSST_EntityId: { EntityId id = 0; ScriptHandle hdl; if (ok = pTable->GetValue(name, hdl)) { id = (EntityId)hdl.n; ser.Value(name, id, 'eid'); } else if (!pTable->HaveValue(name)) { ser.Value(name, id, 'eid'); ok = true; } } break; case eSST_Vec3: { Vec3 temp = ZERO; if (ok = pTable->GetValue(name, temp)) { ser.Value(name, temp); } else if (!pTable->HaveValue(name)) { ser.Value(name, temp); ok = true; } } break; default: CRY_ASSERT(!"type not added to WriteValue"); ok = false; } return ok; }