Merge branch 'next' of git://gitorious.org/fg/simgear into next
This commit is contained in:
+2
-2
@@ -123,14 +123,14 @@ check_include_file(windows.h HAVE_WINDOWS_H)
|
|||||||
|
|
||||||
if(ENABLE_RTI)
|
if(ENABLE_RTI)
|
||||||
# See if we have any rti library variant installed
|
# See if we have any rti library variant installed
|
||||||
find_package(RTI)
|
find_package(RTI)
|
||||||
endif(ENABLE_RTI)
|
endif(ENABLE_RTI)
|
||||||
|
|
||||||
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
||||||
check_function_exists(ftime HAVE_FTIME)
|
check_function_exists(ftime HAVE_FTIME)
|
||||||
check_function_exists(timegm HAVE_TIMEGM)
|
check_function_exists(timegm HAVE_TIMEGM)
|
||||||
check_function_exists(rint HAVE_RINT)
|
check_function_exists(rint HAVE_RINT)
|
||||||
|
check_function_exists(mkdtemp HAVE_MKDTEMP)
|
||||||
|
|
||||||
if(HAVE_UNISTD_H)
|
if(HAVE_UNISTD_H)
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ set(HLA_SOURCES
|
|||||||
HLABasicDataType.cxx
|
HLABasicDataType.cxx
|
||||||
HLADataElement.cxx
|
HLADataElement.cxx
|
||||||
HLADataType.cxx
|
HLADataType.cxx
|
||||||
|
HLADataTypeVisitor.cxx
|
||||||
HLAEnumeratedDataElement.cxx
|
HLAEnumeratedDataElement.cxx
|
||||||
HLAEnumeratedDataType.cxx
|
HLAEnumeratedDataType.cxx
|
||||||
HLAFederate.cxx
|
HLAFederate.cxx
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -22,7 +22,9 @@
|
|||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
HLAArrayDataType::HLAArrayDataType(const std::string& name) :
|
HLAArrayDataType::HLAArrayDataType(const std::string& name) :
|
||||||
HLADataType(name)
|
HLADataType(name),
|
||||||
|
_isOpaque(false),
|
||||||
|
_isString(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +53,18 @@ HLAArrayDataType::setElementDataType(const HLADataType* elementDataType)
|
|||||||
_elementDataType = elementDataType;
|
_elementDataType = elementDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLAArrayDataType::setIsOpaque(bool isOpaque)
|
||||||
|
{
|
||||||
|
_isOpaque = isOpaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLAArrayDataType::setIsString(bool isString)
|
||||||
|
{
|
||||||
|
_isString = isString;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) :
|
HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) :
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -42,8 +42,18 @@ public:
|
|||||||
const HLADataType* getElementDataType() const
|
const HLADataType* getElementDataType() const
|
||||||
{ return _elementDataType.get(); }
|
{ return _elementDataType.get(); }
|
||||||
|
|
||||||
|
void setIsOpaque(bool isOpaque);
|
||||||
|
bool getIsOpaque() const
|
||||||
|
{ return _isOpaque; }
|
||||||
|
|
||||||
|
void setIsString(bool isString);
|
||||||
|
bool getIsString() const
|
||||||
|
{ return _isString; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SGSharedPtr<const HLADataType> _elementDataType;
|
SGSharedPtr<const HLADataType> _elementDataType;
|
||||||
|
bool _isOpaque;
|
||||||
|
bool _isString;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HLAFixedArrayDataType : public HLAArrayDataType {
|
class HLAFixedArrayDataType : public HLAArrayDataType {
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "HLADataTypeVisitor.hxx"
|
||||||
|
|
||||||
|
#include "HLAArrayDataElement.hxx"
|
||||||
|
#include "HLABasicDataElement.hxx"
|
||||||
|
#include "HLADataTypeVisitor.hxx"
|
||||||
|
#include "HLAEnumeratedDataElement.hxx"
|
||||||
|
#include "HLAFixedRecordDataElement.hxx"
|
||||||
|
#include "HLAVariantDataElement.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
HLADataElementFactoryVisitor::~HLADataElementFactoryVisitor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLADataType& dataType)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
|
||||||
|
<< dataType.getName() << "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAInt8DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLASCharDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAUInt8DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAUCharDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAInt16DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAShortDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAUInt16DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAUShortDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAInt32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAIntDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAUInt32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAUIntDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAInt64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLALongDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAUInt64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAULongDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAFloat32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAFloatDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAFloat64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLADoubleDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
class HLADataElementFactoryVisitor::ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
|
||||||
|
public:
|
||||||
|
virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
|
||||||
|
{
|
||||||
|
const HLADataType* dataType = element.getElementDataType();
|
||||||
|
if (!dataType)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
HLADataElementFactoryVisitor visitor;
|
||||||
|
dataType->accept(visitor);
|
||||||
|
return visitor.getDataElement();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAFixedArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
if (dataType.getIsString()) {
|
||||||
|
_dataElement = new HLAStringDataElement(&dataType);
|
||||||
|
} else {
|
||||||
|
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||||
|
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||||
|
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory);
|
||||||
|
arrayDataElement->setNumElements(dataType.getNumElements());
|
||||||
|
_dataElement = arrayDataElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAVariableArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
if (dataType.getIsString()) {
|
||||||
|
_dataElement = new HLAStringDataElement(&dataType);
|
||||||
|
} else {
|
||||||
|
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||||
|
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||||
|
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory);
|
||||||
|
_dataElement = arrayDataElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAEnumeratedDataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new HLAEnumeratedDataElement(&dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAFixedRecordDataType& dataType)
|
||||||
|
{
|
||||||
|
SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
|
||||||
|
recordDataElement = new HLAFixedRecordDataElement(&dataType);
|
||||||
|
|
||||||
|
unsigned numFields = dataType.getNumFields();
|
||||||
|
for (unsigned i = 0; i < numFields; ++i) {
|
||||||
|
HLADataElementFactoryVisitor visitor;
|
||||||
|
dataType.getFieldDataType(i)->accept(visitor);
|
||||||
|
recordDataElement->setField(i, visitor._dataElement.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
_dataElement = recordDataElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
class HLADataElementFactoryVisitor::VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
|
||||||
|
public:
|
||||||
|
virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
|
||||||
|
{
|
||||||
|
const HLAVariantDataType* dataType = element.getDataType();
|
||||||
|
if (!dataType)
|
||||||
|
return 0;
|
||||||
|
const HLADataType* alternativeDataType = element.getAlternativeDataType();
|
||||||
|
if (!alternativeDataType)
|
||||||
|
return 0;
|
||||||
|
HLADataElementFactoryVisitor visitor;
|
||||||
|
alternativeDataType->accept(visitor);
|
||||||
|
return visitor.getDataElement();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
HLADataElementFactoryVisitor::apply(const HLAVariantDataType& dataType)
|
||||||
|
{
|
||||||
|
SGSharedPtr<HLAVariantDataElement> variantDataElement;
|
||||||
|
variantDataElement = new HLAVariantDataElement(&dataType);
|
||||||
|
variantDataElement->setDataElementFactory(new VariantDataElementFactory);
|
||||||
|
_dataElement = variantDataElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace simgear
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
#include "HLAArrayDataType.hxx"
|
#include "HLAArrayDataType.hxx"
|
||||||
#include "HLABasicDataType.hxx"
|
#include "HLABasicDataType.hxx"
|
||||||
#include "HLADataTypeVisitor.hxx"
|
#include "HLADataElement.hxx"
|
||||||
#include "HLAEnumeratedDataType.hxx"
|
#include "HLAEnumeratedDataType.hxx"
|
||||||
#include "HLAFixedRecordDataType.hxx"
|
#include "HLAFixedRecordDataType.hxx"
|
||||||
#include "HLAVariantDataType.hxx"
|
#include "HLAVariantDataType.hxx"
|
||||||
@@ -629,6 +629,43 @@ inline void HLADataTypeEncodeVisitor::apply(const HLAVariableArrayDataType& data
|
|||||||
dataType.getSizeDataType()->accept(numElementsVisitor);
|
dataType.getSizeDataType()->accept(numElementsVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate standard data elements according to the traversed type
|
||||||
|
class HLADataElementFactoryVisitor : public HLADataTypeVisitor {
|
||||||
|
public:
|
||||||
|
virtual ~HLADataElementFactoryVisitor();
|
||||||
|
|
||||||
|
virtual void apply(const HLADataType& dataType);
|
||||||
|
|
||||||
|
virtual void apply(const HLAInt8DataType& dataType);
|
||||||
|
virtual void apply(const HLAUInt8DataType& dataType);
|
||||||
|
virtual void apply(const HLAInt16DataType& dataType);
|
||||||
|
virtual void apply(const HLAUInt16DataType& dataType);
|
||||||
|
virtual void apply(const HLAInt32DataType& dataType);
|
||||||
|
virtual void apply(const HLAUInt32DataType& dataType);
|
||||||
|
virtual void apply(const HLAInt64DataType& dataType);
|
||||||
|
virtual void apply(const HLAUInt64DataType& dataType);
|
||||||
|
virtual void apply(const HLAFloat32DataType& dataType);
|
||||||
|
virtual void apply(const HLAFloat64DataType& dataType);
|
||||||
|
|
||||||
|
virtual void apply(const HLAFixedArrayDataType& dataType);
|
||||||
|
virtual void apply(const HLAVariableArrayDataType& dataType);
|
||||||
|
|
||||||
|
virtual void apply(const HLAEnumeratedDataType& dataType);
|
||||||
|
|
||||||
|
virtual void apply(const HLAFixedRecordDataType& dataType);
|
||||||
|
|
||||||
|
virtual void apply(const HLAVariantDataType& dataType);
|
||||||
|
|
||||||
|
HLADataElement* getDataElement()
|
||||||
|
{ return _dataElement.release(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class ArrayDataElementFactory;
|
||||||
|
class VariantDataElementFactory;
|
||||||
|
|
||||||
|
SGSharedPtr<HLADataElement> _dataElement;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace simgear
|
} // namespace simgear
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -186,9 +186,11 @@ public:
|
|||||||
bool readObjectModelTemplate(const std::string& objectModel,
|
bool readObjectModelTemplate(const std::string& objectModel,
|
||||||
ObjectModelFactory& objectModelFactory);
|
ObjectModelFactory& objectModelFactory);
|
||||||
|
|
||||||
|
/// Get the object class of a given name
|
||||||
HLAObjectClass* getObjectClass(const std::string& name);
|
HLAObjectClass* getObjectClass(const std::string& name);
|
||||||
const HLAObjectClass* getObjectClass(const std::string& name) const;
|
const HLAObjectClass* getObjectClass(const std::string& name) const;
|
||||||
|
|
||||||
|
/// Get the interaction class of a given name
|
||||||
HLAInteractionClass* getInteractionClass(const std::string& name);
|
HLAInteractionClass* getInteractionClass(const std::string& name);
|
||||||
const HLAInteractionClass* getInteractionClass(const std::string& name) const;
|
const HLAInteractionClass* getInteractionClass(const std::string& name) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -439,6 +439,15 @@ HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVis
|
|||||||
}
|
}
|
||||||
arrayDataType->setElementDataType(elementDataType.get());
|
arrayDataType->setElementDataType(elementDataType.get());
|
||||||
|
|
||||||
|
// Check if this should be a string data type
|
||||||
|
if (elementDataType->toBasicDataType()) {
|
||||||
|
if (dataTypeName == "HLAopaqueData") {
|
||||||
|
arrayDataType->setIsOpaque(true);
|
||||||
|
} else if (dataTypeName.find("String") != std::string::npos || dataTypeName.find("string") != std::string::npos) {
|
||||||
|
arrayDataType->setIsString(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return arrayDataType;
|
return arrayDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ HLAObjectInstance::getAttributeDataElement(unsigned index) const
|
|||||||
return _rtiObjectInstance->getDataElement(index);
|
return _rtiObjectInstance->getDataElement(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor {
|
class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
|
||||||
public:
|
public:
|
||||||
DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
|
DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
|
||||||
_pathElementMap(pathElementMap)
|
_pathElementMap(pathElementMap)
|
||||||
@@ -150,7 +150,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLASCharDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt8DataType& dataType)
|
virtual void apply(const HLAUInt8DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAUCharDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt16DataType& dataType)
|
virtual void apply(const HLAInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -166,7 +166,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAShortDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt16DataType& dataType)
|
virtual void apply(const HLAUInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAUShortDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt32DataType& dataType)
|
virtual void apply(const HLAInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -182,7 +182,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAIntDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt32DataType& dataType)
|
virtual void apply(const HLAUInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -190,7 +190,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAUIntDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt64DataType& dataType)
|
virtual void apply(const HLAInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLALongDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt64DataType& dataType)
|
virtual void apply(const HLAUInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAULongDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat32DataType& dataType)
|
virtual void apply(const HLAFloat32DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -214,7 +214,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAFloatDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat64DataType& dataType)
|
virtual void apply(const HLAFloat64DataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -222,7 +222,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLADoubleDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
|
class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
|
||||||
@@ -287,7 +287,7 @@ public:
|
|||||||
if (_dataElement.valid())
|
if (_dataElement.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dataElement = new HLAEnumeratedDataElement(&dataType);
|
HLADataElementFactoryVisitor::apply(dataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(const HLAFixedRecordDataType& dataType)
|
virtual void apply(const HLAFixedRecordDataType& dataType)
|
||||||
@@ -357,9 +357,6 @@ public:
|
|||||||
_dataElement = variantDataElement;
|
_dataElement = variantDataElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SGSharedPtr<HLADataElement>& getDataElement() const
|
|
||||||
{ return _dataElement; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
|
SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
|
||||||
{
|
{
|
||||||
@@ -381,7 +378,6 @@ private:
|
|||||||
return dataElement;
|
return dataElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGSharedPtr<HLADataElement> _dataElement;
|
|
||||||
const HLAPathElementMap& _pathElementMap;
|
const HLAPathElementMap& _pathElementMap;
|
||||||
HLADataElement::Path _path;
|
HLADataElement::Path _path;
|
||||||
};
|
};
|
||||||
@@ -413,26 +409,6 @@ HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
HLAObjectInstance::requestAttributeUpdate(unsigned index)
|
|
||||||
{
|
|
||||||
if (!_rtiObjectInstance.valid()) {
|
|
||||||
SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rtiObjectInstance->setRequestAttributeUpdate(index, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
HLAObjectInstance::requestAttributeUpdate()
|
|
||||||
{
|
|
||||||
if (!_rtiObjectInstance.valid()) {
|
|
||||||
SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rtiObjectInstance->setRequestAttributeUpdate(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HLAObjectInstance::registerInstance()
|
HLAObjectInstance::registerInstance()
|
||||||
{
|
{
|
||||||
@@ -471,16 +447,6 @@ HLAObjectInstance::deleteInstance(const RTIData& tag)
|
|||||||
_rtiObjectInstance->deleteObjectInstance(tag);
|
_rtiObjectInstance->deleteObjectInstance(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
HLAObjectInstance::localDeleteInstance()
|
|
||||||
{
|
|
||||||
if (!_rtiObjectInstance.valid()) {
|
|
||||||
SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rtiObjectInstance->localDeleteObjectInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HLAObjectInstance::updateAttributeValues(const RTIData& tag)
|
HLAObjectInstance::updateAttributeValues(const RTIData& tag)
|
||||||
{
|
{
|
||||||
@@ -505,16 +471,6 @@ HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTI
|
|||||||
_rtiObjectInstance->updateAttributeValues(timeStamp, tag);
|
_rtiObjectInstance->updateAttributeValues(timeStamp, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
|
|
||||||
{
|
|
||||||
if (!_rtiObjectInstance.valid()) {
|
|
||||||
SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rtiObjectInstance->reflectQueuedAttributeValues(timeStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HLAObjectInstance::removeInstance(const RTIData& tag)
|
HLAObjectInstance::removeInstance(const RTIData& tag)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,13 +52,8 @@ public:
|
|||||||
void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
|
void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
|
||||||
void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
|
void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
|
||||||
|
|
||||||
// Ask the rti to provide the attribute at index
|
|
||||||
void requestAttributeUpdate(unsigned index);
|
|
||||||
void requestAttributeUpdate();
|
|
||||||
|
|
||||||
void registerInstance();
|
void registerInstance();
|
||||||
void deleteInstance(const RTIData& tag);
|
void deleteInstance(const RTIData& tag);
|
||||||
void localDeleteInstance();
|
|
||||||
|
|
||||||
class AttributeCallback : public SGReferenced {
|
class AttributeCallback : public SGReferenced {
|
||||||
public:
|
public:
|
||||||
@@ -85,11 +80,6 @@ public:
|
|||||||
void updateAttributeValues(const RTIData& tag);
|
void updateAttributeValues(const RTIData& tag);
|
||||||
void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
|
void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||||
|
|
||||||
// Retrieve queued up updates up to and including timestamp,
|
|
||||||
// Note that this only applies to timestamped updates.
|
|
||||||
// The unordered updates are reflected as they arrive
|
|
||||||
void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void removeInstance(const RTIData& tag);
|
void removeInstance(const RTIData& tag);
|
||||||
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
|
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -17,161 +17,251 @@
|
|||||||
|
|
||||||
#include "HLAPropertyDataElement.hxx"
|
#include "HLAPropertyDataElement.hxx"
|
||||||
|
|
||||||
|
#include "HLAArrayDataElement.hxx"
|
||||||
#include "HLADataTypeVisitor.hxx"
|
#include "HLADataTypeVisitor.hxx"
|
||||||
|
#include "HLAFixedRecordDataElement.hxx"
|
||||||
|
#include "HLAVariantDataElement.hxx"
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor {
|
class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
|
||||||
public:
|
public:
|
||||||
DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) :
|
ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
|
||||||
HLADataTypeDecodeVisitor(stream),
|
HLADataTypeDecodeVisitor(stream),
|
||||||
_propertyReference(propertyReference)
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
virtual ~ScalarDecodeVisitor()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void apply(const HLAInt8DataType& dataType)
|
virtual void apply(const HLAInt8DataType& dataType)
|
||||||
{
|
{
|
||||||
int8_t value = 0;
|
int8_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt8DataType& dataType)
|
virtual void apply(const HLAUInt8DataType& dataType)
|
||||||
{
|
{
|
||||||
uint8_t value = 0;
|
uint8_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt16DataType& dataType)
|
virtual void apply(const HLAInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
int16_t value = 0;
|
int16_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt16DataType& dataType)
|
virtual void apply(const HLAUInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
uint16_t value = 0;
|
uint16_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt32DataType& dataType)
|
virtual void apply(const HLAInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
int32_t value = 0;
|
int32_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt32DataType& dataType)
|
virtual void apply(const HLAUInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setIntValue(value);
|
_propertyNode.setIntValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt64DataType& dataType)
|
virtual void apply(const HLAInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
int64_t value = 0;
|
int64_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setLongValue(value);
|
_propertyNode.setLongValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt64DataType& dataType)
|
virtual void apply(const HLAUInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setLongValue(value);
|
_propertyNode.setLongValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat32DataType& dataType)
|
virtual void apply(const HLAFloat32DataType& dataType)
|
||||||
{
|
{
|
||||||
float value = 0;
|
float value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setFloatValue(value);
|
_propertyNode.setFloatValue(value);
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat64DataType& dataType)
|
virtual void apply(const HLAFloat64DataType& dataType)
|
||||||
{
|
{
|
||||||
double value = 0;
|
double value = 0;
|
||||||
dataType.decode(_stream, value);
|
dataType.decode(_stream, value);
|
||||||
_propertyReference.setDoubleValue(value);
|
_propertyNode.setDoubleValue(value);
|
||||||
}
|
|
||||||
|
|
||||||
virtual void apply(const HLAFixedArrayDataType& dataType)
|
|
||||||
{
|
|
||||||
unsigned numElements = dataType.getNumElements();
|
|
||||||
std::string value;
|
|
||||||
value.reserve(numElements);
|
|
||||||
for (unsigned i = 0; i < numElements; ++i) {
|
|
||||||
HLATemplateDecodeVisitor<char> visitor(_stream);
|
|
||||||
dataType.getElementDataType()->accept(visitor);
|
|
||||||
value.push_back(visitor.getValue());
|
|
||||||
}
|
|
||||||
_propertyReference.setStringValue(value);
|
|
||||||
}
|
|
||||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
|
||||||
{
|
|
||||||
HLATemplateDecodeVisitor<unsigned> numElementsVisitor(_stream);
|
|
||||||
dataType.getSizeDataType()->accept(numElementsVisitor);
|
|
||||||
unsigned numElements = numElementsVisitor.getValue();
|
|
||||||
std::string value;
|
|
||||||
value.reserve(numElements);
|
|
||||||
for (unsigned i = 0; i < numElements; ++i) {
|
|
||||||
HLATemplateDecodeVisitor<char> visitor(_stream);
|
|
||||||
dataType.getElementDataType()->accept(visitor);
|
|
||||||
value.push_back(visitor.getValue());
|
|
||||||
}
|
|
||||||
_propertyReference.setStringValue(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HLAPropertyReference& _propertyReference;
|
SGPropertyNode& _propertyNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor {
|
class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
|
||||||
public:
|
public:
|
||||||
EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) :
|
ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
|
||||||
HLADataTypeEncodeVisitor(stream),
|
HLADataTypeEncodeVisitor(stream),
|
||||||
_propertyReference(propertyReference)
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
virtual ~ScalarEncodeVisitor()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void apply(const HLAInt8DataType& dataType)
|
virtual void apply(const HLAInt8DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt8DataType& dataType)
|
virtual void apply(const HLAUInt8DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt16DataType& dataType)
|
virtual void apply(const HLAInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt16DataType& dataType)
|
virtual void apply(const HLAUInt16DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt32DataType& dataType)
|
virtual void apply(const HLAInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt32DataType& dataType)
|
virtual void apply(const HLAUInt32DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAInt64DataType& dataType)
|
virtual void apply(const HLAInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getLongValue());
|
dataType.encode(_stream, _propertyNode.getLongValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAUInt64DataType& dataType)
|
virtual void apply(const HLAUInt64DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getLongValue());
|
dataType.encode(_stream, _propertyNode.getLongValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat32DataType& dataType)
|
virtual void apply(const HLAFloat32DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getFloatValue());
|
dataType.encode(_stream, _propertyNode.getFloatValue());
|
||||||
}
|
}
|
||||||
virtual void apply(const HLAFloat64DataType& dataType)
|
virtual void apply(const HLAFloat64DataType& dataType)
|
||||||
{
|
{
|
||||||
dataType.encode(_stream, _propertyReference.getDoubleValue());
|
dataType.encode(_stream, _propertyNode.getDoubleValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const SGPropertyNode& _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HLAPropertyDataElement::ScalarDataElement : public HLADataElement {
|
||||||
|
public:
|
||||||
|
ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
|
||||||
|
virtual ~ScalarDataElement();
|
||||||
|
|
||||||
|
virtual bool encode(HLAEncodeStream& stream) const;
|
||||||
|
virtual bool decode(HLADecodeStream& stream);
|
||||||
|
|
||||||
|
virtual const HLADataType* getDataType() const;
|
||||||
|
virtual bool setDataType(const HLADataType* dataType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGSharedPtr<const HLABasicDataType> _dataType;
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
|
||||||
|
_dataType(dataType),
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
|
||||||
|
{
|
||||||
|
ScalarEncodeVisitor visitor(stream, *_propertyNode);
|
||||||
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
|
||||||
|
{
|
||||||
|
ScalarDecodeVisitor visitor(stream, *_propertyNode);
|
||||||
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HLADataType*
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::getDataType() const
|
||||||
|
{
|
||||||
|
return _dataType.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::ScalarDataElement::setDataType(const HLADataType* dataType)
|
||||||
|
{
|
||||||
|
if (!dataType)
|
||||||
|
return false;
|
||||||
|
const HLABasicDataType* basicDataType = dataType->toBasicDataType();
|
||||||
|
if (!basicDataType)
|
||||||
|
return false;
|
||||||
|
_dataType = basicDataType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class HLAPropertyDataElement::StringDecodeVisitor : public HLADataTypeDecodeVisitor {
|
||||||
|
public:
|
||||||
|
StringDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
|
||||||
|
HLADataTypeDecodeVisitor(stream),
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
|
||||||
virtual void apply(const HLAFixedArrayDataType& dataType)
|
virtual void apply(const HLAFixedArrayDataType& dataType)
|
||||||
{
|
{
|
||||||
unsigned numElements = dataType.getNumElements();
|
unsigned numElements = dataType.getNumElements();
|
||||||
std::string value = _propertyReference.getStringValue();
|
std::string value;
|
||||||
|
value.reserve(numElements);
|
||||||
|
for (unsigned i = 0; i < numElements; ++i) {
|
||||||
|
HLATemplateDecodeVisitor<char> visitor(_stream);
|
||||||
|
dataType.getElementDataType()->accept(visitor);
|
||||||
|
value.push_back(visitor.getValue());
|
||||||
|
}
|
||||||
|
_propertyNode.setStringValue(value);
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
HLATemplateDecodeVisitor<std::string::size_type> numElementsVisitor(_stream);
|
||||||
|
dataType.getSizeDataType()->accept(numElementsVisitor);
|
||||||
|
std::string::size_type numElements = numElementsVisitor.getValue();
|
||||||
|
std::string value;
|
||||||
|
value.reserve(numElements);
|
||||||
|
for (std::string::size_type i = 0; i < numElements; ++i) {
|
||||||
|
HLATemplateDecodeVisitor<char> visitor(_stream);
|
||||||
|
dataType.getElementDataType()->accept(visitor);
|
||||||
|
value.push_back(visitor.getValue());
|
||||||
|
}
|
||||||
|
_propertyNode.setStringValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SGPropertyNode& _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HLAPropertyDataElement::StringEncodeVisitor : public HLADataTypeEncodeVisitor {
|
||||||
|
public:
|
||||||
|
StringEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
|
||||||
|
HLADataTypeEncodeVisitor(stream),
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void apply(const HLAFixedArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
unsigned numElements = dataType.getNumElements();
|
||||||
|
std::string value = _propertyNode.getStringValue();
|
||||||
for (unsigned i = 0; i < numElements; ++i) {
|
for (unsigned i = 0; i < numElements; ++i) {
|
||||||
if (i < value.size()) {
|
if (i < value.size()) {
|
||||||
HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
|
HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
|
||||||
@@ -185,7 +275,7 @@ public:
|
|||||||
|
|
||||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||||
{
|
{
|
||||||
std::string value = _propertyReference.getStringValue();
|
std::string value = _propertyNode.getStringValue();
|
||||||
HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
|
HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
|
||||||
dataType.getSizeDataType()->accept(numElementsVisitor);
|
dataType.getSizeDataType()->accept(numElementsVisitor);
|
||||||
for (unsigned i = 0; i < value.size(); ++i) {
|
for (unsigned i = 0; i < value.size(); ++i) {
|
||||||
@@ -195,17 +285,248 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const HLAPropertyReference& _propertyReference;
|
const SGPropertyNode& _propertyNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) :
|
class HLAPropertyDataElement::StringDataElement : public HLADataElement {
|
||||||
_propertyReference(propertyReference)
|
public:
|
||||||
|
StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
|
||||||
|
virtual ~StringDataElement();
|
||||||
|
|
||||||
|
virtual bool encode(HLAEncodeStream& stream) const;
|
||||||
|
virtual bool decode(HLADecodeStream& stream);
|
||||||
|
|
||||||
|
virtual const HLADataType* getDataType() const;
|
||||||
|
virtual bool setDataType(const HLADataType* dataType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGSharedPtr<const HLAArrayDataType> _dataType;
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
|
||||||
|
_dataType(dataType),
|
||||||
|
_propertyNode(propertyNode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) :
|
HLAPropertyDataElement::StringDataElement::~StringDataElement()
|
||||||
_dataType(dataType),
|
{
|
||||||
_propertyReference(propertyReference)
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const
|
||||||
|
{
|
||||||
|
StringEncodeVisitor visitor(stream, *_propertyNode);
|
||||||
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::StringDataElement::decode(HLADecodeStream& stream)
|
||||||
|
{
|
||||||
|
StringDecodeVisitor visitor(stream, *_propertyNode);
|
||||||
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HLADataType*
|
||||||
|
HLAPropertyDataElement::StringDataElement::getDataType() const
|
||||||
|
{
|
||||||
|
return _dataType.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HLAPropertyDataElement::StringDataElement::setDataType(const HLADataType* dataType)
|
||||||
|
{
|
||||||
|
if (!dataType)
|
||||||
|
return false;
|
||||||
|
const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
|
||||||
|
if (!arrayDataType)
|
||||||
|
return false;
|
||||||
|
const HLADataType* elementDataType = arrayDataType->getElementDataType();
|
||||||
|
if (!elementDataType)
|
||||||
|
return false;
|
||||||
|
if (!elementDataType->toBasicDataType())
|
||||||
|
return false;
|
||||||
|
_dataType = arrayDataType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
|
||||||
|
public:
|
||||||
|
DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
virtual ~DataElementFactoryVisitor()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void apply(const HLADataType& dataType)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
|
||||||
|
<< dataType.getName() << "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(const HLAInt8DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAUInt8DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAInt16DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAUInt16DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAInt32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAUInt32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAInt64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAUInt64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAFloat32DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
virtual void apply(const HLAFloat64DataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
|
||||||
|
public:
|
||||||
|
ArrayDataElementFactory(SGPropertyNode* propertyNode) :
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
|
||||||
|
{
|
||||||
|
const HLADataType* dataType = element.getElementDataType();
|
||||||
|
if (!dataType)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SGPropertyNode* parent = _propertyNode->getParent();
|
||||||
|
DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
|
||||||
|
dataType->accept(visitor);
|
||||||
|
return visitor.getDataElement();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void apply(const HLAFixedArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
if (dataType.getIsString()) {
|
||||||
|
_dataElement = new StringDataElement(&dataType, _propertyNode.get());
|
||||||
|
} else {
|
||||||
|
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||||
|
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||||
|
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
|
||||||
|
arrayDataElement->setNumElements(dataType.getNumElements());
|
||||||
|
_dataElement = arrayDataElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||||
|
{
|
||||||
|
if (dataType.getIsString()) {
|
||||||
|
_dataElement = new StringDataElement(&dataType, _propertyNode.get());
|
||||||
|
} else {
|
||||||
|
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||||
|
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||||
|
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
|
||||||
|
_dataElement = arrayDataElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(const HLAEnumeratedDataType& dataType)
|
||||||
|
{
|
||||||
|
_dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(const HLAFixedRecordDataType& dataType)
|
||||||
|
{
|
||||||
|
SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
|
||||||
|
recordDataElement = new HLAFixedRecordDataElement(&dataType);
|
||||||
|
|
||||||
|
unsigned numFields = dataType.getNumFields();
|
||||||
|
for (unsigned i = 0; i < numFields; ++i) {
|
||||||
|
DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true));
|
||||||
|
dataType.getFieldDataType(i)->accept(visitor);
|
||||||
|
recordDataElement->setField(i, visitor._dataElement.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
_dataElement = recordDataElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
|
||||||
|
public:
|
||||||
|
VariantDataElementFactory(SGPropertyNode* propertyNode) :
|
||||||
|
_propertyNode(propertyNode)
|
||||||
|
{ }
|
||||||
|
virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
|
||||||
|
{
|
||||||
|
const HLAVariantDataType* dataType = element.getDataType();
|
||||||
|
if (!dataType)
|
||||||
|
return 0;
|
||||||
|
const HLADataType* alternativeDataType = element.getAlternativeDataType();
|
||||||
|
if (!alternativeDataType)
|
||||||
|
return 0;
|
||||||
|
DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
|
||||||
|
alternativeDataType->accept(visitor);
|
||||||
|
return visitor.getDataElement();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void apply(const HLAVariantDataType& dataType)
|
||||||
|
{
|
||||||
|
SGSharedPtr<HLAVariantDataElement> variantDataElement;
|
||||||
|
variantDataElement = new HLAVariantDataElement(&dataType);
|
||||||
|
variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
|
||||||
|
_dataElement = variantDataElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
HLADataElement* getDataElement()
|
||||||
|
{ return _dataElement.release(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
|
SGSharedPtr<HLADataElement> _dataElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
HLAPropertyDataElement::HLAPropertyDataElement()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
|
||||||
|
{
|
||||||
|
setPropertyNode(propertyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
|
||||||
|
_dataType(dataType)
|
||||||
|
{
|
||||||
|
setPropertyNode(propertyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
|
||||||
|
_dataType(dataType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,31 +537,37 @@ HLAPropertyDataElement::~HLAPropertyDataElement()
|
|||||||
bool
|
bool
|
||||||
HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
|
HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
|
||||||
{
|
{
|
||||||
if (!_dataType.valid())
|
if (_dataElement.valid()) {
|
||||||
return false;
|
return _dataElement->encode(stream);
|
||||||
if (_propertyReference.valid()) {
|
|
||||||
EncodeVisitor visitor(stream, *_propertyReference);
|
|
||||||
_dataType->accept(visitor);
|
|
||||||
} else {
|
} else {
|
||||||
|
if (!_dataType.valid())
|
||||||
|
return false;
|
||||||
HLADataTypeEncodeVisitor visitor(stream);
|
HLADataTypeEncodeVisitor visitor(stream);
|
||||||
_dataType->accept(visitor);
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HLAPropertyDataElement::decode(HLADecodeStream& stream)
|
HLAPropertyDataElement::decode(HLADecodeStream& stream)
|
||||||
{
|
{
|
||||||
if (!_dataType.valid())
|
if (_dataElement.valid()) {
|
||||||
|
return _dataElement->decode(stream);
|
||||||
|
} else if (!_dataType.valid()) {
|
||||||
|
// We cant do anything if the data type is not valid
|
||||||
return false;
|
return false;
|
||||||
if (_propertyReference.valid()) {
|
|
||||||
DecodeVisitor visitor(stream, *_propertyReference);
|
|
||||||
_dataType->accept(visitor);
|
|
||||||
} else {
|
} else {
|
||||||
HLADataTypeDecodeVisitor visitor(stream);
|
HLADataElementFactoryVisitor visitor;
|
||||||
_dataType->accept(visitor);
|
_dataType->accept(visitor);
|
||||||
|
_dataElement = visitor.getDataElement();
|
||||||
|
if (_dataElement.valid()) {
|
||||||
|
return _dataElement->decode(stream);
|
||||||
|
} else {
|
||||||
|
HLADataTypeDecodeVisitor visitor(stream);
|
||||||
|
_dataType->accept(visitor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const HLADataType*
|
const HLADataType*
|
||||||
@@ -252,18 +579,52 @@ HLAPropertyDataElement::getDataType() const
|
|||||||
bool
|
bool
|
||||||
HLAPropertyDataElement::setDataType(const HLADataType* dataType)
|
HLAPropertyDataElement::setDataType(const HLADataType* dataType)
|
||||||
{
|
{
|
||||||
if (dataType->toBasicDataType()) {
|
_dataType = dataType;
|
||||||
_dataType = dataType;
|
if (_dataType.valid() && _propertyNode.valid())
|
||||||
return true;
|
_dataElement = createDataElement(_dataType, _propertyNode);
|
||||||
} else {
|
return true;
|
||||||
const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
|
}
|
||||||
if (arrayDataType && arrayDataType->getElementDataType() &&
|
|
||||||
arrayDataType->getElementDataType()->toBasicDataType()) {
|
void
|
||||||
_dataType = dataType;
|
HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
|
||||||
return true;
|
{
|
||||||
|
_propertyNode = propertyNode;
|
||||||
|
if (_dataType.valid() && _propertyNode.valid())
|
||||||
|
_dataElement = createDataElement(_dataType, _propertyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGPropertyNode*
|
||||||
|
HLAPropertyDataElement::getPropertyNode()
|
||||||
|
{
|
||||||
|
return _propertyNode.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SGPropertyNode*
|
||||||
|
HLAPropertyDataElement::getPropertyNode() const
|
||||||
|
{
|
||||||
|
return _propertyNode.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
HLADataElement*
|
||||||
|
HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
|
||||||
|
const SGSharedPtr<SGPropertyNode>& propertyNode)
|
||||||
|
{
|
||||||
|
DataElementFactoryVisitor visitor(propertyNode);
|
||||||
|
dataType->accept(visitor);
|
||||||
|
SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
|
||||||
|
|
||||||
|
// Copy over the content of the previous data element if there is any.
|
||||||
|
if (_dataElement.valid()) {
|
||||||
|
// FIXME is encode/decode the right tool here??
|
||||||
|
RTIData data;
|
||||||
|
HLAEncodeStream encodeStream(data);
|
||||||
|
if (_dataElement->encode(encodeStream)) {
|
||||||
|
HLADecodeStream decodeStream(data);
|
||||||
|
dataElement->decode(decodeStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return dataElement.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace simgear
|
} // namespace simgear
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
|
// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -18,139 +18,17 @@
|
|||||||
#ifndef HLAPropertyDataElement_hxx
|
#ifndef HLAPropertyDataElement_hxx
|
||||||
#define HLAPropertyDataElement_hxx
|
#define HLAPropertyDataElement_hxx
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include "HLADataElement.hxx"
|
#include "HLADataElement.hxx"
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
|
|
||||||
class HLAPropertyReference : public SGReferenced {
|
|
||||||
public:
|
|
||||||
HLAPropertyReference()
|
|
||||||
{ }
|
|
||||||
HLAPropertyReference(const std::string& relativePath) :
|
|
||||||
_relativePath(relativePath)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void setIntValue(int value)
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return;
|
|
||||||
_propertyNode->setIntValue(value);
|
|
||||||
}
|
|
||||||
int getIntValue() const
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return 0;
|
|
||||||
return _propertyNode->getIntValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLongValue(long value)
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return;
|
|
||||||
_propertyNode->setLongValue(value);
|
|
||||||
}
|
|
||||||
long getLongValue() const
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return 0;
|
|
||||||
return _propertyNode->getLongValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFloatValue(float value)
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return;
|
|
||||||
_propertyNode->setFloatValue(value);
|
|
||||||
}
|
|
||||||
float getFloatValue() const
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return 0;
|
|
||||||
return _propertyNode->getFloatValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDoubleValue(double value)
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return;
|
|
||||||
_propertyNode->setDoubleValue(value);
|
|
||||||
}
|
|
||||||
double getDoubleValue() const
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return 0;
|
|
||||||
return _propertyNode->getDoubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStringValue(const std::string& value)
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return;
|
|
||||||
_propertyNode->setStringValue(value);
|
|
||||||
}
|
|
||||||
std::string getStringValue() const
|
|
||||||
{
|
|
||||||
if (!_propertyNode.valid())
|
|
||||||
return std::string();
|
|
||||||
return _propertyNode->getStringValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPropertyNode* getPropertyNode()
|
|
||||||
{ return _propertyNode.get(); }
|
|
||||||
|
|
||||||
void setRootNode(SGPropertyNode* rootNode)
|
|
||||||
{
|
|
||||||
if (!rootNode)
|
|
||||||
_propertyNode.clear();
|
|
||||||
else
|
|
||||||
_propertyNode = rootNode->getNode(_relativePath, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string _relativePath;
|
|
||||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HLAPropertyReferenceSet : public SGReferenced {
|
|
||||||
public:
|
|
||||||
void insert(const SGSharedPtr<HLAPropertyReference>& propertyReference)
|
|
||||||
{
|
|
||||||
_propertyReferenceSet.insert(propertyReference);
|
|
||||||
propertyReference->setRootNode(_rootNode.get());
|
|
||||||
}
|
|
||||||
void remove(const SGSharedPtr<HLAPropertyReference>& propertyReference)
|
|
||||||
{
|
|
||||||
PropertyReferenceSet::iterator i = _propertyReferenceSet.find(propertyReference);
|
|
||||||
if (i == _propertyReferenceSet.end())
|
|
||||||
return;
|
|
||||||
_propertyReferenceSet.erase(i);
|
|
||||||
propertyReference->setRootNode(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRootNode(SGPropertyNode* rootNode)
|
|
||||||
{
|
|
||||||
_rootNode = rootNode;
|
|
||||||
for (PropertyReferenceSet::iterator i = _propertyReferenceSet.begin();
|
|
||||||
i != _propertyReferenceSet.end(); ++i) {
|
|
||||||
(*i)->setRootNode(_rootNode.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SGPropertyNode* getRootNode()
|
|
||||||
{ return _rootNode.get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SGSharedPtr<SGPropertyNode> _rootNode;
|
|
||||||
|
|
||||||
typedef std::set<SGSharedPtr<HLAPropertyReference> > PropertyReferenceSet;
|
|
||||||
PropertyReferenceSet _propertyReferenceSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HLAPropertyDataElement : public HLADataElement {
|
class HLAPropertyDataElement : public HLADataElement {
|
||||||
public:
|
public:
|
||||||
HLAPropertyDataElement(HLAPropertyReference* propertyReference);
|
HLAPropertyDataElement();
|
||||||
HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference);
|
HLAPropertyDataElement(SGPropertyNode* propertyNode);
|
||||||
|
HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode);
|
||||||
|
HLAPropertyDataElement(const HLADataType* dataType);
|
||||||
virtual ~HLAPropertyDataElement();
|
virtual ~HLAPropertyDataElement();
|
||||||
|
|
||||||
virtual bool encode(HLAEncodeStream& stream) const;
|
virtual bool encode(HLAEncodeStream& stream) const;
|
||||||
@@ -159,12 +37,25 @@ public:
|
|||||||
virtual const HLADataType* getDataType() const;
|
virtual const HLADataType* getDataType() const;
|
||||||
virtual bool setDataType(const HLADataType* dataType);
|
virtual bool setDataType(const HLADataType* dataType);
|
||||||
|
|
||||||
|
void setPropertyNode(SGPropertyNode* propertyNode);
|
||||||
|
SGPropertyNode* getPropertyNode();
|
||||||
|
const SGPropertyNode* getPropertyNode() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class DecodeVisitor;
|
HLADataElement*
|
||||||
class EncodeVisitor;
|
createDataElement(const SGSharedPtr<const HLADataType>& dataType, const SGSharedPtr<SGPropertyNode>& propertyNode);
|
||||||
|
|
||||||
|
class ScalarDecodeVisitor;
|
||||||
|
class ScalarEncodeVisitor;
|
||||||
|
class ScalarDataElement;
|
||||||
|
class StringDecodeVisitor;
|
||||||
|
class StringEncodeVisitor;
|
||||||
|
class StringDataElement;
|
||||||
|
class DataElementFactoryVisitor;
|
||||||
|
|
||||||
SGSharedPtr<const HLADataType> _dataType;
|
SGSharedPtr<const HLADataType> _dataType;
|
||||||
SGSharedPtr<HLAPropertyReference> _propertyReference;
|
SGSharedPtr<HLADataElement> _dataElement;
|
||||||
|
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simgear
|
} // namespace simgear
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ libsghla_a_SOURCES = \
|
|||||||
HLABasicDataType.cxx \
|
HLABasicDataType.cxx \
|
||||||
HLADataElement.cxx \
|
HLADataElement.cxx \
|
||||||
HLADataType.cxx \
|
HLADataType.cxx \
|
||||||
|
HLADataTypeVisitor.cxx \
|
||||||
HLAEnumeratedDataElement.cxx \
|
HLAEnumeratedDataElement.cxx \
|
||||||
HLAEnumeratedDataType.cxx \
|
HLAEnumeratedDataType.cxx \
|
||||||
HLAFederate.cxx \
|
HLAFederate.cxx \
|
||||||
|
|||||||
@@ -299,6 +299,8 @@ public:
|
|||||||
{ _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); }
|
{ _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); }
|
||||||
void timeAdvanceRequestAvailable(const SGTimeStamp& time)
|
void timeAdvanceRequestAvailable(const SGTimeStamp& time)
|
||||||
{ _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); }
|
{ _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); }
|
||||||
|
void flushQueueRequest(const SGTimeStamp& time)
|
||||||
|
{ _rtiAmbassador.flushQueueRequest(toFedTime(time)); }
|
||||||
|
|
||||||
bool queryGALT(SGTimeStamp& timeStamp)
|
bool queryGALT(SGTimeStamp& timeStamp)
|
||||||
{
|
{
|
||||||
|
|||||||
+481
-132
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@ public:
|
|||||||
|
|
||||||
virtual bool timeAdvanceRequest(const SGTimeStamp& timeStamp);
|
virtual bool timeAdvanceRequest(const SGTimeStamp& timeStamp);
|
||||||
virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp);
|
virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp);
|
||||||
|
virtual bool flushQueueRequest(const SGTimeStamp& timeStamp);
|
||||||
virtual bool getTimeAdvancePending();
|
virtual bool getTimeAdvancePending();
|
||||||
|
|
||||||
virtual bool queryFederateTime(SGTimeStamp& timeStamp);
|
virtual bool queryFederateTime(SGTimeStamp& timeStamp);
|
||||||
|
|||||||
@@ -177,47 +177,56 @@ RTI13ObjectInstance::localDeleteObjectInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag)
|
RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag)
|
||||||
{
|
{
|
||||||
// Retrieve an empty update struct from the memory pool
|
// Retrieve an empty update struct from the memory pool
|
||||||
UpdateList updateList;
|
RTIIndexDataPairList indexDataPairList;
|
||||||
getUpdateFromPool(updateList);
|
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||||
|
i != attributeHandleDataPairList.end(); ++i) {
|
||||||
RTI::ULong numAttribs = attributeValuePairSet.size();
|
unsigned index = getAttributeIndex(i->first);
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
|
||||||
unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
|
|
||||||
// Get a RTIData from the data pool
|
// Get a RTIData from the data pool
|
||||||
getDataFromPool(index, updateList.back()._indexDataPairList);
|
getDataFromPool(indexDataPairList);
|
||||||
RTI::ULong length = attributeValuePairSet.getValueLength(i);
|
indexDataPairList.back().first = index;
|
||||||
updateList.back()._indexDataPairList.back().second.resize(length);
|
indexDataPairList.back().second.swap(i->second);
|
||||||
attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
|
}
|
||||||
updateList.back()._tag = tag;
|
|
||||||
|
RTIObjectInstance::reflectAttributeValues(indexDataPairList, tag);
|
||||||
|
|
||||||
|
RTIIndexDataPairList::iterator j = indexDataPairList.begin();
|
||||||
|
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||||
|
i != attributeHandleDataPairList.end(); ++i, ++j) {
|
||||||
|
i->second.swap(j->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag);
|
|
||||||
// Return the update data back to the pool
|
// Return the update data back to the pool
|
||||||
putUpdateToPool(updateList);
|
putDataToPool(indexDataPairList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag)
|
RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
|
||||||
|
const SGTimeStamp& timeStamp, const RTIData& tag)
|
||||||
{
|
{
|
||||||
// Retrieve an empty update struct from the memory pool
|
// Retrieve an empty update struct from the memory pool
|
||||||
UpdateList updateList;
|
RTIIndexDataPairList indexDataPairList;
|
||||||
getUpdateFromPool(updateList);
|
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||||
|
i != attributeHandleDataPairList.end(); ++i) {
|
||||||
RTI::ULong numAttribs = attributeValuePairSet.size();
|
unsigned index = getAttributeIndex(i->first);
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
|
||||||
unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
|
|
||||||
// Get a RTIData from the data pool
|
// Get a RTIData from the data pool
|
||||||
getDataFromPool(index, updateList.back()._indexDataPairList);
|
getDataFromPool(indexDataPairList);
|
||||||
RTI::ULong length = attributeValuePairSet.getValueLength(i);
|
indexDataPairList.back().first = index;
|
||||||
updateList.back()._indexDataPairList.back().second.resize(length);
|
indexDataPairList.back().second.swap(i->second);
|
||||||
attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
|
|
||||||
updateList.back()._tag = tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleUpdates(timeStamp, updateList);
|
RTIObjectInstance::reflectAttributeValues(indexDataPairList, timeStamp, tag);
|
||||||
|
|
||||||
|
RTIIndexDataPairList::iterator j = indexDataPairList.begin();
|
||||||
|
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||||
|
i != attributeHandleDataPairList.end(); ++i, ++j) {
|
||||||
|
i->second.swap(j->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the update data back to the pool
|
||||||
|
putDataToPool(indexDataPairList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -273,12 +282,12 @@ RTI13ObjectInstance::requestObjectAttributeValueUpdate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes)
|
RTI13ObjectInstance::provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||||
{
|
{
|
||||||
// Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update
|
// Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update
|
||||||
RTI::ULong numAttribs = attributes.size();
|
size_t numAttribs = attributeHandleSet.size();
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||||
unsigned index = getAttributeIndex(attributes.getHandle(i));
|
unsigned index = getAttributeIndex(attributeHandleSet[i]);
|
||||||
setAttributeForceUpdate(index);
|
setAttributeForceUpdate(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,72 +409,72 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet)
|
RTI13ObjectInstance::attributesInScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||||
{
|
{
|
||||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
size_t numAttribs = attributeHandleSet.size();
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||||
setAttributeInScope(getAttributeIndex(attributeHandle), true);
|
setAttributeInScope(getAttributeIndex(attributeHandle), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet)
|
RTI13ObjectInstance::attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||||
{
|
{
|
||||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
size_t numAttribs = attributeHandleSet.size();
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||||
setAttributeInScope(getAttributeIndex(attributeHandle), false);
|
setAttributeInScope(getAttributeIndex(attributeHandle), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
|
RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||||
{
|
{
|
||||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
size_t numAttribs = attributeHandleSet.size();
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||||
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true);
|
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
|
RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||||
{
|
{
|
||||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
size_t numAttribs = attributeHandleSet.size();
|
||||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||||
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false);
|
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
|
RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes)
|
RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes)
|
RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes)
|
RTI13ObjectInstance::attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
|
RTI13ObjectInstance::requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes)
|
RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ namespace simgear {
|
|||||||
class RTI13Ambassador;
|
class RTI13Ambassador;
|
||||||
class RTI13ObjectClass;
|
class RTI13ObjectClass;
|
||||||
|
|
||||||
|
typedef std::pair<RTI::AttributeHandle, RTIData> RTI13AttributeHandleDataPair;
|
||||||
|
typedef std::list<RTI13AttributeHandleDataPair> RTI13AttributeHandleDataPairList;
|
||||||
|
|
||||||
class RTI13ObjectInstance : public RTIObjectInstance {
|
class RTI13ObjectInstance : public RTIObjectInstance {
|
||||||
public:
|
public:
|
||||||
RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned);
|
RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned);
|
||||||
@@ -65,27 +68,27 @@ public:
|
|||||||
virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag);
|
virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||||
virtual void localDeleteObjectInstance();
|
virtual void localDeleteObjectInstance();
|
||||||
|
|
||||||
void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag);
|
void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag);
|
||||||
void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag);
|
void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||||
virtual void requestObjectAttributeValueUpdate();
|
virtual void requestObjectAttributeValueUpdate();
|
||||||
void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes);
|
void provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
|
|
||||||
virtual void updateAttributeValues(const RTIData& tag);
|
virtual void updateAttributeValues(const RTIData& tag);
|
||||||
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
|
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||||
|
|
||||||
void attributesInScope(const RTI::AttributeHandleSet& attributes);
|
void attributesInScope(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void attributesOutOfScope(const RTI::AttributeHandleSet& attributes);
|
void attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
|
|
||||||
void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes);
|
void turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes);
|
void turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
|
|
||||||
// Not yet sure what to do here. But the dispatch functions are already there
|
// Not yet sure what to do here. But the dispatch functions are already there
|
||||||
void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
|
void requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
|
||||||
void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes);
|
void attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes);
|
void attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes);
|
void attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
|
void requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
|
||||||
void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes);
|
void confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes);
|
||||||
void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle);
|
void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle);
|
||||||
void attributeIsNotOwned(RTI::AttributeHandle attributeHandle);
|
void attributeIsNotOwned(RTI::AttributeHandle attributeHandle);
|
||||||
void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle);
|
void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle);
|
||||||
|
|||||||
@@ -115,6 +115,13 @@ public:
|
|||||||
ensureCapacity(capacity);
|
ensureCapacity(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void swap(RTIData& data)
|
||||||
|
{
|
||||||
|
std::swap(_data, data._data);
|
||||||
|
std::swap(_size, data._size);
|
||||||
|
std::swap(_capacity, data._capacity);
|
||||||
|
}
|
||||||
|
|
||||||
void setData(char* data, unsigned size)
|
void setData(char* data, unsigned size)
|
||||||
{
|
{
|
||||||
if (_capacity)
|
if (_capacity)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public:
|
|||||||
|
|
||||||
virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0;
|
virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0;
|
||||||
virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) = 0;
|
virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) = 0;
|
||||||
|
virtual bool flushQueueRequest(const SGTimeStamp& timeStamp) = 0;
|
||||||
virtual bool getTimeAdvancePending() = 0;
|
virtual bool getTimeAdvancePending() = 0;
|
||||||
|
|
||||||
virtual bool queryFederateTime(SGTimeStamp& timeStamp) = 0;
|
virtual bool queryFederateTime(SGTimeStamp& timeStamp) = 0;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIDat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hlaObjectClass->discoverInstance(objectInstance, tag);
|
hlaObjectClass->discoverInstance(objectInstance, tag);
|
||||||
|
objectInstance->requestObjectAttributeValueUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -60,20 +60,6 @@ public:
|
|||||||
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
|
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
|
||||||
|
|
||||||
void removeInstance(const RTIData& tag);
|
void removeInstance(const RTIData& tag);
|
||||||
// Call this if you want to roll up the queued timestamed updates
|
|
||||||
// and reflect that into the attached data elements.
|
|
||||||
void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
|
|
||||||
{
|
|
||||||
// replay all updates up to the given timestamp
|
|
||||||
UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
|
|
||||||
for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
|
|
||||||
for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
|
|
||||||
// FIXME have a variant that takes the timestamp?
|
|
||||||
reflectAttributeValues(j->_indexDataPairList, j->_tag);
|
|
||||||
}
|
|
||||||
putUpdateToPool(i->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
|
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
|
||||||
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
|
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||||
void reflectAttributeValue(unsigned i, const RTIData& data)
|
void reflectAttributeValue(unsigned i, const RTIData& data)
|
||||||
@@ -133,6 +119,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
_attributeData[i].setUpdateEnabled(false);
|
_attributeData[i].setUpdateEnabled(false);
|
||||||
_attributeData[i].setOwned(false);
|
_attributeData[i].setOwned(false);
|
||||||
|
if (getAttributeSubscribed(i))
|
||||||
|
_attributeData[i].setRequestUpdate(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_attributeData.resize(numAttributes);
|
_attributeData.resize(numAttributes);
|
||||||
@@ -140,9 +128,13 @@ public:
|
|||||||
if (getAttributePublished(i)) {
|
if (getAttributePublished(i)) {
|
||||||
_attributeData[i].setUpdateEnabled(true);
|
_attributeData[i].setUpdateEnabled(true);
|
||||||
_attributeData[i].setOwned(owned);
|
_attributeData[i].setOwned(owned);
|
||||||
|
if (!owned && getAttributeSubscribed(i))
|
||||||
|
_attributeData[i].setRequestUpdate(true);
|
||||||
} else {
|
} else {
|
||||||
_attributeData[i].setUpdateEnabled(false);
|
_attributeData[i].setUpdateEnabled(false);
|
||||||
_attributeData[i].setOwned(false);
|
_attributeData[i].setOwned(false);
|
||||||
|
if (getAttributeSubscribed(i))
|
||||||
|
_attributeData[i].setRequestUpdate(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,80 +227,25 @@ protected:
|
|||||||
// Is true if we should emit a requestattr
|
// Is true if we should emit a requestattr
|
||||||
bool _pendingAttributeUpdateRequest;
|
bool _pendingAttributeUpdateRequest;
|
||||||
|
|
||||||
// Contains a full update as it came in from the RTI
|
// Pool of update list entries
|
||||||
struct Update {
|
RTIIndexDataPairList _indexDataPairList;
|
||||||
RTIIndexDataPairList _indexDataPairList;
|
|
||||||
RTIData _tag;
|
|
||||||
};
|
|
||||||
// A bunch of updates for the same timestamp
|
|
||||||
typedef std::list<Update> UpdateList;
|
|
||||||
// The timestamp sorted list of updates
|
|
||||||
typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
|
|
||||||
|
|
||||||
// The timestamped updates sorted by timestamp
|
|
||||||
UpdateListMap _updateListMap;
|
|
||||||
|
|
||||||
// The pool of unused updates so that we do not need to malloc/free each time
|
|
||||||
UpdateList _updateList;
|
|
||||||
|
|
||||||
void getUpdateFromPool(UpdateList& updateList)
|
|
||||||
{
|
|
||||||
if (_updateList.empty())
|
|
||||||
updateList.push_back(Update());
|
|
||||||
else
|
|
||||||
updateList.splice(updateList.end(), _updateList, _updateList.begin());
|
|
||||||
}
|
|
||||||
void putUpdateToPool(UpdateList& updateList)
|
|
||||||
{
|
|
||||||
for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
|
|
||||||
putDataToPool(i->_indexDataPairList);
|
|
||||||
_updateList.splice(_updateList.end(), updateList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appends the updates in the list to the given timestamps updates
|
|
||||||
void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
|
|
||||||
{
|
|
||||||
UpdateListMap::iterator i = _updateListMap.find(timeStamp);
|
|
||||||
if (i == _updateListMap.end())
|
|
||||||
i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
|
|
||||||
i->second.splice(i->second.end(), updateList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This adds raw storage for attribute index i to the end of the dataPairList.
|
// This adds raw storage for attribute index i to the end of the dataPairList.
|
||||||
void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
|
void getDataFromPool(RTIIndexDataPairList& dataPairList)
|
||||||
{
|
{
|
||||||
if (_attributeData.size() <= i) {
|
|
||||||
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing left in the pool - so allocate something
|
// Nothing left in the pool - so allocate something
|
||||||
if (_attributeData[i]._indexDataPairList.empty()) {
|
if (_indexDataPairList.empty()) {
|
||||||
dataPairList.push_back(RTIIndexDataPairList::value_type());
|
dataPairList.push_back(RTIIndexDataPairList::value_type());
|
||||||
dataPairList.back().first = i;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take one from the pool
|
// Take one from the pool
|
||||||
dataPairList.splice(dataPairList.end(),
|
dataPairList.splice(dataPairList.end(), _indexDataPairList, _indexDataPairList.begin());
|
||||||
_attributeData[i]._indexDataPairList,
|
|
||||||
_attributeData[i]._indexDataPairList.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void putDataToPool(RTIIndexDataPairList& dataPairList)
|
void putDataToPool(RTIIndexDataPairList& dataPairList)
|
||||||
{
|
{
|
||||||
while (!dataPairList.empty()) {
|
_indexDataPairList.splice(_indexDataPairList.begin(), dataPairList);
|
||||||
// Put back into the pool
|
|
||||||
unsigned i = dataPairList.front().first;
|
|
||||||
if (_attributeData.size() <= i) {
|
|
||||||
// should not happen!!!
|
|
||||||
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
|
|
||||||
dataPairList.pop_front();
|
|
||||||
} else {
|
|
||||||
_attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
|
|
||||||
dataPairList, dataPairList.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AttributeData {
|
struct AttributeData {
|
||||||
|
|||||||
@@ -57,3 +57,22 @@ target_link_libraries(httpget
|
|||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${WINSOCK_LIBRARY}
|
${WINSOCK_LIBRARY}
|
||||||
${RT_LIBRARY})
|
${RT_LIBRARY})
|
||||||
|
|
||||||
|
add_executable(decode_binobj decode_binobj.cxx)
|
||||||
|
target_link_libraries(decode_binobj
|
||||||
|
sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${WINSOCK_LIBRARY}
|
||||||
|
${ZLIB_LIBRARY}
|
||||||
|
${RT_LIBRARY})
|
||||||
|
|
||||||
|
add_executable(test_binobj test_binobj.cxx)
|
||||||
|
target_link_libraries(test_binobj
|
||||||
|
sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${WINSOCK_LIBRARY}
|
||||||
|
${ZLIB_LIBRARY}
|
||||||
|
${RT_LIBRARY})
|
||||||
|
|
||||||
|
add_test(binobj ${EXECUTABLE_OUTPUT_PATH}/test_binobj)
|
||||||
|
|
||||||
@@ -4,9 +4,13 @@
|
|||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "sg_binobj.hxx"
|
#include "sg_binobj.hxx"
|
||||||
|
|
||||||
|
|||||||
+643
-785
File diff suppressed because it is too large
Load Diff
+28
-11
@@ -27,29 +27,24 @@
|
|||||||
#ifndef _SG_BINOBJ_HXX
|
#ifndef _SG_BINOBJ_HXX
|
||||||
#define _SG_BINOBJ_HXX
|
#define _SG_BINOBJ_HXX
|
||||||
|
|
||||||
|
#include <zlib.h> // for gzFile
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/math/sg_types.hxx>
|
#include <simgear/math/sg_types.hxx>
|
||||||
#include <simgear/bucket/newbucket.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <vector>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** STL Structure used to store object information */
|
/** STL Structure used to store object information */
|
||||||
typedef std::vector < int_list > group_list;
|
typedef std::vector < int_list > group_list;
|
||||||
typedef group_list::iterator group_list_iterator;
|
typedef group_list::iterator group_list_iterator;
|
||||||
typedef group_list::const_iterator const_group_list_iterator;
|
typedef group_list::const_iterator const_group_list_iterator;
|
||||||
|
|
||||||
|
// forward decls
|
||||||
/** Magic Number for our file format */
|
class SGBucket;
|
||||||
#define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + SG_BINOBJ_VERSION )
|
class SGPath;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to manipulate the simgear 3d object format.
|
* A class to manipulate the simgear 3d object format.
|
||||||
@@ -85,6 +80,7 @@ typedef group_list::const_iterator const_group_list_iterator;
|
|||||||
* - vertex: FLOAT, FLOAT, FLOAT
|
* - vertex: FLOAT, FLOAT, FLOAT
|
||||||
*/
|
*/
|
||||||
class SGBinObject {
|
class SGBinObject {
|
||||||
|
private:
|
||||||
unsigned short version;
|
unsigned short version;
|
||||||
|
|
||||||
SGVec3d gbs_center;
|
SGVec3d gbs_center;
|
||||||
@@ -119,6 +115,24 @@ class SGBinObject {
|
|||||||
group_list fans_tc; // fans texture coordinate index
|
group_list fans_tc; // fans texture coordinate index
|
||||||
string_list fan_materials; // fans materials
|
string_list fan_materials; // fans materials
|
||||||
|
|
||||||
|
void read_properties(gzFile fp, int nproperties);
|
||||||
|
|
||||||
|
void read_object( gzFile fp,
|
||||||
|
int obj_type,
|
||||||
|
int nproperties,
|
||||||
|
int nelements,
|
||||||
|
group_list& vertices,
|
||||||
|
group_list& normals,
|
||||||
|
group_list& colors,
|
||||||
|
group_list& texCoords,
|
||||||
|
string_list& materials);
|
||||||
|
|
||||||
|
void write_header(gzFile fp, int type, int nProps, int nElements);
|
||||||
|
void write_objects(gzFile fp, int type, const group_list& verts,
|
||||||
|
const group_list& normals, const group_list& colors,
|
||||||
|
const group_list& texCoords, const string_list& materials);
|
||||||
|
|
||||||
|
unsigned int count_objects(const string_list& materials);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
inline unsigned short get_version() const { return version; }
|
inline unsigned short get_version() const { return version; }
|
||||||
@@ -207,6 +221,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool write_bin( const std::string& base, const std::string& name, const SGBucket& b );
|
bool write_bin( const std::string& base, const std::string& name, const SGBucket& b );
|
||||||
|
|
||||||
|
|
||||||
|
bool write_bin_file(const SGPath& file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write out the structures to an ASCII file. We assume that the
|
* Write out the structures to an ASCII file. We assume that the
|
||||||
* groups come to us sorted by material property. If not, things
|
* groups come to us sorted by material property. If not, things
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define random rand
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
|
|
||||||
|
#include "sg_binobj.hxx"
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
#define COMPARE(a, b) \
|
||||||
|
if ((a) != (b)) { \
|
||||||
|
cerr << "failed:" << #a << " != " << #b << endl; \
|
||||||
|
cerr << "\tgot:" << a << endl; \
|
||||||
|
exit(1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VERIFY(a) \
|
||||||
|
if (!(a)) { \
|
||||||
|
cerr << "failed:" << #a << endl; \
|
||||||
|
exit(1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_points(int count, std::vector<SGVec3d>& vec)
|
||||||
|
{
|
||||||
|
for (int i=0; i<count; ++i) {
|
||||||
|
vec.push_back(SGVec3d(i * 0.5, i * i, i * 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_normals(int count, std::vector<SGVec3f>& vec)
|
||||||
|
{
|
||||||
|
for (int i=0; i<count; ++i) {
|
||||||
|
vec.push_back(normalize(SGVec3f(i, i * 2, i * -4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_tcs(int count, std::vector<SGVec2f>& vec)
|
||||||
|
{
|
||||||
|
for (int i=0; i<count; ++i) {
|
||||||
|
vec.push_back(SGVec2f(1.0 / i, 16.0 / i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_empty()
|
||||||
|
{
|
||||||
|
SGBinObject empty;
|
||||||
|
SGPath path(simgear::Dir::current().file("empty.btg.gz"));
|
||||||
|
bool ok = empty.write_bin_file(path);
|
||||||
|
VERIFY( ok );
|
||||||
|
SGBinObject rd;
|
||||||
|
ok = rd.read_bin(path.str()) ;
|
||||||
|
VERIFY( ok);
|
||||||
|
|
||||||
|
COMPARE(rd.get_wgs84_nodes().size(), 0);
|
||||||
|
VERIFY(rd.get_pt_materials().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void comparePoints(const SGBinObject& rd, const std::vector<SGVec3d>& b)
|
||||||
|
{
|
||||||
|
for (unsigned int i=1; i<b.size(); i += 10) {
|
||||||
|
SGVec3d pos = rd.get_wgs84_nodes()[i];
|
||||||
|
pos += rd.get_gbs_center();
|
||||||
|
|
||||||
|
if (!equivalent(pos, b[i], 0.1)) {
|
||||||
|
cout << "i=" << i << endl;
|
||||||
|
cout << b[i] << endl;
|
||||||
|
cout << pos << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(equivalent(pos, b[i], 0.1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void compareTexCoords(const SGBinObject& rd, const std::vector<SGVec2f>& b)
|
||||||
|
{
|
||||||
|
for (unsigned int i=1; i<b.size(); i += 10) {
|
||||||
|
SGVec2f pos = rd.get_texcoords()[i];
|
||||||
|
VERIFY(equivalent(pos, b[i], 0.001f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int_list make_tri(int maxIndex)
|
||||||
|
{
|
||||||
|
int_list r;
|
||||||
|
r.push_back(random() % maxIndex);
|
||||||
|
r.push_back(random() % maxIndex);
|
||||||
|
r.push_back(random() % maxIndex);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compareTris(const SGBinObject& a, const SGBinObject& b)
|
||||||
|
{
|
||||||
|
unsigned int count = a.get_tri_materials().size();
|
||||||
|
for (unsigned int i=0; i<count; i += 39) {
|
||||||
|
const int_list& vA(a.get_tris_v()[i]);
|
||||||
|
const int_list& vB(b.get_tris_v()[i]);
|
||||||
|
VERIFY(vA == vB);
|
||||||
|
|
||||||
|
COMPARE(a.get_tri_materials()[i], b.get_tri_materials()[i]);
|
||||||
|
|
||||||
|
const int_list& tA(a.get_tris_tc()[i]);
|
||||||
|
const int_list& tB(b.get_tris_tc()[i]);
|
||||||
|
VERIFY(tA == tB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_tris(SGBinObject& b, int count)
|
||||||
|
{
|
||||||
|
group_list v, n, tc;
|
||||||
|
string_list materials;
|
||||||
|
|
||||||
|
int maxVertices = b.get_wgs84_nodes().size();
|
||||||
|
int maxNormals = b.get_normals().size();
|
||||||
|
int maxTCs = b.get_texcoords().size();
|
||||||
|
|
||||||
|
for (int t=0; t<count; ++t) {
|
||||||
|
v.push_back(make_tri(maxVertices));
|
||||||
|
n.push_back(make_tri(maxNormals));
|
||||||
|
tc.push_back(make_tri(maxTCs));
|
||||||
|
materials.push_back("material1");
|
||||||
|
}
|
||||||
|
|
||||||
|
b.set_tris_v(v);
|
||||||
|
b.set_tris_n(n);
|
||||||
|
b.set_tris_tc(tc);
|
||||||
|
b.set_tri_materials(materials);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_basic()
|
||||||
|
{
|
||||||
|
SGBinObject basic;
|
||||||
|
SGPath path(simgear::Dir::current().file("basic.btg.gz"));
|
||||||
|
|
||||||
|
SGVec3d center(1, 2, 3);
|
||||||
|
basic.set_gbs_center(center);
|
||||||
|
basic.set_gbs_radius(12345);
|
||||||
|
|
||||||
|
std::vector<SGVec3d> points;
|
||||||
|
generate_points(1024, points);
|
||||||
|
std::vector<SGVec3f> normals;
|
||||||
|
generate_normals(1024, normals);
|
||||||
|
std::vector<SGVec2f> texCoords;
|
||||||
|
generate_tcs(10000, texCoords);
|
||||||
|
|
||||||
|
basic.set_wgs84_nodes(points);
|
||||||
|
basic.set_normals(normals);
|
||||||
|
basic.set_texcoords(texCoords);
|
||||||
|
|
||||||
|
bool ok = basic.write_bin_file(path);
|
||||||
|
VERIFY( ok );
|
||||||
|
|
||||||
|
SGBinObject rd;
|
||||||
|
ok = rd.read_bin(path.str()) ;
|
||||||
|
VERIFY( ok);
|
||||||
|
COMPARE(rd.get_version(), 7); // should be version 7 since indices are < 2^16
|
||||||
|
COMPARE(rd.get_gbs_center(), center);
|
||||||
|
COMPARE(rd.get_gbs_radius(), 12345);
|
||||||
|
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||||
|
|
||||||
|
comparePoints(rd, points);
|
||||||
|
compareTexCoords(rd, texCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_many_tcs()
|
||||||
|
{
|
||||||
|
SGBinObject basic;
|
||||||
|
SGPath path(simgear::Dir::current().file("many_tex.btg.gz"));
|
||||||
|
|
||||||
|
SGVec3d center(1, 2, 3);
|
||||||
|
basic.set_gbs_center(center);
|
||||||
|
basic.set_gbs_radius(12345);
|
||||||
|
|
||||||
|
std::vector<SGVec3d> points;
|
||||||
|
generate_points(10000, points);
|
||||||
|
std::vector<SGVec3f> normals;
|
||||||
|
generate_normals(1024, normals);
|
||||||
|
std::vector<SGVec2f> texCoords;
|
||||||
|
generate_tcs(100000, texCoords);
|
||||||
|
|
||||||
|
basic.set_wgs84_nodes(points);
|
||||||
|
basic.set_normals(normals);
|
||||||
|
basic.set_texcoords(texCoords);
|
||||||
|
|
||||||
|
generate_tris(basic, 20000);
|
||||||
|
|
||||||
|
bool ok = basic.write_bin_file(path);
|
||||||
|
VERIFY( ok );
|
||||||
|
|
||||||
|
SGBinObject rd;
|
||||||
|
ok = rd.read_bin(path.str()) ;
|
||||||
|
VERIFY( ok);
|
||||||
|
COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16
|
||||||
|
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||||
|
COMPARE(rd.get_texcoords().size(), texCoords.size());
|
||||||
|
|
||||||
|
comparePoints(rd, points);
|
||||||
|
compareTexCoords(rd, texCoords);
|
||||||
|
compareTris(basic, rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_big()
|
||||||
|
{
|
||||||
|
SGBinObject basic;
|
||||||
|
SGPath path(simgear::Dir::current().file("big.btg.gz"));
|
||||||
|
|
||||||
|
SGVec3d center(1, 2, 3);
|
||||||
|
basic.set_gbs_center(center);
|
||||||
|
basic.set_gbs_radius(12345);
|
||||||
|
|
||||||
|
std::vector<SGVec3d> points;
|
||||||
|
generate_points(200000, points);
|
||||||
|
std::vector<SGVec3f> normals;
|
||||||
|
generate_normals(1024, normals);
|
||||||
|
std::vector<SGVec2f> texCoords;
|
||||||
|
generate_tcs(300000, texCoords);
|
||||||
|
|
||||||
|
basic.set_wgs84_nodes(points);
|
||||||
|
basic.set_normals(normals);
|
||||||
|
basic.set_texcoords(texCoords);
|
||||||
|
|
||||||
|
generate_tris(basic, 200000);
|
||||||
|
|
||||||
|
bool ok = basic.write_bin_file(path);
|
||||||
|
VERIFY( ok );
|
||||||
|
|
||||||
|
SGBinObject rd;
|
||||||
|
ok = rd.read_bin(path.str()) ;
|
||||||
|
VERIFY( ok);
|
||||||
|
COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16
|
||||||
|
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||||
|
COMPARE(rd.get_texcoords().size(), texCoords.size());
|
||||||
|
|
||||||
|
comparePoints(rd, points);
|
||||||
|
compareTexCoords(rd, texCoords);
|
||||||
|
compareTris(basic, rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
test_empty();
|
||||||
|
test_basic();
|
||||||
|
test_many_tcs();
|
||||||
|
test_big();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -41,3 +41,8 @@ target_link_libraries(test_tabbed_values sgmisc)
|
|||||||
add_executable(test_strings strutils_test.cxx )
|
add_executable(test_strings strutils_test.cxx )
|
||||||
add_test(test_strings ${EXECUTABLE_OUTPUT_PATH}/test_strings)
|
add_test(test_strings ${EXECUTABLE_OUTPUT_PATH}/test_strings)
|
||||||
target_link_libraries(test_strings sgmisc)
|
target_link_libraries(test_strings sgmisc)
|
||||||
|
|
||||||
|
add_executable(test_path path_test.cxx )
|
||||||
|
add_test(test_path ${EXECUTABLE_OUTPUT_PATH}/test_path)
|
||||||
|
target_link_libraries(test_path sgmisc sgdebug)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
#define COMPARE(a, b) \
|
||||||
|
if ((a) != (b)) { \
|
||||||
|
cerr << "failed:" << #a << " != " << #b << endl; \
|
||||||
|
exit(1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VERIFY(a) \
|
||||||
|
if (!(a)) { \
|
||||||
|
cerr << "failed:" << #a << endl; \
|
||||||
|
exit(1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
|
|
||||||
|
void test_dir()
|
||||||
|
{
|
||||||
|
simgear::Dir temp = simgear::Dir::tempDir("foo");
|
||||||
|
cout << "created:" << temp.path().str() << endl;
|
||||||
|
|
||||||
|
VERIFY(temp.exists());
|
||||||
|
VERIFY(temp.path().isDir());
|
||||||
|
VERIFY(!temp.path().isFile());
|
||||||
|
|
||||||
|
SGPath fileInDir = temp.file("foobaz");
|
||||||
|
VERIFY(!fileInDir.exists());
|
||||||
|
|
||||||
|
if (!temp.remove(true)) {
|
||||||
|
cout << "remove failed!" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << temp.path().modTime() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
SGPath pa;
|
||||||
|
VERIFY(pa.isNull());
|
||||||
|
COMPARE(pa.exists(), false);
|
||||||
|
|
||||||
|
// test basic parsing
|
||||||
|
SGPath pb("/Foo/bar/something.png");
|
||||||
|
COMPARE(pb.str(), std::string("/Foo/bar/something.png"));
|
||||||
|
COMPARE(strcmp(pb.c_str(), "/Foo/bar/something.png"), 0);
|
||||||
|
COMPARE(pb.dir(), std::string("/Foo/bar"));
|
||||||
|
COMPARE(pb.file(), std::string("something.png"));
|
||||||
|
COMPARE(pb.base(), std::string("/Foo/bar/something"));
|
||||||
|
COMPARE(pb.file_base(), std::string("something"));
|
||||||
|
COMPARE(pb.extension(), std::string("png"));
|
||||||
|
VERIFY(pb.isAbsolute());
|
||||||
|
VERIFY(!pb.isRelative());
|
||||||
|
|
||||||
|
// relative paths
|
||||||
|
SGPath ra("where/to/begin.txt");
|
||||||
|
COMPARE(ra.str(), std::string("where/to/begin.txt"));
|
||||||
|
COMPARE(ra.dir(), std::string("where/to"));
|
||||||
|
COMPARE(ra.file(), std::string("begin.txt"));
|
||||||
|
COMPARE(ra.file_base(), std::string("begin"));
|
||||||
|
VERIFY(!ra.isAbsolute());
|
||||||
|
VERIFY(ra.isRelative());
|
||||||
|
|
||||||
|
// dots in paths / missing extensions
|
||||||
|
SGPath pk("/Foo/bar.dot/thing");
|
||||||
|
COMPARE(pk.dir(), std::string("/Foo/bar.dot"));
|
||||||
|
COMPARE(pk.file(), std::string("thing"));
|
||||||
|
COMPARE(pk.base(), std::string("/Foo/bar.dot/thing"));
|
||||||
|
COMPARE(pk.file_base(), std::string("thing"));
|
||||||
|
COMPARE(pk.extension(), std::string());
|
||||||
|
|
||||||
|
// multiple file extensions
|
||||||
|
SGPath pj("/Foo/zot.dot/thing.tar.gz");
|
||||||
|
COMPARE(pj.dir(), std::string("/Foo/zot.dot"));
|
||||||
|
COMPARE(pj.file(), std::string("thing.tar.gz"));
|
||||||
|
COMPARE(pj.base(), std::string("/Foo/zot.dot/thing"));
|
||||||
|
COMPARE(pj.file_base(), std::string("thing"));
|
||||||
|
COMPARE(pj.extension(), std::string("gz"));
|
||||||
|
COMPARE(pj.complete_lower_extension(), std::string("tar.gz"));
|
||||||
|
|
||||||
|
// path fixing
|
||||||
|
SGPath rd("where\\to\\begin.txt");
|
||||||
|
COMPARE(rd.str(), std::string("where/to/begin.txt"));
|
||||||
|
|
||||||
|
// test modification
|
||||||
|
// append
|
||||||
|
SGPath d1("/usr/local");
|
||||||
|
SGPath pc = d1;
|
||||||
|
COMPARE(pc.str(), std::string("/usr/local"));
|
||||||
|
pc.append("include");
|
||||||
|
|
||||||
|
COMPARE(pc.str(), std::string("/usr/local/include"));
|
||||||
|
COMPARE(pc.file(), std::string("include"));
|
||||||
|
|
||||||
|
// add
|
||||||
|
pc.add("/opt/local");
|
||||||
|
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
||||||
|
|
||||||
|
// concat
|
||||||
|
SGPath pd = pb;
|
||||||
|
pd.concat("-1");
|
||||||
|
COMPARE(pd.str(), std::string("/Foo/bar/something.png-1"));
|
||||||
|
|
||||||
|
// create with relative path
|
||||||
|
SGPath rb(d1, "include/foo");
|
||||||
|
COMPARE(rb.str(), std::string("/usr/local/include/foo"));
|
||||||
|
VERIFY(rb.isAbsolute());
|
||||||
|
|
||||||
|
// lower-casing of file extensions
|
||||||
|
SGPath extA("FOO.ZIP");
|
||||||
|
COMPARE(extA.base(), "FOO");
|
||||||
|
COMPARE(extA.extension(), "ZIP");
|
||||||
|
COMPARE(extA.lower_extension(), "zip");
|
||||||
|
COMPARE(extA.complete_lower_extension(), "zip");
|
||||||
|
|
||||||
|
SGPath extB("BAH/FOO.HTML.GZ");
|
||||||
|
COMPARE(extB.extension(), "GZ");
|
||||||
|
COMPARE(extB.base(), "BAH/FOO");
|
||||||
|
COMPARE(extB.lower_extension(), "gz");
|
||||||
|
COMPARE(extB.complete_lower_extension(), "html.gz");
|
||||||
|
#ifdef _WIN32
|
||||||
|
COMPARE(d1.str_native(), std::string("\\usr\\local"));
|
||||||
|
|
||||||
|
SGPath winAbs("C:\\Windows\\System32");
|
||||||
|
COMPARE(winAbs.str(), std::string("C:/Windows/System32"));
|
||||||
|
#else
|
||||||
|
COMPARE(d1.str_native(), std::string("/usr/local"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
test_dir();
|
||||||
|
|
||||||
|
cout << "all tests passed OK" << endl;
|
||||||
|
return 0; // passed
|
||||||
|
}
|
||||||
|
|
||||||
@@ -18,33 +18,89 @@
|
|||||||
//
|
//
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <simgear/misc/sg_dir.hxx>
|
#include <simgear/misc/sg_dir.hxx>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
# include <direct.h>
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Dir::Dir()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Dir::Dir(const SGPath& path) :
|
Dir::Dir(const SGPath& path) :
|
||||||
_path(path)
|
_path(path)
|
||||||
{
|
{
|
||||||
|
_path.set_cached(false); // disable caching, so create/remove work
|
||||||
}
|
}
|
||||||
|
|
||||||
Dir::Dir(const Dir& rel, const SGPath& relPath) :
|
Dir::Dir(const Dir& rel, const SGPath& relPath) :
|
||||||
_path(rel.file(relPath.str()))
|
_path(rel.file(relPath.str()))
|
||||||
{
|
{
|
||||||
|
_path.set_cached(false); // disable caching, so create/remove work
|
||||||
|
}
|
||||||
|
|
||||||
|
Dir Dir::current()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* buf = _getcwd(NULL, 0);
|
||||||
|
#else
|
||||||
|
char* buf = ::getcwd(NULL, 0);
|
||||||
|
#endif
|
||||||
|
SGPath p(buf);
|
||||||
|
free(buf);
|
||||||
|
return Dir(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dir Dir::tempDir(const std::string& templ)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MKDTEMP
|
||||||
|
char buf[1024];
|
||||||
|
char* tempPath = ::getenv("TMPDIR");
|
||||||
|
if (!tempPath) {
|
||||||
|
tempPath = "/tmp/";
|
||||||
|
}
|
||||||
|
// Mac OS-X / BSD manual says any number of 'X's, but GLibc manual
|
||||||
|
// says exactly six, so that's what I'm going with
|
||||||
|
::snprintf(buf, 1024, "%s%s-XXXXXX", tempPath, templ.c_str());
|
||||||
|
if (!mkdtemp(buf)) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "mkdtemp failed:" << strerror(errno));
|
||||||
|
return Dir();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dir(SGPath(buf));
|
||||||
|
#else
|
||||||
|
SGPath p(tempnam(0, templ.c_str()));
|
||||||
|
Dir t(p);
|
||||||
|
if (!t.create(0700)) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "failed to create temporary directory at " << p.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PathList Dir::children(int types, const std::string& nameFilter) const
|
PathList Dir::children(int types, const std::string& nameFilter) const
|
||||||
@@ -175,8 +231,79 @@ bool Dir::exists() const
|
|||||||
SGPath Dir::file(const std::string& name) const
|
SGPath Dir::file(const std::string& name) const
|
||||||
{
|
{
|
||||||
SGPath childPath = _path;
|
SGPath childPath = _path;
|
||||||
|
childPath.set_cached(true);
|
||||||
childPath.append(name);
|
childPath.append(name);
|
||||||
return childPath;
|
return childPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define sgMkDir(d,m) _mkdir(d)
|
||||||
|
#else
|
||||||
|
# define sgMkDir(d,m) mkdir(d,m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Dir::create(mode_t mode)
|
||||||
|
{
|
||||||
|
if (exists()) {
|
||||||
|
return false; // already exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively create parent directories
|
||||||
|
Dir pr(parent());
|
||||||
|
if (!pr.exists()) {
|
||||||
|
bool ok = pr.create(mode);
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, create ourselves
|
||||||
|
int err = sgMkDir(_path.c_str(), mode);
|
||||||
|
if (err) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "directory creation failed: (" << _path.str() << ") " << strerror(errno) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return (err == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Dir::remove(bool recursive)
|
||||||
|
{
|
||||||
|
if (!exists()) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recursive) {
|
||||||
|
bool ok;
|
||||||
|
PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR);
|
||||||
|
BOOST_FOREACH(SGPath path, cs) {
|
||||||
|
if (path.isDir()) {
|
||||||
|
Dir childDir(path);
|
||||||
|
ok = childDir.remove(true);
|
||||||
|
} else {
|
||||||
|
ok = path.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // of child iteration
|
||||||
|
} // of recursive deletion
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = _rmdir(_path.c_str());
|
||||||
|
#else
|
||||||
|
int err = rmdir(_path.c_str());
|
||||||
|
#endif
|
||||||
|
if (err) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "rmdir failed:" << _path.str() << ":" << strerror(errno));
|
||||||
|
}
|
||||||
|
return (err == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dir Dir::parent() const
|
||||||
|
{
|
||||||
|
return Dir(_path.dir());
|
||||||
|
}
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -31,6 +31,10 @@
|
|||||||
#include <simgear/math/sg_types.hxx>
|
#include <simgear/math/sg_types.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef int mode_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
typedef std::vector<SGPath> PathList;
|
typedef std::vector<SGPath> PathList;
|
||||||
@@ -38,6 +42,15 @@ namespace simgear
|
|||||||
class Dir
|
class Dir
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Dir();
|
||||||
|
|
||||||
|
static Dir current();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a temporary directory, using the supplied name
|
||||||
|
*/
|
||||||
|
static Dir tempDir(const std::string& templ);
|
||||||
|
|
||||||
Dir(const SGPath& path);
|
Dir(const SGPath& path);
|
||||||
Dir(const Dir& rel, const SGPath& relPath);
|
Dir(const Dir& rel, const SGPath& relPath);
|
||||||
|
|
||||||
@@ -53,10 +66,31 @@ namespace simgear
|
|||||||
|
|
||||||
SGPath file(const std::string& name) const;
|
SGPath file(const std::string& name) const;
|
||||||
|
|
||||||
|
SGPath path() const
|
||||||
|
{ return _path; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the directory (and any parents as required) with the
|
||||||
|
* request mode, or return failure
|
||||||
|
*/
|
||||||
|
bool create(mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove the directory.
|
||||||
|
* If recursive is true, contained files and directories are
|
||||||
|
* recursively removed
|
||||||
|
*/
|
||||||
|
bool remove(bool recursive = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the directory at the path exists (and is a directory!)
|
* Check that the directory at the path exists (and is a directory!)
|
||||||
*/
|
*/
|
||||||
bool exists() const;
|
bool exists() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parent directory, if one exists
|
||||||
|
*/
|
||||||
|
Dir parent() const;
|
||||||
private:
|
private:
|
||||||
mutable SGPath _path;
|
mutable SGPath _path;
|
||||||
};
|
};
|
||||||
|
|||||||
+118
-30
@@ -28,13 +28,16 @@
|
|||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
#endif
|
#endif
|
||||||
#include "sg_path.hxx"
|
#include "sg_path.hxx"
|
||||||
|
|
||||||
using std::string;
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* define directory path separators
|
* define directory path separators
|
||||||
@@ -58,14 +61,14 @@ SGPath::fix()
|
|||||||
{
|
{
|
||||||
for ( string::size_type i = 0; i < path.size(); ++i ) {
|
for ( string::size_type i = 0; i < path.size(); ++i ) {
|
||||||
#if defined( WIN32 )
|
#if defined( WIN32 )
|
||||||
// for windoze, don't replace the ":" for the second character
|
// for windoze, don't replace the ":" for the second character
|
||||||
if ( i == 1 ) {
|
if ( i == 1 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ( path[i] == sgDirPathSepBad ) {
|
if ( path[i] == sgDirPathSepBad ) {
|
||||||
path[i] = sgDirPathSep;
|
path[i] = sgDirPathSep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +76,8 @@ SGPath::fix()
|
|||||||
// default constructor
|
// default constructor
|
||||||
SGPath::SGPath()
|
SGPath::SGPath()
|
||||||
: path(""),
|
: path(""),
|
||||||
_cached(false)
|
_cached(false),
|
||||||
|
_cacheEnabled(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +85,8 @@ SGPath::SGPath()
|
|||||||
// create a path based on "path"
|
// create a path based on "path"
|
||||||
SGPath::SGPath( const std::string& p )
|
SGPath::SGPath( const std::string& p )
|
||||||
: path(p),
|
: path(p),
|
||||||
_cached(false)
|
_cached(false),
|
||||||
|
_cacheEnabled(true)
|
||||||
{
|
{
|
||||||
fix();
|
fix();
|
||||||
}
|
}
|
||||||
@@ -89,7 +94,8 @@ SGPath::SGPath( const std::string& p )
|
|||||||
// create a path based on "path" and a "subpath"
|
// create a path based on "path" and a "subpath"
|
||||||
SGPath::SGPath( const SGPath& p, const std::string& r )
|
SGPath::SGPath( const SGPath& p, const std::string& r )
|
||||||
: path(p.path),
|
: path(p.path),
|
||||||
_cached(false)
|
_cached(false),
|
||||||
|
_cacheEnabled(p._cacheEnabled)
|
||||||
{
|
{
|
||||||
append(r);
|
append(r);
|
||||||
fix();
|
fix();
|
||||||
@@ -98,9 +104,11 @@ SGPath::SGPath( const SGPath& p, const std::string& r )
|
|||||||
SGPath::SGPath(const SGPath& p) :
|
SGPath::SGPath(const SGPath& p) :
|
||||||
path(p.path),
|
path(p.path),
|
||||||
_cached(p._cached),
|
_cached(p._cached),
|
||||||
|
_cacheEnabled(p._cacheEnabled),
|
||||||
_exists(p._exists),
|
_exists(p._exists),
|
||||||
_isDir(p._isDir),
|
_isDir(p._isDir),
|
||||||
_isFile(p._isFile)
|
_isFile(p._isFile),
|
||||||
|
_modTime(p._modTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,9 +116,11 @@ SGPath& SGPath::operator=(const SGPath& p)
|
|||||||
{
|
{
|
||||||
path = p.path;
|
path = p.path;
|
||||||
_cached = p._cached;
|
_cached = p._cached;
|
||||||
|
_cacheEnabled = p._cacheEnabled;
|
||||||
_exists = p._exists;
|
_exists = p._exists;
|
||||||
_isDir = p._isDir;
|
_isDir = p._isDir;
|
||||||
_isFile = p._isFile;
|
_isFile = p._isFile;
|
||||||
|
_modTime = p._modTime;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,16 +136,20 @@ void SGPath::set( const string& p ) {
|
|||||||
_cached = false;
|
_cached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SGPath::set_cached(bool cached)
|
||||||
|
{
|
||||||
|
_cacheEnabled = cached;
|
||||||
|
}
|
||||||
|
|
||||||
// append another piece to the existing path
|
// append another piece to the existing path
|
||||||
void SGPath::append( const string& p ) {
|
void SGPath::append( const string& p ) {
|
||||||
if ( path.size() == 0 ) {
|
if ( path.size() == 0 ) {
|
||||||
path = p;
|
path = p;
|
||||||
} else {
|
} else {
|
||||||
if ( p[0] != sgDirPathSep ) {
|
if ( p[0] != sgDirPathSep ) {
|
||||||
path += sgDirPathSep;
|
path += sgDirPathSep;
|
||||||
}
|
}
|
||||||
path += p;
|
path += p;
|
||||||
}
|
}
|
||||||
fix();
|
fix();
|
||||||
_cached = false;
|
_cached = false;
|
||||||
@@ -151,9 +165,9 @@ void SGPath::add( const string& p ) {
|
|||||||
// path separator
|
// path separator
|
||||||
void SGPath::concat( const string& p ) {
|
void SGPath::concat( const string& p ) {
|
||||||
if ( path.size() == 0 ) {
|
if ( path.size() == 0 ) {
|
||||||
path = p;
|
path = p;
|
||||||
} else {
|
} else {
|
||||||
path += p;
|
path += p;
|
||||||
}
|
}
|
||||||
fix();
|
fix();
|
||||||
_cached = false;
|
_cached = false;
|
||||||
@@ -164,9 +178,9 @@ void SGPath::concat( const string& p ) {
|
|||||||
string SGPath::file() const {
|
string SGPath::file() const {
|
||||||
int index = path.rfind(sgDirPathSep);
|
int index = path.rfind(sgDirPathSep);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
return path.substr(index + 1);
|
return path.substr(index + 1);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,20 +189,45 @@ string SGPath::file() const {
|
|||||||
string SGPath::dir() const {
|
string SGPath::dir() const {
|
||||||
int index = path.rfind(sgDirPathSep);
|
int index = path.rfind(sgDirPathSep);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
return path.substr(0, index);
|
return path.substr(0, index);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the base part of the path (everything but the extension.)
|
// get the base part of the path (everything but the extension.)
|
||||||
string SGPath::base() const {
|
string SGPath::base() const {
|
||||||
int index = path.rfind(".");
|
unsigned int index = path.rfind(sgDirPathSep);
|
||||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
if (index == string::npos) {
|
||||||
return path.substr(0, index);
|
index = 0; // no separator in the name
|
||||||
} else {
|
} else {
|
||||||
return "";
|
++index; // skip past the separator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the first dot after the final separator
|
||||||
|
unsigned int firstDot = path.find(".", index);
|
||||||
|
if (firstDot == string::npos) {
|
||||||
|
return path; // no extension, return whole path
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.substr(0, firstDot);
|
||||||
|
}
|
||||||
|
|
||||||
|
string SGPath::file_base() const
|
||||||
|
{
|
||||||
|
unsigned int index = path.rfind(sgDirPathSep);
|
||||||
|
if (index == string::npos) {
|
||||||
|
index = 0; // no separator in the name
|
||||||
|
} else {
|
||||||
|
++index; // skip past the separator
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int firstDot = path.find(".", index);
|
||||||
|
if (firstDot == string::npos) {
|
||||||
|
return path.substr(index); // no extensions
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.substr(index, firstDot - index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the extension (everything after the final ".")
|
// get the extension (everything after the final ".")
|
||||||
@@ -197,15 +236,36 @@ string SGPath::base() const {
|
|||||||
string SGPath::extension() const {
|
string SGPath::extension() const {
|
||||||
int index = path.rfind(".");
|
int index = path.rfind(".");
|
||||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||||
return path.substr(index + 1);
|
return path.substr(index + 1);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string SGPath::lower_extension() const {
|
||||||
|
return boost::to_lower_copy(extension());
|
||||||
|
}
|
||||||
|
|
||||||
|
string SGPath::complete_lower_extension() const
|
||||||
|
{
|
||||||
|
unsigned int index = path.rfind(sgDirPathSep);
|
||||||
|
if (index == string::npos) {
|
||||||
|
index = 0; // no separator in the name
|
||||||
|
} else {
|
||||||
|
++index; // skip past the separator
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstDot = path.find(".", index);
|
||||||
|
if ((firstDot >= 0) && (path.find(sgDirPathSep, firstDot) == string::npos)) {
|
||||||
|
return boost::to_lower_copy(path.substr(firstDot + 1));
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGPath::validate() const
|
void SGPath::validate() const
|
||||||
{
|
{
|
||||||
if (_cached) {
|
if (_cached && _cacheEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +281,7 @@ void SGPath::validate() const
|
|||||||
_exists = true;
|
_exists = true;
|
||||||
_isFile = ((S_IFREG & buf.st_mode ) !=0);
|
_isFile = ((S_IFREG & buf.st_mode ) !=0);
|
||||||
_isDir = ((S_IFDIR & buf.st_mode ) !=0);
|
_isDir = ((S_IFDIR & buf.st_mode ) !=0);
|
||||||
|
_modTime = buf.st_mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -232,6 +293,7 @@ void SGPath::validate() const
|
|||||||
_exists = true;
|
_exists = true;
|
||||||
_isFile = ((S_ISREG(buf.st_mode )) != 0);
|
_isFile = ((S_ISREG(buf.st_mode )) != 0);
|
||||||
_isDir = ((S_ISDIR(buf.st_mode )) != 0);
|
_isDir = ((S_ISDIR(buf.st_mode )) != 0);
|
||||||
|
_modTime = buf.st_mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -383,3 +445,29 @@ std::string SGPath::str_native() const
|
|||||||
return str();
|
return str();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SGPath::remove()
|
||||||
|
{
|
||||||
|
int err = ::unlink(c_str());
|
||||||
|
if (err) {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "file remove failed: (" << str() << ") " << strerror(errno));
|
||||||
|
}
|
||||||
|
return (err == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t SGPath::modTime() const
|
||||||
|
{
|
||||||
|
validate();
|
||||||
|
return _modTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SGPath::operator==(const SGPath& other) const
|
||||||
|
{
|
||||||
|
return (path == other.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SGPath::operator!=(const SGPath& other) const
|
||||||
|
{
|
||||||
|
return (path != other.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include <simgear/math/sg_types.hxx>
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
|
||||||
@@ -49,10 +50,6 @@
|
|||||||
|
|
||||||
class SGPath {
|
class SGPath {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::string path;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Default constructor */
|
/** Default constructor */
|
||||||
@@ -86,6 +83,15 @@ public:
|
|||||||
void set( const std::string& p );
|
void set( const std::string& p );
|
||||||
SGPath& operator= ( const char* p ) { this->set(p); return *this; }
|
SGPath& operator= ( const char* p ) { this->set(p); return *this; }
|
||||||
|
|
||||||
|
bool operator==(const SGPath& other) const;
|
||||||
|
bool operator!=(const SGPath& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if file information (exists, type, mod-time) is cached or
|
||||||
|
* retrieved each time it is queried. Caching is enabled by default
|
||||||
|
*/
|
||||||
|
void set_cached(bool cached);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append another piece to the existing path. Inserts a path
|
* Append another piece to the existing path. Inserts a path
|
||||||
* separator between the existing component and the new component.
|
* separator between the existing component and the new component.
|
||||||
@@ -123,12 +129,33 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string base() const;
|
std::string base() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the base part of the filename (everything before the first '.')
|
||||||
|
* @return the base filename
|
||||||
|
*/
|
||||||
|
std::string file_base() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the extension part of the path (everything after the final ".")
|
* Get the extension part of the path (everything after the final ".")
|
||||||
* @return the extension string
|
* @return the extension string
|
||||||
*/
|
*/
|
||||||
std::string extension() const;
|
std::string extension() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extension part of the path (everything after the final ".")
|
||||||
|
* converted to lowercase
|
||||||
|
* @return the extension string
|
||||||
|
*/
|
||||||
|
std::string lower_extension() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the complete extension part of the path (everything after the first ".")
|
||||||
|
* this might look like 'tar.gz' or 'txt.Z', or might be identical to 'extension' above
|
||||||
|
* the extension is converted to lowercase.
|
||||||
|
* @return the extension string
|
||||||
|
*/
|
||||||
|
std::string complete_lower_extension() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path string
|
* Get the path string
|
||||||
* @return path string
|
* @return path string
|
||||||
@@ -176,16 +203,30 @@ public:
|
|||||||
* check for default constructed path
|
* check for default constructed path
|
||||||
*/
|
*/
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete the file, if possible
|
||||||
|
*/
|
||||||
|
bool remove();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* modification time of the file
|
||||||
|
*/
|
||||||
|
time_t modTime() const;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void fix();
|
void fix();
|
||||||
|
|
||||||
void validate() const;
|
void validate() const;
|
||||||
|
|
||||||
mutable bool _cached;
|
std::string path;
|
||||||
mutable bool _exists;
|
|
||||||
mutable bool _isDir;
|
mutable bool _cached : 1;
|
||||||
mutable bool _isFile;
|
bool _cacheEnabled : 1; ///< cacheing can be disbled if required
|
||||||
|
mutable bool _exists : 1;
|
||||||
|
mutable bool _isDir : 1;
|
||||||
|
mutable bool _isFile : 1;
|
||||||
|
mutable time_t _modTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,26 @@ namespace simgear {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compare_versions(const string& v1, const string& v2)
|
||||||
|
{
|
||||||
|
vector<string> v1parts(split(v1, "."));
|
||||||
|
vector<string> v2parts(split(v2, "."));
|
||||||
|
|
||||||
|
int lastPart = std::min(v1parts.size(), v2parts.size());
|
||||||
|
for (int part=0; part < lastPart; ++part) {
|
||||||
|
int part1 = to_int(v1parts[part]);
|
||||||
|
int part2 = to_int(v2parts[part]);
|
||||||
|
|
||||||
|
if (part1 != part2) {
|
||||||
|
return part1 - part2;
|
||||||
|
}
|
||||||
|
} // of parts iteration
|
||||||
|
|
||||||
|
// reached end - longer wins
|
||||||
|
return v1parts.size() - v2parts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end namespace strutils
|
} // end namespace strutils
|
||||||
|
|
||||||
} // end namespace simgear
|
} // end namespace simgear
|
||||||
|
|||||||
@@ -127,6 +127,14 @@ namespace simgear {
|
|||||||
* convert a string representing a decimal number, to an int
|
* convert a string representing a decimal number, to an int
|
||||||
*/
|
*/
|
||||||
int to_int(const std::string& s, int base = 10);
|
int to_int(const std::string& s, int base = 10);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like strcmp(), but for dotted versions strings NN.NN.NN
|
||||||
|
* any number of terms are support.
|
||||||
|
* @return 0 if versions match, -ve number if v1 is lower, +ve if v1
|
||||||
|
* is greater
|
||||||
|
*/
|
||||||
|
int compare_versions(const std::string& v1, const std::string& v2);
|
||||||
} // end namespace strutils
|
} // end namespace strutils
|
||||||
} // end namespace simgear
|
} // end namespace simgear
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,16 @@ int main (int ac, char ** av)
|
|||||||
COMPARE(to_int("0000000"), 0);
|
COMPARE(to_int("0000000"), 0);
|
||||||
COMPARE(to_int("-10000"), -10000);
|
COMPARE(to_int("-10000"), -10000);
|
||||||
|
|
||||||
|
VERIFY(compare_versions("1.0.12", "1.1") < 0);
|
||||||
|
VERIFY(compare_versions("1.1", "1.0.12") > 0);
|
||||||
|
VERIFY(compare_versions("10.6.7", "10.6.7") == 0);
|
||||||
|
VERIFY(compare_versions("2.0", "2.0.99") < 0);
|
||||||
|
VERIFY(compare_versions("99", "99") == 0);
|
||||||
|
VERIFY(compare_versions("99", "98") > 0);
|
||||||
|
|
||||||
|
// since we compare numerically, leasing zeros shouldn't matter
|
||||||
|
VERIFY(compare_versions("0.06.7", "0.6.07") == 0);
|
||||||
|
|
||||||
cout << "all tests passed successfully!" << endl;
|
cout << "all tests passed successfully!" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1938,6 +1938,36 @@ struct Hash
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Convenience class for change listener callbacks without
|
||||||
|
* creating a derived class implementing a "valueChanged" method.
|
||||||
|
* Also removes listener on destruction automatically.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
class SGPropertyChangeCallback
|
||||||
|
: public SGPropertyChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SGPropertyChangeCallback(T* obj, void (T::*method)(SGPropertyNode*),
|
||||||
|
SGPropertyNode_ptr property,bool initial=false)
|
||||||
|
: _obj(obj), _callback(method), _property(property)
|
||||||
|
{
|
||||||
|
_property->addChangeListener(this,initial);
|
||||||
|
}
|
||||||
|
virtual ~SGPropertyChangeCallback()
|
||||||
|
{
|
||||||
|
_property->removeChangeListener(this);
|
||||||
|
}
|
||||||
|
void valueChanged (SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
(_obj->*_callback)(node);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
T* _obj;
|
||||||
|
void (T::*_callback)(SGPropertyNode*);
|
||||||
|
SGPropertyNode_ptr _property;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // __PROPS_HXX
|
#endif // __PROPS_HXX
|
||||||
|
|
||||||
// end of props.hxx
|
// end of props.hxx
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ SGModelPlacement::SGModelPlacement () :
|
|||||||
_selector(new osg::Switch),
|
_selector(new osg::Switch),
|
||||||
_transform(new osg::PositionAttitudeTransform)
|
_transform(new osg::PositionAttitudeTransform)
|
||||||
{
|
{
|
||||||
|
_selector->addChild(_transform.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
SGModelPlacement::~SGModelPlacement ()
|
SGModelPlacement::~SGModelPlacement ()
|
||||||
@@ -34,10 +35,11 @@ SGModelPlacement::~SGModelPlacement ()
|
|||||||
void
|
void
|
||||||
SGModelPlacement::init( osg::Node * model )
|
SGModelPlacement::init( osg::Node * model )
|
||||||
{
|
{
|
||||||
|
// remove previous model (in case of reinit)
|
||||||
|
_transform->removeChild(0,1);
|
||||||
if (model != 0) {
|
if (model != 0) {
|
||||||
_transform->addChild(model);
|
_transform->addChild(model);
|
||||||
}
|
}
|
||||||
_selector->addChild(_transform.get());
|
|
||||||
_selector->setValue(0, 1);
|
_selector->setValue(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,20 +110,24 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
|||||||
const CloudSprite& t = _cloudsprites[itr->idx];
|
const CloudSprite& t = _cloudsprites[itr->idx];
|
||||||
GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x,
|
GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x,
|
||||||
(GLfloat) t.texture_index_y/varieties_y,
|
(GLfloat) t.texture_index_y/varieties_y,
|
||||||
(GLfloat) t.width };
|
(GLfloat) t.width };
|
||||||
GLfloat ua2[3] = { (GLfloat) t.height,
|
GLfloat ua2[3] = { (GLfloat) t.height,
|
||||||
(GLfloat) t.shade,
|
(GLfloat) shade_factor,
|
||||||
(GLfloat) t.cloud_height };
|
(GLfloat) cloud_height };
|
||||||
|
GLfloat ua3[3] = { (GLfloat) bottom_factor,
|
||||||
|
(GLfloat) middle_factor,
|
||||||
|
(GLfloat) top_factor };
|
||||||
|
|
||||||
extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 );
|
extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 );
|
||||||
extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 );
|
extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 );
|
||||||
|
extensions->glVertexAttrib3fv(USR_ATTR_3, ua3 );
|
||||||
glColor4f(t.position.x(), t.position.y(), t.position.z(), zscale);
|
glColor4f(t.position.x(), t.position.y(), t.position.z(), zscale);
|
||||||
_geometry->draw(renderInfo);
|
_geometry->draw(renderInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
|
void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
|
||||||
float w, float h,
|
float w, float h, float cull)
|
||||||
float s, float cull, float cloud_height)
|
|
||||||
{
|
{
|
||||||
// Only add the sprite if it is further than the cull distance to all other sprites
|
// Only add the sprite if it is further than the cull distance to all other sprites
|
||||||
// except for the center sprite.
|
// except for the center sprite.
|
||||||
@@ -137,8 +141,8 @@ void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s, cloud_height));
|
_cloudsprites.push_back(CloudSprite(p, tx, ty, w, h));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||||
@@ -166,13 +170,13 @@ bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
|||||||
while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
|
while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
|
||||||
SGVec3f v;
|
SGVec3f v;
|
||||||
int tx, ty;
|
int tx, ty;
|
||||||
float w, h, s, ch;
|
float w, h;
|
||||||
if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
|
if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
|
||||||
&& fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&
|
&& fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&
|
||||||
fr[5].getFloat(w) && fr[6].getFloat(h)&& fr[7].getFloat(s) && fr[8].getFloat(ch)) {
|
fr[5].getFloat(w) && fr[6].getFloat(h)) {
|
||||||
fr += 5;
|
fr += 5;
|
||||||
//SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
|
//SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
|
||||||
geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s,ch));
|
geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h));
|
||||||
} else {
|
} else {
|
||||||
++fr;
|
++fr;
|
||||||
}
|
}
|
||||||
@@ -197,8 +201,7 @@ bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
|
|||||||
fw.indent() << itr->position.x() << " " << itr->position.y() << " "
|
fw.indent() << itr->position.x() << " " << itr->position.y() << " "
|
||||||
<< itr->position.z() << " " << itr->texture_index_x << " "
|
<< itr->position.z() << " " << itr->texture_index_x << " "
|
||||||
<< itr->texture_index_y << " " << itr->width << " "
|
<< itr->texture_index_y << " " << itr->width << " "
|
||||||
<< itr->height << " " << itr->shade
|
<< itr->height << " " << std::endl;
|
||||||
<< itr->cloud_height << " "<< std::endl;
|
|
||||||
}
|
}
|
||||||
fw.moveOut();
|
fw.moveOut();
|
||||||
fw.indent() << "}" << std::endl;
|
fw.indent() << "}" << std::endl;
|
||||||
|
|||||||
@@ -46,14 +46,15 @@ class CloudShaderGeometry : public osg::Drawable
|
|||||||
|
|
||||||
const static unsigned int USR_ATTR_1 = 10;
|
const static unsigned int USR_ATTR_1 = 10;
|
||||||
const static unsigned int USR_ATTR_2 = 11;
|
const static unsigned int USR_ATTR_2 = 11;
|
||||||
|
const static unsigned int USR_ATTR_3 = 12;
|
||||||
|
|
||||||
CloudShaderGeometry()
|
CloudShaderGeometry()
|
||||||
{
|
{
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudShaderGeometry(int vx, int vy, float width, float height, float zsc) :
|
CloudShaderGeometry(int vx, int vy, float width, float height, float ts, float ms, float bs, float shade, float ch, float zsc) :
|
||||||
varieties_x(vx), varieties_y(vy), zscale(zsc)
|
varieties_x(vx), varieties_y(vy), top_factor(ts), middle_factor(ms), bottom_factor(bs), shade_factor(shade), cloud_height(ch), zscale(zsc)
|
||||||
{
|
{
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
float x = width/2.0f;
|
float x = width/2.0f;
|
||||||
@@ -69,9 +70,8 @@ class CloudShaderGeometry : public osg::Drawable
|
|||||||
META_Object(flightgear, CloudShaderGeometry);
|
META_Object(flightgear, CloudShaderGeometry);
|
||||||
|
|
||||||
struct CloudSprite {
|
struct CloudSprite {
|
||||||
CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h,
|
CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h) :
|
||||||
float s, float ch) :
|
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h)
|
||||||
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s), cloud_height(ch)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
SGVec3f position;
|
SGVec3f position;
|
||||||
@@ -79,8 +79,6 @@ class CloudShaderGeometry : public osg::Drawable
|
|||||||
int texture_index_y;
|
int texture_index_y;
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
float shade;
|
|
||||||
float cloud_height;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<CloudSprite> CloudSpriteList;
|
typedef std::vector<CloudSprite> CloudSpriteList;
|
||||||
@@ -88,8 +86,8 @@ class CloudShaderGeometry : public osg::Drawable
|
|||||||
|
|
||||||
void insert(const CloudSprite& t)
|
void insert(const CloudSprite& t)
|
||||||
{ _cloudsprites.push_back(t); }
|
{ _cloudsprites.push_back(t); }
|
||||||
void insert(SGVec3f& p, int tx, int ty, float w, float h, float s, float ch)
|
void insert(SGVec3f& p, int tx, int ty, float w, float h)
|
||||||
{ insert(CloudSprite(p, tx, ty, w, h, s, ch)); }
|
{ insert(CloudSprite(p, tx, ty, w, h)); }
|
||||||
|
|
||||||
unsigned getNumCloudSprite() const
|
unsigned getNumCloudSprite() const
|
||||||
{ return _cloudsprites.size(); }
|
{ return _cloudsprites.size(); }
|
||||||
@@ -107,15 +105,19 @@ class CloudShaderGeometry : public osg::Drawable
|
|||||||
_geometry = geometry;
|
_geometry = geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addSprite(const SGVec3f& p, int tx, int ty, float w, float h,
|
void addSprite(const SGVec3f& p, int tx, int ty, float w, float h, float cull);
|
||||||
float s, float cull, float cloud_height);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Drawable> _geometry;
|
osg::ref_ptr<osg::Drawable> _geometry;
|
||||||
|
|
||||||
int varieties_x;
|
int varieties_x;
|
||||||
int varieties_y;
|
int varieties_y;
|
||||||
|
float top_factor;
|
||||||
|
float middle_factor;
|
||||||
|
float bottom_factor;
|
||||||
|
float shade_factor;
|
||||||
|
float cloud_height;
|
||||||
float zscale;
|
float zscale;
|
||||||
|
|
||||||
// Bounding box extents.
|
// Bounding box extents.
|
||||||
osg::BoundingBox _bbox;
|
osg::BoundingBox _bbox;
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
|||||||
float lon, float lat, float alt, float x, float y) {
|
float lon, float lat, float alt, float x, float y) {
|
||||||
|
|
||||||
// Get the base position
|
// Get the base position
|
||||||
SGGeod loc = SGGeod::fromDegFt(lon, lat, alt);
|
SGGeod loc = SGGeod::fromDegFt(lon, lat, 0.0);
|
||||||
|
|
||||||
// Determine any shift by x/y
|
// Determine any shift by x/y
|
||||||
if ((x != 0.0f) || (y != 0.0f)) {
|
if ((x != 0.0f) || (y != 0.0f)) {
|
||||||
@@ -248,24 +248,24 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
|||||||
|
|
||||||
SGGeod base_pos = SGGeod::fromDegFt(lon, lat, 0.0f);
|
SGGeod base_pos = SGGeod::fromDegFt(lon, lat, 0.0f);
|
||||||
SGGeodesy::direct(base_pos, crs, dst, loc, endcrs);
|
SGGeodesy::direct(base_pos, crs, dst, loc, endcrs);
|
||||||
|
|
||||||
// The direct call provides the position at 0 alt, so adjust as required.
|
|
||||||
loc.setElevationFt(alt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The direct call provides the position at 0 alt, so adjust as required.
|
||||||
|
loc.setElevationFt(alt);
|
||||||
|
|
||||||
// Work out where this cloud should go in OSG coordinates.
|
// Work out where this cloud should go in OSG coordinates.
|
||||||
SGVec3<double> cart;
|
SGVec3<double> cart;
|
||||||
SGGeodesy::SGGeodToCart(loc, cart);
|
SGGeodesy::SGGeodToCart(loc, cart);
|
||||||
osg::Vec3f pos = toOsg(cart);
|
osg::Vec3f pos = toOsg(cart);
|
||||||
|
|
||||||
// Convert to the scenegraph orientation where we just rotate around
|
|
||||||
// the y axis 180 degrees.
|
|
||||||
osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
|
|
||||||
|
|
||||||
if (old_pos == osg::Vec3f(0.0f, 0.0f, 0.0f)) {
|
if (old_pos == osg::Vec3f(0.0f, 0.0f, 0.0f)) {
|
||||||
// First se tup.
|
// First setup.
|
||||||
SGVec3<double> fieldcenter;
|
SGVec3<double> fieldcenter;
|
||||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(lon, lat, 0.0f), fieldcenter);
|
SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(loc.getLongitudeDeg(), loc.getLatitudeDeg(), 0.0f), fieldcenter);
|
||||||
|
// Convert to the scenegraph orientation where we just rotate around
|
||||||
|
// the y axis 180 degrees.
|
||||||
|
osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(loc.getLongitudeDeg(), loc.getLatitudeDeg()) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
|
||||||
|
|
||||||
field_transform->setPosition(toOsg(fieldcenter));
|
field_transform->setPosition(toOsg(fieldcenter));
|
||||||
field_transform->setAttitude(orient);
|
field_transform->setAttitude(orient);
|
||||||
@@ -274,7 +274,8 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
|||||||
|
|
||||||
pos = pos - field_transform->getPosition();
|
pos = pos - field_transform->getPosition();
|
||||||
|
|
||||||
pos = orient.inverse() * pos;
|
//pos = orient.inverse() * pos;
|
||||||
|
pos = field_transform->getAttitude().inverse() * pos;
|
||||||
|
|
||||||
// We have a two level dynamic quad tree which the cloud will be added
|
// We have a two level dynamic quad tree which the cloud will be added
|
||||||
// to. If there are no appropriate nodes in the quad tree, they are
|
// to. If there are no appropriate nodes in the quad tree, they are
|
||||||
|
|||||||
@@ -60,6 +60,8 @@
|
|||||||
|
|
||||||
using namespace simgear;
|
using namespace simgear;
|
||||||
using namespace osg;
|
using namespace osg;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -67,24 +69,36 @@ typedef std::map<std::string, osg::ref_ptr<Effect> > EffectMap;
|
|||||||
EffectMap effectMap;
|
EffectMap effectMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
double SGNewCloud::sprite_density = 1.0;
|
float SGNewCloud::sprite_density = 1.0;
|
||||||
|
|
||||||
SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def)
|
SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def)
|
||||||
{
|
{
|
||||||
min_width = cld_def->getDoubleValue("min-cloud-width-m", 500.0);
|
min_width = cld_def->getFloatValue("min-cloud-width-m", 500.0);
|
||||||
max_width = cld_def->getDoubleValue("max-cloud-width-m", min_width*2);
|
max_width = cld_def->getFloatValue("max-cloud-width-m", min_width*2);
|
||||||
min_height = cld_def->getDoubleValue("min-cloud-height-m", 400.0);
|
min_height = cld_def->getFloatValue("min-cloud-height-m", 400.0);
|
||||||
max_height = cld_def->getDoubleValue("max-cloud-height-m", min_height*2);
|
max_height = cld_def->getFloatValue("max-cloud-height-m", min_height*2);
|
||||||
min_sprite_width = cld_def->getDoubleValue("min-sprite-width-m", 200.0);
|
min_sprite_width = cld_def->getFloatValue("min-sprite-width-m", 200.0);
|
||||||
max_sprite_width = cld_def->getDoubleValue("max-sprite-width-m", min_sprite_width*1.5);
|
max_sprite_width = cld_def->getFloatValue("max-sprite-width-m", min_sprite_width*1.5);
|
||||||
min_sprite_height = cld_def->getDoubleValue("min-sprite-height-m", 150);
|
min_sprite_height = cld_def->getFloatValue("min-sprite-height-m", 150);
|
||||||
max_sprite_height = cld_def->getDoubleValue("max-sprite-height-m", min_sprite_height*1.5);
|
max_sprite_height = cld_def->getFloatValue("max-sprite-height-m", min_sprite_height*1.5);
|
||||||
num_sprites = cld_def->getIntValue("num-sprites", 20);
|
num_sprites = cld_def->getIntValue("num-sprites", 20);
|
||||||
num_textures_x = cld_def->getIntValue("num-textures-x", 4);
|
num_textures_x = cld_def->getIntValue("num-textures-x", 4);
|
||||||
num_textures_y = cld_def->getIntValue("num-textures-y", 4);
|
num_textures_y = cld_def->getIntValue("num-textures-y", 4);
|
||||||
height_map_texture = cld_def->getBoolValue("height-map-texture", false);
|
height_map_texture = cld_def->getBoolValue("height-map-texture", false);
|
||||||
bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0);
|
|
||||||
zscale = cld_def->getDoubleValue("z-scale", 1.0);
|
min_bottom_lighting_factor = cld_def->getFloatValue("min-bottom-lighting-factor", 1.0);
|
||||||
|
max_bottom_lighting_factor = cld_def->getFloatValue("max-bottom-lighting-factor", min(min_bottom_lighting_factor + 0.1, 1.0));
|
||||||
|
|
||||||
|
min_middle_lighting_factor = cld_def->getFloatValue("min-middle-lighting-factor", 1.0);
|
||||||
|
max_middle_lighting_factor = cld_def->getFloatValue("max-middle-lighting-factor", min(min_middle_lighting_factor + 0.1, 1.0));
|
||||||
|
|
||||||
|
min_top_lighting_factor = cld_def->getFloatValue("min-top-lighting-factor", 1.0);
|
||||||
|
max_top_lighting_factor = cld_def->getFloatValue("max-top-lighting-factor", min(min_top_lighting_factor + 0.1, 1.0));
|
||||||
|
|
||||||
|
min_shade_lighting_factor = cld_def->getFloatValue("min-shade-lighting-factor", 0.5);
|
||||||
|
max_shade_lighting_factor = cld_def->getFloatValue("max-shade-lighting-factor", min(min_shade_lighting_factor + 0.1, 1.0));
|
||||||
|
|
||||||
|
zscale = cld_def->getFloatValue("z-scale", 1.0);
|
||||||
texture = cld_def->getStringValue("texture", "cl_cumulus.png");
|
texture = cld_def->getStringValue("texture", "cl_cumulus.png");
|
||||||
|
|
||||||
// Create a new Effect for the texture, if required.
|
// Create a new Effect for the texture, if required.
|
||||||
@@ -167,24 +181,40 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
|||||||
|
|
||||||
osg::ref_ptr<EffectGeode> geode = new EffectGeode;
|
osg::ref_ptr<EffectGeode> geode = new EffectGeode;
|
||||||
|
|
||||||
CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x,
|
|
||||||
num_textures_y,
|
|
||||||
max_width + max_sprite_width,
|
|
||||||
max_height + max_sprite_height,
|
|
||||||
zscale);
|
|
||||||
|
|
||||||
// Determine how big this specific cloud instance is. Note that we subtract
|
// Determine how big this specific cloud instance is. Note that we subtract
|
||||||
// the sprite size because the width/height is used to define the limits of
|
// the sprite size because the width/height is used to define the limits of
|
||||||
// the center of the sprites, not their edges.
|
// the center of the sprites, not their edges.
|
||||||
float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width;
|
float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width;
|
||||||
float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height;
|
float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height;
|
||||||
|
|
||||||
|
if (width < 0.0) { width = 0.0; }
|
||||||
|
if (height < 0.0) { height = 0.0; }
|
||||||
|
|
||||||
|
// Determine appropriate shading factors
|
||||||
|
float top_factor = min_top_lighting_factor + sg_random() * (max_top_lighting_factor - min_top_lighting_factor);
|
||||||
|
float middle_factor = min_middle_lighting_factor + sg_random() * (max_middle_lighting_factor - min_middle_lighting_factor);
|
||||||
|
float bottom_factor = min_bottom_lighting_factor + sg_random() * (max_bottom_lighting_factor - min_bottom_lighting_factor);
|
||||||
|
float shade_factor = min_shade_lighting_factor + sg_random() * (max_shade_lighting_factor - min_shade_lighting_factor);
|
||||||
|
|
||||||
|
//printf("Cloud: %2f, %2f, %2f, %2f\n", top_factor, middle_factor, bottom_factor, shade_factor);
|
||||||
|
|
||||||
|
CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x,
|
||||||
|
num_textures_y,
|
||||||
|
max_width + max_sprite_width,
|
||||||
|
max_height + max_sprite_height,
|
||||||
|
top_factor,
|
||||||
|
middle_factor,
|
||||||
|
bottom_factor,
|
||||||
|
shade_factor,
|
||||||
|
height,
|
||||||
|
zscale);
|
||||||
|
|
||||||
// Determine the cull distance. This is used to remove sprites that are too close together.
|
// Determine the cull distance. This is used to remove sprites that are too close together.
|
||||||
// The value is squared as we use vector calculations.
|
// The value is squared as we use vector calculations.
|
||||||
float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f;
|
float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f;
|
||||||
|
|
||||||
// The number of sprites we actually use is a function of the (user-controlled) density
|
// The number of sprites we actually use is a function of the (user-controlled) density
|
||||||
int n_sprites = num_sprites * sprite_density * (0.5 + sg_random());
|
int n_sprites = num_sprites * sprite_density * (0.5f + sg_random());
|
||||||
|
|
||||||
for (int i = 0; i < n_sprites; i++)
|
for (int i = 0; i < n_sprites; i++)
|
||||||
{
|
{
|
||||||
@@ -202,8 +232,8 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
|||||||
y = 0;
|
y = 0;
|
||||||
z = height * 0.5;
|
z = height * 0.5;
|
||||||
} else {
|
} else {
|
||||||
double theta = sg_random() * SGD_2PI;
|
float theta = sg_random() * SGD_2PI;
|
||||||
double elev = sg_random() * SGD_PI;
|
float elev = sg_random() * SGD_PI;
|
||||||
x = width * cos(theta) * 0.5f * sin(elev);
|
x = width * cos(theta) * 0.5f * sin(elev);
|
||||||
y = width * sin(theta) * 0.5f * sin(elev);
|
y = width * sin(theta) * 0.5f * sin(elev);
|
||||||
z = height * cos(elev) * 0.5f + height * 0.5f;
|
z = height * cos(elev) * 0.5f + height * 0.5f;
|
||||||
@@ -235,7 +265,7 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
|||||||
|
|
||||||
// Determine the sprite texture indexes.
|
// Determine the sprite texture indexes.
|
||||||
int index_x = (int) floor(sg_random() * num_textures_x);
|
int index_x = (int) floor(sg_random() * num_textures_x);
|
||||||
if (index_x == num_textures_x) { index_x--; }
|
if (index_x >= num_textures_x) { index_x = num_textures_x - 1; }
|
||||||
|
|
||||||
int index_y = (int) floor(sg_random() * num_textures_y);
|
int index_y = (int) floor(sg_random() * num_textures_y);
|
||||||
|
|
||||||
@@ -243,20 +273,17 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
|||||||
// The y index depends on the position of the sprite within the cloud.
|
// The y index depends on the position of the sprite within the cloud.
|
||||||
// This allows cloud designers to have particular sprites for the base
|
// This allows cloud designers to have particular sprites for the base
|
||||||
// and tops of the cloud.
|
// and tops of the cloud.
|
||||||
index_y = (int) floor((z / height + 0.5f) * num_textures_y);
|
index_y = (int) floor((z / height) * num_textures_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index_y == num_textures_y) { index_y--; }
|
if (index_y >= num_textures_y) { index_y = num_textures_y - 1; }
|
||||||
|
|
||||||
|
|
||||||
sg->addSprite(SGVec3f(x, y, z),
|
sg->addSprite(SGVec3f(x, y, z),
|
||||||
index_x,
|
index_x,
|
||||||
index_y,
|
index_y,
|
||||||
sprite_width,
|
sprite_width,
|
||||||
sprite_height,
|
sprite_height,
|
||||||
bottom_shade,
|
cull_distance_squared);
|
||||||
cull_distance_squared,
|
|
||||||
height * 0.5f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sg->setGeometry(quad);
|
sg->setGeometry(quad);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
// Generate a Cloud
|
// Generate a Cloud
|
||||||
osg::ref_ptr<simgear::EffectGeode> genCloud ();
|
osg::ref_ptr<simgear::EffectGeode> genCloud ();
|
||||||
|
|
||||||
static double getDensity(void)
|
static float getDensity(void)
|
||||||
{
|
{
|
||||||
return sprite_density;
|
return sprite_density;
|
||||||
}
|
}
|
||||||
@@ -61,16 +61,37 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
double min_width;
|
float min_width;
|
||||||
double max_width;
|
float max_width;
|
||||||
double min_height;
|
float min_height;
|
||||||
double max_height;
|
float max_height;
|
||||||
double min_sprite_width;
|
float min_sprite_width;
|
||||||
double max_sprite_width;
|
float max_sprite_width;
|
||||||
double min_sprite_height;
|
float min_sprite_height;
|
||||||
double max_sprite_height;
|
float max_sprite_height;
|
||||||
double bottom_shade;
|
|
||||||
double zscale;
|
// Minimum and maximum bottom, middle, top, sunny, shade lighting
|
||||||
|
// factors. For individual clouds we choose a bottom/middle/top
|
||||||
|
// shade from between each min/max value
|
||||||
|
float min_bottom_lighting_factor;
|
||||||
|
float max_bottom_lighting_factor;
|
||||||
|
float min_middle_lighting_factor;
|
||||||
|
float max_middle_lighting_factor;
|
||||||
|
float min_top_lighting_factor;
|
||||||
|
float max_top_lighting_factor;
|
||||||
|
float min_shade_lighting_factor;
|
||||||
|
float max_shade_lighting_factor;
|
||||||
|
|
||||||
|
// The density of the cloud is the shading applied
|
||||||
|
// to cloud sprites on the opposite side of the cloud
|
||||||
|
// from the sun. For an invidual cloud instance a value
|
||||||
|
// between min_density and max_density is chosen.
|
||||||
|
float min_density;
|
||||||
|
float max_density;
|
||||||
|
|
||||||
|
// zscale indicates how sprites should be scaled vertically
|
||||||
|
// after billboarding.
|
||||||
|
float zscale;
|
||||||
bool height_map_texture;
|
bool height_map_texture;
|
||||||
int num_sprites;
|
int num_sprites;
|
||||||
int num_textures_x;
|
int num_textures_x;
|
||||||
@@ -78,7 +99,7 @@ private:
|
|||||||
string texture;
|
string texture;
|
||||||
osg::Geometry* quad;
|
osg::Geometry* quad;
|
||||||
osg::ref_ptr<simgear::Effect> effect;
|
osg::ref_ptr<simgear::Effect> effect;
|
||||||
static double sprite_density;
|
static float sprite_density;
|
||||||
|
|
||||||
osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y);
|
osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y);
|
||||||
|
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ struct AddTreesLeafObject
|
|||||||
{
|
{
|
||||||
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
||||||
{
|
{
|
||||||
Geode* geode = static_cast<Geode*>(lod->getChild(rand() % SG_TREE_FADE_OUT_LEVELS));
|
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
||||||
addTreeToLeafGeode(geode, tree.position);
|
addTreeToLeafGeode(geode, tree.position);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace simgear;
|
using namespace simgear;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
const char* rsync_cmd =
|
const char* rsync_cmd =
|
||||||
"rsync --verbose --archive --delete --perms --owner --group";
|
"rsync --verbose --archive --delete --perms --owner --group";
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ protected:
|
|||||||
void syncAirportsModels();
|
void syncAirportsModels();
|
||||||
void syncArea(int lat, int lon);
|
void syncArea(int lat, int lon);
|
||||||
void syncAreas(int lat, int lon, int lat_dir, int lon_dir);
|
void syncAreas(int lat, int lon, int lat_dir, int lon_dir);
|
||||||
void refreshScenery(SGPath path,const string& relativeDir);
|
void refreshScenery(SGPath path,const std::string& relativeDir);
|
||||||
|
|
||||||
class SvnThread;
|
class SvnThread;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#cmakedefine HAVE_TIMEGM
|
#cmakedefine HAVE_TIMEGM
|
||||||
#cmakedefine HAVE_ISNAN
|
#cmakedefine HAVE_ISNAN
|
||||||
#cmakedefine HAVE_WINDOWS_H
|
#cmakedefine HAVE_WINDOWS_H
|
||||||
|
#cmakedefine HAVE_MKDTEMP
|
||||||
|
|
||||||
#cmakedefine HAVE_SVN_CLIENT_H
|
#cmakedefine HAVE_SVN_CLIENT_H
|
||||||
#cmakedefine HAVE_LIBSVN_CLIENT_1
|
#cmakedefine HAVE_LIBSVN_CLIENT_1
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
extern bool isNaN(float *v);
|
extern bool isNaN(float *v);
|
||||||
|
|
||||||
|
|||||||
@@ -1248,7 +1248,7 @@ namespace simgear
|
|||||||
ConvertExpression() {}
|
ConvertExpression() {}
|
||||||
ConvertExpression(::SGExpression<OpType>* expr0)
|
ConvertExpression(::SGExpression<OpType>* expr0)
|
||||||
{
|
{
|
||||||
addOperand(expr0);
|
this->addOperand(expr0);
|
||||||
}
|
}
|
||||||
virtual void eval(T& value, const simgear::expression::Binding* b) const
|
virtual void eval(T& value, const simgear::expression::Binding* b) const
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user