/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */ #include "stdafx.h" #include "V8DataModel/Surface.h" #include "V8DataModel/PartInstance.h" #include "V8World/Primitive.h" #include "Util/Hash.h" DYNAMIC_FASTFLAGVARIABLE(UseRemoveTypeIDTricks,true) namespace RBX { //////////////////////////////////////////////////////////////// // // Surface Surface::Surface( PartInstance* partInstance, NormalId surfId ) : partInstance(partInstance) , surfId(surfId) { } Surface::Surface() : partInstance(NULL), surfId(NORM_X) { } Surface::Surface(const Surface& lhs) : partInstance(lhs.partInstance), surfId(lhs.surfId) { } SurfaceType Surface::getSurfaceType() const { return partInstance->getSurfaceType(surfId); } void Surface::setSurfaceType(SurfaceType type) { partInstance->setSurfaceType(surfId, type); } LegacyController::InputType Surface::getInput() const { return partInstance->getInput(surfId); } void Surface::setSurfaceInput(RBX::LegacyController::InputType value) { partInstance->setSurfaceInput(surfId, value); } float Surface::getParamA() const { return partInstance->getParamA(surfId); } float Surface::getParamB() const { return partInstance->getParamB(surfId); } void Surface::setParamA(float value) { partInstance->setParamA(surfId, value); } void Surface::setParamB(float value) { partInstance->setParamB(surfId, value); } void Surface::toggleSurfaceType() { if (this->getSurfaceType() == NO_SURFACE) { this->setSurfaceType(GLUE); } else { this->setSurfaceType(NO_SURFACE); } } void Surface::flat() { setSurfaceType(NO_SURFACE); setSurfaceInput(SurfaceData::empty().inputType); setParamA(SurfaceData::empty().paramA); setParamB(SurfaceData::empty().paramB); } namespace Reflection { template<> const Type& Type::getSingleton() { static TType type("Surface", "Complex"); return type; } }//namespace Reflection template class SurfaceGetSet : public Reflection::TypedPropertyDescriptor::GetSet { Get get; Set set; public: SurfaceGetSet(Get get, Set set):get(get),set(set) {} virtual bool isReadOnly() const { return false; } virtual bool isWriteOnly() const { return false; } virtual V getValue(const Reflection::DescribedBase* instance) const { if (DFFlag::UseRemoveTypeIDTricks) { debugAssertM(dynamic_cast(instance)!=NULL, instance->getClassName().toString()); } else { debugAssertM(dynamic_cast(instance)!=NULL, typeid(*instance).name()); } //return (static_cast(instance)->getSurfaces()[face].*get)(); const PartInstance* part = static_cast(instance); return ((*part).*get)(face); } virtual void setValue(Reflection::DescribedBase* instance, const V& value) const { if (DFFlag::UseRemoveTypeIDTricks) { debugAssertM(dynamic_cast(instance)!=NULL, instance->getClassName().toString()); } else { debugAssertM(dynamic_cast(instance)!=NULL, typeid(*instance).name()); } //(static_cast(instance)->getSurfaces()[face].*set)(value); PartInstance* part = static_cast(instance); ((*part).*set)(face, value); } }; // Specialized PropertyDescriptor use for referencing Surface Poperties of a PartInstance // TODO: When we refactor Surface to be an Instance then this class can melt away (or be used for legacy reading only) template class SurfacePropDescriptor : public Reflection::TypedPropertyDescriptor { public: template SurfacePropDescriptor(const char* name, const char* category, Get get, Set set, RBX::Reflection::PropertyDescriptor::Functionality flags = RBX::Reflection::PropertyDescriptor::STANDARD, Security::Permissions security = Security::None) :Reflection::TypedPropertyDescriptor( PartInstance::classDescriptor(), name, category, std::auto_ptr::GetSet>(new SurfaceGetSet(get, set)), flags, security ) { } }; // TODO: This is almost identical to EnumPropDescriptor. Perhaps we could use a Functor of some kind // to make the GetFunc/SetFunc more generic. Then we could insert the "getSurfaces()[face]." bit into // a common class. template class SurfaceEnumPropDescriptor : public Reflection::EnumPropertyDescriptor { std::auto_ptr::GetSet> getset; public: template SurfaceEnumPropDescriptor(const char* name, const char* category, Get get, Set set, Functionality flags = STANDARD) :Reflection::EnumPropertyDescriptor(PartInstance::classDescriptor(), Reflection::EnumDesc::singleton(), name, category, flags) ,getset(new SurfaceGetSet(get, set)) {} virtual bool isReadOnly() const { return getset->isReadOnly(); } virtual bool isWriteOnly() const { return getset->isWriteOnly(); } /*implement*/ void get(const Reflection::DescribedBase* instance, Reflection::Variant& value) const { value = getset->getValue(instance); } /*implement*/ void set(Reflection::DescribedBase* instance, const Reflection::Variant& value) const { // TODO: This might be inefficient. How is the value stored in getset??? getset->setValue(instance, value.get()); } V getValue(const Reflection::DescribedBase* object) const { return getset->getValue(object); } /*implement*/ void getVariant(const Reflection::DescribedBase* instance, Reflection::Variant& value) const { value = getset->getValue(instance); } /*implement*/ void setVariant(Reflection::DescribedBase* instance, const Reflection::Variant& value) const { // TODO: This might be inefficient. How is the value stored in getset??? getset->setValue(instance, value.get()); } void setValue(Reflection::DescribedBase* object, const V& value) const { getset->setValue(object, value); } /*implement*/ void copyValue(const Reflection::DescribedBase* source, Reflection::DescribedBase* destination) const { setValue(destination, getValue(source)); } /*implement*/ const Reflection::EnumDescriptor::Item* getEnumItem(const Reflection::DescribedBase* instance) const { const Reflection::EnumDescriptor::Item* result = Reflection::EnumDesc::singleton().convertToItem(getValue(instance)); return result; } /*implement*/ bool equalValues(const Reflection::DescribedBase* a, const Reflection::DescribedBase* b) const { return getValue(a) == getValue(b); } /*implement*/ int getEnumValue(const Reflection::DescribedBase* instance) const { return (int) getValue(instance); } /*implement*/ bool setEnumValue(Reflection::DescribedBase* instance, int intValue) const { if (Reflection::EnumDesc::singleton().isValue(intValue)) { setValue(instance, (V) intValue); return true; } else return false; } virtual size_t getIndexValue(const Reflection::DescribedBase* instance) const { return Reflection::EnumDesc::singleton().convertToIndex(getValue(instance)); } virtual bool setIndexValue(Reflection::DescribedBase* instance, size_t index) const { V value; if (Reflection::EnumDesc::singleton().convertToValue(index, value)) { setValue(instance, value); return true; } else return false; } // PropertyDescriptor implementation: virtual bool hasStringValue() const { return true; } virtual std::string getStringValue(const Reflection::DescribedBase* instance) const { return Reflection::EnumDesc::singleton().convertToString(getValue(instance)); } virtual bool setStringValue(Reflection::DescribedBase* instance, const std::string& text) const { V value; if (Reflection::EnumDesc::singleton().convertToValue(text.c_str(), value)) { setValue(instance, value); return true; } else return false; } // An alternate, more efficient version of setStringValue virtual bool setStringValue(Reflection::DescribedBase* instance, const RBX::Name& name) const { V value; if (Reflection::EnumDesc::singleton().convertToValue(name, value)) { setValue(instance, value); return true; } else return false; } virtual void readValue(Reflection::DescribedBase* instance, const XmlElement* element, RBX::IReferenceBinder& binder) const { if (!element->isXsiNil()) { if (element->isValueType()) { // Legacy code to handle files older than 10/29/05 // TODO: Opt: Remove this legacy code sometime? It slows text XML down a bit std::string sValue; if (element->getValue(sValue)) { V e; if (Reflection::EnumDesc::singleton().convertToValue(sValue.c_str(), e)) { setValue(instance, e); return; } } } int value; if (element->getValue(value)) { setValue(instance, static_cast(value)); return; } RBXASSERT(false); } } virtual void writeValue(const Reflection::DescribedBase* instance, XmlElement* element) const { element->setValue(static_cast(getValue(instance))); } }; namespace Reflection { template<> SurfaceType& Variant::convert(void) { return genericConvert(); } template<> LegacyController::InputType& Variant::convert(void) { return genericConvert(); } }//namespace Reflection template<> bool StringConverter::convertToValue(const std::string& text, SurfaceType& value) { return false; } template<> bool StringConverter::convertToValue(const std::string& text, LegacyController::InputType& value) { return false; } static SurfaceEnumPropDescriptor desc_TopType("TopSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_TopSurfaceInput("TopSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_TopParamA("TopParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_TopParamB("TopParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); static SurfaceEnumPropDescriptor desc_BottomType("BottomSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_BottomSurfaceInput("BottomSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_BottomParamA("BottomParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_BottomParamB("BottomParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); static SurfaceEnumPropDescriptor desc_LeftType("LeftSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_LeftSurfaceInput("LeftSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_LeftParamA("LeftParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_LeftParamB("LeftParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); static SurfaceEnumPropDescriptor desc_RightType("RightSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_RightSurfaceInput("RightSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_RightParamA("RightParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_RightParamB("RightParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); static SurfaceEnumPropDescriptor desc_FrontType("FrontSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_FrontSurfaceInput("FrontSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_FrontParamA("FrontParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_FrontParamB("FrontParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); static SurfaceEnumPropDescriptor desc_BackType("BackSurface", "Surface", &PartInstance::getSurfaceType, &PartInstance::setSurfaceType); static SurfaceEnumPropDescriptor desc_BackSurfaceInput("BackSurfaceInput", "Surface Inputs", &PartInstance::getInput, &PartInstance::setSurfaceInput); static SurfacePropDescriptor desc_BackParamA("BackParamA", "Surface Inputs", &PartInstance::getParamA, &PartInstance::setParamA); static SurfacePropDescriptor desc_BackParamB("BackParamB", "Surface Inputs", &PartInstance::getParamB, &PartInstance::setParamB); RBX_REGISTER_TYPE(RBX::Surface); // This is already getting registered as an Enum in Factory Registration.cpp // Enum also registers is as Type, so following is not required, complains as duplicate symbols on gcc //RBX_REGISTER_TYPE(RBX::SurfaceType); void Surface::registerSurfaceDescriptors() { // Simply being here causes the descriptors to load } bool Surface::isSurfaceDescriptor(const Reflection::PropertyDescriptor& desc) { if (desc==desc_TopType) return true; if (desc==desc_BottomType) return true; if (desc==desc_LeftType) return true; if (desc==desc_RightType) return true; if (desc==desc_FrontType) return true; if (desc==desc_BackType) return true; return false; } const Reflection::PropertyDescriptor& Surface::getSurfaceTypeStatic(NormalId face) { switch (face) { default: RBXASSERT(false); case NORM_Y: return desc_TopType; case NORM_Y_NEG: return desc_BottomType; case NORM_Z: return desc_BackType; case NORM_Z_NEG: return desc_FrontType; case NORM_X: return desc_RightType; case NORM_X_NEG: return desc_LeftType; } } const Reflection::PropertyDescriptor& Surface::getSurfaceInputStatic(NormalId face) { switch (face) { default: RBXASSERT(false); case NORM_Y: return desc_TopSurfaceInput; case NORM_Y_NEG: return desc_BottomSurfaceInput; case NORM_Z: return desc_BackSurfaceInput; case NORM_Z_NEG: return desc_FrontSurfaceInput; case NORM_X: return desc_RightSurfaceInput; case NORM_X_NEG: return desc_LeftSurfaceInput; } } const Reflection::PropertyDescriptor& Surface::getParamAStatic(NormalId face) { switch (face) { default: RBXASSERT(false); case NORM_Y: return desc_TopParamA; case NORM_Y_NEG: return desc_BottomParamA; case NORM_Z: return desc_BackParamA; case NORM_Z_NEG: return desc_FrontParamA; case NORM_X: return desc_RightParamA; case NORM_X_NEG: return desc_LeftParamA; } } const Reflection::PropertyDescriptor& Surface::getParamBStatic(NormalId face) { switch (face) { default: RBXASSERT(false); case NORM_Y: return desc_TopParamB; case NORM_Y_NEG: return desc_BottomParamB; case NORM_Z: return desc_BackParamB; case NORM_Z_NEG: return desc_FrontParamB; case NORM_X: return desc_RightParamB; case NORM_X_NEG: return desc_LeftParamB; } } } // namespace