import OpenGL


struct OpenGLState
{
	struct Capability: OptionSet
	{
		let rawValue: UInt32

		static let alphaTest       = Self(rawValue: 1 <<  0)
		static let blend           = Self(rawValue: 1 <<  1)
		static let colourMaterial  = Self(rawValue: 1 <<  2)
		static let colourSum       = Self(rawValue: 1 <<  3)
		static let cullFace        = Self(rawValue: 1 <<  4)
		static let depthTest       = Self(rawValue: 1 <<  5)
		static let dither          = Self(rawValue: 1 <<  6)
		static let fog             = Self(rawValue: 1 <<  7)
		static let light0          = Self(rawValue: 1 <<  8)
		static let light1          = Self(rawValue: 1 <<  9)
		static let light2          = Self(rawValue: 1 << 10)
		static let light3          = Self(rawValue: 1 << 11)
		static let light4          = Self(rawValue: 1 << 12)
		static let light5          = Self(rawValue: 1 << 13)
		static let light6          = Self(rawValue: 1 << 14)
		static let light7          = Self(rawValue: 1 << 15)
		static let lighting        = Self(rawValue: 1 << 16)
		//static let lineSmooth      = Self(rawValue: 1 << 17)
		static let lineStipple     = Self(rawValue: 1 << 18)
		static let multiSample     = Self(rawValue: 1 << 19)
		//static let pointSmooth     = Self(rawValue: 1 << 20)
		static let scissorTest     = Self(rawValue: 1 << 21)
		static let stencilTest     = Self(rawValue: 1 << 22)
		//static let texture1D       = Self(rawValue: 1 << 23)
		static let texture2D       = Self(rawValue: 1 << 24)
		static let clipPlane0      = Self(rawValue: 1 << 25)
		static let clipPlane1      = Self(rawValue: 1 << 26)
		static let clipPlane2      = Self(rawValue: 1 << 27)
		static let clipPlane3      = Self(rawValue: 1 << 28)
		static let clipPlane4      = Self(rawValue: 1 << 29)
		static let clipPlane5      = Self(rawValue: 1 << 30)
		//static let colourLogicOp   = Self(rawValue: 1 << 31)

		static let sampleCoverage  = Self(rawValue: 1 << 17)
		static let alphaToOne      = Self(rawValue: 1 << 20)
		static let rescaleNormal   = Self(rawValue: 1 << 23)
		static let frameBufferSrgb = Self(rawValue: 1 << 31)

		static let all: [Self] = [ .alphaTest, .blend, .colourMaterial, .colourSum, .cullFace, .depthTest, .dither,
			.fog, .light0, .light1, .light2, .light3, .light4, .light5, .light6, .light7, .lighting, /*.lineSmooth,*/
			.lineStipple, /*.pointSmooth,*/ .multiSample, .scissorTest, .stencilTest, /*.texture1D,*/ .texture2D,
			.clipPlane0, .clipPlane1, .clipPlane2, .clipPlane3, .clipPlane4, .clipPlane5, /*.colourLogicOp,*/

			.sampleCoverage, .alphaToOne, .rescaleNormal, .frameBufferSrgb ]
		static let initial: Self = [ .dither, .multiSample ]

