Framework.Design
Microsoft.Xna.Framework.Design is the one XNA 4.0 namespace that earlier versions of this site listed as the “only namespace CNA does not cover”. In this snapshot it exists: CNA implements it as the opt-in CNA::Design module, thirteen public types that convert XNA math value types to and from text, expose their components as property descriptors, and describe how to rebuild a value. This page documents exactly what is there, how to link it, how it behaves, and what it deliberately is not.
What this module is — and is not. In XNA these classes are the TypeConverters that the Visual Studio / Windows Forms property grid uses to show and edit a Vector3 or a Color. CNA implements the converter half on top of Sharp Runtime’s System::ComponentModel. It has no property-grid UI, no CodeDOM serialization and no general .NET reflection — CNA’s own notes list those as out of scope. What you get is a small, culture-aware parse/format facility for math values that is useful in tools and data files.
The thirteen types
All twelve concrete converters derive from MathTypeConverter, which derives from System::ComponentModel::ExpandableObjectConverter (XNA’s hierarchy is TypeConverter → ExpandableObjectConverter → MathTypeConverter → concrete converter). Every one of them exposes its components as property descriptors, supports CreateInstance, and converts to an executable InstanceDescriptor.
| Converter | Converts | Properties exposed, in order | Parses a string? |
|---|---|---|---|
MathTypeConverter | (base class) | set by the derived converter | String input enabled by default |
PointConverter | Point | X, Y (ints) | Yes |
RectangleConverter | Rectangle | X, Y, Width, Height (ints) | No |
Vector2Converter | Vector2 | X, Y | Yes |
Vector3Converter | Vector3 | X, Y, Z | Yes |
Vector4Converter | Vector4 | X, Y, Z, W | Yes |
QuaternionConverter | Quaternion | X, Y, Z, W | Yes |
MatrixConverter | Matrix | Translation, then M11 through M44 row-major | No |
ColorConverter | Color | R, G, B, A (bytes, 0–255) | Yes |
BoundingBoxConverter | BoundingBox | Min, Max | No |
BoundingSphereConverter | BoundingSphere | Center, Radius | No |
PlaneConverter | Plane | Normal, D | No |
RayConverter | Ray | Position, Direction | No |
The headers are under modules/design/include/Microsoft/Xna/Framework/Design/, plus the umbrella Microsoft/Xna/Framework/Design.hpp. The inventory matches the public types Microsoft’s own assembly documents; CNA’s notes record that no further public Design types exist in XNA 4.0 (three property-descriptor helper classes in the Microsoft assembly are non-public, and CNA likewise keeps its descriptor implementations internal).
Build and link: an opt-in target
The module is declared with cna_add_module(cna_design Design ...), so the CMake target is cna_design with the alias CNA::Design. It is a static library that links CNA::Math and Sharp Runtime’s ComponentModel component and nothing else — CNA’s own link-closure probe (probe_design, registered in cmake/Tests/ModuleProbes.cmake) checks that the closure has no runtime, renderer, SDL, media or networking dependency.
It is not part of the CNA umbrella target. The umbrella comment is explicit: tooling-only CNA::Design stays opt-in so that converter registration and ComponentModel code do not enter games that never use them. There is no CMake option to switch it on: the subdirectory is always added, and you opt in by linking the target.
# Tools, editors, importers or data loaders that want the converters:
target_link_libraries(my_tool PRIVATE CNA::Design)
# A game that also renders links the umbrella as usual and adds Design only if it needs it:
target_link_libraries(my_game PRIVATE CNA CNA::Design)
CNA’s C++ framework has no general install/export package, so a consumer reaches CNA::Design the same way it reaches CNA: through add_subdirectory of the CNA checkout (see Tutorial 03), with sharp-runtime on its next branch beside it. Tutorial 140 builds a complete example that links only CNA::Design.
Registration is automatic
You do not call a registration function. Every converter header includes CNA/Internal/Design/Registration.hpp, which defines an inline variable whose initializer runs EnsureFrameworkDesignConvertersRegistered(). That function, guarded by std::call_once, associates each of the twelve value types with its converter factory through TypeDescriptor::RegisterType (modules/design/src/Registration.cpp). The practical rule: include a Design header (the umbrella Design.hpp is simplest) in the translation unit that asks TypeDescriptor::GetConverter for an XNA type, and link CNA::Design.
Using the converters
The registry lives in Sharp Runtime. Ask it for the converter of a type, then use the standard TypeConverter conversions. Values travel as std::any, the C++ spelling of CLR object.
#include <any>
#include "Microsoft/Xna/Framework/Design.hpp"
#include "Microsoft/Xna/Framework/Vector3.hpp"
#include "System/ComponentModel/TypeDescriptor.hpp"
#include "System/Globalization/CultureInfo.hpp"
using namespace Microsoft::Xna::Framework;
using System::ComponentModel::TypeDescriptor;
const auto converter = TypeDescriptor::GetConverter(System::Type::From<Vector3>());
// text -> value (invariant culture: '.' decimal point, ", " list separator)
Vector3 v = std::any_cast<Vector3>(converter->ConvertFromInvariantString("1.5, 2.25, -3.75"));
// value -> text
std::string text = converter->ConvertToInvariantString(std::any(v)); // "1.5, 2.25, -3.75"
// culture-aware: Czech has a decimal comma, so the list separator is ';'
const System::Globalization::CultureInfo czech("cs-CZ");
std::string cz = converter->ConvertToString(nullptr, &czech, std::any(v)); // "1,5; 2,25; -3,75"
Behaviour, rule by rule
These rules come from CNA’s reference audit of the Microsoft XNA 4.0 assembly (the public inventory, constructor signatures, conversion flags, property order and converter IL were recovered from a local copy of Microsoft.Xna.Framework.dll) and from the module’s tests. FNA was used only as a secondary source for names, because its Design source has incomplete descriptor paths.
- String input is per type. Only
Point,Color,QuaternionandVector2/3/4parse component-list strings.Rectangle,Matrix,BoundingBox,BoundingSphere,PlaneandRayreject string input (CanConvertFrom(std::string)is false andConvertFromStringthrowsSystem::NotSupportedException) but still convert to a string, using the value’s ownToString(). - Lists follow the culture. Text is split on
CultureInfo::getTextInfoProperty().getListSeparatorProperty(), surrounding whitespace is trimmed, output uses the separator followed by one space, and each component is converted with the converter registered for its own type (float,int,byte). A null culture means the current culture. The tests cover the invariant culture,en-USandcs-CZ, and prove that the Czech decimal comma and semicolon separator stay distinct:"1,5, 2,25, -3,75"is rejected undercs-CZ. - Malformed text throws. A component that will not parse, or a list with the wrong number of components, raises
System::ArgumentException— the exception type XNA uses. CNA does not reproduce the localized CLR message text. - Colors are bytes.
ColorConverterparses each component as a byte, so"0, 1, 2, 256"and"0, 1, -1, 2"throwArgumentException.PointConverterparses integers. CreateInstancerebuilds the value.GetCreateInstanceSupported()is always true.CreateInstance(context, hashtable)takes aSystem::Collections::Hashtablekeyed by property name and returns the boxed value. Editing one component through aPropertyDescriptormutates a boxed copy; the XNA property-grid workflow recreates the whole value from the edited components.InstanceDescriptor.ConvertTo(value, Type::From<InstanceDescriptor>())returns a descriptor carrying the exact constructor arguments in XNA order;Invoke()reconstructs an equal value (tests check this for every type, including the nested-Vector3types and all sixteenMatrixelements). Asking for an unsupported destination type (for exampleint) raisesNotSupportedException; an emptySystem::Type()raisesArgumentNullException.- Matrix is deliberately asymmetric. XNA disables string input for
Matrixbut the baseTypeConverterpath still permits string output. Its descriptor list containsTranslationplus all sixteen fields, butCreateInstanceand theInstanceDescriptoruse only the sixteen constructor fields;Translationis an alternate view ofM41,M42,M43.
Subclassing MathTypeConverter
XNA’s documented protected surface is present and spelled as XNA spells it: the protected fields propertyDescriptions (the ordered PropertyDescriptorCollection) and supportStringConvert (whether the converter converts to and from strings), plus ConvertFrom overrides on BoundingBoxConverter, BoundingSphereConverter and RayConverter that forward to the base. A subclass outside CNA can therefore populate the descriptor list in its constructor and clear supportStringConvert exactly as XNA’s own converters do. The protected-surface tests fail to compile if either field is renamed or duplicated behind an alias.
Representation, tests and evidence
| Question | Answer at this snapshot |
|---|---|
| Is it counted in the XNA census? | Yes. The Microsoft runtime XML documents 13 Design types and 53 Design members; CNA’s generated census marks them all represented (part of 331/331 types and 3,627/3,627 members). That is representation — see how the XNA Compatibility page measures it. The census records behavior_assessed: false for every entry. |
| What tests exist? | Two files under modules/design/tests/ with 25 test definitions: FrameworkDesignTests.cpp (17: per-type conversion, descriptor, creation and InstanceDescriptor behaviour, string round trips, culture handling, byte-range rejection, Matrix edge cases) and MathTypeConverterProtectedSurfaceTests.cpp (8). The focused executable is CnaDesignTests; the same sources are part of CnaTests. |
| Do they run in CI? | We did not find a workflow that names the Design target. They are ordinary GoogleTest sources built when CNA_BUILD_TESTS is on (its default), so you can run them locally. |
| Compared against real XNA? | CNA’s audit recovered the rules from the genuine Microsoft assembly, and CNA records no known conversion, descriptor or reconstruction difference within the boundaries below. We did not re-run that comparison; there is no automated oracle test for Design. |
Limits and boundaries
- No designer UI. There is no property grid, no Windows Forms host, no CodeDOM serialization and no arbitrary runtime reflection.
- Explicit metadata, not attributes. Converter discovery is explicit static registration; descriptors name known fields (and the
MatrixTranslationandColoraccessors) instead of scanning C++ classes.ITypeDescriptorContextand the reflection types expose only the subset conversion and reconstruction need. - Twelve value types. Only the XNA math value types listed above are registered; your own types are not, unless you register them with Sharp Runtime’s
TypeDescriptoryourself. - Exception text. Exception types match XNA; localized CLR message text does not.
- Not a serialization system. For XML there is the separate, opt-in
Microsoft/Xna/Framework/XmlSerializationEXT.hpp(a CNAEXT header that pulls Sharp Runtime’s XML serialization); for compiled assets see XNB Loading.
Related pages
- Tutorial 140: Parse and Format Math Values with Type Converters — a complete, end-to-end use.
- XNA Compatibility — the namespace-by-namespace state and the meaning of 331/331 and 3,627/3,627.
- Math Types and PackedVector Types — the value types the converters describe.
- CNA’s own
docs/framework-design.mdat the documented snapshot.
Known issues in this area
Current defects, gaps and limitations at this snapshot that touch this subject.
- CNA-BUG-216: MathTypeConverter::supportStringConvert's comment names three converters that clear it; six do — The Doxygen comment says only the BoundingBox, BoundingSphere and Ray converters clear supportStringConvert and that the matrix and rectangle converters leave it set; the Rectangle, Matrix, BoundingBox, BoundingSphere, P
- CNA-BUG-217: docs/framework-design.md says the Framework.Design registration associates the twelve value types with ordered descriptor collections; registerConverter registers only converter factories — registerConverter registers only a TypeConverterAttribute for each of the twelve math types, while CNA's design note says the registration associates the types with converter factories and ordered descriptor collections.