/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include "EditorDefs.h" #include "Variable.h" #include "UsedResources.h" // for CUsedResources ////////////////////////////////////////////////////////////////////////// CVarBlock* CVarBlock::Clone(bool bRecursive) const { CVarBlock* vb = new CVarBlock; for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; vb->AddVariable(var->Clone(bRecursive)); } return vb; } ////////////////////////////////////////////////////////////////////////// void CVarBlock::CopyValues(const CVarBlock* fromVarBlock) { // Copy all variables. int numSrc = fromVarBlock->GetNumVariables(); int numTrg = GetNumVariables(); for (int i = 0; i < numSrc && i < numTrg; i++) { GetVariable(i)->CopyValue(fromVarBlock->GetVariable(i)); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::CopyValuesByName(CVarBlock* fromVarBlock) { // Copy values using saving and loading to/from xml. XmlNodeRef node = XmlHelpers::CreateXmlNode("Temp"); fromVarBlock->Serialize(node, false); Serialize(node, true); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::OnSetValues() { for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; var->OnSetValue(true); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::SetRecreateSplines() { for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; var->SetFlagRecursive(IVariable::UI_CREATE_SPLINE); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::AddVariable(IVariable* var) { //assert( !strstr(var->GetName(), " ") ); // spaces not allowed because of serialization m_vars.push_back(var); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::AddVariable(IVariable* pVar, const char* varName, unsigned char dataType) { if (varName) { pVar->SetName(varName); } pVar->SetDataType(dataType); AddVariable(pVar); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::AddVariable(CVariableBase& var, const char* varName, unsigned char dataType) { if (varName) { var.SetName(varName); } var.SetDataType(dataType); AddVariable(&var); } ////////////////////////////////////////////////////////////////////////// bool CVarBlock::DeleteVariable(IVariable* var, bool bRecursive) { bool found = stl::find_and_erase(m_vars, var); if (!found && bRecursive) { for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { if ((*it)->DeleteVariable(var, bRecursive)) { return true; } } } return found; } ////////////////////////////////////////////////////////////////////////// bool CVarBlock::IsContainsVariable(IVariable* pVar, bool bRecursive) const { for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { if (*it == pVar) { return true; } } // If not found search childs. if (bRecursive) { // Search all top level variables. for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { if ((*it)->IsContainsVariable(pVar)) { return true; } } } return false; } namespace { IVariable* FindVariable(const char* name, bool bRecursive, bool bHumanName, const std::vector& vars) { // Search all top level variables. for (std::vector::const_iterator it = vars.begin(); it != vars.end(); ++it) { IVariable* var = *it; if (bHumanName && QString::compare(var->GetHumanName(), name, Qt::CaseInsensitive) == 0) { return var; } else if (!bHumanName && QString::compare(var->GetName(), name) == 0) { return var; } } // If not found search childs. if (bRecursive) { // Search all top level variables. for (std::vector::const_iterator it = vars.begin(); it != vars.end(); ++it) { IVariable* var = *it; IVariable* found = var->FindVariable(name, bRecursive, bHumanName); if (found) { return found; } } } return nullptr; } } ////////////////////////////////////////////////////////////////////////// IVariable* CVarBlock::FindVariable(const char* name, bool bRecursive, bool bHumanName) const { return ::FindVariable(name, bRecursive, bHumanName, m_vars); } ////////////////////////////////////////////////////////////////////////// IVariable* CVariableArray::FindVariable(const char* name, bool bRecursive, bool bHumanName) const { return ::FindVariable(name, bRecursive, bHumanName, m_vars); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::Serialize(XmlNodeRef vbNode, bool load) { if (load) { // Loading. QString name; for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; if (var->GetNumVariables()) { XmlNodeRef child = vbNode->findChild(var->GetName().toUtf8().data()); if (child) { var->Serialize(child, load); } } else { var->Serialize(vbNode, load); } } } else { // Saving. for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; if (var->GetNumVariables()) { XmlNodeRef child = vbNode->newChild(var->GetName().toUtf8().data()); var->Serialize(child, load); } else { var->Serialize(vbNode, load); } } } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::ReserveNumVariables(int numVars) { m_vars.reserve(numVars); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::WireVar(IVariable* src, IVariable* trg, bool bWire) { if (bWire) { src->Wire(trg); } else { src->Unwire(trg); } int numSrcVars = src->GetNumVariables(); if (numSrcVars > 0) { int numTrgVars = trg->GetNumVariables(); for (int i = 0; i < numSrcVars && i < numTrgVars; i++) { WireVar(src->GetVariable(i), trg->GetVariable(i), bWire); } } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::Wire(CVarBlock* toVarBlock) { Variables::iterator tit = toVarBlock->m_vars.begin(); Variables::iterator sit = m_vars.begin(); for (; sit != m_vars.end() && tit != toVarBlock->m_vars.end(); ++sit, ++tit) { IVariable* src = *sit; IVariable* trg = *tit; WireVar(src, trg, true); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::Unwire(CVarBlock* toVarBlock) { Variables::iterator tit = toVarBlock->m_vars.begin(); Variables::iterator sit = m_vars.begin(); for (; sit != m_vars.end() && tit != toVarBlock->m_vars.end(); ++sit, ++tit) { IVariable* src = *sit; IVariable* trg = *tit; WireVar(src, trg, false); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::AddOnSetCallback(IVariable::OnSetCallback* func) { for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; SetCallbackToVar(func, var, true); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::RemoveOnSetCallback(IVariable::OnSetCallback* func) { for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) { IVariable* var = *it; SetCallbackToVar(func, var, false); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::SetCallbackToVar(IVariable::OnSetCallback* func, IVariable* pVar, bool bAdd) { if (bAdd) { pVar->AddOnSetCallback(func); } else { pVar->RemoveOnSetCallback(func); } int numVars = pVar->GetNumVariables(); if (numVars > 0) { for (int i = 0; i < numVars; i++) { SetCallbackToVar(func, pVar->GetVariable(i), bAdd); } } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::GatherUsedResources(CUsedResources& resources) { for (int i = 0; i < GetNumVariables(); i++) { IVariable* pVar = GetVariable(i); GatherUsedResourcesInVar(pVar, resources); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::EnableUpdateCallbacks(bool boEnable) { for (int i = 0; i < GetNumVariables(); i++) { IVariable* pVar = GetVariable(i); pVar->EnableUpdateCallbacks(boEnable); } } ////////////////////////////////////////////////////////////////////////// void CVarBlock::GatherUsedResourcesInVar(IVariable* pVar, CUsedResources& resources) { int type = pVar->GetDataType(); if (type == IVariable::DT_TEXTURE) { // this is file. QString filename; pVar->Get(filename); if (!filename.isEmpty()) { resources.Add(filename.toUtf8().data()); } } for (int i = 0; i < pVar->GetNumVariables(); i++) { GatherUsedResourcesInVar(pVar->GetVariable(i), resources); } } ////////////////////////////////////////////////////////////////////////// inline bool CompareNames(const IVariable* pVar1, const IVariable* pVar2) { return (QString::compare(pVar1->GetHumanName(), pVar2->GetHumanName(), Qt::CaseInsensitive) < 0); } ////////////////////////////////////////////////////////////////////////// void CVarBlock::Sort() { std::sort(m_vars.begin(), m_vars.end(), CompareNames); } ////////////////////////////////////////////////////////////////////////// CVarObject::CVarObject() {} ////////////////////////////////////////////////////////////////////////// CVarObject::~CVarObject() {} ////////////////////////////////////////////////////////////////////////// void CVarObject::AddVariable(CVariableBase& var, const QString& varName, VarOnSetCallback* cb, unsigned char dataType) { if (!m_vars) { m_vars = new CVarBlock; } var.AddRef(); // Variables are local and must not be released by CVarBlock. var.SetName(varName); var.SetDataType(dataType); if (cb) { var.AddOnSetCallback(cb); } m_vars->AddVariable(&var); } ////////////////////////////////////////////////////////////////////////// void CVarObject::AddVariable(CVariableBase& var, const QString& varName, const QString& varHumanName, VarOnSetCallback* cb, unsigned char dataType) { if (!m_vars) { m_vars = new CVarBlock; } var.AddRef(); // Variables are local and must not be released by CVarBlock. var.SetName(varName); var.SetHumanName(varHumanName); var.SetDataType(dataType); if (cb) { var.AddOnSetCallback(cb); } m_vars->AddVariable(&var); } ////////////////////////////////////////////////////////////////////////// void CVarObject::AddVariable(CVariableArray& table, CVariableBase& var, const QString& varName, const QString& varHumanName, VarOnSetCallback* cb, unsigned char dataType) { if (!m_vars) { m_vars = new CVarBlock; } var.AddRef(); // Variables are local and must not be released by CVarBlock. var.SetName(varName); var.SetHumanName(varHumanName); var.SetDataType(dataType); if (cb) { var.AddOnSetCallback(cb); } table.AddVariable(&var); } ////////////////////////////////////////////////////////////////////////// void CVarObject::RemoveVariable(IVariable* var) { if (m_vars != nullptr) { m_vars->DeleteVariable(var); } } ////////////////////////////////////////////////////////////////////////// void CVarObject::EnableUpdateCallbacks(bool boEnable) { if (m_vars != nullptr) { m_vars->EnableUpdateCallbacks(boEnable); } } ////////////////////////////////////////////////////////////////////////// void CVarObject::OnSetValues() { if (m_vars != nullptr) { m_vars->OnSetValues(); } } ////////////////////////////////////////////////////////////////////////// void CVarObject::ReserveNumVariables(int numVars) { if (m_vars != nullptr) { m_vars->ReserveNumVariables(numVars); } } ////////////////////////////////////////////////////////////////////////// void CVarObject::CopyVariableValues(CVarObject* sourceObject) { // Check if compatible types. assert(metaObject() == sourceObject->metaObject()); if (m_vars != nullptr && sourceObject->m_vars != nullptr) { m_vars->CopyValues(sourceObject->m_vars); } } ////////////////////////////////////////////////////////////////////////// void CVarObject::Serialize(XmlNodeRef node, bool load) { if (m_vars) { m_vars->Serialize(node, load); } }