		var glCap: GLenum
		{
			let capEnum = switch self
			{
			case .alphaTest:       GL_ALPHA_TEST
			case .blend:           GL_BLEND
			case .colourMaterial:  GL_COLOR_MATERIAL
			case .colourSum:       GL_COLOR_SUM
			case .cullFace:        GL_CULL_FACE
			case .depthTest:       GL_DEPTH_TEST
			case .dither:          GL_DITHER
			case .fog:             GL_FOG
			case .light0:          GL_LIGHT0
			case .light1:          GL_LIGHT1
			case .light2:          GL_LIGHT2
			case .light3:          GL_LIGHT3
			case .light4:          GL_LIGHT4
			case .light5:          GL_LIGHT5
			case .light6:          GL_LIGHT6
			case .light7:          GL_LIGHT7
			case .lighting:        GL_LIGHTING
			//case .lineSmooth:      GL_LINE_SMOOTH
			case .lineStipple:     GL_LINE_STIPPLE
			case .multiSample:     GL_MULTISAMPLE
			//case .pointSmooth:     GL_POINT_SMOOTH
			case .scissorTest:     GL_SCISSOR_TEST
			case .stencilTest:     GL_STENCIL_TEST
			//case .texture1D:       GL_TEXTURE_1D
			case .texture2D:       GL_TEXTURE_2D
			case .clipPlane0:      GL_CLIP_PLANE0
			case .clipPlane1:      GL_CLIP_PLANE1
			case .clipPlane2:      GL_CLIP_PLANE2
			case .clipPlane3:      GL_CLIP_PLANE3
			case .clipPlane4:      GL_CLIP_PLANE4
			case .clipPlane5:      GL_CLIP_PLANE5
			//case .colourLogicOp:   GL_COLOR_LOGIC_OP
			case .sampleCoverage:  GL_SAMPLE_COVERAGE
			case .alphaToOne:      GL_SAMPLE_ALPHA_TO_ONE
			case .rescaleNormal:   GL_RESCALE_NORMAL
			case .frameBufferSrgb: GL_FRAMEBUFFER_SRGB
			default: fatalError()
			}
			return GLenum(capEnum)
		}
	}

	private var _capabilities: Capability = .initial

	private mutating func toggle(_ cap: Capability, _ en: Bool)
	{
		if en
		{
			if !_capabilities.contains(cap)
			{
				glEnable(cap.glCap)
				_capabilities.insert(cap)
			}
		}
		else
		{
			if _capabilities.contains(cap)
			{
				glDisable(cap.glCap)
				_capabilities.remove(cap)
			}
		}
	}

	mutating func enable(_ caps: Capability)
	{
		if Capability.all.contains(caps)
		{
			toggle(caps, true)
		}
		else
		{
			for i in Capability.all
			{
				if i.intersection(caps) == i { toggle(i, true) }
			}
		}
	}

	mutating func disable(_ caps: Capability)
	{
		if Capability.all.contains(caps)
		{
			toggle(caps, false)
		}
		else
		{
			for i in Capability.all
			{
				if i.intersection(caps) == i { toggle(i, false) }
			}
		}
	}

	
	struct ClientState: OptionSet
	{
		let rawValue: UInt32
		static let colour          = Self(rawValue: 1 << 0)
		static let edgeFlag        = Self(rawValue: 1 << 1)
		static let fogCoord        = Self(rawValue: 1 << 2)
		static let index           = Self(rawValue: 1 << 3)
		static let normal          = Self(rawValue: 1 << 4)
		static let secondaryColour = Self(rawValue: 1 << 5)
		static let textureCoord    = Self(rawValue: 1 << 6)
		static let vertex          = Self(rawValue: 1 << 7)

		static let all: [Self] = [ .colour, .edgeFlag, .fogCoord, .index, .normal, .secondaryColour, .textureCoord, .vertex ]
		static let initial: Self = []

		var glCap: GLenum
		{
			let capEnum = switch self
			{
			case .colour:          GL_COLOR_ARRAY
			case .edgeFlag:        GL_EDGE_FLAG_ARRAY
			case .fogCoord:        GL_FOG_COORD_ARRAY
			case .index:           GL_INDEX_ARRAY
			case .normal:          GL_NORMAL_ARRAY
			case .secondaryColour: GL_SECONDARY_COLOR_ARRAY
			case .textureCoord:    GL_TEXTURE_COORD_ARRAY
			case .vertex:          GL_VERTEX_ARRAY
			default: fatalError()
			}
			return GLenum(capEnum)
		}
	}

	private var _clientState: ClientState = .initial

	private mutating func toggleClientState(_ cap: ClientState, _ en: Bool)
	{
		if en
		{
			if !_clientState.contains(cap)
			{
				glEnableClientState(cap.glCap)
				_clientState.insert(cap)
			}
		}
		else
		{
			if _clientState.contains(cap)
			{
				glDisableClientState(cap.glCap)
				_clientState.remove(cap)
			}
		}
	}

	mutating func enableClient(_ caps: ClientState)
	{
		if ClientState.all.contains(caps)
		{
			toggleClientState(caps, true)
		}
		else
		{
			for i in ClientState.all
			{
				if i.intersection(caps) == i { toggleClientState(i, true) }
			}
		}
	}

	mutating func disableClient(_ caps: ClientState)
	{
		if ClientState.all.contains(caps)
		{
			toggleClientState(caps, false)
		}
		else
		{
			for i in ClientState.all
			{
				if i.intersection(caps) == i { toggleClientState(i, false) }
			}
		}
	}

	private var _activeTexture2D = 0

	private mutating func setActiveTexture2D(_ active: Int)
	{
		if active != _activeTexture2D
		{
			let slots = [ GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3, GL_TEXTURE4, GL_TEXTURE5, GL_TEXTURE6,
				GL_TEXTURE7, GL_TEXTURE8, GL_TEXTURE9, GL_TEXTURE10, GL_TEXTURE11, GL_TEXTURE12, GL_TEXTURE13,
				GL_TEXTURE14, GL_TEXTURE15, GL_TEXTURE16, GL_TEXTURE17, GL_TEXTURE18, GL_TEXTURE19, GL_TEXTURE20,
				GL_TEXTURE21, GL_TEXTURE22, GL_TEXTURE23, GL_TEXTURE24, GL_TEXTURE25, GL_TEXTURE26, GL_TEXTURE27,
				GL_TEXTURE28, GL_TEXTURE29, GL_TEXTURE30, GL_TEXTURE31 ]

			glActiveTexture(GLenum(slots[active]))
			_activeTexture2D = active
		}
	}

	static let defaultTexture: UInt32 = 0
	private var _texture2D: GLuint = GLuint(defaultTexture)

	mutating func bindTexture2D(active: Int, texture: UInt32)
	{
		if GLuint(texture) != _texture2D
		{
			setActiveTexture2D(active)
			glBindTexture(GLenum(GL_TEXTURE_2D), GLuint(texture))
			_texture2D = GLuint(texture)
		}
	}

	enum TexureParameter { case magFilter, minFilter, wrapS, wrapT }

	mutating func texture2DParameter(active: Int, param: TexureParameter, int value: Int32)
	{
		setActiveTexture2D(active)
		let pname = switch param
		{
		case .magFilter: GL_TEXTURE_MAG_FILTER
		case .minFilter: GL_TEXTURE_MIN_FILTER
		case .wrapS:     GL_TEXTURE_WRAP_S
		case .wrapT:     GL_TEXTURE_WRAP_T
		}
		glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(pname), GLint(value))
	}

	private var _clearDepth: GLclampd = 1

	var clearDepth: Double
	{
		get { Double(_clearDepth) }
		set(newDepth)
		{
			if GLclampd(newDepth) != _clearDepth
			{
				glClearDepth(newDepth)
				_clearDepth = GLclampd(newDepth)
			}
		}
	}

	private var _clearColour: Colour = .zero

	mutating func clearColour(_ newColour: Colour)
	{
		if newColour != _clearColour
		{
			glClearColor(newColour.r, newColour.g, newColour.b, newColour.a)
			_clearColour = newColour
		}
	}

	enum CullFace { case front, back, frontAndBack }
	private var _cullFace: CullFace = .back

	var cullFace: CullFace
	{
		get { _cullFace }
		set(newMode)
		{
			if newMode != _cullFace
			{
				let modeEnum = switch newMode
				{
				case .front:        GL_FRONT
				case .back:         GL_BACK
				case .frontAndBack: GL_FRONT_AND_BACK
				}
				glCullFace(GLenum(modeEnum))
				_cullFace = newMode
			}
		}
	}

	enum DepthFunc { case never, less, equal, lessOrEqual, greater, notEqual, greaterOrEqual, always }
	private var _depthFunc: DepthFunc = .less

	var depthFunc: DepthFunc
	{
		get { _depthFunc }
		set(newFunc)
		{
			if newFunc != _depthFunc
			{
				let funcEnum = switch newFunc
				{
				case .never:          GL_NEVER
				case .less:           GL_LESS
				case .equal:          GL_EQUAL
				case .lessOrEqual:    GL_LEQUAL
				case .greater:        GL_GREATER
				case .notEqual:       GL_NOTEQUAL
				case .greaterOrEqual: GL_GEQUAL
				case .always:         GL_ALWAYS
				}
				glDepthFunc(GLenum(funcEnum))
				_depthFunc = newFunc
			}
		}
	}

	enum FogMode { case linear, exp, exp2 }
	private var _fogMode: FogMode = .exp

	var fogMode: FogMode
	{
		get { _fogMode }
		set(newMode)
		{
			if newMode != _fogMode
			{
				let modeEnum = switch newMode
				{
				case .linear: GL_LINEAR
				case .exp:    GL_EXP
				case .exp2:   GL_EXP2
				}
				glFogi(GLenum(GL_FOG_MODE), modeEnum)
				_fogMode = newMode
			}
		}
	}

	private var _fogDensity: Float = 1

	var fogDensity: Float
	{
		get { _fogDensity }
		set(newDensity)
		{
			if newDensity != _fogDensity
			{
				glFogf(GLenum(GL_FOG_DENSITY), newDensity)
				_fogDensity = newDensity
			}
		}
	}

	private var _fogStart: Float = 0

	var fogStart: Float
	{
		get { _fogStart }
		set(newStart)
		{
			if newStart != _fogStart
			{
				glFogf(GLenum(GL_FOG_START), newStart)
				_fogStart = newStart
			}
		}
	}

	private var _fogEnd: Float = 1

	var fogEnd: Float
	{
		get { _fogEnd }
		set(newEnd)
		{
			if newEnd != _fogEnd
			{
				glFogf(GLenum(GL_FOG_END), newEnd)
				_fogEnd = newEnd
			}
		}
	}

	private var _fogColour: Colour = .zero

	var fogColour: Colour
	{
		get { _fogColour }
		set(newColour)
		{
			if newColour != _fogColour
			{
				withUnsafePointer(to: newColour)
				{
					$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
					{
						glFogfv(GLenum(GL_FOG_COLOR), $0)
					}
				}
			}
		}
	}

	enum FogCoordinateSource { case coordinate, fragmentDepth }
	private var _fogCoordinateSource: FogCoordinateSource = .fragmentDepth

	var fogCoodinateSource: FogCoordinateSource
	{
		get { _fogCoordinateSource }
		set(newCoordinateSource)
		{
			if newCoordinateSource != _fogCoordinateSource
			{
				let coordinateSourceEnum = switch newCoordinateSource
				{
				case .coordinate:    GL_FOG_COORD
				case .fragmentDepth: GL_FRAGMENT_DEPTH
				}
				glFogi(GLenum(GL_FOG_COORD_SRC), coordinateSourceEnum)
				_fogCoordinateSource = newCoordinateSource
			}
		}
	}

	enum Hint
	{
		case fog
		case generateMipmap
		case lineSmooth
		case perspectiveCorrection
		case pointSmooth
		case polygonSmooth
		case textureCompression
	}
	enum HintBehaviour { case fastest, nicest, dontCare }

	func setHint(target: Hint, hint: HintBehaviour)
	{
		let target = switch target
		{
		case .fog:                   GL_FOG_HINT
		case .generateMipmap:        GL_GENERATE_MIPMAP_HINT
		case .lineSmooth:            GL_LINE_SMOOTH_HINT
		case .perspectiveCorrection: GL_PERSPECTIVE_CORRECTION_HINT
		case .pointSmooth:           GL_POINT_SMOOTH_HINT
		case .polygonSmooth:         GL_POLYGON_SMOOTH_HINT
		case .textureCompression:    GL_TEXTURE_COMPRESSION_HINT
		}
		let mode = switch hint
		{
		case .fastest:  GL_FASTEST
		case .nicest:   GL_NICEST
		case .dontCare: GL_DONT_CARE
		}
		glHint(GLenum(target), GLenum(mode))
	}

	struct LightAmbientProperty
	{
		private var _lightAmbient = [Colour](repeating: .black, count: 8)

		subscript(index: Int) -> Colour
		{
			get { _lightAmbient[index] }
			set(newAmbient)
			{
				if newAmbient != _lightAmbient[index]
				{
					withUnsafePointer(to: newAmbient)
					{
						$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
						{
							// glLightModelfv(GLenum(GL_LIGHT_MODEL_AMBIENT), ambientColour)
							glLightfv(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_AMBIENT), $0)
						}
					}
					_lightAmbient[index] = newAmbient
				}
			}
		}
	}

	var lightAmbient = LightAmbientProperty()

	struct LightDiffuseProperty
	{
		private var _lightDiffuse: [Colour]  = [ .white, .black, .black, .black, .black, .black, .black, .black ]

		subscript(index: Int) -> Colour
		{
			get { _lightDiffuse[index] }
			set(newDiffuse)
			{
				if newDiffuse != _lightDiffuse[index]
				{
					withUnsafePointer(to: newDiffuse)
					{
						$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
						{
							glLightfv(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_DIFFUSE), $0)
						}
					}
					_lightDiffuse[index] = newDiffuse
				}
			}
		}
	}

	var lightDiffuse = LightDiffuseProperty()

	struct LightSpecularProperty
	{
		private var _lightSpecular: [Colour] = [ .white, .black, .black, .black, .black, .black, .black, .black ]

		subscript(index: Int) -> Colour
		{
			get { _lightSpecular[index] }
			set(newSpecular)
			{
				if newSpecular != _lightSpecular[index]
				{
					withUnsafePointer(to: newSpecular)
					{
						$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
						{
							glLightfv(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_SPECULAR), $0)
						}
					}
					_lightSpecular[index] = newSpecular
				}
			}
		}
	}

	var lightSpecular = LightSpecularProperty()

	struct LightPositionProperty
	{
		private var _lightPosition = [Vec4f](repeating: .Z, count: 8)

		subscript(index: Int) -> Vec4f
		{
			get { _lightPosition[index] }
			set(newPosition)
			{
				withUnsafePointer(to: newPosition)
				{
					$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
					{
						glLightfv(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_POSITION), $0)
					}
				}
				_lightPosition[index] = newPosition
			}
		}
	}

	var lightPosition = LightPositionProperty()

	//private var _lightSpotDirection = [Vec4f](repeating: .zero, count: 8)
	//private var _lightSpotExponent  = [Vec4f](repeating: .zero, count: 8)
	//private var _lightSpotCutoff    = [Vec4f](repeating: .zero, count: 8)

	struct LightConstantAttenuationProperty
	{
		private var _lightConstantAttenuation = [Float](repeating: 1, count: 8)

		subscript(index: Int) -> Float
		{
			get { _lightConstantAttenuation[index] }
			set(newConstantAttenuation)
			{
				if newConstantAttenuation != _lightConstantAttenuation[index]
				{
					glLightf(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_CONSTANT_ATTENUATION), newConstantAttenuation)
					_lightConstantAttenuation[index] = newConstantAttenuation
				}
			}
		}
	}

	var lightConstantAttenuation = LightConstantAttenuationProperty()

	struct LightLinearAttenuationProperty
	{
		private var _lightLinearAttenuation = [Float](repeating: 0, count: 8)

		subscript(index: Int) -> Float
		{
			get { _lightLinearAttenuation[index] }
			set(newLinearAttenuation)
			{
				if newLinearAttenuation != _lightLinearAttenuation[index]
				{
					glLightf(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_LINEAR_ATTENUATION), newLinearAttenuation)
					_lightLinearAttenuation[index] = newLinearAttenuation
				}
			}
		}
	}

	var lightLinearAttenuation = LightLinearAttenuationProperty()

	struct LightQuadraticAttenuation
	{
		private var _lightQuadraticAttenuation = [Float](repeating: 0, count: 8)

		subscript(index: Int) -> Float
		{
			get { _lightQuadraticAttenuation[index] }
			set(newQuadraticAttenuation)
			{
				if newQuadraticAttenuation != _lightQuadraticAttenuation[index]
				{
					glLightf(GLenum(GL_LIGHT0 + Int32(index)), GLenum(GL_QUADRATIC_ATTENUATION), newQuadraticAttenuation)
					_lightQuadraticAttenuation[index] = newQuadraticAttenuation
				}
			}
		}
	}

	var lightQuadraticAttenuation = LightQuadraticAttenuation()

	var _lightModelAmbient = Colour(r: 0.2, g: 0.2, b: 0.2, a: 1)

	var lightModelAmbient: Colour
	{
		get { _lightModelAmbient }
		set(newAmbient)
		{
			if newAmbient != _lightModelAmbient
			{
				
				withUnsafePointer(to: newAmbient)
				{
					$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
					{
						glLightModelfv(GLenum(GL_LIGHT_MODEL_AMBIENT), $0)
					}
				}
				_lightModelAmbient = newAmbient
			}
		}
	}

	
	enum LightModelColourControl { case single, separateSpecular }
	var _lightModelColourControl: LightModelColourControl = .single

	var lightModelColourControl: LightModelColourControl
	{
		get { _lightModelColourControl }
		set(newControl)
		{
			if newControl != _lightModelColourControl
			{
				let param = switch newControl
				{
				case .single:           GL_SINGLE_COLOR
				case .separateSpecular: GL_SEPARATE_SPECULAR_COLOR
				}
				glLightModelf(GLenum(GL_LIGHT_MODEL_COLOR_CONTROL), GLfloat(param))
				_lightModelColourControl = newControl
			}
		}
	}

	var _lightModelLocalViewer = false

	var lightModelLocalViewer: Bool
	{
		get { _lightModelLocalViewer }
		set(newMode)
		{
			if newMode != _lightModelLocalViewer
			{
				glLightModeli(GLenum(GL_LIGHT_MODEL_LOCAL_VIEWER), newMode ? 1 : 0)
				_lightModelLocalViewer = newMode
			}
		}
	}
	
	var _lightModeTwoSide = false

	var lightModeTwoSide: Bool
	{
		get { _lightModeTwoSide }
		set(newMode)
		{
			if newMode != _lightModeTwoSide
			{
				glLightModeli(GLenum(GL_LIGHT_MODEL_TWO_SIDE), newMode ? 1 : 0)
				_lightModeTwoSide = newMode
			}
		}
	}

	enum MatrixMode { case modelView, projection, texture, colour }
	private var _matrixMode: MatrixMode = .modelView

	var matrixMode: MatrixMode
	{
		get { _matrixMode }
		set(newMode)
		{
			if newMode != _matrixMode
			{
				let modeEnum = switch newMode
				{
				case .modelView:  GL_MODELVIEW
				case .projection: GL_PROJECTION
				case .texture:    GL_TEXTURE
				case .colour:     GL_COLOR
				}
				glMatrixMode(GLenum(modeEnum))
				_matrixMode = newMode
			}
		}
	}


	static let defaultBuffer: UInt32 = 0

	private var _arrayBuffer = GLuint(defaultBuffer)
	
	var arrayBuffer: UInt32
	{
		get { UInt32(_arrayBuffer) }
		set(newBuf)
		{
			if newBuf != _arrayBuffer
			{
				_arrayBuffer = GLuint(newBuf)
				glBindBuffer(GLenum(GL_ARRAY_BUFFER), _arrayBuffer)
			}
		}
	}

	private var _elementArrayBuffer = GLuint(defaultBuffer)

	var elementArrayBuffer: UInt32
	{
		get { UInt32(_elementArrayBuffer) }
		set(newBuf)
		{
			if newBuf != _elementArrayBuffer
			{
				_elementArrayBuffer = GLuint(newBuf)
				glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), _elementArrayBuffer)
			}
		}
	}

	enum PolygonMode { case point, line, fill }
	private var _polygonMode = PolygonMode.fill

	var polygonMode: PolygonMode
	{
		get { _polygonMode }
		set(newMode)
		{
			if newMode != _polygonMode
			{
				let modeEnum = switch newMode
				{
				case .point: GL_POINT
				case .line:  GL_LINE
				case .fill:  GL_FILL
				}
				glPolygonMode(GLenum(GL_FRONT_AND_BACK), GLenum(modeEnum));
				_polygonMode = newMode
			}
		}
	}
}
