h-raylib 5.1.3.0 → 5.5.0.0
raw patch · 126 files changed
+26648/−15867 lines, 126 filesdep +linearPVP ok
version bump matches the API change (PVP)
Dependencies added: linear
API changes (from Hackage documentation)
- Raylib.Core: freeAutomationEventList :: AutomationEventListRef -> WindowResources -> IO ()
- Raylib.Types.Core: Vector2 :: Float -> Float -> Vector2
- Raylib.Types.Core: Vector3 :: Float -> Float -> Float -> Vector3
- Raylib.Types.Core: Vector4 :: Float -> Float -> Float -> Float -> Vector4
- Raylib.Types.Core: [vector2'x] :: Vector2 -> Float
- Raylib.Types.Core: [vector2'y] :: Vector2 -> Float
- Raylib.Types.Core: [vector3'x] :: Vector3 -> Float
- Raylib.Types.Core: [vector3'y] :: Vector3 -> Float
- Raylib.Types.Core: [vector3'z] :: Vector3 -> Float
- Raylib.Types.Core: [vector4'w] :: Vector4 -> Float
- Raylib.Types.Core: [vector4'x] :: Vector4 -> Float
- Raylib.Types.Core: [vector4'y] :: Vector4 -> Float
- Raylib.Types.Core: [vector4'z] :: Vector4 -> Float
- Raylib.Types.Core: data Vector2
- Raylib.Types.Core: data Vector3
- Raylib.Types.Core: data Vector4
- Raylib.Types.Core: instance Foreign.Storable.Storable Raylib.Types.Core.Vector2
- Raylib.Types.Core: instance Foreign.Storable.Storable Raylib.Types.Core.Vector3
- Raylib.Types.Core: instance Foreign.Storable.Storable Raylib.Types.Core.Vector4
- Raylib.Types.Core: instance GHC.Classes.Eq Raylib.Types.Core.Vector2
- Raylib.Types.Core: instance GHC.Classes.Eq Raylib.Types.Core.Vector3
- Raylib.Types.Core: instance GHC.Classes.Eq Raylib.Types.Core.Vector4
- Raylib.Types.Core: instance GHC.Show.Show Raylib.Types.Core.Vector2
- Raylib.Types.Core: instance GHC.Show.Show Raylib.Types.Core.Vector3
- Raylib.Types.Core: instance GHC.Show.Show Raylib.Types.Core.Vector4
- Raylib.Types.Core: instance Raylib.Internal.Foreign.Freeable Raylib.Types.Core.Vector2
- Raylib.Types.Core: instance Raylib.Internal.Foreign.Freeable Raylib.Types.Core.Vector3
- Raylib.Types.Core: instance Raylib.Internal.Foreign.Freeable Raylib.Types.Core.Vector4
- Raylib.Types.Util.GUI: Icon223 :: GuiIconName
- Raylib.Types.Util.GUI: Icon224 :: GuiIconName
- Raylib.Types.Util.GUI: Icon225 :: GuiIconName
- Raylib.Types.Util.GUI: Icon226 :: GuiIconName
- Raylib.Types.Util.GUI: Icon227 :: GuiIconName
+ Raylib.Core: c'isFileNameValid :: CString -> IO CBool
+ Raylib.Core: initWindowUnmanaged :: Int -> Int -> String -> IO ()
+ Raylib.Core: isFileNameValid :: String -> IO Bool
+ Raylib.Core: unloadAutomationEventList :: AutomationEventListRef -> WindowResources -> IO ()
+ Raylib.Core.Models: loadModelFromMeshManaged :: Mesh -> WindowResources -> IO Model
+ Raylib.Core.Shapes: c'checkCollisionCircleLine :: Ptr Vector2 -> CFloat -> Ptr Vector2 -> Ptr Vector2 -> IO CBool
+ Raylib.Core.Shapes: c'drawRectangleRoundedLinesEx :: Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()
+ Raylib.Core.Shapes: checkCollisionCircleLine :: Vector2 -> Float -> Vector2 -> Vector2 -> Bool
+ Raylib.Core.Shapes: drawRectangleRoundedLinesEx :: Rectangle -> Float -> Int -> Float -> Color -> IO ()
+ Raylib.Core.Textures: c'imageDrawTriangle :: Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()
+ Raylib.Core.Textures: c'imageDrawTriangleEx :: Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()
+ Raylib.Core.Textures: c'imageDrawTriangleFan :: Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()
+ Raylib.Core.Textures: c'imageDrawTriangleLines :: Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()
+ Raylib.Core.Textures: c'imageDrawTriangleStrip :: Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()
+ Raylib.Core.Textures: c'imageFromChannel :: Ptr Image -> CInt -> IO (Ptr Image)
+ Raylib.Core.Textures: imageDrawTriangle :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> IO Image
+ Raylib.Core.Textures: imageDrawTriangleEx :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> Color -> Color -> IO Image
+ Raylib.Core.Textures: imageDrawTriangleFan :: Image -> [Vector2] -> Color -> IO Image
+ Raylib.Core.Textures: imageDrawTriangleLines :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> IO Image
+ Raylib.Core.Textures: imageDrawTriangleStrip :: Image -> [Vector2] -> Color -> IO Image
+ Raylib.Core.Textures: imageFromChannel :: Image -> Int -> IO Image
+ Raylib.Internal: WindowResources :: IORef [CUInt] -> IORef (Map Integer (Map String Int)) -> IORef [CUInt] -> IORef [CUInt] -> IORef [CUInt] -> IORef [CUInt] -> IORef [(CInt, Ptr ())] -> IORef [Ptr ()] -> IORef [Ptr ()] -> IORef [Ptr ()] -> IORef [FunPtr ()] -> WindowResources
+ Raylib.Internal: [audioBufferAliases] :: WindowResources -> IORef [Ptr ()]
+ Raylib.Internal: [audioBuffers] :: WindowResources -> IORef [Ptr ()]
+ Raylib.Internal: [automationEventLists] :: WindowResources -> IORef [Ptr ()]
+ Raylib.Internal: [ctxDataPtrs] :: WindowResources -> IORef [(CInt, Ptr ())]
+ Raylib.Internal: [frameBuffers] :: WindowResources -> IORef [CUInt]
+ Raylib.Internal: [funPtrs] :: WindowResources -> IORef [FunPtr ()]
+ Raylib.Internal: [shaderIds] :: WindowResources -> IORef [CUInt]
+ Raylib.Internal: [shaderLocations] :: WindowResources -> IORef (Map Integer (Map String Int))
+ Raylib.Internal: [textureIds] :: WindowResources -> IORef [CUInt]
+ Raylib.Internal: [vaoIds] :: WindowResources -> IORef [CUInt]
+ Raylib.Internal: [vboIds] :: WindowResources -> IORef [CUInt]
+ Raylib.Internal: _unloadAutomationEventList :: Ptr () -> IO ()
+ Raylib.Internal: addAudioBuffer :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: addAudioBufferAlias :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: addAutomationEventList :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: addCtxData :: Integral a => a -> Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: addFrameBuffer :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: addFunPtr :: FunPtr () -> WindowResources -> IO ()
+ Raylib.Internal: addShaderId :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: addTextureId :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: addToWindowResources :: Closeable a => WindowResources -> a -> IO ()
+ Raylib.Internal: addVaoId :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: addVboIds :: Integral a => Maybe [a] -> WindowResources -> IO ()
+ Raylib.Internal: c'getPixelDataSize :: CInt -> CInt -> CInt -> IO CInt
+ Raylib.Internal: c'rlGetShaderIdDefault :: IO CUInt
+ Raylib.Internal: c'rlUnloadFramebuffer :: CUInt -> IO ()
+ Raylib.Internal: c'rlUnloadShaderProgram :: CUInt -> IO ()
+ Raylib.Internal: c'rlUnloadTexture :: CUInt -> IO ()
+ Raylib.Internal: c'rlUnloadVertexArray :: CUInt -> IO ()
+ Raylib.Internal: c'rlUnloadVertexBuffer :: CUInt -> IO ()
+ Raylib.Internal: c'unloadAudioBuffer :: Ptr () -> IO ()
+ Raylib.Internal: c'unloadAudioBufferAlias :: Ptr () -> IO ()
+ Raylib.Internal: c'unloadMusicStreamData :: CInt -> Ptr () -> IO ()
+ Raylib.Internal: class Closeable a
+ Raylib.Internal: close :: Closeable a => a -> IO ()
+ Raylib.Internal: data WindowResources
+ Raylib.Internal: defaultWindowResources :: IO WindowResources
+ Raylib.Internal: getPixelDataSize :: Int -> Int -> Int -> Int
+ Raylib.Internal: instance Raylib.Internal.Closeable (GHC.Ptr.FunPtr a)
+ Raylib.Internal: instance Raylib.Internal.Closeable a => Raylib.Internal.Closeable [a]
+ Raylib.Internal: managed :: Closeable a => WindowResources -> IO a -> IO a
+ Raylib.Internal: releaseAllWindowResources :: WindowResources -> IO ()
+ Raylib.Internal: releaseAudioWindowResources :: WindowResources -> IO ()
+ Raylib.Internal: releaseNonAudioWindowResources :: WindowResources -> IO ()
+ Raylib.Internal: unloadAudioBufferAliases :: WindowResources -> IO ()
+ Raylib.Internal: unloadAudioBuffers :: WindowResources -> IO ()
+ Raylib.Internal: unloadAutomationEventLists :: WindowResources -> IO ()
+ Raylib.Internal: unloadCtxData :: WindowResources -> IO ()
+ Raylib.Internal: unloadFrameBuffers :: WindowResources -> IO ()
+ Raylib.Internal: unloadFunPtrs :: WindowResources -> IO ()
+ Raylib.Internal: unloadShaders :: WindowResources -> IO ()
+ Raylib.Internal: unloadSingleAudioBuffer :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleAudioBufferAlias :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleAutomationEventList :: Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleCtxDataPtr :: Integral a => a -> Ptr () -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleFrameBuffer :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleFunPtr :: FunPtr () -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleShader :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleTexture :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleVaoId :: Integral a => a -> WindowResources -> IO ()
+ Raylib.Internal: unloadSingleVboIdList :: Integral a => Maybe [a] -> WindowResources -> IO ()
+ Raylib.Internal: unloadTextures :: WindowResources -> IO ()
+ Raylib.Internal: unloadVaoIds :: WindowResources -> IO ()
+ Raylib.Internal: unloadVboIds :: WindowResources -> IO ()
+ Raylib.Internal.Foreign: c'free :: Ptr () -> IO ()
+ Raylib.Internal.Foreign: class Freeable a
+ Raylib.Internal.Foreign: configsToBitflag :: Enum a => [a] -> Integer
+ Raylib.Internal.Foreign: freeMaybePtr :: Ptr () -> IO ()
+ Raylib.Internal.Foreign: instance (Raylib.Internal.Foreign.Freeable a, Foreign.Storable.Storable a) => Raylib.Internal.Foreign.Freeable [a]
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable (GHC.Ptr.Ptr Foreign.C.Types.CChar)
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable (Linear.V2.V2 a)
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable (Linear.V3.V3 a)
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable (Linear.V4.V4 a)
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CBool
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CChar
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CFloat
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CInt
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CShort
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CUChar
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CUInt
+ Raylib.Internal.Foreign: instance Raylib.Internal.Foreign.Freeable Foreign.C.Types.CUShort
+ Raylib.Internal.Foreign: newMaybeArray :: Storable a => Maybe [a] -> IO (Ptr a)
+ Raylib.Internal.Foreign: p'free :: FunPtr (Ptr a -> IO ())
+ Raylib.Internal.Foreign: peekMaybe :: Storable a => Ptr (Ptr a) -> IO (Maybe a)
+ Raylib.Internal.Foreign: peekMaybeArray :: Storable a => Int -> Ptr a -> IO (Maybe [a])
+ Raylib.Internal.Foreign: peekMaybeOff :: Storable a => Ptr (Ptr a) -> Int -> IO (Maybe a)
+ Raylib.Internal.Foreign: peekStaticArray :: Storable a => Int -> Ptr a -> IO [a]
+ Raylib.Internal.Foreign: peekStaticArrayOff :: Storable a => Int -> Ptr a -> Int -> IO [a]
+ Raylib.Internal.Foreign: pokeMaybe :: Storable a => Ptr (Ptr a) -> Maybe a -> IO ()
+ Raylib.Internal.Foreign: pokeMaybeOff :: Storable a => Ptr (Ptr a) -> Int -> Maybe a -> IO ()
+ Raylib.Internal.Foreign: pokeStaticArray :: Storable a => Ptr a -> [a] -> IO ()
+ Raylib.Internal.Foreign: pokeStaticArrayOff :: Storable a => Ptr a -> Int -> [a] -> IO ()
+ Raylib.Internal.Foreign: pop :: (Freeable a, Storable a) => Ptr a -> IO a
+ Raylib.Internal.Foreign: popCArray :: (Freeable a, Storable a) => Int -> Ptr a -> IO [a]
+ Raylib.Internal.Foreign: popCString :: CString -> IO String
+ Raylib.Internal.Foreign: rightPad :: Int -> a -> [a] -> [a]
+ Raylib.Internal.Foreign: rlFree :: Freeable a => a -> Ptr a -> IO ()
+ Raylib.Internal.Foreign: rlFreeDependents :: Freeable a => a -> Ptr a -> IO ()
+ Raylib.Internal.Foreign: rlFreeMaybeArray :: (Freeable a, Storable a) => Maybe [a] -> Ptr a -> IO ()
+ Raylib.Internal.Foreign: withCStringBuffer :: String -> Maybe Int -> (Int -> CString -> IO b) -> IO (b, String)
+ Raylib.Internal.Foreign: withFreeable :: (Freeable a, Storable a) => a -> (Ptr a -> IO b) -> IO b
+ Raylib.Internal.Foreign: withFreeableArray :: (Freeable a, Storable a) => [a] -> (Ptr a -> IO b) -> IO b
+ Raylib.Internal.Foreign: withFreeableArray2D :: (Freeable a, Storable a) => [[a]] -> (Ptr (Ptr a) -> IO b) -> IO b
+ Raylib.Internal.Foreign: withFreeableArrayLen :: (Freeable a, Storable a) => [a] -> (Int -> Ptr a -> IO b) -> IO b
+ Raylib.Internal.Foreign: withMaybe :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b
+ Raylib.Internal.Foreign: withMaybeCString :: Maybe String -> (CString -> IO b) -> IO b
+ Raylib.Types.Core: instance Raylib.Internal.Closeable Raylib.Types.Core.AutomationEventListRef
+ Raylib.Types.Core: pattern Vector2 :: Float -> Float -> Vector2
+ Raylib.Types.Core: pattern Vector3 :: Float -> Float -> Float -> Vector3
+ Raylib.Types.Core: pattern Vector4 :: a -> a -> a -> a -> V4 a
+ Raylib.Types.Core: type Vector2 = V2 Float
+ Raylib.Types.Core: type Vector3 = V3 Float
+ Raylib.Types.Core: type Vector4 = V4 Float
+ Raylib.Types.Core: vector2'x :: Vector2 -> Float
+ Raylib.Types.Core: vector2'y :: Vector2 -> Float
+ Raylib.Types.Core: vector3'x :: Vector3 -> Float
+ Raylib.Types.Core: vector3'y :: Vector3 -> Float
+ Raylib.Types.Core: vector3'z :: Vector3 -> Float
+ Raylib.Types.Core: vector4'w :: V4 a -> a
+ Raylib.Types.Core: vector4'x :: V4 a -> a
+ Raylib.Types.Core: vector4'y :: V4 a -> a
+ Raylib.Types.Core: vector4'z :: V4 a -> a
+ Raylib.Types.Core.Audio: instance Raylib.Internal.Closeable Raylib.Types.Core.Audio.AudioStream
+ Raylib.Types.Core.Audio: instance Raylib.Internal.Closeable Raylib.Types.Core.Audio.Music
+ Raylib.Types.Core.Audio: instance Raylib.Internal.Closeable Raylib.Types.Core.Audio.Sound
+ Raylib.Types.Core.Models: instance Raylib.Internal.Closeable Raylib.Types.Core.Models.Material
+ Raylib.Types.Core.Models: instance Raylib.Internal.Closeable Raylib.Types.Core.Models.Mesh
+ Raylib.Types.Core.Models: instance Raylib.Internal.Closeable Raylib.Types.Core.Models.Model
+ Raylib.Types.Core.Models: instance Raylib.Internal.Closeable Raylib.Types.Core.Models.Shader
+ Raylib.Types.Core.Text: instance Raylib.Internal.Closeable Raylib.Types.Core.Text.Font
+ Raylib.Types.Core.Textures: instance Raylib.Internal.Closeable Raylib.Types.Core.Textures.RenderTexture
+ Raylib.Types.Core.Textures: instance Raylib.Internal.Closeable Raylib.Types.Core.Textures.Texture
+ Raylib.Types.Util.GUI: DropdownArrowHidden :: GuiDropdownBoxProperty
+ Raylib.Types.Util.GUI: IconLayers2 :: GuiIconName
+ Raylib.Types.Util.GUI: IconLayersIso :: GuiIconName
+ Raylib.Types.Util.GUI: IconMLayers :: GuiIconName
+ Raylib.Types.Util.GUI: IconMaps :: GuiIconName
+ Raylib.Types.Util.GUI: IconPriority :: GuiIconName
+ Raylib.Types.Util.GUI: ListItemsBorderWidth :: GuiListViewProperty
+ Raylib.Types.Util.RLGL: [rlVertexBuffer'normals] :: RLVertexBuffer -> [Vector3]
+ Raylib.Util: class Closeable a
+ Raylib.Util: close :: Closeable a => a -> IO ()
+ Raylib.Util: managed :: Closeable a => WindowResources -> IO a -> IO a
+ Raylib.Util.GUI: c'guiValueBoxFloat :: Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CBool -> IO CInt
+ Raylib.Util.GUI: guiValueBoxFloat :: Rectangle -> Maybe String -> String -> Maybe Int -> Float -> Bool -> IO (Bool, Float, String)
+ Raylib.Util.GUI.Styles: guiLoadStyleAmber :: IO ()
+ Raylib.Util.Lenses: _rlVertexBuffer'normals :: Lens' RLVertexBuffer [Vector3]
+ Raylib.Util.Math: matrixDecompose :: Matrix -> (Vector3, Quaternion, Vector3)
+ Raylib.Util.Math: quaternionCubicHermiteSpline :: Quaternion -> Quaternion -> Quaternion -> Quaternion -> Float -> Quaternion
+ Raylib.Util.Math: vector3CubicHermite :: Vector3 -> Vector3 -> Vector3 -> Vector3 -> Float -> Vector3
+ Raylib.Util.RLGL: c'rlGetCullDistanceFar :: IO CDouble
+ Raylib.Util.RLGL: c'rlGetCullDistanceNear :: IO CDouble
+ Raylib.Util.RLGL: c'rlSetClipPlanes :: CDouble -> CDouble -> IO ()
+ Raylib.Util.RLGL: rlGetCullDistanceFar :: IO Double
+ Raylib.Util.RLGL: rlGetCullDistanceNear :: IO Double
+ Raylib.Util.RLGL: rlSetClipPlanes :: Double -> Double -> IO ()
- Raylib.Core: closeWindow :: WindowResources -> IO ()
+ Raylib.Core: closeWindow :: Maybe WindowResources -> IO ()
- Raylib.Core: loadShader :: Maybe String -> Maybe String -> WindowResources -> IO Shader
+ Raylib.Core: loadShader :: Maybe String -> Maybe String -> IO Shader
- Raylib.Core: loadShaderFromMemory :: Maybe String -> Maybe String -> WindowResources -> IO Shader
+ Raylib.Core: loadShaderFromMemory :: Maybe String -> Maybe String -> IO Shader
- Raylib.Core: setAutomationEventList :: AutomationEventList -> WindowResources -> IO AutomationEventListRef
+ Raylib.Core: setAutomationEventList :: AutomationEventList -> IO AutomationEventListRef
- Raylib.Core: setLoadFileDataCallback :: LoadFileDataCallback -> WindowResources -> IO C'LoadFileDataCallback
+ Raylib.Core: setLoadFileDataCallback :: LoadFileDataCallback -> IO C'LoadFileDataCallback
- Raylib.Core: setLoadFileTextCallback :: LoadFileTextCallback -> WindowResources -> IO C'LoadFileTextCallback
+ Raylib.Core: setLoadFileTextCallback :: LoadFileTextCallback -> IO C'LoadFileTextCallback
- Raylib.Core: setSaveFileDataCallback :: Storable a => SaveFileDataCallback a -> WindowResources -> IO C'SaveFileDataCallback
+ Raylib.Core: setSaveFileDataCallback :: Storable a => SaveFileDataCallback a -> IO C'SaveFileDataCallback
- Raylib.Core: setSaveFileTextCallback :: SaveFileTextCallback -> WindowResources -> IO C'SaveFileTextCallback
+ Raylib.Core: setSaveFileTextCallback :: SaveFileTextCallback -> IO C'SaveFileTextCallback
- Raylib.Core.Audio: closeAudioDevice :: WindowResources -> IO ()
+ Raylib.Core.Audio: closeAudioDevice :: Maybe WindowResources -> IO ()
- Raylib.Core.Audio: loadAudioStream :: Integer -> Integer -> Integer -> WindowResources -> IO AudioStream
+ Raylib.Core.Audio: loadAudioStream :: Integer -> Integer -> Integer -> IO AudioStream
- Raylib.Core.Audio: loadMusicStream :: String -> WindowResources -> IO Music
+ Raylib.Core.Audio: loadMusicStream :: String -> IO Music
- Raylib.Core.Audio: loadMusicStreamFromMemory :: String -> [Integer] -> WindowResources -> IO Music
+ Raylib.Core.Audio: loadMusicStreamFromMemory :: String -> [Integer] -> IO Music
- Raylib.Core.Audio: loadSound :: String -> WindowResources -> IO Sound
+ Raylib.Core.Audio: loadSound :: String -> IO Sound
- Raylib.Core.Audio: loadSoundAlias :: Sound -> WindowResources -> IO Sound
+ Raylib.Core.Audio: loadSoundAlias :: Sound -> IO Sound
- Raylib.Core.Audio: loadSoundFromWave :: Wave -> WindowResources -> IO Sound
+ Raylib.Core.Audio: loadSoundFromWave :: Wave -> IO Sound
- Raylib.Core.Models: genMeshCone :: Float -> Float -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshCone :: Float -> Float -> Int -> IO Mesh
- Raylib.Core.Models: genMeshCube :: Float -> Float -> Float -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshCube :: Float -> Float -> Float -> IO Mesh
- Raylib.Core.Models: genMeshCubicmap :: Image -> Vector3 -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshCubicmap :: Image -> Vector3 -> IO Mesh
- Raylib.Core.Models: genMeshCylinder :: Float -> Float -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshCylinder :: Float -> Float -> Int -> IO Mesh
- Raylib.Core.Models: genMeshHeightmap :: Image -> Vector3 -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshHeightmap :: Image -> Vector3 -> IO Mesh
- Raylib.Core.Models: genMeshHemiSphere :: Float -> Int -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshHemiSphere :: Float -> Int -> Int -> IO Mesh
- Raylib.Core.Models: genMeshKnot :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshKnot :: Float -> Float -> Int -> Int -> IO Mesh
- Raylib.Core.Models: genMeshPlane :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshPlane :: Float -> Float -> Int -> Int -> IO Mesh
- Raylib.Core.Models: genMeshPoly :: Int -> Float -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshPoly :: Int -> Float -> IO Mesh
- Raylib.Core.Models: genMeshSphere :: Float -> Int -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshSphere :: Float -> Int -> Int -> IO Mesh
- Raylib.Core.Models: genMeshTorus :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh
+ Raylib.Core.Models: genMeshTorus :: Float -> Float -> Int -> Int -> IO Mesh
- Raylib.Core.Models: loadMaterials :: String -> WindowResources -> IO [Material]
+ Raylib.Core.Models: loadMaterials :: String -> IO [Material]
- Raylib.Core.Models: loadModel :: String -> WindowResources -> IO Model
+ Raylib.Core.Models: loadModel :: String -> IO Model
- Raylib.Core.Models: loadModelFromMesh :: Mesh -> WindowResources -> IO Model
+ Raylib.Core.Models: loadModelFromMesh :: Mesh -> IO Model
- Raylib.Core.Models: setMaterialTexture :: Material -> Int -> Texture -> IO Material
+ Raylib.Core.Models: setMaterialTexture :: Material -> MaterialMapIndex -> Texture -> IO Material
- Raylib.Core.Models: uploadMesh :: Mesh -> Bool -> WindowResources -> IO Mesh
+ Raylib.Core.Models: uploadMesh :: Mesh -> Bool -> IO Mesh
- Raylib.Core.Shapes: c'drawRectangleRoundedLines :: Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()
+ Raylib.Core.Shapes: c'drawRectangleRoundedLines :: Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()
- Raylib.Core.Shapes: drawRectangleRoundedLines :: Rectangle -> Float -> Int -> Float -> Color -> IO ()
+ Raylib.Core.Shapes: drawRectangleRoundedLines :: Rectangle -> Float -> Int -> Color -> IO ()
- Raylib.Core.Text: loadFont :: String -> WindowResources -> IO Font
+ Raylib.Core.Text: loadFont :: String -> IO Font
- Raylib.Core.Text: loadFontData :: [Integer] -> Int -> [Int] -> Int -> FontType -> IO GlyphInfo
+ Raylib.Core.Text: loadFontData :: [Integer] -> Int -> Maybe [Int] -> FontType -> IO GlyphInfo
- Raylib.Core.Text: loadFontEx :: String -> Int -> [Int] -> Int -> WindowResources -> IO Font
+ Raylib.Core.Text: loadFontEx :: String -> Int -> Maybe [Int] -> IO Font
- Raylib.Core.Text: loadFontFromImage :: Image -> Color -> Int -> WindowResources -> IO Font
+ Raylib.Core.Text: loadFontFromImage :: Image -> Color -> Int -> IO Font
- Raylib.Core.Text: loadFontFromMemory :: String -> [Integer] -> Int -> [Int] -> Int -> WindowResources -> IO Font
+ Raylib.Core.Text: loadFontFromMemory :: String -> [Integer] -> Int -> Maybe [Int] -> IO Font
- Raylib.Core.Textures: loadRenderTexture :: Int -> Int -> WindowResources -> IO RenderTexture
+ Raylib.Core.Textures: loadRenderTexture :: Int -> Int -> IO RenderTexture
- Raylib.Core.Textures: loadTexture :: String -> WindowResources -> IO Texture
+ Raylib.Core.Textures: loadTexture :: String -> IO Texture
- Raylib.Core.Textures: loadTextureCubemap :: Image -> CubemapLayout -> WindowResources -> IO Texture
+ Raylib.Core.Textures: loadTextureCubemap :: Image -> CubemapLayout -> IO Texture
- Raylib.Core.Textures: loadTextureFromImage :: Image -> WindowResources -> IO Texture
+ Raylib.Core.Textures: loadTextureFromImage :: Image -> IO Texture
- Raylib.Types.Util.RLGL: RLVertexBuffer :: Int -> [Vector3] -> [Vector2] -> [Color] -> [Integer] -> Integer -> [Integer] -> RLVertexBuffer
+ Raylib.Types.Util.RLGL: RLVertexBuffer :: Int -> [Vector3] -> [Vector2] -> [Vector3] -> [Color] -> [Integer] -> Integer -> [Integer] -> RLVertexBuffer
- Raylib.Util.RLGL: c'rlSetVertexAttribute :: CUInt -> CInt -> CInt -> CBool -> CInt -> Ptr () -> IO ()
+ Raylib.Util.RLGL: c'rlSetVertexAttribute :: CUInt -> CInt -> CInt -> CBool -> CInt -> CInt -> IO ()
- Raylib.Util.RLGL: rlSetVertexAttribute :: Integer -> Int -> Int -> Bool -> Int -> Ptr () -> IO ()
+ Raylib.Util.RLGL: rlSetVertexAttribute :: Integer -> Int -> Int -> Bool -> Int -> Int -> IO ()
Files
- CHANGELOG.md +24/−56
- DOCUMENTATION.md +32/−22
- default.nix +3/−3
- examples/basic-audio/src/Main.hs +35/−29
- examples/basic-automation-events/src/Main.hs +94/−83
- examples/basic-callbacks/src/Main.hs +8/−9
- examples/basic-images/src/Main.hs +9/−15
- examples/basic-models/src/Main.hs +9/−10
- examples/basic-rlgl/src/Main.hs +8/−9
- examples/basic-shaders/src/Main.hs +18/−17
- examples/basic-window/src/Main.hs +1/−2
- examples/bunnymark/src/Main.hs +8/−9
- examples/camera-ray-collision/src/Main.hs +10/−10
- examples/custom-font-text/src/Main.hs +8/−14
- examples/first-person-camera/src/Main.hs +3/−2
- examples/postprocessing-effects/src/Main.hs +11/−10
- examples/raygui-suite/src/Main.hs +5/−4
- flake.nix +6/−18
- h-raylib.cabal +32/−16
- lib/rgui_bindings.c +9/−0
- lib/rgui_bindings.h +5/−0
- lib/rl_bindings.c +60/−13
- lib/rl_bindings.h +30/−12
- lib/rlgl_bindings.c +14/−1
- lib/rlgl_bindings.h +7/−1
- raygui/examples/styles/style_ashes.h +0/−578
- raygui/examples/styles/style_bluish.h +0/−619
- raygui/examples/styles/style_candy.h +0/−589
- raygui/examples/styles/style_cherry.h +0/−617
- raygui/examples/styles/style_cyber.h +0/−591
- raygui/examples/styles/style_dark.h +0/−589
- raygui/examples/styles/style_enefete.h +0/−600
- raygui/examples/styles/style_jungle.h +0/−578
- raygui/examples/styles/style_lavanda.h +0/−607
- raygui/examples/styles/style_sunny.h +0/−616
- raygui/examples/styles/style_terminal.h +0/−569
- raygui/src/raygui.h +201/−37
- raygui/styles/amber/style_amber.h +609/−0
- raygui/styles/ashes/style_ashes.h +578/−0
- raygui/styles/bluish/style_bluish.h +619/−0
- raygui/styles/candy/style_candy.h +589/−0
- raygui/styles/cherry/style_cherry.h +617/−0
- raygui/styles/cyber/style_cyber.h +591/−0
- raygui/styles/dark/style_dark.h +589/−0
- raygui/styles/enefete/style_enefete.h +600/−0
- raygui/styles/jungle/style_jungle.h +578/−0
- raygui/styles/lavanda/style_lavanda.h +607/−0
- raygui/styles/sunny/style_sunny.h +616/−0
- raygui/styles/terminal/style_terminal.h +569/−0
- raylib/examples/audio/audio_mixed_processor.c +1/−1
- raylib/examples/core/core_2d_camera_mouse_zoom.c +50/−19
- raylib/examples/core/core_2d_camera_platformer.c +2/−2
- raylib/examples/core/core_custom_frame_control.c +1/−1
- raylib/examples/core/core_input_gamepad.c +2/−2
- raylib/examples/core/core_input_mouse_wheel.c +1/−1
- raylib/examples/core/core_random_sequence.c +8/−8
- raylib/examples/core/core_smooth_pixelperfect.c +4/−4
- raylib/examples/core/core_storage_values.c +1/−1
- raylib/examples/models/models_billboard.c +6/−4
- raylib/examples/models/models_cubicmap.c +5/−1
- raylib/examples/models/models_draw_cube_texture.c +1/−1
- raylib/examples/models/models_loading_gltf.c +9/−10
- raylib/examples/models/models_skybox.c +3/−4
- raylib/examples/models/models_waving_cubes.c +2/−0
- raylib/examples/shaders/shaders_basic_lighting.c +6/−12
- raylib/examples/shaders/shaders_deferred_render.c +3/−3
- raylib/examples/shaders/shaders_palette_switch.c +1/−1
- raylib/examples/shapes/shapes_draw_rectangle_rounded.c +1/−1
- raylib/examples/shapes/shapes_lines_bezier.c +2/−2
- raylib/examples/shapes/shapes_splines_drawing.c +32/−6
- raylib/examples/text/text_codepoints_loading.c +1/−1
- raylib/examples/text/text_font_loading.c +1/−1
- raylib/examples/textures/textures_image_channel.c +106/−0
- raylib/parser/raylib_parser.c +21/−10
- raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +1/−1
- raylib/src/config.h +17/−9
- raylib/src/external/RGFW.h +6633/−0
- raylib/src/external/rl_gputex.h +6/−2
- raylib/src/external/rprand.h +8/−3
- raylib/src/external/sinfl.h +1/−1
- raylib/src/platforms/rcore_android.c +9/−9
- raylib/src/platforms/rcore_desktop.c +0/−1836
- raylib/src/platforms/rcore_desktop_glfw.c +1872/−0
- raylib/src/platforms/rcore_desktop_rgfw.c +1343/−0
- raylib/src/platforms/rcore_desktop_sdl.c +61/−61
- raylib/src/platforms/rcore_drm.c +67/−18
- raylib/src/platforms/rcore_web.c +37/−5
- raylib/src/raudio.c +304/−227
- raylib/src/raylib.h +43/−30
- raylib/src/raymath.h +105/−7
- raylib/src/rcamera.h +4/−3
- raylib/src/rcore.c +127/−53
- raylib/src/rlgl.h +281/−68
- raylib/src/rmodels.c +6209/−5845
- raylib/src/rshapes.c +93/−56
- raylib/src/rtext.c +82/−28
- raylib/src/rtextures.c +590/−169
- raylib/src/utils.c +1/−1
- src/Raylib/Core.hs +37/−44
- src/Raylib/Core/Audio.hs +24/−54
- src/Raylib/Core/Camera.hs +0/−1
- src/Raylib/Core/Models.hs +44/−74
- src/Raylib/Core/Shapes.hs +20/−6
- src/Raylib/Core/Text.hs +46/−30
- src/Raylib/Core/Textures.hs +49/−33
- src/Raylib/Internal.hs +63/−2
- src/Raylib/Internal/Foreign.hs +7/−1
- src/Raylib/Internal/TH.hs +0/−2
- src/Raylib/Internal/Web/Processable.hs +0/−1
- src/Raylib/Types.hs +0/−2
- src/Raylib/Types/Core.hs +50/−61
- src/Raylib/Types/Core/Audio.hs +13/−2
- src/Raylib/Types/Core/Camera.hs +0/−2
- src/Raylib/Types/Core/Models.hs +50/−5
- src/Raylib/Types/Core/Text.hs +5/−2
- src/Raylib/Types/Core/Textures.hs +15/−3
- src/Raylib/Types/Util/GUI.hs +23/−16
- src/Raylib/Types/Util/RLGL.hs +18/−12
- src/Raylib/Util.hs +8/−5
- src/Raylib/Util/Camera.hs +2/−2
- src/Raylib/Util/Colors.hs +0/−2
- src/Raylib/Util/GUI.hs +49/−4
- src/Raylib/Util/GUI/Styles.hs +7/−3
- src/Raylib/Util/Lenses.hs +30/−6
- src/Raylib/Util/Math.hs +87/−4
- src/Raylib/Util/RLGL.hs +25/−5
CHANGELOG.md view
@@ -1,5 +1,14 @@ # h-raylib changelog +## Version 5.5.0.0+_12 July 2024_++- **BREAKING CHANGE**: Reimplemented `Vector2/3/4` using `linear`'s `V2/3/4`+- \[[#55](https://github.com/Anut-py/h-raylib/issues/55)\] **BREAKING CHANGE**: Completely reworked memory management (check `DOCUMENTATION.md` and the example programs)+- Dropped ghc 8.10 support+- \[[#54](https://github.com/Anut-py/h-raylib/issues/54)\] Exposed internal modules+- \[[#56](https://github.com/Anut-py/h-raylib/issues/56)\] Fixed a bug with `loadFontEx` and other font-related functions not working+ ## Version 5.1.3.0 _13 April, 2024_ @@ -22,27 +31,15 @@ - Added support for callbacks - Added more thorough Haddock documentation - Added pointer utility functions (`p'*`)--\[[#4](https://github.com/Anut-py/h-raylib/issues/4)\]--- Started working on web support--\[[#34](https://github.com/Anut-py/h-raylib/issues/34)\]--- Added bindings for raygui (`Raylib.Util.GUI`, `Raylib.Util.GUI.Styles`)+- \[[#4](https://github.com/Anut-py/h-raylib/issues/4)\] Started working on web support+- \[[#34](https://github.com/Anut-py/h-raylib/issues/34)\] Added bindings for raygui (`Raylib.Util.GUI`, `Raylib.Util.GUI.Styles`) ## Version 5.1.0.1 _16 January, 2024_ - Updated raylib to the master branch--\[[#26](https://github.com/Anut-py/h-raylib/pull/26)\]--- New `platform-nixos` build flag--\[[#27](https://github.com/Anut-py/h-raylib/pull/27), [#35](https://github.com/Anut-py/h-raylib/pull/35)\]--- Added flake.nix+- \[[#26](https://github.com/Anut-py/h-raylib/pull/26)\] New `platform-nixos` build flag+- \[[#27](https://github.com/Anut-py/h-raylib/pull/27), [#35](https://github.com/Anut-py/h-raylib/pull/35)\] Added flake.nix ## Version 4.6.0.7 _10 September, 2023_@@ -57,35 +54,21 @@ ## Version 4.6.0.5 _29 June, 2023_ -\[[#22](https://github.com/Anut-py/h-raylib/pull/22)\]--- Allowed `base-4.18` to support GHC 9.4 and higher--\[[#23](https://github.com/Anut-py/h-raylib/pull/23)\]--- Added helper functions in `Raylib.Util` as an alternative to the `begin*` and `end*` functions+- \[[#22](https://github.com/Anut-py/h-raylib/pull/22)\] Allowed `base-4.18` to support GHC 9.4 and higher+- \[[#23](https://github.com/Anut-py/h-raylib/pull/23)\] Added helper functions in `Raylib.Util` as an alternative to the `begin*` and `end*` functions ## Version 4.6.0.4 _16 June, 2023_ - Updated raylib to the master branch--\[[#19](https://github.com/Anut-py/h-raylib/pull/19)\]--- Changed all the `Raylib.Util` functions to use `MonadIO` for flexibility--\[[#20](https://github.com/Anut-py/h-raylib/pull/20)\]--- Changed `CFloat` to `Float` in `drawCapsule` and `drawCapsuleWires`+- \[[#19](https://github.com/Anut-py/h-raylib/pull/19)\] Changed all the `Raylib.Util` functions to use `MonadIO` for flexibility+- \[[#20](https://github.com/Anut-py/h-raylib/pull/20)\] Changed `CFloat` to `Float` in `drawCapsule` and `drawCapsuleWires` ## Version 4.6.0.3 _23 April, 2023_ - Updated raylib to the master branch--\[[#18](https://github.com/Anut-py/h-raylib/pull/18)\]--- Added lenses for raylib data structures+- \[[#18](https://github.com/Anut-py/h-raylib/pull/18)\] Added lenses for raylib data structures ## Version 4.6.0.2 _8 April, 2023_@@ -97,10 +80,7 @@ _2 April, 2023_ - Created the `Raylib.Util.Math` and `Raylib.Util.Camera` modules. They are Haskell implementations of `raymath` and `rcamera`.--\[[#15](https://github.com/Anut-py/h-raylib/pull/15)\]--- Fixed a memory issue with `getFontDefault`+- \[[#15](https://github.com/Anut-py/h-raylib/pull/15)\] Fixed a memory issue with `getFontDefault` ## Version 4.5.3.4 _19 March, 2023_@@ -117,19 +97,14 @@ ## Version 4.5.3.2 _1 March, 2023_ -\[[#12](https://github.com/Anut-py/h-raylib/pull/12)\]--- Added rlgl bindings (`Raylib.Util.RLGL`)+- \[[#12](https://github.com/Anut-py/h-raylib/pull/12)\] Added rlgl bindings (`Raylib.Util.RLGL`) ## Version 4.5.3.1 _27 February, 2023_ - Added manual asset unloading functions - Updated raylib to the master branch--\[[#11](https://github.com/Anut-py/h-raylib/pull/11)\]--- Fixed a build issue on MacOS+- \[[#11](https://github.com/Anut-py/h-raylib/pull/11)\] Fixed a build issue on MacOS ## Version 4.5.3.0 _24 February, 2023_@@ -159,10 +134,7 @@ - **BREAKING CHANGE**: Changed all types to minimize usage of `Ptr`s - **BREAKING CHANGE**: Split the `Raylib` module into six modules: `Raylib.Audio`, `Raylib.Core`, `Raylib.Models`, `Raylib.Shapes`, `Raylib.Text`, and `Raylib.Textures` - Added the internal `Freeable` typeclass to prevent memory leaks--\[[#8](https://github.com/Anut-py/h-raylib/issues/8)\]--- Added `Xext` as a dependency again+- \[[#8](https://github.com/Anut-py/h-raylib/issues/8)\] Added `Xext` as a dependency again ## Version 4.5.0.12 _14 January, 2023_@@ -189,9 +161,7 @@ ## Version 4.5.0.8 _18 December, 2022_ -\[[#9](https://github.com/Anut-py/h-raylib/issues/9)\]--- Fixed an issue on Mac where `clang` failed to detect that `rglfw.c` was using objective-c+- \[[#9](https://github.com/Anut-py/h-raylib/issues/9)\] Fixed an issue on Mac where `clang` failed to detect that `rglfw.c` was using objective-c ## Version 4.5.0.7 _26 November, 2022_@@ -205,9 +175,7 @@ ## Version 4.5.0.6 _24 November, 2022_ -\[[#6](https://github.com/Anut-py/h-raylib/issues/6)\]--- Fixed `Font` marshalling+- \[[#6](https://github.com/Anut-py/h-raylib/issues/6)\] Fixed `Font` marshalling ## Version 4.5.0.5 _19 November, 2022_
DOCUMENTATION.md view
@@ -1,42 +1,52 @@ # h-raylib documentation -This file only contains h-raylib specific information. For documentation on individual functions, check the [raylib cheatsheet](https://www.raylib.com/cheatsheet/cheatsheet.html) and the [h-raylib Haddock documentation](https://hackage.haskell.org/package/h-raylib). You can also look at the examples included here in the `examples` directory (written in Haskell), or you can look at the more extensive set of examples [on the raylib website](https://www.raylib.com/examples.html) (written in C). For information about raylib in general, view the [raylib wiki](https://github.com/raysan5/raylib/wiki).--For regular users of the library, the Haddock documentation should be more than enough (although much of it is auto-generated, so make sure to create an issue if you find anything that seems wrong). The documentation included here is more useful for contributors or anyone who wants to learn about how h-raylib works internally.+This file only contains h-raylib specific information. For documentation on individual functions, check the [raylib cheatsheet](https://www.raylib.com/cheatsheet/cheatsheet.html) and the [h-raylib Haddock documentation (incomplete)](https://hackage.haskell.org/package/h-raylib). You can also look at the examples included here in the `examples` directory (written in Haskell), or you can look at the more extensive set of examples [on the raylib website](https://www.raylib.com/examples.html) (written in C). For information about raylib in general, view the [raylib wiki](https://github.com/raysan5/raylib/wiki). ## Versioning scheme The first two numbers in the version track the underlying C raylib version. For example, `5.1.x.x` versions use raylib 5.1 under the hood. The third number represents breaking changes (renamed/deleted functions or modules). The last number represents non-breaking changes (new functions or modules, bug fixes, etc). -## Project structure+## Memory management -h-raylib contains bindings for raylib.h, raymath.h, rcamera.h, rlgl.h, and raygui.h. The public modules' documentation can be found in Haddock, as mentioned above, and documentation for the private modules can be found in the source files.+### Automatic management flow (recommended) -### Public modules+This flow is the one used in most of the example programs and should be used unless it is absolutely necessary not to. -The binding functions in h-raylib are an almost one-to-one mapping to their corresponding raylib functions. The types and functions are, in some cases, slightly modified if it is possible to utilize Haskell features.+1. A `WindowResources` handle is retrieved by calling `initWindow`+2. A `load*` function is called (e.g. `loadModel`) along with `managed` (e.g. `model <- managed window $ loadModel filePath`, where `window :: WindowResources`)+3. The data is loaded+4. Any data that requires extra functions be called to unload it is automatically stored in the `WindowResources` handle+5. The window is closed and `closeWindow` is called with the `WindowResources` handle (`closeWindow (Just window)`)+6. All the data stored in the handle is now automatically unloaded -The `initWindow` function (Raylib.Core) returns a `WindowResources` value that must be passed to some `load*` functions and several other functions. +In some cases, models and other data used by a program are extremely large and thus expensive to keep in memory for the entire duration of the program. For this reason, the `unload*` functions are available to manually unload auto-managed data on the fly (be sure *not* to use the `close` function on automatically managed resources). -The `unload*` functions are optional; even if you do not call them, all assets used by a program will be automatically be unloaded when it terminates. For some types (e.g. `Image`), an unloading function is not necessary.+Make sure to take a look at the examples to get a better understanding of this. -These changes are for automatic memory management. See the "Memory management" section for details.+### Manual management flow -(Most) functions that took a pointer as an argument in C were changed to take a regular type as an argument and return an updated version of the argument (there are a few exceptions, because `Ptr`s are difficult to avoid in some cases).+In some cases, you may want to opt out of automatic memory management, like so: -You can also access the underlying C functions by prepending `c'` to the function name (e.g. `c'initWindow`). This may be necessary for performance reasons. Note that if you do this, you will have to manually unload and free everything.+1. `initWindowUnmanaged` is called (it does not return a `WindowResources` handle)+2. A `load*` function is called *without* using `managed` (e.g. `model <- loadModel filePath`)+3. The data is loaded+4. The data must be manually unloaded with `close` (e.g. `close model`)+5. The window is closed by calling `closeWindow` without a `WindowResources` handle (`closeWindow Nothing`) -## Memory management+Note that if you are using the automatic memory management flow, then you can still load unmanaged resources by simply omitting `managed` when loading something (e.g. `model <- loadModel filePath`); however, you will still have to unload it manually with `close`, just like in the manual management flow. -The automatic memory management flow is as follows:+The `Raylib.Internal` module is available for advanced users who want to create their own `WindowResources` object and manually add resources to it. This should be used with caution; it is error-prone, and in the vast majority of cases, simply using the automatic or manual management flows is sufficient. -1. A `WindowResources` value is retrieved by calling `initWindow`.-2. A `load*` function is called (e.g. `loadModel`).-3. The data is loaded.-4. Any data that requires extra functions be called to unload it is stored in `Raylib.Internal` (e.g. shaders need to be freed from the GPU).-5. The window is closed and `closeWindow` is called.-6. All the data stored in `Raylib.Internal` is now unloaded (e.g. `rlUnloadShaderProgram` is called on all loaded shaders).+## Project structure -Keep in mind that this is all automatic; no extra action in the code is necessary for this to happen. Take a look at `Raylib.Internal` to see the functions used for this.+h-raylib contains bindings for raylib.h, raymath.h, rcamera.h, rlgl.h, and raygui.h. The public modules' documentation can be found in Haddock, as mentioned above, and documentation for the private modules can be found in the source files. -In some cases, models and other data used by a program are extremely large and thus expensive to keep in memory for the entire duration of the program. For this reason, the `unload*` functions are available to manually unload data on the fly.+### Public modules++The binding functions in h-raylib are an almost one-to-one mapping to their corresponding raylib functions. The types and functions are, in some cases, slightly modified if it is possible to utilize Haskell features.++The `initWindow` function (Raylib.Core) returns a `WindowResources` value that must be passed to the `managed` function for automatic memory management.++(Most) functions that took a pointer as an argument in C were changed to take a regular type as an argument and return an updated version of the argument (there are a few exceptions, because `Ptr`s are difficult to avoid in some cases).++You can also access the underlying C functions by prepending `c'` to the function name (e.g. `c'initWindow`). This may be necessary for performance reasons. Note that if you do this, you will have to manually unload and free everything.
default.nix view
@@ -1,14 +1,14 @@ { mkDerivation, base, containers, exceptions, lens, template-haskell, text, bytestring-, lib, systemDeps, buildExamples, ...+, linear, lib, systemDeps, buildExamples, ... }: mkDerivation { pname = "h-raylib";- version = "5.1.3.0";+ version = "5.5.0.0"; src = ./.; isLibrary = true; isExecutable = buildExamples; configureFlags = ["-fplatform-nixos"] ++ lib.optional buildExamples ["-fexamples"];- libraryHaskellDepends = [ base containers exceptions lens template-haskell text bytestring ];+ libraryHaskellDepends = [ base containers exceptions lens linear template-haskell text bytestring ]; librarySystemDepends = systemDeps; description = "Raylib bindings for Haskell"; license = lib.licenses.asl20;
examples/basic-audio/src/Main.hs view
@@ -1,39 +1,45 @@-{-# OPTIONS -Wall #-}-+{-# LANGUAGE TemplateHaskell #-} module Main where -import Control.Monad (unless, void)-import Raylib.Core (changeDirectory, clearBackground, getApplicationDirectory)+import Paths_h_raylib (getDataFileName)+import Raylib.Core (clearBackground, initWindow, setTargetFPS, windowShouldClose, closeWindow) import Raylib.Core.Audio (closeAudioDevice, initAudioDevice, loadMusicStream, playMusicStream, updateMusicStream) import Raylib.Core.Text (drawText)-import Raylib.Util (drawing, inGHCi, whileWindowOpen0, withWindow)+import Raylib.Util (drawing, managed, WindowResources, raylibApplication) import Raylib.Util.Colors (lightGray, rayWhite)+import Raylib.Types (Music) +type AppState = (WindowResources, Music)+ musicPath :: String-musicPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-audio/assets/mini1111.xm"+musicPath = "examples/basic-audio/assets/mini1111.xm" -main :: IO ()-main = do- withWindow- 650- 400- "raylib [audio] example - basic audio"- 60- ( \window -> do- initAudioDevice- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory)+startup :: IO AppState+startup = do+ window <- initWindow 650 400 "raylib [audio] example - basic audio"+ setTargetFPS 60+ initAudioDevice - music <- loadMusicStream musicPath window- playMusicStream music+ music <- managed window $ loadMusicStream =<< getDataFileName musicPath - whileWindowOpen0- ( drawing- ( do- clearBackground rayWhite- drawText "You should hear music playing!" 20 20 20 lightGray- )- >> updateMusicStream music- )- - closeAudioDevice window- )+ playMusicStream music++ return (window, music)++mainLoop :: AppState -> IO AppState+mainLoop state@(_, music) = do+ drawing $ do+ clearBackground rayWhite+ drawText "You should hear music playing!" 20 20 20 lightGray+ updateMusicStream music+ return state++shouldClose :: AppState -> IO Bool+shouldClose _ = windowShouldClose++teardown :: AppState -> IO ()+teardown (window, _) = do+ closeAudioDevice (Just window)+ closeWindow (Just window)++raylibApplication 'startup 'mainLoop 'shouldClose 'teardown
examples/basic-automation-events/src/Main.hs view
@@ -1,4 +1,5 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TemplateHaskell #-} module Main where @@ -6,8 +7,10 @@ import Data.Maybe (fromJust, isJust) import Raylib.Core ( clearBackground,+ closeWindow, getFrameTime, getMousePosition,+ initWindow, isKeyDown, isKeyPressed, isMouseButtonPressed,@@ -16,111 +19,119 @@ playAutomationEvent, setAutomationEventBaseFrame, setAutomationEventList,+ setTargetFPS, startAutomationEventRecording, stopAutomationEventRecording,+ windowShouldClose, ) import Raylib.Core.Shapes (drawCircleV, drawRectangle, drawRectangleLines) import Raylib.Core.Text (drawText, measureText) import Raylib.Types ( AutomationEvent (AutomationEvent), AutomationEventList (automationEventList'events),+ AutomationEventListRef, Color (Color), KeyboardKey (KeyDown, KeyLeft, KeyP, KeyR, KeyRight, KeyUp), MouseButton (MouseButtonLeft),- Vector2 (Vector2),+ pattern Vector2, )-import Raylib.Util (drawing, whileWindowOpen_, withWindow)+import Raylib.Types.Core (Vector2)+import Raylib.Util (WindowResources, drawing, managed, raylibApplication) import Raylib.Util.Colors (black, red, white) -main :: IO ()-main =- withWindow- 800- 600- "raylib [core] example - basic automation events"- 60- ( \window -> do- rWidth <- measureText "REC" 30- pWidth <- measureText "PLAY" 30+type AppState = (WindowResources, Int, Int, Maybe (Vector2, Float), Maybe ([AutomationEvent], Integer), Bool, Bool, Maybe AutomationEventListRef) - whileWindowOpen_- ( \(mState, playback, playing, recording, lRef) ->- drawing- ( do- toggleRec <- (&& not playing) <$> isKeyPressed KeyR- let recording' = if toggleRec then not recording else recording- lRef' <-- if toggleRec && recording'- then- ( do- l <- newAutomationEventList- Just <$> setAutomationEventList l window- )- else return lRef- when toggleRec $ if recording' then setAutomationEventBaseFrame 60 >> startAutomationEventRecording else stopAutomationEventRecording- when recording' $ drawText "REC" (790 - rWidth) 10 30 red+startup :: IO AppState+startup = do+ window <- initWindow 800 600 "raylib [core] example - basic automation events"+ setTargetFPS 60+ rWidth <- measureText "REC" 30+ pWidth <- measureText "PLAY" 30+ return (window, rWidth, pWidth, Nothing, Nothing, False, False, Nothing) - lEvents <- case lRef' of- Nothing -> return []- Just l -> automationEventList'events <$> peekAutomationEventList l- let playback' =- if toggleRec && not recording'- then Just (lEvents, 0)- else playback- startPlay <- isKeyPressed KeyP- let playing' = isJust playback' && not recording' && (startPlay || playing)+mainLoop :: AppState -> IO AppState+mainLoop (window, rWidth, pWidth, mState, playback, playing, recording, lRef) = do+ drawing+ ( do+ toggleRec <- (&& not playing) <$> isKeyPressed KeyR+ let recording' = if toggleRec then not recording else recording+ lRef' <-+ if toggleRec && recording'+ then+ ( do+ l <- newAutomationEventList+ Just <$> managed window (setAutomationEventList l)+ )+ else return lRef+ when toggleRec $ if recording' then setAutomationEventBaseFrame 60 >> startAutomationEventRecording else stopAutomationEventRecording+ when recording' $ drawText "REC" (790 - rWidth) 10 30 red - playback'' <-- if playing'- then- ( do- let (events, f) = fromJust playback'- let (thisFrame, rest) = span (\(AutomationEvent frame _ _) -> frame == f) events+ lEvents <- case lRef' of+ Nothing -> return []+ Just l -> automationEventList'events <$> peekAutomationEventList l+ let playback' =+ if toggleRec && not recording'+ then Just (lEvents, 0)+ else playback+ startPlay <- isKeyPressed KeyP+ let playing' = isJust playback' && not recording' && (startPlay || playing) - drawText "PLAY" (790 - pWidth) 10 30 red- mapM_ playAutomationEvent thisFrame+ playback'' <-+ if playing'+ then+ ( do+ let (events, f) = fromJust playback'+ let (thisFrame, rest) = span (\(AutomationEvent frame _ _) -> frame == f) events - if null events then return Nothing else return $ Just (rest, f + 1)- )- else return playback'- let (playback''', playing'') =- case playback'' of- Nothing -> if null lEvents then (Nothing, False) else (Just (lEvents, 0), False)- v -> (v, playing')+ drawText "PLAY" (790 - pWidth) 10 30 red+ mapM_ playAutomationEvent thisFrame - clearBackground white+ if null events then return Nothing else return $ Just (rest, f + 1)+ )+ else return playback'+ let (playback''', playing'') =+ case playback'' of+ Nothing -> if null lEvents then (Nothing, False) else (Just (lEvents, 0), False)+ v -> (v, playing') - mousePressed <- isMouseButtonPressed MouseButtonLeft- mousePos <- getMousePosition- frameTime <- getFrameTime- let mState' = if mousePressed then Just (mousePos, 0) else (\(p, t) -> (p, t + frameTime)) <$> mState- let mState'' = mState' >>= (\m@(_, t) -> if t > 2 then Nothing else Just m)+ clearBackground white - case mState'' of- Nothing -> drawText "Click somewhere or press the arrow keys" 10 10 20 black >> drawText "Press 'R' to start or stop recording, and 'P' to play the recording" 10 40 20 black- Just (p@(Vector2 x y), t) ->- ( do- when (t < 1.0) $ drawCircleV p (sin (realToFrac t * pi / 1.0) * 10) red- drawText ("Mouse clicked at (" ++ show x ++ ", " ++ show y ++ ")") 10 (if y < 50 && t < 1.0 then 570 else 10) 20 black- )+ mousePressed <- isMouseButtonPressed MouseButtonLeft+ mousePos <- getMousePosition+ frameTime <- getFrameTime+ let mState' = if mousePressed then Just (mousePos, 0) else (\(p, t) -> (p, t + frameTime)) <$> mState+ let mState'' = mState' >>= (\m@(_, t) -> if t > 2 then Nothing else Just m) - uDown <- isKeyDown KeyUp- dDown <- isKeyDown KeyDown- lDown <- isKeyDown KeyLeft- rDown <- isKeyDown KeyRight- let lb = Color 172 204 252 255- let shiftLeft =- case mState'' of- Nothing -> 0- Just (Vector2 x y, t) -> if x > 580 && y > 490 && t < 1.0 then -580 else 0+ case mState'' of+ Nothing -> drawText "Click somewhere or press the arrow keys" 10 10 20 black >> drawText "Press 'R' to start or stop recording, and 'P' to play the recording" 10 40 20 black+ Just (p@(Vector2 x y), t) ->+ ( do+ when (t < 1.0) $ drawCircleV p (sin (realToFrac t * pi / 1.0) * 10) red+ drawText ("Mouse clicked at (" ++ show x ++ ", " ++ show y ++ ")") 10 (if y < 50 && t < 1.0 then 570 else 10) 20 black+ ) - (if uDown then drawRectangle else drawRectangleLines) (660 + shiftLeft) 500 60 40 lb- (if dDown then drawRectangle else drawRectangleLines) (660 + shiftLeft) 550 60 40 lb- (if lDown then drawRectangle else drawRectangleLines) (590 + shiftLeft) 550 60 40 lb- (if rDown then drawRectangle else drawRectangleLines) (730 + shiftLeft) 550 60 40 lb+ uDown <- isKeyDown KeyUp+ dDown <- isKeyDown KeyDown+ lDown <- isKeyDown KeyLeft+ rDown <- isKeyDown KeyRight+ let lb = Color 172 204 252 255+ let shiftLeft =+ case mState'' of+ Nothing -> 0+ Just (Vector2 x y, t) -> if x > 580 && y > 490 && t < 1.0 then -580 else 0 - return (mState'', playback''', playing'', recording', lRef')- )- )- (Nothing, Nothing, False, False, Nothing)+ (if uDown then drawRectangle else drawRectangleLines) (660 + shiftLeft) 500 60 40 lb+ (if dDown then drawRectangle else drawRectangleLines) (660 + shiftLeft) 550 60 40 lb+ (if lDown then drawRectangle else drawRectangleLines) (590 + shiftLeft) 550 60 40 lb+ (if rDown then drawRectangle else drawRectangleLines) (730 + shiftLeft) 550 60 40 lb++ return (window, rWidth, pWidth, mState'', playback''', playing'', recording', lRef') )++shouldClose :: AppState -> IO Bool+shouldClose _ = windowShouldClose++teardown :: AppState -> IO ()+teardown (window, _, _, _, _, _, _, _) = closeWindow (Just window)++raylibApplication 'startup 'mainLoop 'shouldClose 'teardown
examples/basic-callbacks/src/Main.hs view
@@ -1,14 +1,14 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} module Main where -import Raylib.Core (clearBackground, initWindow, setTargetFPS, windowShouldClose, closeWindow, setLoadFileTextCallback, loadFileText, getApplicationDirectory)+import Paths_h_raylib (getDataFileName)+import Raylib.Core (clearBackground, initWindow, setTargetFPS, windowShouldClose, closeWindow, setLoadFileTextCallback, loadFileText) import Raylib.Core.Text (drawText)-import Raylib.Util (drawing, raylibApplication, WindowResources, inGHCi)+import Raylib.Util (drawing, raylibApplication, WindowResources, managed) import Raylib.Util.Colors (black, rayWhite) filePath :: String-filePath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-callbacks/assets/data.txt"+filePath = "examples/basic-callbacks/assets/data.txt" type AppState = (String, WindowResources) @@ -16,9 +16,8 @@ startup = do window <- initWindow 600 450 "raylib [core] example - basic callbacks" setTargetFPS 60- executableDir <- getApplicationDirectory- _ <- setLoadFileTextCallback (\s -> putStrLn ("opening file: " ++ executableDir ++ s) >> readFile (executableDir ++ s)) window- text <- loadFileText filePath+ _ <- managed window $ setLoadFileTextCallback (\s -> putStrLn ("opening file: " ++ s) >> readFile s)+ text <- loadFileText =<< getDataFileName filePath return (text, window) mainLoop :: AppState -> IO AppState@@ -34,6 +33,6 @@ shouldClose _ = windowShouldClose teardown :: AppState -> IO ()-teardown = closeWindow . snd+teardown = closeWindow . Just . snd -$(raylibApplication 'startup 'mainLoop 'shouldClose 'teardown)+raylibApplication 'startup 'mainLoop 'shouldClose 'teardown
examples/basic-images/src/Main.hs view
@@ -1,12 +1,8 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} module Main where -import Control.Monad (unless, void)-import Raylib.Core- ( changeDirectory,- clearBackground,- getApplicationDirectory,- )+import Paths_h_raylib (getDataFileName)+import Raylib.Core (clearBackground) import Raylib.Core.Text (drawText) import Raylib.Core.Textures ( drawTexture,@@ -16,12 +12,12 @@ loadRenderTexture, loadTextureFromImage, )-import Raylib.Types (Rectangle (Rectangle), RenderTexture (renderTexture'texture), Vector2 (Vector2))-import Raylib.Util (drawing, inGHCi, textureMode, whileWindowOpen0, withWindow)+import Raylib.Types (Rectangle (Rectangle), RenderTexture (renderTexture'texture), pattern Vector2)+import Raylib.Util (drawing, textureMode, whileWindowOpen0, withWindow, managed) import Raylib.Util.Colors (black, lightGray, orange, white) logoPath :: String-logoPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-images/assets/raylib-logo.png"+logoPath = "examples/basic-images/assets/raylib-logo.png" main :: IO () main = do@@ -31,11 +27,9 @@ "raylib [textures] example - basic images" 60 ( \window -> do- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory)-- texture <- genImagePerlinNoise 600 450 20 20 2 >>= (`loadTextureFromImage` window)- logo <- loadImage logoPath >>= (`loadTextureFromImage` window)- rt <- loadRenderTexture 200 200 window+ texture <- managed window $ loadTextureFromImage =<< genImagePerlinNoise 600 450 20 20 2+ logo <- managed window $ loadTextureFromImage =<< loadImage =<< getDataFileName logoPath+ rt <- managed window $ loadRenderTexture 200 200 whileWindowOpen0 ( drawing
examples/basic-models/src/Main.hs view
@@ -1,17 +1,17 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} module Main where -import Control.Monad (unless, void)-import Raylib.Core (changeDirectory, clearBackground, disableCursor, getApplicationDirectory)+import Paths_h_raylib (getDataFileName)+import Raylib.Core (clearBackground, disableCursor) import Raylib.Core.Camera (updateCamera) import Raylib.Core.Models (drawGrid, drawModel, genMeshCube, loadModel, loadModelFromMesh)-import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), Vector3 (Vector3))-import Raylib.Util (drawing, inGHCi, mode3D, whileWindowOpen_, withWindow)+import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), pattern Vector3)+import Raylib.Util (drawing, mode3D, whileWindowOpen_, withWindow, managed) import Raylib.Util.Colors (orange, white) modelPath :: String-modelPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-models/assets/Model.obj"+modelPath = "examples/basic-models/assets/Model.obj" main :: IO () main = do@@ -22,11 +22,10 @@ 60 ( \window -> do disableCursor- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory) - mesh <- genMeshCube 2 3 4 window- cubeModel <- loadModelFromMesh mesh window- customModel <- loadModel modelPath window+ mesh <- managed window $ genMeshCube 2 3 4+ cubeModel <- managed window $ loadModelFromMesh mesh+ customModel <- managed window $ loadModel =<< getDataFileName modelPath let camera = Camera3D (Vector3 3 2 3) (Vector3 0 0 0) (Vector3 0 1 0) 70 CameraPerspective
examples/basic-rlgl/src/Main.hs view
@@ -1,18 +1,19 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+ module Main where -import Control.Monad (unless, void)-import Raylib.Core (changeDirectory, clearBackground, getApplicationDirectory)+import Paths_h_raylib (getDataFileName)+import Raylib.Core (clearBackground) import Raylib.Core.Models (drawGrid) import Raylib.Core.Textures (loadTexture)-import Raylib.Types (Camera3D (Camera3D), CameraProjection (CameraPerspective), Color (Color), RLDrawMode (RLQuads), Rectangle (Rectangle), Texture (texture'height, texture'id, texture'width), Vector3 (Vector3))-import Raylib.Util (drawing, inGHCi, mode3D, whileWindowOpen0, withWindow)+import Raylib.Types (Camera3D (Camera3D), CameraProjection (CameraPerspective), Color (Color), RLDrawMode (RLQuads), Rectangle (Rectangle), Texture (texture'height, texture'id, texture'width), Vector3, pattern Vector3)+import Raylib.Util (drawing, mode3D, whileWindowOpen0, withWindow, managed) import Raylib.Util.Colors (rayWhite, white) import Raylib.Util.RLGL (rlBegin, rlColor4ub, rlEnd, rlNormal3f, rlPopMatrix, rlPushMatrix, rlRotatef, rlScalef, rlSetTexture, rlTexCoord2f, rlTranslatef, rlVertex3f) import Prelude hiding (length) texturePath :: String-texturePath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-rlgl/assets/cubicmap_atlas.png"+texturePath = "examples/basic-rlgl/assets/cubicmap_atlas.png" main :: IO () main = do@@ -22,11 +23,9 @@ "raylib [rlgl] example - basic rlgl" 60 ( \window -> do- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory)- let camera = Camera3D (Vector3 0 10 10) (Vector3 0 0 0) (Vector3 0 1 0) 45 CameraPerspective - texture <- loadTexture texturePath window+ texture <- managed window $ loadTexture =<< getDataFileName texturePath whileWindowOpen0 ( drawing
examples/basic-shaders/src/Main.hs view
@@ -1,19 +1,18 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} module Main where -import Control.Monad (unless, void, when)+import Paths_h_raylib (getDataFileName)+import Control.Monad (when) import Numeric (showFFloat) import Raylib.Core ( beginDrawing, beginMode3D,- changeDirectory, clearBackground, closeWindow, disableCursor, endDrawing, endMode3D,- getApplicationDirectory, getFrameTime, initWindow, isKeyDown,@@ -34,26 +33,28 @@ ShaderUniformVec3, ShaderUniformVec4 ),- Vector3 (Vector3),- Vector4 (Vector4, vector4'w),+ vector4'w, vectorToColor,+ pattern Vector3,+ pattern Vector4, )-import Raylib.Util (inGHCi, setMaterialShader, whileWindowOpen_)+import Raylib.Util (setMaterialShader, whileWindowOpen_, managed) import Raylib.Util.Colors (black, blue, lightGray, orange, white) assetsPath :: String-assetsPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/basic-shaders/assets/"+assetsPath = "examples/basic-shaders/assets/" main :: IO () main = do window <- initWindow 1300 800 "raylib [shaders] example - basic shaders" setTargetFPS 60 disableCursor- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory) let camera = Camera3D (Vector3 1 3 3) (Vector3 1 0 1) (Vector3 0 1 0) 45 CameraPerspective - shader <- loadShader (Just $ assetsPath ++ "lighting.vert") (Just $ assetsPath ++ "lighting.frag") window+ vert <- getDataFileName (assetsPath ++ "lighting.vert")+ frag <- getDataFileName (assetsPath ++ "lighting.frag")+ shader <- managed window $ loadShader (Just vert) (Just frag) let pointLightPosition = Vector3 0 3 2 let pointLightColor = Vector4 1 1 1 1@@ -69,16 +70,16 @@ setShaderValue shader "ambientLightColor" (ShaderUniformVec4 ambientLightColor) window setShaderValue shader "ambientStrength" (ShaderUniformFloat ambientStrength) window - cubeMesh <- genMeshCube 2 2 2 window- cubeModel' <- loadModelFromMesh cubeMesh window+ cubeMesh <- managed window $ genMeshCube 2 2 2+ cubeModel' <- managed window $ loadModelFromMesh cubeMesh let cubeModel = setMaterialShader cubeModel' 0 shader - sphereMesh <- genMeshSphere 0.5 32 32 window- sphereModel' <- loadModelFromMesh sphereMesh window+ sphereMesh <- managed window $ genMeshSphere 0.5 32 32+ sphereModel' <- managed window $ loadModelFromMesh sphereMesh let sphereModel = setMaterialShader sphereModel' 0 shader - planeMesh <- genMeshPlane 100 100 20 20 window- planeModel' <- loadModelFromMesh planeMesh window+ planeMesh <- managed window $ genMeshPlane 100 100 20 20+ planeModel' <- managed window $ loadModelFromMesh planeMesh let planeModel = setMaterialShader planeModel' 0 shader whileWindowOpen_@@ -133,7 +134,7 @@ ) (camera, pointLightStrength, specularStrength) - closeWindow window+ closeWindow (Just window) clamp :: Float -> Float -> Float -> Float clamp x l h = min h (max x l)
examples/basic-window/src/Main.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} module Main where @@ -25,6 +24,6 @@ shouldClose _ = windowShouldClose teardown :: WindowResources -> IO ()-teardown = closeWindow+teardown = closeWindow . Just $(raylibApplication 'startup 'mainLoop 'shouldClose 'teardown)
examples/bunnymark/src/Main.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE TemplateHaskell #-} @@ -7,7 +6,8 @@ module Main where -import Control.Monad (forM_, unless, void, when)+import Paths_h_raylib (getDataFileName)+import Control.Monad (forM_, when) import Foreign ( ForeignPtr, Ptr,@@ -26,27 +26,25 @@ c'getMouseX, c'getMouseY, c'getRandomValue,- changeDirectory, clearBackground, endDrawing,- getApplicationDirectory, getFrameTime, getScreenHeight, getScreenWidth, initWindow, isMouseButtonDown, setTargetFPS,- windowShouldClose,+ windowShouldClose, closeWindow, ) import Raylib.Core.Shapes (drawRectangle) import Raylib.Core.Text (drawFPS, drawText) import Raylib.Core.Textures (c'drawTexture, c'loadTexture, c'unloadTexture) import Raylib.Types (Color (Color), MouseButton (MouseButtonLeft), Texture, p'texture'height, p'texture'width)-import Raylib.Util (inGHCi, raylibApplication)+import Raylib.Util (raylibApplication) import Raylib.Util.Colors (black, green, maroon, rayWhite) texPath :: String-texPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/bunnymark/assets/wabbit_alpha.png"+texPath = "examples/bunnymark/assets/wabbit_alpha.png" maxBunnies :: Int maxBunnies = 500000 -- 500K bunnies limit@@ -116,8 +114,8 @@ startup = do _ <- initWindow 800 450 "raylib [textures] example - bunnymark" setTargetFPS 60- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory)- texPtr <- withCString texPath c'loadTexture+ texPath' <- getDataFileName texPath+ texPtr <- withCString texPath' c'loadTexture -- Use `peek` when you need to access the underlying fields -- This could be rewritten as@@ -220,5 +218,6 @@ -- Unload and free functions have to be manually called c'unloadTexture (texBunny state) free (texBunny state)+ closeWindow Nothing $(raylibApplication 'startup 'mainLoop 'shouldClose 'teardown)
examples/camera-ray-collision/src/Main.hs view
@@ -1,10 +1,11 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+ module Main where import Control.Monad (when)-import Raylib.Core (clearBackground, disableCursor)+import Raylib.Core (clearBackground, disableCursor, getWorldToScreen) import Raylib.Core.Camera (updateCamera)-import Raylib.Core.Models (drawBoundingBox, drawPoint3D, getRayCollisionQuad)+import Raylib.Core.Models (drawBoundingBox, getRayCollisionQuad) import Raylib.Core.Text (drawFPS) import Raylib.Types ( BoundingBox (BoundingBox),@@ -12,10 +13,11 @@ CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), RayCollision (rayCollision'hit, rayCollision'point),- Vector3 (Vector3),+ pattern Vector3, ) import Raylib.Util (cameraDirectionRay, drawing, mode3D, whileWindowOpen_, withWindow) import Raylib.Util.Colors (black, red, white)+import Raylib.Core.Shapes (drawCircleV) main :: IO () main = do@@ -39,12 +41,10 @@ let collision = getRayCollisionQuad (cameraDirectionRay c) (Vector3 0 0 0) (Vector3 0 2 0) (Vector3 0 2 4) (Vector3 0 0 4) let color = if rayCollision'hit collision then red else white - mode3D- c- ( do- drawBoundingBox (BoundingBox (Vector3 0 0 0) (Vector3 0 2 4)) color- when (rayCollision'hit collision) $ drawPoint3D (rayCollision'point collision) red- )+ mode3D c $ drawBoundingBox (BoundingBox (Vector3 0 0 0) (Vector3 0 2 4)) color+ when (rayCollision'hit collision) $ do+ p <- getWorldToScreen (rayCollision'point collision) c+ drawCircleV p 1 red ) >> updateCamera c CameraModeFirstPerson )
examples/custom-font-text/src/Main.hs view
@@ -1,21 +1,17 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+ module Main where -import Control.Monad (unless, void)+import Paths_h_raylib (getDataFileName) import Foreign (fromBool)-import Raylib.Core- ( changeDirectory,- clearBackground,- getApplicationDirectory,- isKeyPressed,- )+import Raylib.Core (clearBackground, isKeyPressed) import Raylib.Core.Text (drawText, drawTextEx, loadFont)-import Raylib.Types (KeyboardKey (KeyDown, KeyUp), Vector2 (Vector2))-import Raylib.Util (inGHCi, whileWindowOpen_, withWindow, drawing)+import Raylib.Types (KeyboardKey (KeyDown, KeyUp), pattern Vector2)+import Raylib.Util (whileWindowOpen_, withWindow, drawing, managed) import Raylib.Util.Colors (black, rayWhite) mainFontPath :: String-mainFontPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/custom-font-text/assets/Lato-Regular.ttf"+mainFontPath = "examples/custom-font-text/assets/Lato-Regular.ttf" main :: IO () main = do@@ -25,9 +21,7 @@ "raylib [text] example - custom font text" 60 ( \window -> do- unless inGHCi (void $ changeDirectory =<< getApplicationDirectory)-- mainFont <- loadFont mainFontPath window+ mainFont <- managed window $ loadFont =<< getDataFileName mainFontPath whileWindowOpen_ ( \size -> do
examples/first-person-camera/src/Main.hs view
@@ -1,11 +1,12 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+ module Main where import Raylib.Core (clearBackground, disableCursor) import Raylib.Core.Camera (updateCamera) import Raylib.Core.Models (drawCircle3D, drawCubeWiresV, drawLine3D) import Raylib.Core.Text (drawFPS)-import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), Vector3 (Vector3))+import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), pattern Vector3) import Raylib.Util (drawing, mode3D, whileWindowOpen_, withWindow) import Raylib.Util.Colors (black, white)
examples/postprocessing-effects/src/Main.hs view
@@ -1,19 +1,20 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} module Main where +import Paths_h_raylib (getDataFileName) import Control.Monad (unless, void) import Raylib.Core (changeDirectory, clearBackground, getApplicationDirectory, isKeyPressed, loadShader, setShaderValue) import Raylib.Core.Camera (updateCamera) import Raylib.Core.Models (drawCube, drawGrid, drawSphere) import Raylib.Core.Text (drawText) import Raylib.Core.Textures (drawTextureRec, loadRenderTexture)-import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeOrbital), CameraProjection (CameraPerspective), KeyboardKey (KeyLeft, KeyRight), Rectangle (Rectangle), RenderTexture (renderTexture'texture), ShaderUniformData (ShaderUniformVec2), Vector2 (Vector2), Vector3 (Vector3))-import Raylib.Util (inGHCi, mode3D, textureMode, whileWindowOpen_, withWindow, drawing, shaderMode)+import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeOrbital), CameraProjection (CameraPerspective), KeyboardKey (KeyLeft, KeyRight), Rectangle (Rectangle), RenderTexture (renderTexture'texture), ShaderUniformData (ShaderUniformVec2), pattern Vector2, pattern Vector3)+import Raylib.Util (inGHCi, mode3D, textureMode, whileWindowOpen_, withWindow, drawing, shaderMode, managed) import Raylib.Util.Colors (black, blue, darkBlue, darkGreen, green, maroon, orange, red, white) assetsPath :: String-assetsPath = (if not inGHCi then "../../../../../../../../../../" else "./") ++ "examples/postprocessing-effects/assets/"+assetsPath = "examples/postprocessing-effects/assets/" main :: IO () main = do@@ -30,14 +31,14 @@ let camera = Camera3D (Vector3 3 4 3) (Vector3 0 1 0) (Vector3 0 1 0) 45 CameraPerspective - rt <- loadRenderTexture width height window+ rt <- managed window $ loadRenderTexture width height -- Most of the shaders here are based on the ones at https://github.com/raysan5/raylib/tree/master/examples/shaders/resources/shaders/glsl330- defaultShader <- loadShader Nothing Nothing window- grayscaleShader <- loadShader Nothing (Just $ assetsPath ++ "grayscale.frag") window- blurShader <- loadShader Nothing (Just $ assetsPath ++ "blur.frag") window- pixelateShader <- loadShader Nothing (Just $ assetsPath ++ "pixelate.frag") window- bloomShader <- loadShader Nothing (Just $ assetsPath ++ "bloom.frag") window+ defaultShader <- managed window $ loadShader Nothing Nothing+ grayscaleShader <- managed window $ loadShader Nothing . Just =<< getDataFileName (assetsPath ++ "grayscale.frag")+ blurShader <- managed window $ loadShader Nothing . Just =<< getDataFileName (assetsPath ++ "blur.frag")+ pixelateShader <- managed window $ loadShader Nothing . Just =<< getDataFileName (assetsPath ++ "pixelate.frag")+ bloomShader <- managed window $ loadShader Nothing . Just =<< getDataFileName (assetsPath ++ "bloom.frag") let shaders = [("None", defaultShader), ("Grayscale", grayscaleShader), ("Blur", blurShader), ("Pixelate", pixelateShader), ("Bloom", bloomShader)]
examples/raygui-suite/src/Main.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} module Main where@@ -38,7 +37,8 @@ guiWindowBox, guiCheckBox, guiColorPicker, ) import Raylib.Util.GUI.Styles- ( guiLoadStyleAshes,+ ( guiLoadStyleAmber,+ guiLoadStyleAshes, guiLoadStyleBluish, guiLoadStyleCandy, guiLoadStyleCherry,@@ -113,6 +113,7 @@ themes :: [IO ()] themes = [ guiLoadStyleDefault,+ guiLoadStyleAmber, guiLoadStyleAshes, guiLoadStyleBluish, guiLoadStyleCandy,@@ -289,7 +290,7 @@ guiLabel (Rectangle 20 100 400 30) "Theme" guiSetStyleTextSize 20- (scroll', theme') <- guiListView (Rectangle 20 140 400 (height - 660)) "default;ashes;bluish;candy;cherry;cyber;dark;enefete;jungle;lavanda;sunny;terminal" (scroll ps) (theme ps)+ (scroll', theme') <- guiListView (Rectangle 20 140 400 (height - 660)) "default;amber;ashes;bluish;candy;cherry;cyber;dark;enefete;jungle;lavanda;sunny;terminal" (scroll ps) (theme ps) guiSetStyleTextSize 30 guiLabel (Rectangle 20 (height - 510) 360 30) "Custom background color"@@ -307,6 +308,6 @@ shouldClose = const windowShouldClose teardown :: AppState -> IO ()-teardown s = closeWindow (window s)+teardown s = closeWindow (Just (window s)) $(raylibApplication 'startup 'mainLoop 'shouldClose 'teardown)
flake.nix view
@@ -5,14 +5,14 @@ outputs = { self, nixpkgs, ... }@inputs: let- supportedSystems = [ "x86_64-linux" "x86_64-darwin" ];+ supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; forAllSystems' = nixpkgs.lib.genAttrs; forAllSystems = forAllSystems' supportedSystems; - raylibRev = "289e7d3a6c5b9ee05ff9e4f77db6de7f897e49ec";- raylibHash = "sha256-uWpk+N3hgTptenHbNbhFyXksRuBJ6jABaXMJMNcspFM=";- rayguiRev = "f21318f5008e2d4b1a4980b7fd22b3885206981a";- rayguiHash = "sha256-uh8DWqG7KSsxsxe38ovvJtkMsMmno7DhnTXcUzDU7XY=";+ raylibRev = "8d5374a443509036063a350d1649408e009425e7";+ raylibHash = "sha256-kYuqEUkyw8dngy5yBneNn+Br0xQr6NagP/s2CPM+q44=";+ rayguiRev = "3fb9d77a67243497e10ae0448374a52a2a65e26f";+ rayguiHash = "sha256-aWfXimbGU7RYqqOd44GmH3jPN8gcN4D/ygB71jIEr2c="; pkgsForSystem = system:@@ -41,20 +41,8 @@ sha256 = rayguiHash; }; nativeBuildInputs = [];- postFixup = "mkdir -p $out/include/ && cp ./src/raygui.h $out/include/ && cp ./examples/styles/*.h $out/include/";+ postFixup = "mkdir -p $out/include/ && cp ./src/raygui.h $out/include/ && cp ./styles/**/*.h $out/include/"; };- # temporary fix for CI/CD- # TODO: remove when github.com/NixOS/nixpkgs/pull/293296 gets merged- glfw = super.glfw.overrideAttrs (old: {- version = "3.4.0";- src = self.fetchFromGitHub {- owner = "glfw";- repo = "GLFW";- rev = "3.4";- sha256 = "sha256-FcnQPDeNHgov1Z07gjFze0VMz2diOrpbKZCsI96ngz0=";- };- cmakeFlags = old.cmakeFlags ++ [ "-DGLFW_BUILD_WAYLAND=OFF" ];- }); }) ]; };
h-raylib.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: h-raylib-version: 5.1.3.0+version: 5.5.0.0 synopsis: Raylib bindings for Haskell category: graphics description:@@ -18,6 +18,18 @@ README.md extra-source-files:+ default.nix+ flake.nix+ lib/**/*.c+ lib/**/*.h+ lib/**/*.m+ raygui/src/*.h+ raygui/styles/**/*.h+ raylib/**/*.c+ raylib/**/*.h+ raylib/**/*.m++data-files: examples/**/*.frag examples/**/*.mtl examples/**/*.obj@@ -26,16 +38,6 @@ examples/**/*.txt examples/**/*.vert examples/**/*.xm- lib/**/*.c- lib/**/*.h- lib/**/*.m- raygui/examples/styles/*.h- raygui/src/*.h- raylib/**/*.c- raylib/**/*.h- raylib/**/*.m- flake.nix- default.nix source-repository head type: git@@ -106,9 +108,14 @@ , base , h-raylib + other-modules: Paths_h_raylib+ autogen-modules: Paths_h_raylib+ other-extensions: BangPatterns TemplateHaskell+ + ghc-options: -Wall if flag(platform-web) ghc-options:@@ -203,6 +210,8 @@ Raylib.Core.Shapes Raylib.Core.Text Raylib.Core.Textures+ Raylib.Internal+ Raylib.Internal.Foreign Raylib.Types Raylib.Types.Core Raylib.Types.Core.Audio@@ -222,8 +231,6 @@ Raylib.Util.RLGL other-modules:- Raylib.Internal- Raylib.Internal.Foreign Raylib.Internal.TH Raylib.Internal.Web.Native Raylib.Internal.Web.Processable@@ -234,6 +241,7 @@ , containers >=0.6.0 && <0.7.0 , exceptions >=0.10.4 && <0.10.8 , lens >=4.0 && <5.2.4+ , linear >=1.22 && <1.23 , template-haskell >=2.16.0.0 && <2.22.0.0 , text >=2.0 && <2.2 @@ -245,9 +253,12 @@ DeriveAnyClass FlexibleInstances ForeignFunctionInterface+ PatternSynonyms ScopedTypeVariables TemplateHaskell TemplateHaskellQuotes+ + ghc-options: -Wall if (flag(platform-windows) || (flag(detect-platform) && os(windows))) if flag(mingw-cross)@@ -286,7 +297,8 @@ Xi Xext - cc-options: -Wno-implicit-function-declaration -Wno-unused-result -D_GLFW_X11+ cc-options:+ -Wno-implicit-function-declaration -Wno-unused-result -D_GLFW_X11 elif (flag(platform-mac) || (flag(detect-platform) && os(osx))) frameworks: OpenGL Cocoa IOKit CoreVideo CoreAudio CoreFoundation@@ -310,7 +322,7 @@ c-sources: lib/web.c else- cc-options: -DPLATFORM_DESKTOP+ cc-options: -DPLATFORM_DESKTOP_GLFW -Wno-int-to-void-pointer-cast c-sources: lib/rgui_bindings.c lib/rl_bindings.c@@ -320,7 +332,11 @@ if !flag(platform-nixos) include-dirs: raylib/src raylib/src/external/glfw/src- raylib/src/external/glfw/include raygui/src raygui/examples/styles+ raylib/src/external/glfw/include raygui/src raygui/styles/amber+ raygui/styles/ashes raygui/styles/bluish raygui/styles/candy+ raygui/styles/cherry raygui/styles/cyber raygui/styles/dark+ raygui/styles/enefete raygui/styles/jungle raygui/styles/lavanda+ raygui/styles/sunny raygui/styles/terminal c-sources: raylib/src/raudio.c
lib/rgui_bindings.c view
@@ -78,6 +78,11 @@ return GuiLoadStyleDefault(); } +RLBIND void GuiLoadStyleAmber_(void)+{+ GuiLoadStyleAmber();+}+ RLBIND void GuiLoadStyleAshes_(void) { GuiLoadStyleAshes();@@ -256,6 +261,10 @@ RLBIND int GuiValueBox_(Rectangle *bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) { return GuiValueBox(*bounds, text, value, minValue, maxValue, editMode);+}++RLBIND int GuiValueBoxFloat_(Rectangle *bounds, const char *text, char *textValue, float *value, bool editMode) {+ return GuiValueBoxFloat(*bounds, text, textValue, value, editMode); } RLBIND int GuiTextBox_(Rectangle *bounds, char *text, int textSize, bool editMode)
lib/rgui_bindings.h view
@@ -5,6 +5,7 @@ */ #include "rl_common.h"+#include <style_amber.h> #include <style_ashes.h> #include <style_bluish.h> #include <style_candy.h>@@ -45,6 +46,8 @@ void GuiLoadStyleDefault_(void); +void GuiLoadStyleAmber_(void);+ void GuiLoadStyleAshes_(void); void GuiLoadStyleBluish_(void);@@ -116,6 +119,8 @@ int GuiSpinner_(Rectangle *bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); int GuiValueBox_(Rectangle *bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);++int GuiValueBoxFloat_(Rectangle *bounds, const char *text, char *textValue, float *value, bool editMode); int GuiTextBox_(Rectangle *bounds, char *text, int textSize, bool editMode);
lib/rl_bindings.c view
@@ -326,7 +326,7 @@ DrawLineEx(*a, *b, c, *d); } -RLBIND void DrawLineStrip_(Vector2 *a, int b, Color *c)+RLBIND void DrawLineStrip_(const Vector2 *a, int b, Color *c) { DrawLineStrip(a, b, *c); }@@ -441,11 +441,16 @@ DrawRectangleRounded(*a, b, c, *d); } -RLBIND void DrawRectangleRoundedLines_(Rectangle *a, float b, int c, float d, Color *e)+RLBIND void DrawRectangleRoundedLines_(Rectangle *a, float b, int c, Color *d) {- DrawRectangleRoundedLines(*a, b, c, d, *e);+ DrawRectangleRoundedLines(*a, b, c, *d); } +RLBIND void DrawRectangleRoundedLinesEx_(Rectangle *a, float b, int c, float d, Color *e)+{+ DrawRectangleRoundedLinesEx(*a, b, c, d, *e);+}+ RLBIND void DrawTriangle_(Vector2 *a, Vector2 *b, Vector2 *c, Color *d) { DrawTriangle(*a, *b, *c, *d);@@ -456,12 +461,12 @@ DrawTriangleLines(*a, *b, *c, *d); } -RLBIND void DrawTriangleFan_(Vector2 *a, int b, Color *c)+RLBIND void DrawTriangleFan_(const Vector2 *a, int b, Color *c) { DrawTriangleFan(a, b, *c); } -RLBIND void DrawTriangleStrip_(Vector2 *a, int b, Color *c)+RLBIND void DrawTriangleStrip_(const Vector2 *a, int b, Color *c) { DrawTriangleStrip(a, b, *c); }@@ -481,27 +486,27 @@ DrawPolyLinesEx(*a, b, c, d, e, *f); } -RLBIND void DrawSplineLinear_(Vector2 *a, int b, float c, Color *d)+RLBIND void DrawSplineLinear_(const Vector2 *a, int b, float c, Color *d) { DrawSplineLinear(a, b, c, *d); } -RLBIND void DrawSplineBasis_(Vector2 *a, int b, float c, Color *d)+RLBIND void DrawSplineBasis_(const Vector2 *a, int b, float c, Color *d) { DrawSplineBasis(a, b, c, *d); } -RLBIND void DrawSplineCatmullRom_(Vector2 *a, int b, float c, Color *d)+RLBIND void DrawSplineCatmullRom_(const Vector2 *a, int b, float c, Color *d) { DrawSplineCatmullRom(a, b, c, *d); } -RLBIND void DrawSplineBezierQuadratic_(Vector2 *a, int b, float c, Color *d)+RLBIND void DrawSplineBezierQuadratic_(const Vector2 *a, int b, float c, Color *d) { DrawSplineBezierQuadratic(a, b, c, *d); } -RLBIND void DrawSplineBezierCubic_(Vector2 *a, int b, float c, Color *d)+RLBIND void DrawSplineBezierCubic_(const Vector2 *a, int b, float c, Color *d) { DrawSplineBezierCubic(a, b, c, *d); }@@ -596,7 +601,7 @@ return CheckCollisionPointTriangle(*a, *b, *c, *d); } -RLBIND bool CheckCollisionPointPoly_(Vector2 *a, Vector2 *b, int c)+RLBIND bool CheckCollisionPointPoly_(Vector2 *a, const Vector2 *b, int c) { return CheckCollisionPointPoly(*a, b, c); }@@ -611,6 +616,11 @@ return CheckCollisionPointLine(*a, *b, *c, d); } +RLBIND bool CheckCollisionCircleLine_(Vector2 *a, float b, Vector2 *c, Vector2 *d)+{+ return CheckCollisionCircleLine(*a, b, *c, *d);+}+ RLBIND Rectangle *GetCollisionRec_(Rectangle *a, Rectangle *b) { Rectangle *ptr = (Rectangle *)malloc(sizeof(Rectangle));@@ -776,6 +786,13 @@ return ptr; } +RLBIND Image *ImageFromChannel_(Image *a, int b)+{+ Image *ptr = (Image *)malloc(sizeof(Image));+ *ptr = ImageFromChannel(*a, b);+ return ptr;+}+ RLBIND Image *ImageText_(char *a, int b, Color *c) { Image *ptr = (Image *)malloc(sizeof(Image));@@ -914,6 +931,31 @@ ImageDrawRectangleLines(a, *b, c, *d); } +RLBIND void ImageDrawTriangle_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e)+{+ ImageDrawTriangle(a, *b, *c, *d, *e);+}++RLBIND void ImageDrawTriangleEx_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e, Color *f, Color *g)+{+ ImageDrawTriangleEx(a, *b, *c, *d, *e, *f, *g);+}++RLBIND void ImageDrawTriangleLines_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e)+{+ ImageDrawTriangleLines(a, *b, *c, *d, *e);+}++RLBIND void ImageDrawTriangleFan_(Image *a, Vector2 *b, int c, Color *d)+{+ ImageDrawTriangleFan(a, b, c, *d);+}++RLBIND void ImageDrawTriangleStrip_(Image *a, Vector2 *b, int c, Color *d)+{+ ImageDrawTriangleStrip(a, b, c, *d);+}+ RLBIND void ImageDraw_(Image *a, Image *b, Rectangle *c, Rectangle *d, Color *e) { ImageDraw(a, *b, *c, *d, *e);@@ -1270,7 +1312,7 @@ DrawTriangle3D(*a, *b, *c, *d); } -RLBIND void DrawTriangleStrip3D_(Vector3 *a, int b, Color *c)+RLBIND void DrawTriangleStrip3D_(const Vector3 *a, int b, Color *c) { DrawTriangleStrip3D(a, b, *c); }@@ -2440,6 +2482,11 @@ return IsPathFile(a); } +RLBIND bool IsFileNameValid_(const char *a)+{+ return IsFileNameValid(a);+}+ RLBIND bool IsFileDropped_() { return IsFileDropped();@@ -2715,7 +2762,7 @@ ImageBlurGaussian(a, b); } -RLBIND void ImageKernelConvolution_(Image *a, float *b, int c)+RLBIND void ImageKernelConvolution_(Image *a, const float *b, int c) { ImageKernelConvolution(a, b, c); }
lib/rl_bindings.h view
@@ -118,7 +118,7 @@ void DrawLineEx_(Vector2 *a, Vector2 *b, float c, Color *d); -void DrawLineStrip_(Vector2 *a, int b, Color *c);+void DrawLineStrip_(const Vector2 *a, int b, Color *c); void DrawLineBezier_(Vector2 *a, Vector2 *b, float c, Color *d); @@ -164,15 +164,17 @@ void DrawRectangleRounded_(Rectangle *a, float b, int c, Color *d); -void DrawRectangleRoundedLines_(Rectangle *a, float b, int c, float d, Color *e);+void DrawRectangleRoundedLines_(Rectangle *a, float b, int c, Color *d); +void DrawRectangleRoundedLinesEx_(Rectangle *a, float b, int c, float d, Color *e);+ void DrawTriangle_(Vector2 *a, Vector2 *b, Vector2 *c, Color *d); void DrawTriangleLines_(Vector2 *a, Vector2 *b, Vector2 *c, Color *d); -void DrawTriangleFan_(Vector2 *a, int b, Color *c);+void DrawTriangleFan_(const Vector2 *a, int b, Color *c); -void DrawTriangleStrip_(Vector2 *a, int b, Color *c);+void DrawTriangleStrip_(const Vector2 *a, int b, Color *c); void DrawPoly_(Vector2 *a, int b, float c, float d, Color *e); @@ -180,15 +182,15 @@ void DrawPolyLinesEx_(Vector2 *a, int b, float c, float d, float e, Color *f); -void DrawSplineLinear_(Vector2 *a, int b, float c, Color *d);+void DrawSplineLinear_(const Vector2 *a, int b, float c, Color *d); -void DrawSplineBasis_(Vector2 *a, int b, float c, Color *d);+void DrawSplineBasis_(const Vector2 *a, int b, float c, Color *d); -void DrawSplineCatmullRom_(Vector2 *a, int b, float c, Color *d);+void DrawSplineCatmullRom_(const Vector2 *a, int b, float c, Color *d); -void DrawSplineBezierQuadratic_(Vector2 *a, int b, float c, Color *d);+void DrawSplineBezierQuadratic_(const Vector2 *a, int b, float c, Color *d); -void DrawSplineBezierCubic_(Vector2 *a, int b, float c, Color *d);+void DrawSplineBezierCubic_(const Vector2 *a, int b, float c, Color *d); void DrawSplineSegmentLinear_(Vector2 *a, Vector2 *b, float c, Color *d); @@ -222,12 +224,14 @@ bool CheckCollisionPointTriangle_(Vector2 *a, Vector2 *b, Vector2 *c, Vector2 *d); -bool CheckCollisionPointPoly_(Vector2 *a, Vector2 *b, int c);+bool CheckCollisionPointPoly_(Vector2 *a, const Vector2 *b, int c); bool CheckCollisionLines_(Vector2 *a, Vector2 *b, Vector2 *c, Vector2 *d, Vector2 *e); bool CheckCollisionPointLine_(Vector2 *a, Vector2 *b, Vector2 *c, int d); +bool CheckCollisionCircleLine_(Vector2 *a, float b, Vector2 *c, Vector2 *d);+ Rectangle *GetCollisionRec_(Rectangle *a, Rectangle *b); Image *LoadImage_(char *a);@@ -278,6 +282,8 @@ Image *ImageFromImage_(Image *a, Rectangle *b); +Image *ImageFromChannel_(Image *a, int b);+ Image *ImageText_(char *a, int b, Color *c); Image *ImageTextEx_(Font *a, char *b, float c, float d, Color *e);@@ -330,6 +336,16 @@ void ImageDrawRectangleLines_(Image *a, Rectangle *b, int c, Color *d); +void ImageDrawTriangle_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e);++void ImageDrawTriangleEx_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e, Color *f, Color *g);++void ImageDrawTriangleLines_(Image *a, Vector2 *b, Vector2 *c, Vector2 *d, Color *e);++void ImageDrawTriangleFan_(Image *a, Vector2 *b, int c, Color *d);++void ImageDrawTriangleStrip_(Image *a, Vector2 *b, int c, Color *d);+ void ImageDraw_(Image *a, Image *b, Rectangle *c, Rectangle *d, Color *e); void ImageDrawText_(Image *a, char *b, int c, int d, int e, Color *f);@@ -440,7 +456,7 @@ void DrawTriangle3D_(Vector3 *a, Vector3 *b, Vector3 *c, Color *d); -void DrawTriangleStrip3D_(Vector3 *a, int b, Color *c);+void DrawTriangleStrip3D_(const Vector3 *a, int b, Color *c); void DrawCube_(Vector3 *a, float b, float c, float d, Color *e); @@ -888,6 +904,8 @@ bool IsPathFile_(const char *a); +bool IsFileNameValid_(const char *a);+ bool IsFileDropped_(); long GetFileModTime_(const char *a);@@ -998,7 +1016,7 @@ void ImageBlurGaussian_(Image *a, int b); -void ImageKernelConvolution_(Image *a, float *b, int c);+void ImageKernelConvolution_(Image *a, const float *b, int c); void ImageResize_(Image *a, int b, int c);
lib/rlgl_bindings.c view
@@ -116,6 +116,19 @@ rlViewport(a, b, c, d); } +RLBIND void rlSetClipPlanes_(double a, double b)+{+ rlSetClipPlanes(a, b);+}++RLBIND double rlGetCullDistanceNear_() {+ return rlGetCullDistanceNear();+}++RLBIND double rlGetCullDistanceFar_() {+ return rlGetCullDistanceFar();+}+ RLBIND void rlBegin_(int a) { rlBegin(a);@@ -391,7 +404,7 @@ rlUnloadVertexBuffer(a); } -RLBIND void rlSetVertexAttribute_(unsigned int a, int b, int c, bool d, int e, const void *f)+RLBIND void rlSetVertexAttribute_(unsigned int a, int b, int c, bool d, int e, int f) { rlSetVertexAttribute(a, b, c, d, e, f); }
lib/rlgl_bindings.h view
@@ -46,6 +46,12 @@ void rlViewport_(int a, int b, int c, int d); +void rlSetClipPlanes_(double a, double b);++double rlGetCullDistanceNear_();++double rlGetCullDistanceFar_();+ void rlBegin_(int a); void rlVertex2i_(int a, int b);@@ -156,7 +162,7 @@ void rlUnloadVertexBuffer_(unsigned int a); -void rlSetVertexAttribute_(unsigned int a, int b, int c, bool d, int e, const void *f);+void rlSetVertexAttribute_(unsigned int a, int b, int c, bool d, int e, int f); void rlSetVertexAttributeDivisor_(unsigned int a, int b);
− raygui/examples/styles/style_ashes.h
@@ -1,578 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleAshes(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define ASHES_STYLE_PROPS_COUNT 16--// Custom style name: Ashes-static const GuiStyleProp ashesStyleProps[ASHES_STYLE_PROPS_COUNT] = {- { 0, 0, 0xf0f0f0ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x868686ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xe6e6e6ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0x929999ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xeaeaeaff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0x98a1a8ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0x3f3f3fff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xf6f6f6ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x414141ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x8b8b8bff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x777777ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x959595ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 18, 0x9dadb1ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x6b6b6bff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "v5loxical.ttf" (size: 16, spacing: 1)--#define ASHES_STYLE_FONT_ATLAS_COMP_SIZE 2042--// Font atlas image pixels data: DEFLATE compressed-static unsigned char ashesFontData[ASHES_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0xd1, 0xb2, 0xab, 0x36, 0x0c, 0x05, 0x50, 0xff, 0xff, 0x4f, 0xab, 0x0f, 0x9d, 0x4e, 0xdb, 0x69, 0x13, 0x90, 0x2c,- 0x83, 0x21, 0xeb, 0xae, 0xb7, 0x9c, 0xdc, 0x40, 0x0c, 0x1b, 0x63, 0x88, 0x45, 0x0c, 0x00, 0x00, 0x00, 0xe0, 0xe7, 0xc5,- 0xff, 0xbe, 0x12, 0x1f, 0xdf, 0x19, 0xa7, 0x3f, 0xe7, 0xdf, 0xaf, 0xc7, 0x87, 0xbf, 0xe6, 0x3e, 0x2f, 0x4e, 0x2f, 0xb7,- 0xf2, 0x97, 0xf8, 0xdf, 0xf5, 0x8b, 0xe9, 0xa5, 0xc6, 0xe9, 0x6f, 0xf3, 0xed, 0xbd, 0xdf, 0x96, 0xf9, 0xe9, 0x93, 0x22,- 0xb1, 0x8c, 0xec, 0xfb, 0x3f, 0x7f, 0xce, 0xd5, 0x2d, 0x1e, 0x5f, 0xfe, 0xf2, 0xfd, 0xaf, 0xd9, 0xd7, 0xe3, 0xe4, 0xab,- 0xdf, 0xfe, 0x12, 0x07, 0x7f, 0x39, 0x9b, 0xbb, 0x78, 0x40, 0xfe, 0xe3, 0xcb, 0xe7, 0x7d, 0xff, 0xc4, 0x98, 0x38, 0x26,- 0x9c, 0x5b, 0xee, 0x95, 0xed, 0xf9, 0x69, 0x4f, 0xcf, 0x6d, 0xeb, 0xef, 0x6d, 0x9c, 0xcb, 0x5c, 0x34, 0xac, 0xff, 0x6c,- 0xab, 0x45, 0xc3, 0xbb, 0xe3, 0xc4, 0xde, 0x92, 0xd9, 0x9b, 0xb3, 0x69, 0xab, 0xbd, 0x7f, 0x34, 0x6c, 0xaf, 0x6b, 0xf3,- 0xff, 0xcf, 0x7f, 0x23, 0x75, 0x14, 0x1c, 0x4d, 0xf9, 0xcf, 0xf7, 0xb9, 0xdf, 0x8e, 0xbe, 0x71, 0xd1, 0xd9, 0xd4, 0xb9,- 0x3d, 0xb4, 0xfe, 0x7a, 0xdf, 0xa7, 0x5f, 0x9d, 0xff, 0x68, 0xfc, 0x1f, 0x47, 0x6b, 0x17, 0xf2, 0x3f, 0xbd, 0x15, 0xa2,- 0xd8, 0xdb, 0x56, 0x7b, 0xa2, 0xd9, 0xad, 0x1f, 0x8b, 0x7b, 0xfa, 0x55, 0x09, 0xad, 0x1d, 0xcd, 0x22, 0xf9, 0x7f, 0x72,- 0x7d, 0x6c, 0x4c, 0x6f, 0xbd, 0xf3, 0xfb, 0x44, 0x7e, 0xfd, 0x8e, 0xf7, 0x00, 0xf9, 0xbf, 0x22, 0xff, 0x95, 0xe4, 0xc6,- 0x92, 0xa3, 0x7f, 0xf5, 0xca, 0xc0, 0x8a, 0xb6, 0xcc, 0xe5, 0x3f, 0x1a, 0x5b, 0x20, 0xdb, 0x6f, 0xe7, 0xd7, 0xff, 0xec,- 0x48, 0x3d, 0x6e, 0xec, 0xff, 0xbf, 0x1d, 0x1d, 0x33, 0x47, 0xcd, 0x6c, 0x3a, 0x73, 0xcb, 0xfd, 0x7b, 0x5d, 0xe7, 0xaf,- 0x88, 0xac, 0xc8, 0x7f, 0xf5, 0xfc, 0xbf, 0x72, 0x86, 0x3a, 0x36, 0xc9, 0xf3, 0xf5, 0xf9, 0x8f, 0xf6, 0x16, 0x58, 0x99,- 0xff, 0xb3, 0x6d, 0x1f, 0x0b, 0xc7, 0xff, 0xb9, 0xab, 0xab, 0xfb, 0xf7, 0xff, 0xf7, 0x5f, 0xff, 0x1b, 0xe5, 0xeb, 0x46,- 0xd9, 0x6b, 0x80, 0x71, 0xea, 0xec, 0xe1, 0x29, 0xf9, 0xef, 0x38, 0xfe, 0x55, 0x47, 0x4a, 0x1d, 0x57, 0xb8, 0xb2, 0xf9,- 0x8f, 0x86, 0xb6, 0x8f, 0xa5, 0x47, 0xff, 0x4a, 0xaf, 0x24, 0xff, 0xbd, 0xe3, 0xff, 0x38, 0x71, 0x06, 0x18, 0xaf, 0xe8,- 0xff, 0xf3, 0xa3, 0x9c, 0x68, 0xb8, 0x07, 0x57, 0xb9, 0xbb, 0x9a, 0xed, 0x31, 0x2b, 0xf7, 0x24, 0x77, 0x68, 0x77, 0xfd,- 0xff, 0x75, 0xdb, 0xa0, 0xb6, 0x2f, 0xfc, 0xf5, 0xff, 0x9e, 0xdf, 0xff, 0xef, 0xb4, 0x35, 0x90, 0xff, 0xab, 0xf7, 0xdb,- 0xb8, 0xb5, 0x7f, 0x95, 0x7f, 0xbf, 0x60, 0xeb, 0xca, 0xff, 0xda, 0xdf, 0xff, 0xc4, 0x41, 0x6f, 0x38, 0x1e, 0xd9, 0xff,- 0x5f, 0xb3, 0x36, 0x21, 0x79, 0xe0, 0x58, 0x2f, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0xfc, 0xd0, 0xec, 0x99, 0xcc, 0xec, 0xe5, 0x6a, 0x15, 0xe0, 0x8e, 0xf7, 0x57, 0x97, 0x10, 0x6d, 0xf5, 0x1f, 0xfb,- 0xaa, 0x49, 0x7e, 0x9e, 0x4d, 0x9a, 0x99, 0xf7, 0x9c, 0xab, 0x6f, 0x9e, 0xab, 0x24, 0x17, 0xc9, 0x9a, 0x6d, 0x91, 0xac,- 0x5b, 0x9c, 0xdd, 0x8e, 0xf3, 0xb3, 0xec, 0xe7, 0xfe, 0xff, 0xdf, 0xb5, 0x2a, 0xfa, 0xf6, 0xe5, 0xd1, 0xd4, 0x32, 0xd7,- 0xe5, 0x7f, 0xb4, 0xd7, 0x54, 0xcd, 0x57, 0xa8, 0xca, 0xd7, 0xc7, 0x1f, 0x9b, 0xe5, 0x3f, 0xb3, 0x3f, 0x66, 0xeb, 0xfe,- 0x44, 0x61, 0x56, 0x64, 0x4c, 0xcf, 0xb7, 0x8c, 0x85, 0xfb, 0x5d, 0x57, 0x05, 0xc9, 0x31, 0x99, 0xff, 0x3b, 0xf7, 0xfd,- 0x4a, 0x6d, 0x46, 0xf9, 0x7f, 0x43, 0xfe, 0x2b, 0xd5, 0x3d, 0x3b, 0xe6, 0x45, 0x77, 0xd5, 0xc7, 0x8d, 0xf4, 0x79, 0x51,- 0x66, 0x7f, 0x88, 0xa9, 0xca, 0xea, 0x91, 0x3e, 0x0e, 0xef, 0x98, 0x7f, 0xfd, 0x7f, 0xa5, 0x36, 0xde, 0xdd, 0xf9, 0x9f,- 0x7b, 0x22, 0xc0, 0xea, 0xea, 0x07, 0x6b, 0xfb, 0xa7, 0xde, 0xfe, 0x3f, 0x26, 0xf2, 0x9f, 0x7d, 0x86, 0xd9, 0x5e, 0xf9,- 0x9f, 0x3f, 0xff, 0xaf, 0x57, 0x3b, 0xef, 0x1a, 0x05, 0x8f, 0x86, 0xe3, 0x7d, 0xf5, 0x49, 0x82, 0x5d, 0xf9, 0x1f, 0x85,- 0xa7, 0xc0, 0xcd, 0x9e, 0x8f, 0x3e, 0x3b, 0xff, 0xb9, 0x2b, 0x11, 0xeb, 0xf2, 0xff, 0xec, 0xfe, 0x7f, 0xbc, 0xe0, 0xfc,- 0xbf, 0x63, 0x7b, 0x8f, 0x4d, 0xcf, 0xff, 0xbb, 0x46, 0xd1, 0xef, 0xcb, 0x7f, 0xf6, 0x7b, 0x76, 0x7c, 0xfe, 0x5b, 0xcf,- 0xff, 0xe5, 0xff, 0xed, 0xf9, 0xbf, 0xeb, 0x49, 0x66, 0x7b, 0xe4, 0x3f, 0x9a, 0xaa, 0xef, 0xca, 0xff, 0x5b, 0xf3, 0xbf,- 0xeb, 0xf5, 0xbf, 0xe7, 0xe6, 0x7f, 0x94, 0xc6, 0x66, 0x73, 0xef, 0x7e, 0x42, 0xff, 0x3f, 0x0a, 0xd7, 0xac, 0xf2, 0x23,- 0xd9, 0xeb, 0xc6, 0xff, 0xf2, 0x7f, 0xee, 0xee, 0xd9, 0xdd, 0xf9, 0x5f, 0x73, 0xff, 0xab, 0xef, 0xbc, 0xa0, 0xe3, 0xdd,- 0x7b, 0x8f, 0xff, 0x57, 0xff, 0x16, 0x67, 0xed, 0xf2, 0x7b, 0xae, 0xb4, 0x45, 0xf9, 0xba, 0x7d, 0xcf, 0x6f, 0x49, 0xf2,- 0xd7, 0xdf, 0xb2, 0x47, 0xce, 0x38, 0x78, 0x7f, 0x34, 0xf5, 0x73, 0x95, 0xea, 0xf0, 0x3b, 0xe4, 0x3f, 0xfb, 0xd4, 0x9f,- 0xec, 0xbb, 0xf7, 0xc8, 0xff, 0xfa, 0x96, 0xbd, 0x3a, 0xff, 0x4f, 0xfc, 0xb5, 0xe2, 0xef, 0xb5, 0x42, 0x2c, 0x7e, 0xff,- 0x6f, 0xef, 0x0b, 0x7b, 0x3d, 0x31, 0xcb, 0x76, 0xe5, 0xca, 0xbe, 0x15, 0xad, 0x05, 0x8e, 0xac, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9b, 0xfb, 0x70, 0x34, 0x7f, 0x32, 0x9a, 0xaa, 0x20, 0x64, 0xeb, 0xc0,- 0x8d, 0xd3, 0xb5, 0xf0, 0xa3, 0x54, 0x79, 0x76, 0xbe, 0xba, 0xc2, 0xf7, 0x19, 0xcd, 0x9f, 0xbf, 0x69, 0x14, 0x66, 0x09,- 0x67, 0x9f, 0x6d, 0x50, 0xa9, 0xad, 0x50, 0x5f, 0x56, 0x14, 0xab, 0x48, 0xce, 0xb7, 0x41, 0x14, 0x9e, 0xef, 0x70, 0xf4,- 0x5d, 0xf2, 0x5b, 0x21, 0xf3, 0x5a, 0x65, 0x6e, 0xf9, 0x38, 0xf1, 0xdc, 0x81, 0x38, 0x9c, 0xdf, 0xd0, 0x9b, 0xff, 0xd5,- 0x75, 0xb0, 0x2b, 0xb5, 0x3c, 0xfe, 0xfb, 0xda, 0x7d, 0x75, 0x27, 0xbe, 0x1d, 0x77, 0x2a, 0x55, 0x28, 0xb2, 0xc7, 0xe1,- 0xfc, 0x5e, 0x38, 0xb7, 0xac, 0x91, 0xda, 0x02, 0x95, 0x7a, 0xe6, 0x9d, 0x6d, 0x1a, 0x85, 0x9a, 0x17, 0xe7, 0x7b, 0x9f,- 0x28, 0xb6, 0xfd, 0x4c, 0xcd, 0x9d, 0x33, 0x33, 0x8a, 0xa3, 0xb0, 0xe7, 0x75, 0xd5, 0xc1, 0x8d, 0x96, 0x4c, 0x77, 0x54,- 0xc1, 0xca, 0xd5, 0xee, 0xcd, 0xce, 0x24, 0x8d, 0xc9, 0xfd, 0x38, 0xbf, 0x7f, 0x47, 0x4b, 0x35, 0xae, 0xe3, 0x65, 0xc5,- 0x97, 0x65, 0x65, 0xf2, 0x5f, 0xef, 0x4b, 0xd7, 0xe7, 0x3f, 0xbf, 0x06, 0x99, 0x0a, 0x52, 0x73, 0xbd, 0xe3, 0x7c, 0xfe,- 0x77, 0xed, 0xff, 0xef, 0xce, 0x7f, 0xbe, 0x06, 0xcc, 0xd1, 0x79, 0x77, 0x65, 0x2f, 0x8a, 0x52, 0x26, 0xb3, 0xfb, 0x60,- 0xbd, 0xff, 0x8f, 0xd2, 0x39, 0x55, 0xe7, 0xb6, 0xbd, 0x22, 0xff, 0x63, 0x61, 0xfe, 0xef, 0xee, 0xff, 0xf7, 0xcc, 0x7f,- 0x5f, 0x2d, 0xdf, 0xb9, 0xfc, 0xe7, 0x53, 0x3e, 0x8a, 0x6b, 0xde, 0x77, 0xfe, 0x1f, 0xe9, 0xf1, 0xd3, 0xcc, 0xb2, 0xa2,- 0xe5, 0x5c, 0x6b, 0x1c, 0x3c, 0x9f, 0xf0, 0xf9, 0xf9, 0x1f, 0xc5, 0x33, 0xe0, 0xa3, 0xa7, 0x61, 0xe4, 0xdb, 0x67, 0x76,- 0x84, 0xbb, 0xbe, 0x0a, 0xf2, 0xf5, 0xcf, 0xc1, 0x88, 0x86, 0xb3, 0xfc, 0xa3, 0xca, 0x85, 0xb1, 0x41, 0xfe, 0xeb, 0xd7,- 0x87, 0xbb, 0xfa, 0xff, 0xee, 0xeb, 0xd6, 0x3d, 0xf9, 0x1f, 0xa5, 0x71, 0x4c, 0x5f, 0x3b, 0x8f, 0xa9, 0xfe, 0x7f, 0xbc,- 0x2c, 0xff, 0xd7, 0x3f, 0x07, 0x23, 0x5a, 0x46, 0xf9, 0x51, 0x7c, 0xde, 0x50, 0xef, 0xf9, 0xff, 0xb7, 0xe7, 0xe2, 0x46,- 0xf9, 0xd9, 0x70, 0x6b, 0xf3, 0x7f, 0xee, 0x6a, 0xf5, 0xca, 0xfc, 0x0f, 0xf9, 0x3f, 0x79, 0x87, 0xeb, 0xe8, 0x5e, 0xc5,- 0x48, 0xdf, 0x75, 0x99, 0xbd, 0x77, 0x74, 0xe5, 0xf9, 0xff, 0x75, 0xfd, 0xff, 0x58, 0x72, 0xfd, 0x7f, 0x45, 0x3f, 0xfb,- 0xa4, 0xfe, 0xff, 0xfb, 0x9e, 0xfd, 0x9c, 0xfc, 0x9f, 0x49, 0xdc, 0x78, 0x44, 0x45, 0xd1, 0xae, 0x4a, 0xd0, 0xd7, 0x5e,- 0xff, 0xeb, 0xbe, 0x9f, 0xd1, 0x73, 0xfe, 0x9f, 0xef, 0x49, 0xe7, 0x46, 0xb9, 0x9d, 0xcb, 0xba, 0xee, 0xfc, 0xff, 0x1d,- 0xf9, 0xef, 0x59, 0xbb, 0xfb, 0x2b, 0x20, 0xee, 0x99, 0xff, 0x51, 0xfc, 0x7d, 0xcd, 0xbd, 0xe7, 0xff, 0x57, 0xe6, 0x6c,- 0x8f, 0x7d, 0xe6, 0xbd, 0xf9, 0x3f, 0xfa, 0xfd, 0xcf, 0x13, 0xb7, 0xdb, 0xec, 0xd1, 0x27, 0x16, 0xbd, 0xf7, 0xae, 0xb3,- 0xa3, 0x98, 0xba, 0x56, 0x21, 0xff, 0x9d, 0xf9, 0x7f, 0x53, 0xc2, 0x9e, 0x92, 0xff, 0x55, 0x47, 0x8c, 0xa7, 0x3c, 0x19,- 0x42, 0xfe, 0xaf, 0xcd, 0xff, 0xaf, 0x24, 0xec, 0xbd, 0xf9, 0x7f, 0xdf, 0xd1, 0x2c, 0x3b, 0x86, 0x8e, 0x0b, 0xc7, 0xdd,- 0x71, 0xe3, 0x18, 0xbf, 0xba, 0x5e, 0xd7, 0xac, 0xf3, 0xae, 0x2d, 0xf3, 0x84, 0xb5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x67, 0xb9, 0x44, 0xcb, 0x6c, 0xd9, 0x51, 0xaa, 0xc3, 0x9e, 0x9f, 0x0b, 0x99, 0xad,- 0x35, 0x3f, 0x5a, 0xea, 0x14, 0x57, 0xaa, 0xc5, 0x1e, 0xcf, 0x37, 0x8d, 0x64, 0x5b, 0xde, 0xb5, 0xad, 0xa2, 0xbc, 0xf4,- 0x95, 0xdb, 0xe4, 0xf3, 0xac, 0xa0, 0xfc, 0x93, 0x16, 0x2a, 0xd5, 0x33, 0xae, 0xcb, 0xc1, 0xea, 0xd9, 0xfc, 0xf9, 0xba,- 0xfc, 0xf3, 0x55, 0x4f, 0xfb, 0x9e, 0x14, 0xd0, 0xfd, 0x2d, 0x32, 0x75, 0x5e, 0xcf, 0xb5, 0x42, 0x34, 0xb5, 0xe5, 0x5d,- 0xdb, 0xea, 0x68, 0x8d, 0x62, 0xf9, 0xda, 0x76, 0xd5, 0xeb, 0x8e, 0x52, 0x3f, 0x78, 0x47, 0x0e, 0x2a, 0xfd, 0xd1, 0xfd,- 0xb3, 0x5c, 0xe7, 0xe7, 0xf7, 0xd6, 0xf3, 0xff, 0xd4, 0xf3, 0xb1, 0x67, 0x7c, 0xa7, 0xef, 0xb5, 0xb4, 0x76, 0xfa, 0x0e,- 0xd5, 0xfc, 0x77, 0x54, 0x97, 0xe9, 0x9c, 0xe7, 0x1e, 0x5f, 0x6a, 0x2e, 0x47, 0xeb, 0xf9, 0xff, 0x4e, 0xaf, 0x57, 0xf3,- 0x9f, 0x1f, 0x2f, 0xcc, 0x8e, 0x2f, 0xe6, 0x9f, 0x50, 0x94, 0xaf, 0xde, 0x79, 0xdf, 0xeb, 0xdd, 0xcf, 0x48, 0x5a, 0xfd,- 0x7a, 0x25, 0xff, 0xbb, 0xf6, 0x0d, 0x3d, 0xf9, 0x8f, 0x0d, 0xb7, 0x52, 0x7e, 0xf4, 0x36, 0x7f, 0x9e, 0x59, 0x3d, 0xbe,- 0x74, 0xe7, 0x7f, 0xc7, 0xb6, 0xcf, 0x8f, 0xff, 0x9f, 0x97, 0xff, 0x28, 0xf4, 0xc3, 0xf7, 0xf5, 0x83, 0x99, 0xa7, 0x58,- 0xd6, 0xc7, 0xf8, 0xfb, 0xef, 0x83, 0xf2, 0x7f, 0x77, 0xdb, 0x8f, 0x1f, 0xe8, 0xff, 0xf7, 0xd9, 0xef, 0xba, 0xc7, 0xc1,- 0xf2, 0x2f, 0xff, 0xf2, 0x1f, 0x27, 0xc6, 0x63, 0x7b, 0xbc, 0x7e, 0x5d, 0xfe, 0x73, 0x95, 0xf9, 0xd7, 0xbf, 0x5e, 0xcb,- 0xed, 0xda, 0x6d, 0x24, 0xff, 0xfb, 0xe5, 0x7f, 0xe6, 0x89, 0x61, 0x4f, 0x68, 0xf3, 0xde, 0xfb, 0x7f, 0xcf, 0x1a, 0x6b,- 0xea, 0xff, 0xe5, 0xbf, 0x7e, 0xff, 0xff, 0x1d, 0xf9, 0xef, 0xbe, 0x97, 0xf7, 0x94, 0xeb, 0x7f, 0xe3, 0xe0, 0xb9, 0x40,- 0x71, 0xcb, 0x73, 0xc4, 0xd6, 0xe4, 0xff, 0x19, 0xdb, 0xe4, 0x78, 0xaf, 0x7a, 0x52, 0xfe, 0x9f, 0xdf, 0xe6, 0x9d, 0xf7,- 0x25, 0xdf, 0xf1, 0xbd, 0x9f, 0x99, 0xff, 0x37, 0x6c, 0x93, 0xa3, 0x11, 0xd3, 0x9e, 0xfd, 0xff, 0xf3, 0x73, 0x10, 0x8b,- 0x7f, 0x83, 0xb2, 0x6f, 0xfe, 0xc7, 0x6b, 0xfa, 0xff, 0xe7, 0x6f, 0x93, 0xb8, 0xf1, 0x5b, 0xf4, 0xe6, 0x7f, 0xb7, 0xfb,- 0x7f, 0x77, 0xff, 0x06, 0xed, 0x69, 0xe7, 0x3d, 0xcf, 0xfb, 0xfd, 0x4f, 0x6d, 0x4c, 0xfd, 0xa4, 0x7d, 0xf1, 0xae, 0x3b,- 0xe7, 0x2a, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xd6, 0x55, 0xdf, 0x3c, 0x8a,- 0x33, 0xab, 0xce, 0xbd, 0x56, 0xa9, 0xe6, 0x1e, 0xcb, 0xbe, 0x6b, 0xa5, 0x36, 0x4b, 0xb4, 0xcd, 0x5d, 0xea, 0xda, 0x32,- 0x9f, 0x97, 0x1b, 0xc5, 0x2a, 0x2c, 0xbc, 0xeb, 0x08, 0xb0, 0xaa, 0x42, 0xfe, 0x68, 0xa8, 0x92, 0x5f, 0xab, 0xe6, 0x78,- 0x4f, 0x2d, 0xf7, 0xb9, 0x99, 0xb2, 0xeb, 0xb6, 0x4c, 0x6f, 0x9d, 0x7c, 0xde, 0x75, 0x04, 0x58, 0xf9, 0x1c, 0x91, 0x68,- 0xfc, 0xcc, 0xd8, 0xea, 0xbb, 0x8e, 0xaf, 0x33, 0xcf, 0x46, 0xa2, 0xf2, 0xc4, 0xfa, 0xb5, 0x8d, 0xd6, 0x96, 0x85, 0x3b,- 0x8e, 0x59, 0xcf, 0xde, 0x4b, 0xf7, 0xeb, 0x51, 0xe5, 0xff, 0xd7, 0x92, 0xb4, 0x7a, 0x8e, 0xf8, 0x6c, 0x5d, 0x8e, 0xfc,- 0x59, 0xea, 0x7e, 0x35, 0x1b, 0xa2, 0x30, 0xa7, 0x7f, 0x78, 0x4e, 0x06, 0x37, 0xf5, 0x3f, 0x9d, 0x75, 0x3b, 0xae, 0xcf,- 0xff, 0x5e, 0xaf, 0xd7, 0xfa, 0x7f, 0xf9, 0x47, 0xfe, 0xe5, 0x5f, 0xfe, 0x91, 0xff, 0xf7, 0xe6, 0x3f, 0xe4, 0x9f, 0x5b,- 0x47, 0xff, 0x2b, 0x9f, 0xdb, 0x21, 0xff, 0x73, 0x77, 0xff, 0xe4, 0x9f, 0x3b, 0xee, 0xfe, 0xf7, 0x55, 0xc8, 0x95, 0xff,- 0xda, 0xaf, 0xaf, 0xe4, 0x1f, 0xf9, 0x7f, 0x7b, 0xff, 0x2f, 0xff, 0xb8, 0xff, 0x77, 0x4d, 0xfe, 0xd5, 0xc9, 0xce, 0xfd,- 0x4a, 0x3a, 0xf7, 0x24, 0x44, 0xb8, 0xfe, 0xba, 0x85, 0xbd, 0xb1, 0xff, 0xb7, 0x99, 0x47, 0x2d, 0xab, 0xc5, 0xe1, 0x17,- 0xe6, 0x7f, 0xc9, 0x3f, 0xfc, 0xda, 0xc8, 0xaf, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe3, 0xcf, 0x7f, 0xda, 0x01, 0xe4, 0x1f, 0xf8, 0xb9, 0xfc, 0xff,- 0x01 };--// Font glyphs rectangles data (on atlas)-static const Rectangle ashesFontRecs[189] = {- { 4, 4, 4 , 16 },- { 16, 4, 1 , 10 },- { 25, 4, 3 , 3 },- { 36, 4, 6 , 8 },- { 50, 4, 5 , 11 },- { 63, 4, 7 , 8 },- { 78, 4, 6 , 9 },- { 92, 4, 1 , 3 },- { 101, 4, 3 , 12 },- { 112, 4, 3 , 12 },- { 123, 4, 5 , 5 },- { 136, 4, 5 , 5 },- { 149, 4, 2 , 2 },- { 159, 4, 4 , 1 },- { 171, 4, 1 , 1 },- { 180, 4, 5 , 10 },- { 193, 4, 4 , 8 },- { 205, 4, 2 , 8 },- { 215, 4, 4 , 8 },- { 227, 4, 4 , 8 },- { 239, 4, 6 , 8 },- { 253, 4, 4 , 8 },- { 265, 4, 4 , 8 },- { 277, 4, 4 , 8 },- { 289, 4, 4 , 8 },- { 301, 4, 4 , 8 },- { 313, 4, 1 , 5 },- { 322, 4, 2 , 6 },- { 332, 4, 4 , 7 },- { 344, 4, 4 , 4 },- { 356, 4, 4 , 7 },- { 368, 4, 4 , 10 },- { 380, 4, 8 , 7 },- { 396, 4, 4 , 10 },- { 408, 4, 4 , 10 },- { 420, 4, 4 , 10 },- { 432, 4, 4 , 10 },- { 444, 4, 4 , 10 },- { 456, 4, 5 , 10 },- { 469, 4, 4 , 10 },- { 481, 4, 4 , 10 },- { 493, 4, 1 , 10 },- { 4, 28, 3 , 10 },- { 15, 28, 4 , 10 },- { 27, 28, 4 , 10 },- { 39, 28, 7 , 10 },- { 54, 28, 4 , 10 },- { 66, 28, 4 , 10 },- { 78, 28, 4 , 10 },- { 90, 28, 5 , 11 },- { 103, 28, 4 , 10 },- { 115, 28, 4 , 10 },- { 127, 28, 5 , 10 },- { 140, 28, 4 , 10 },- { 152, 28, 4 , 10 },- { 164, 28, 7 , 10 },- { 179, 28, 4 , 10 },- { 191, 28, 4 , 10 },- { 203, 28, 4 , 10 },- { 215, 28, 2 , 12 },- { 225, 28, 5 , 10 },- { 238, 28, 2 , 12 },- { 248, 28, 5 , 3 },- { 261, 28, 5 , 1 },- { 274, 28, 2 , 2 },- { 284, 28, 4 , 8 },- { 296, 28, 4 , 10 },- { 308, 28, 3 , 8 },- { 319, 28, 4 , 10 },- { 331, 28, 4 , 8 },- { 343, 28, 3 , 10 },- { 354, 28, 5 , 11 },- { 367, 28, 4 , 10 },- { 379, 28, 1 , 10 },- { 388, 28, 3 , 13 },- { 399, 28, 4 , 10 },- { 411, 28, 2 , 10 },- { 421, 28, 7 , 8 },- { 436, 28, 4 , 8 },- { 448, 28, 4 , 8 },- { 460, 28, 4 , 11 },- { 472, 28, 4 , 11 },- { 484, 28, 3 , 8 },- { 495, 28, 4 , 8 },- { 4, 52, 3 , 10 },- { 15, 52, 4 , 8 },- { 27, 52, 5 , 8 },- { 40, 52, 7 , 8 },- { 55, 52, 4 , 8 },- { 67, 52, 4 , 11 },- { 79, 52, 4 , 8 },- { 91, 52, 4 , 12 },- { 103, 52, 1 , 10 },- { 112, 52, 4 , 12 },- { 124, 52, 4 , 2 },- { 136, 52, 1 , 10 },- { 145, 52, 4 , 12 },- { 157, 52, 5 , 10 },- { 170, 52, 5 , 10 },- { 183, 52, 5 , 10 },- { 196, 52, 6 , 13 },- { 210, 52, 4 , 10 },- { 222, 52, 6 , 13 },- { 236, 52, 7 , 9 },- { 251, 52, 3 , 7 },- { 262, 52, 6 , 5 },- { 276, 52, 6 , 13 },- { 290, 52, 7 , 9 },- { 305, 52, 4 , 1 },- { 317, 52, 3 , 5 },- { 328, 52, 5 , 7 },- { 341, 52, 3 , 5 },- { 352, 52, 6 , 13 },- { 366, 52, 6 , 13 },- { 380, 52, 4 , 11 },- { 392, 52, 6 , 10 },- { 406, 52, 3 , 3 },- { 417, 52, 6 , 13 },- { 431, 52, 2 , 5 },- { 441, 52, 3 , 5 },- { 452, 52, 6 , 5 },- { 466, 52, 7 , 10 },- { 481, 52, 7 , 8 },- { 496, 52, 6 , 13 },- { 4, 76, 4 , 10 },- { 16, 76, 4 , 13 },- { 28, 76, 4 , 13 },- { 40, 76, 4 , 13 },- { 52, 76, 4 , 13 },- { 64, 76, 4 , 13 },- { 76, 76, 4 , 13 },- { 88, 76, 7 , 10 },- { 103, 76, 4 , 13 },- { 115, 76, 4 , 13 },- { 127, 76, 4 , 13 },- { 139, 76, 4 , 13 },- { 151, 76, 4 , 13 },- { 163, 76, 2 , 13 },- { 173, 76, 2 , 13 },- { 183, 76, 3 , 13 },- { 194, 76, 3 , 13 },- { 205, 76, 5 , 10 },- { 218, 76, 4 , 13 },- { 230, 76, 4 , 13 },- { 242, 76, 4 , 13 },- { 254, 76, 4 , 13 },- { 266, 76, 4 , 13 },- { 278, 76, 4 , 13 },- { 290, 76, 5 , 5 },- { 303, 76, 6 , 12 },- { 317, 76, 4 , 13 },- { 329, 76, 4 , 13 },- { 341, 76, 4 , 13 },- { 353, 76, 4 , 13 },- { 365, 76, 4 , 13 },- { 377, 76, 6 , 13 },- { 391, 76, 5 , 12 },- { 404, 76, 4 , 12 },- { 416, 76, 4 , 12 },- { 428, 76, 4 , 12 },- { 440, 76, 4 , 12 },- { 452, 76, 4 , 12 },- { 464, 76, 4 , 12 },- { 476, 76, 7 , 8 },- { 491, 76, 3 , 11 },- { 4, 100, 4 , 12 },- { 16, 100, 4 , 12 },- { 28, 100, 4 , 12 },- { 40, 100, 4 , 12 },- { 52, 100, 3 , 12 },- { 63, 100, 3 , 12 },- { 74, 100, 3 , 12 },- { 85, 100, 3 , 12 },- { 96, 100, 6 , 13 },- { 110, 100, 4 , 12 },- { 122, 100, 4 , 12 },- { 134, 100, 4 , 12 },- { 146, 100, 4 , 12 },- { 158, 100, 4 , 12 },- { 170, 100, 4 , 12 },- { 182, 100, 5 , 5 },- { 195, 100, 6 , 10 },- { 209, 100, 4 , 12 },- { 221, 100, 4 , 12 },- { 233, 100, 4 , 12 },- { 245, 100, 4 , 12 },- { 257, 100, 4 , 15 },- { 269, 100, 6 , 13 },- { 283, 100, 4 , 15 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo ashesFontGlyphs[189] = {- { 32, 0, 13, 4, { 0 }},- { 33, 0, 3, 4, { 0 }},- { 34, 0, 1, 5, { 0 }},- { 35, 0, 4, 8, { 0 }},- { 36, 0, 2, 7, { 0 }},- { 37, 0, 5, 9, { 0 }},- { 38, 0, 4, 8, { 0 }},- { 39, 0, 1, 3, { 0 }},- { 40, 0, 2, 5, { 0 }},- { 41, 0, 2, 5, { 0 }},- { 42, 0, 3, 7, { 0 }},- { 43, 0, 6, 7, { 0 }},- { 44, 0, 12, 4, { 0 }},- { 45, 0, 9, 5, { 0 }},- { 46, 0, 12, 3, { 0 }},- { 47, 0, 3, 7, { 0 }},- { 48, 0, 5, 6, { 0 }},- { 49, 0, 5, 4, { 0 }},- { 50, 0, 5, 6, { 0 }},- { 51, 0, 5, 6, { 0 }},- { 52, 0, 5, 8, { 0 }},- { 53, 0, 5, 6, { 0 }},- { 54, 0, 5, 6, { 0 }},- { 55, 0, 5, 6, { 0 }},- { 56, 0, 5, 6, { 0 }},- { 57, 0, 5, 6, { 0 }},- { 58, 0, 8, 3, { 0 }},- { 59, 0, 8, 4, { 0 }},- { 60, 0, 5, 6, { 0 }},- { 61, 0, 7, 7, { 0 }},- { 62, 0, 5, 6, { 0 }},- { 63, 1, 3, 7, { 0 }},- { 64, 0, 5, 10, { 0 }},- { 65, 0, 3, 6, { 0 }},- { 66, 0, 3, 6, { 0 }},- { 67, 0, 3, 6, { 0 }},- { 68, 0, 3, 6, { 0 }},- { 69, 0, 3, 6, { 0 }},- { 70, 0, 3, 6, { 0 }},- { 71, 0, 3, 6, { 0 }},- { 72, 0, 3, 6, { 0 }},- { 73, 0, 3, 3, { 0 }},- { 74, 0, 3, 5, { 0 }},- { 75, 0, 3, 6, { 0 }},- { 76, 0, 3, 6, { 0 }},- { 77, 0, 3, 9, { 0 }},- { 78, 0, 3, 6, { 0 }},- { 79, 0, 3, 6, { 0 }},- { 80, 0, 3, 6, { 0 }},- { 81, 0, 3, 7, { 0 }},- { 82, 0, 3, 6, { 0 }},- { 83, 0, 3, 6, { 0 }},- { 84, 0, 3, 6, { 0 }},- { 85, 0, 3, 6, { 0 }},- { 86, 0, 3, 6, { 0 }},- { 87, 0, 3, 9, { 0 }},- { 88, 0, 3, 6, { 0 }},- { 89, 0, 3, 6, { 0 }},- { 90, 0, 3, 6, { 0 }},- { 91, 0, 2, 4, { 0 }},- { 92, 0, 3, 7, { 0 }},- { 93, 0, 2, 4, { 0 }},- { 94, 0, 3, 7, { 0 }},- { 95, 0, 12, 7, { 0 }},- { 96, 0, 1, 4, { 0 }},- { 97, 0, 5, 6, { 0 }},- { 98, 0, 3, 6, { 0 }},- { 99, 0, 5, 5, { 0 }},- { 100, 0, 3, 6, { 0 }},- { 101, 0, 5, 6, { 0 }},- { 102, 0, 3, 5, { 0 }},- { 103, 0, 5, 6, { 0 }},- { 104, 0, 3, 6, { 0 }},- { 105, 0, 3, 3, { 0 }},- { 106, 0, 3, 5, { 0 }},- { 107, 0, 3, 6, { 0 }},- { 108, 0, 3, 4, { 0 }},- { 109, 0, 5, 9, { 0 }},- { 110, 0, 5, 6, { 0 }},- { 111, 0, 5, 6, { 0 }},- { 112, 0, 5, 6, { 0 }},- { 113, 0, 5, 6, { 0 }},- { 114, 0, 5, 5, { 0 }},- { 115, 0, 5, 6, { 0 }},- { 116, 0, 3, 5, { 0 }},- { 117, 0, 5, 6, { 0 }},- { 118, 0, 5, 7, { 0 }},- { 119, 0, 5, 9, { 0 }},- { 120, 0, 5, 6, { 0 }},- { 121, 0, 5, 6, { 0 }},- { 122, 0, 5, 6, { 0 }},- { 123, 0, 2, 6, { 0 }},- { 124, 0, 3, 3, { 0 }},- { 125, 0, 2, 6, { 0 }},- { 126, 0, 1, 6, { 0 }},- { 161, 0, 4, 4, { 0 }},- { 162, 0, 3, 6, { 0 }},- { 163, 0, 3, 7, { 0 }},- { 8364, 0, 3, 7, { 0 }},- { 165, 0, 3, 7, { 0 }},- { 352, 1, 0, 8, { 0 }},- { 167, 0, 3, 6, { 0 }},- { 353, 1, 0, 8, { 0 }},- { 169, 0, 1, 9, { 0 }},- { 170, 0, 1, 5, { 0 }},- { 171, 0, 6, 8, { 0 }},- { 172, 1, 0, 8, { 0 }},- { 174, 0, 1, 9, { 0 }},- { 175, 0, 0, 6, { 0 }},- { 176, 0, 1, 5, { 0 }},- { 177, 0, 5, 7, { 0 }},- { 178, 0, 1, 5, { 0 }},- { 179, 1, 0, 8, { 0 }},- { 381, 1, 0, 8, { 0 }},- { 181, 0, 5, 6, { 0 }},- { 182, 0, 3, 8, { 0 }},- { 183, 0, 7, 5, { 0 }},- { 382, 1, 0, 8, { 0 }},- { 185, 0, 1, 4, { 0 }},- { 186, 0, 1, 5, { 0 }},- { 187, 0, 6, 8, { 0 }},- { 338, 0, 3, 9, { 0 }},- { 339, 0, 5, 9, { 0 }},- { 376, 1, 0, 8, { 0 }},- { 191, 0, 4, 6, { 0 }},- { 192, 0, 0, 6, { 0 }},- { 193, 0, 0, 6, { 0 }},- { 194, 0, 0, 6, { 0 }},- { 195, 0, 0, 6, { 0 }},- { 196, 0, 0, 6, { 0 }},- { 197, 0, 0, 6, { 0 }},- { 198, 0, 3, 9, { 0 }},- { 199, 0, 3, 6, { 0 }},- { 200, 0, 0, 6, { 0 }},- { 201, 0, 0, 6, { 0 }},- { 202, 0, 0, 6, { 0 }},- { 203, 0, 0, 6, { 0 }},- { 204, 0, 0, 4, { 0 }},- { 205, 0, 0, 4, { 0 }},- { 206, 0, 0, 5, { 0 }},- { 207, 0, 0, 5, { 0 }},- { 208, 0, 3, 7, { 0 }},- { 209, 0, 0, 6, { 0 }},- { 210, 0, 0, 6, { 0 }},- { 211, 0, 0, 6, { 0 }},- { 212, 0, 0, 6, { 0 }},- { 213, 0, 0, 6, { 0 }},- { 214, 0, 0, 6, { 0 }},- { 215, 0, 7, 7, { 0 }},- { 216, 0, 2, 8, { 0 }},- { 217, 0, 0, 6, { 0 }},- { 218, 0, 0, 6, { 0 }},- { 219, 0, 0, 6, { 0 }},- { 220, 0, 0, 6, { 0 }},- { 221, 0, 0, 6, { 0 }},- { 222, 1, 0, 8, { 0 }},- { 223, 0, 3, 7, { 0 }},- { 224, 0, 1, 6, { 0 }},- { 225, 0, 1, 6, { 0 }},- { 226, 0, 1, 6, { 0 }},- { 227, 0, 1, 6, { 0 }},- { 228, 0, 1, 6, { 0 }},- { 229, 0, 1, 6, { 0 }},- { 230, 0, 5, 9, { 0 }},- { 231, 0, 5, 5, { 0 }},- { 232, 0, 1, 6, { 0 }},- { 233, 0, 1, 6, { 0 }},- { 234, 0, 1, 6, { 0 }},- { 235, 0, 1, 6, { 0 }},- { 236, 0, 1, 5, { 0 }},- { 237, 0, 1, 5, { 0 }},- { 238, 0, 1, 5, { 0 }},- { 239, 0, 1, 5, { 0 }},- { 240, 1, 0, 8, { 0 }},- { 241, 0, 1, 6, { 0 }},- { 242, 0, 1, 6, { 0 }},- { 243, 0, 1, 6, { 0 }},- { 244, 0, 1, 6, { 0 }},- { 245, 0, 1, 6, { 0 }},- { 246, 0, 1, 6, { 0 }},- { 247, 0, 7, 7, { 0 }},- { 248, 0, 4, 8, { 0 }},- { 249, 0, 1, 6, { 0 }},- { 250, 0, 1, 6, { 0 }},- { 251, 0, 1, 6, { 0 }},- { 252, 0, 1, 6, { 0 }},- { 253, 0, 1, 6, { 0 }},- { 254, 1, 0, 8, { 0 }},- { 255, 0, 1, 6, { 0 }},-};--// Style loading function: Ashes-static void GuiLoadStyleAshes(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < ASHES_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(ashesStyleProps[i].controlId, ashesStyleProps[i].propertyId, ashesStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int ashesFontDataSize = 0;- unsigned char *data = DecompressData(ashesFontData, ASHES_STYLE_FONT_ATLAS_COMP_SIZE, &ashesFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, ashesFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, ashesFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_bluish.h
@@ -1,619 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleBluish(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define BLUISH_STYLE_PROPS_COUNT 14--// Custom style name: Bluish-static const GuiStyleProp bluishStyleProps[BLUISH_STYLE_PROPS_COUNT] = {- { 0, 0, 0x5ca6a6ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0xb4e8f3ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0x447e77ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0x5f8792ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xcdeff7ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0x4c6c74ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0x3b5b5fff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xeaffffff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x275057ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x96aaacff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0xc8d7d9ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x8c9c9eff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0xe8eef1ff }, // DEFAULT_BACKGROUND_COLOR -};--// WARNING: This style uses a custom font: "homespun.ttf" (size: 10, spacing: 1)--#define BLUISH_STYLE_FONT_ATLAS_COMP_SIZE 2914--// Font atlas image pixels data: DEFLATE compressed-static unsigned char bluishFontData[BLUISH_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0x9d, 0xb1, 0x8e, 0x24, 0x49, 0x11, 0x86, 0x2b, 0xf3, 0x00, 0x09, 0x13, 0x01, 0x12, 0xe0, 0x20, 0x81, 0x90, 0xf0, 0x10,- 0x12, 0x2e, 0x16, 0x3c, 0x02, 0x2f, 0x02, 0x0e, 0xef, 0x81, 0x07, 0x12, 0x06, 0x12, 0xce, 0x99, 0x38, 0x48, 0x20, 0xe1,- 0x81, 0x83, 0xc0, 0xc3, 0xc5, 0xe5, 0x2c, 0x8c, 0xc3, 0x81, 0x93, 0x26, 0x33, 0xd0, 0x4e, 0xcf, 0x2e, 0xe2, 0xae, 0xfe,- 0xc8, 0x8a, 0xac, 0xa8, 0xea, 0xea, 0x9b, 0x6f, 0x3f, 0xed, 0x1a, 0x95, 0x5d, 0xd5, 0x99, 0x19, 0x59, 0x35, 0xb3, 0x9d,- 0x5f, 0x47, 0xd8, 0x02, 0x00, 0x00, 0x00, 0xf0, 0x09, 0xaa, 0x38, 0x56, 0xe5, 0xab, 0x6b, 0xe0, 0x4a, 0xb7, 0xe3, 0xd5,- 0x69, 0x8f, 0x5d, 0xad, 0x06, 0xae, 0xe0, 0xb5, 0xf8, 0x6d, 0x1f, 0xa7, 0xbc, 0x90, 0x31, 0xb3, 0xf5, 0xdd, 0x7c, 0xac,- 0xcf, 0x52, 0xe4, 0xf5, 0x35, 0x34, 0x8a, 0x75, 0x4c, 0x1c, 0xeb, 0xab, 0xe3, 0x35, 0x2b, 0xa2, 0xa5, 0x9a, 0x89, 0xfe,- 0xd8, 0xf3, 0x59, 0xeb, 0x57, 0xf4, 0xce, 0x5a, 0x7b, 0x8f, 0xb6, 0x72, 0x8d, 0x26, 0x57, 0xc5, 0x9b, 0x77, 0x54, 0x33,- 0xd4, 0x45, 0x3c, 0x6d, 0xf5, 0xb5, 0x37, 0xca, 0xa6, 0x57, 0x7b, 0xef, 0x60, 0xd6, 0xac, 0xbd, 0xcc, 0xc7, 0xc7, 0x47,- 0x61, 0xa1, 0xd7, 0xeb, 0x96, 0xfd, 0xf1, 0xef, 0xcf, 0xfd, 0x29, 0x2b, 0xf7, 0xc1, 0x9b, 0x68, 0x75, 0x11, 0x2f, 0xd5,- 0x9f, 0xdb, 0xcc, 0x95, 0xd5, 0x2b, 0x7a, 0x67, 0x2d, 0x9b, 0x67, 0x7b, 0xfd, 0xfc, 0x5b, 0x4f, 0xd7, 0xc7, 0x51, 0x9e,- 0xdb, 0xd6, 0xe6, 0xae, 0x25, 0x3d, 0x57, 0xd5, 0x78, 0x17, 0xf7, 0xde, 0x5a, 0x9f, 0x85, 0x1e, 0x6a, 0xd9, 0x1f, 0x7f,- 0xbd, 0xa2, 0xed, 0xe5, 0xaf, 0x1a, 0x59, 0x13, 0xfd, 0x29, 0xa2, 0xc5, 0x3f, 0x6b, 0x4f, 0xfc, 0xcb, 0x4b, 0x4f, 0xab,- 0xb8, 0x9f, 0x4d, 0xdc, 0xd1, 0x47, 0x46, 0x3f, 0x1e, 0xff, 0xf2, 0xb2, 0x56, 0x8b, 0xf8, 0xa9, 0x74, 0x6e, 0xfc, 0xcb,- 0xcb, 0xf3, 0xbf, 0x8a, 0xde, 0x17, 0x19, 0x7d, 0xfd, 0xb4, 0x8d, 0xfc, 0x5c, 0x8d, 0xdd, 0xff, 0xb7, 0x79, 0x56, 0x6b,- 0xeb, 0xb8, 0xd8, 0xfb, 0xe3, 0x8d, 0xc5, 0xdf, 0xe4, 0x4f, 0x9e, 0xb7, 0xab, 0x78, 0xef, 0x28, 0x7a, 0xd2, 0xfd, 0xdf,- 0x65, 0x7f, 0xca, 0xcb, 0xf3, 0x7f, 0x7d, 0xcc, 0x91, 0xbb, 0x30, 0x12, 0xff, 0x51, 0x8c, 0x8f, 0xbc, 0xf7, 0xf5, 0xb5,- 0xe3, 0xf1, 0xbf, 0x5d, 0x71, 0xed, 0x5d, 0x8e, 0x5e, 0xc5, 0x4b, 0xe8, 0xf7, 0xbf, 0xe2, 0xfc, 0xce, 0xf3, 0x76, 0xed,- 0x44, 0xc6, 0x97, 0x15, 0xe7, 0xf3, 0xb1, 0xe1, 0x08, 0x22, 0xf1, 0x2f, 0x72, 0x56, 0xcb, 0xe9, 0x3f, 0xff, 0xbd, 0xf8,- 0x7b, 0x3d, 0xf5, 0xe2, 0x1f, 0x1b, 0x85, 0x05, 0x7f, 0x07, 0xbf, 0x5e, 0xfc, 0xed, 0xdd, 0xff, 0x87, 0xb6, 0x8d, 0x4d,- 0xbd, 0xde, 0xbb, 0xd2, 0x7d, 0x46, 0x3d, 0xd3, 0x9f, 0xab, 0x8d, 0x02, 0xf6, 0xf0, 0x34, 0x11, 0xc7, 0x27, 0x62, 0x0f,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x66, 0xf9, 0x64, 0x19, 0x26, 0xd9, 0x2d, 0xfb, 0xac, 0x20, 0x6d, 0xe7,- 0x78, 0x46, 0x92, 0xdf, 0xcb, 0xb3, 0xe6, 0x63, 0x39, 0xc9, 0xf9, 0xb1, 0x09, 0x23, 0xe5, 0xac, 0x96, 0xb6, 0xd9, 0xc2,- 0x58, 0xdf, 0xcd, 0xd5, 0x76, 0x4e, 0x17, 0x73, 0x35, 0xea, 0xe5, 0x79, 0xf3, 0x51, 0x27, 0x7a, 0x37, 0xf3, 0x69, 0xb9,- 0x0d, 0x76, 0xe7, 0x5a, 0xa8, 0xa5, 0x0f, 0xf7, 0xfa, 0x62, 0xe6, 0xcb, 0xbe, 0x7d, 0x55, 0xcf, 0xce, 0x53, 0xfe, 0x87,- 0xd7, 0x4b, 0xe5, 0x55, 0xd8, 0xf4, 0xa8, 0x5b, 0xea, 0x39, 0x6d, 0x2a, 0xfe, 0x7a, 0x54, 0x7a, 0x6f, 0xde, 0xb7, 0x1e,- 0xf5, 0xd5, 0x62, 0x2d, 0xdb, 0xed, 0x03, 0x15, 0x63, 0xed, 0x48, 0x44, 0xdd, 0x19, 0x73, 0xbc, 0x8a, 0xd1, 0xd8, 0x5a,- 0x68, 0x6f, 0xd2, 0x06, 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x66, 0x67, 0x74, 0x67, 0xbc, 0xbe, 0x61, 0xd2, 0x43, 0xe7, 0xf4,- 0x04, 0x5f, 0x25, 0xba, 0x7a, 0x3c, 0x0f, 0xa7, 0x3b, 0xf1, 0xaf, 0xc1, 0xb1, 0xdd, 0x5a, 0x6a, 0x68, 0x2f, 0xd8, 0x06,- 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x36, 0x7f, 0x65, 0xfa, 0x89, 0x9d, 0x75, 0xce, 0x71, 0x2b, 0xc0, 0xc2, 0xd7, 0xb1, 0x77,- 0x2b, 0x35, 0xf3, 0xf9, 0x5f, 0x26, 0x7e, 0x22, 0x97, 0xdd, 0xae, 0xc6, 0xf6, 0x27, 0xf6, 0x9c, 0x61, 0x92, 0x75, 0xce,- 0xb5, 0xdc, 0x8d, 0x32, 0xf9, 0xc4, 0x3e, 0xa7, 0xe5, 0x88, 0xf8, 0xcf, 0x1a, 0x26, 0x3d, 0xed, 0x9c, 0xe5, 0x74, 0xa7,- 0xc7, 0xe4, 0xfd, 0xef, 0xcd, 0x47, 0xe6, 0x1c, 0x7a, 0x1e, 0x90, 0xdf, 0x83, 0xd7, 0x40, 0xe3, 0x33, 0x1b, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xe3, 0xdb, 0x37, 0x31, 0x43, 0xc5, 0xb7, 0x76, 0xa2, 0x39, 0x7a,- 0xea, 0xe9, 0xd6, 0x4d, 0x76, 0xcb, 0xcc, 0x5c, 0x8c, 0x5a, 0x62, 0x67, 0x8e, 0x3f, 0xef, 0xd6, 0x4e, 0x89, 0xfa, 0x54,- 0xbb, 0x3d, 0x9f, 0x95, 0xb3, 0xfb, 0x67, 0xc3, 0x9e, 0xdd, 0xfe, 0xad, 0x17, 0xf4, 0x93, 0x3c, 0x73, 0xe9, 0x6d, 0xcf,- 0x33, 0x77, 0x0b, 0x6f, 0x2d, 0x6d, 0x75, 0x2e, 0x66, 0xf7, 0xd0, 0x66, 0x3c, 0x14, 0x7f, 0x37, 0x2c, 0x2f, 0xfe, 0xb3,- 0x63, 0x3e, 0xb7, 0x25, 0x9a, 0x47, 0xe4, 0x7a, 0xf1, 0xf7, 0x2c, 0x9f, 0xac, 0xf8, 0xef, 0xf3, 0x60, 0xf2, 0xe2, 0x3f,- 0xe3, 0x70, 0xe9, 0xbe, 0x7b, 0x1e, 0xd4, 0x99, 0xf1, 0xd7, 0x79, 0xb4, 0xb6, 0xc4, 0x3f, 0x6e, 0xf9, 0xc4, 0xe3, 0xbf,- 0xcf, 0x83, 0xc9, 0x8b, 0xff, 0x8c, 0xc3, 0xd1, 0x9d, 0x6c, 0x51, 0x3d, 0x9c, 0x7b, 0xc4, 0x06, 0x8e, 0x61, 0x9b, 0x88,- 0x7f, 0x91, 0x7d, 0xdc, 0xeb, 0x7f, 0x46, 0xee, 0xff, 0x72, 0x98, 0x07, 0x93, 0xfb, 0xfc, 0xcf, 0x9a, 0x87, 0x32, 0xb0,- 0x0f, 0xcb, 0x84, 0x2d, 0xd2, 0x93, 0xe7, 0x62, 0x9b, 0xef, 0x90, 0x13, 0xff, 0x99, 0x6b, 0x6d, 0x3b, 0x27, 0x1a, 0xff,- 0x32, 0x11, 0xff, 0xcc, 0xbe, 0xfb, 0xf1, 0x2f, 0x8e, 0x2d, 0x32, 0x3e, 0x27, 0x3b, 0xfe, 0xb3, 0x56, 0x4b, 0x49, 0xbc,- 0x96, 0x25, 0xc7, 0x3f, 0xee, 0xc9, 0xe4, 0xf6, 0xdd, 0x8f, 0xff, 0x7c, 0xef, 0x6e, 0x7f, 0xea, 0x01, 0x0e, 0x3d, 0x90,- 0x71, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xb3, 0x38, 0x15, 0xa9, 0x7c, 0xcb, 0x68, 0xbb,- 0x2d, 0xf4, 0xd6, 0xa0, 0x58, 0xf7, 0x27, 0x72, 0x32, 0xfd, 0x8c, 0x6b, 0x77, 0x45, 0xdf, 0x47, 0xcd, 0xd6, 0x4c, 0xdf,- 0x8e, 0xae, 0x71, 0xb6, 0xcd, 0xf2, 0xf1, 0xbc, 0x97, 0xd8, 0x77, 0x50, 0x55, 0x6e, 0x9a, 0x2a, 0x32, 0xdd, 0x44, 0xbf,- 0xbb, 0xef, 0xe5, 0xaa, 0xd0, 0xd7, 0xc9, 0xcc, 0x62, 0x61, 0x72, 0xbd, 0xda, 0x44, 0xdf, 0x9a, 0x38, 0xaa, 0xae, 0x51,- 0xa7, 0xbf, 0x29, 0x3d, 0x9f, 0xcb, 0x61, 0x6b, 0x4e, 0x25, 0xbd, 0x63, 0x78, 0xdb, 0xeb, 0x8e, 0xae, 0x80, 0x2e, 0xef,- 0xb1, 0xf5, 0xbe, 0x56, 0xe9, 0xb7, 0x2c, 0xb2, 0x9a, 0x59, 0x3c, 0x57, 0x8d, 0x89, 0xaa, 0x61, 0xfe, 0xfe, 0x91, 0xea,- 0x9b, 0xaa, 0x96, 0xb4, 0x88, 0x6b, 0xb4, 0xe9, 0xef, 0x84, 0xdb, 0xa0, 0x8e, 0x54, 0xe4, 0xca, 0xde, 0x0a, 0xf0, 0x2a,- 0xb9, 0xb5, 0x84, 0x5a, 0x25, 0xf1, 0x5c, 0x35, 0x9e, 0x79, 0xe0, 0x5f, 0x2d, 0x9a, 0x9b, 0x45, 0xaf, 0x99, 0xd8, 0x93,- 0x21, 0x2b, 0xc3, 0xcc, 0xb6, 0x27, 0x67, 0x71, 0x46, 0xb4, 0x84, 0x57, 0xc0, 0xb1, 0x95, 0x3c, 0x8e, 0x33, 0x0f, 0xb6,- 0x8e, 0x22, 0x7b, 0x67, 0x79, 0x7b, 0xfc, 0x97, 0x5d, 0x39, 0x41, 0xca, 0xb4, 0x2b, 0x13, 0x5b, 0x01, 0x47, 0xc7, 0xff,- 0x28, 0xf3, 0x20, 0x2b, 0x03, 0x47, 0xbf, 0x68, 0xfc, 0x47, 0xd9, 0x66, 0xe2, 0xb1, 0x8c, 0x1b, 0xa3, 0xcb, 0x5d, 0x9e,- 0x0c, 0xd9, 0xe7, 0x2c, 0xe1, 0xff, 0xc9, 0x5c, 0x23, 0xfe, 0x73, 0x19, 0x6a, 0x4a, 0x38, 0x97, 0xd0, 0xbd, 0xe2, 0x1f,- 0xaf, 0x23, 0x35, 0x77, 0x4e, 0xbe, 0x7b, 0x79, 0x46, 0xfc, 0xe1, 0x71, 0x32, 0x1f, 0x35, 0xfc, 0x24, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x52, 0xfe, 0x8f, 0x88, 0xbd, 0x72, 0xff, 0x96, 0x3a, 0xd8, 0xd5, 0x2a, 0xd3, 0x2d,- 0x25, 0xed, 0x9a, 0x9e, 0x63, 0xb4, 0xb7, 0xe6, 0xd9, 0xdb, 0x6b, 0x97, 0x69, 0xfb, 0xe7, 0x7f, 0x7b, 0xd0, 0xb7, 0x7f,- 0x6b, 0xd2, 0xce, 0x7a, 0x7e, 0xcb, 0xf1, 0xdf, 0xe6, 0x3f, 0x22, 0xdf, 0x80, 0x97, 0x21, 0xa2, 0x6e, 0x76, 0x2b, 0x9a,- 0xdc, 0x53, 0xed, 0x32, 0x67, 0x40, 0x9b, 0xd8, 0x83, 0xb8, 0x7f, 0x96, 0x9d, 0x16, 0xac, 0x43, 0x55, 0x4f, 0xcc, 0xb1,- 0xd1, 0x07, 0x3e, 0x4c, 0xcc, 0xa1, 0xd1, 0x39, 0x14, 0x96, 0xd0, 0x6b, 0x55, 0x4d, 0xa2, 0xf2, 0x90, 0xf1, 0x5f, 0x82,- 0x6e, 0x5f, 0xdf, 0x90, 0x2f, 0x23, 0x2b, 0xc7, 0x46, 0x99, 0x30, 0x7c, 0x8a, 0x53, 0x7f, 0x2c, 0x16, 0x7f, 0x55, 0xad,- 0x2e, 0xfe, 0x6c, 0x3c, 0x23, 0xcb, 0x46, 0x7e, 0x05, 0x9b, 0xbc, 0x6c, 0x1e, 0xf9, 0x39, 0x36, 0xbc, 0x9d, 0x72, 0xed,- 0x55, 0xc6, 0xe2, 0x1f, 0xcd, 0xed, 0x70, 0x46, 0xfc, 0x67, 0x6b, 0xdb, 0xe4, 0x66, 0xe6, 0x28, 0x17, 0xc9, 0xb1, 0x11,- 0xcd, 0x10, 0xb2, 0xff, 0xf9, 0x9f, 0xed, 0x23, 0xe4, 0xed, 0x54, 0x9f, 0x93, 0x67, 0x63, 0xc6, 0xd3, 0x39, 0x6a, 0x67,- 0x3e, 0xbe, 0x3b, 0x1f, 0x71, 0x2b, 0xfb, 0x43, 0xc5, 0xff, 0xca, 0x6e, 0xcf, 0x95, 0x38, 0xb2, 0xe6, 0x19, 0xf6, 0xcf,- 0xa3, 0xae, 0x69, 0xe6, 0xe0, 0x75, 0x5b, 0x5e, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x93, 0x01,- 0x68, 0x91, 0x39, 0x6d, 0x3e, 0x79, 0xfc, 0x8b, 0x56, 0xed, 0x5b, 0xf6, 0x35, 0xfb, 0x8e, 0x7d, 0xd7, 0xbe, 0xe2, 0x5c,- 0xb1, 0xa6, 0xe5, 0x1b, 0x1a, 0x9d, 0x53, 0x83, 0x75, 0xca, 0x4a, 0xd8, 0xd7, 0xd9, 0x57, 0x8b, 0x2c, 0x36, 0xf3, 0xd1,- 0x6b, 0x8d, 0xe2, 0xe1, 0xfb, 0x5f, 0x9e, 0x45, 0xb1, 0x9e, 0xb7, 0xe7, 0xe7, 0xf6, 0x64, 0x1f, 0xda, 0x3f, 0xed, 0x1f,- 0xf6, 0x37, 0xfb, 0xd0, 0x3e, 0x2b, 0x3f, 0xc3, 0x5c, 0xf7, 0x52, 0xde, 0x8c, 0xe1, 0x29, 0x58, 0x4d, 0xcb, 0x3f, 0x47,- 0x55, 0x08, 0x53, 0xd7, 0x2b, 0xcf, 0xd6, 0x44, 0x0b, 0xf9, 0x3a, 0xe3, 0x77, 0x52, 0xdf, 0xf1, 0x6e, 0xe1, 0x0a, 0x01,- 0x7e, 0x55, 0xb1, 0x78, 0x3c, 0xe6, 0x32, 0xa7, 0xdc, 0xf6, 0xd7, 0xd6, 0xc6, 0xf4, 0x7b, 0xfb, 0x8f, 0xfd, 0xc0, 0xaa,- 0xfd, 0xd0, 0xbe, 0x6a, 0x7f, 0xb5, 0xcf, 0xc9, 0xbc, 0x36, 0xeb, 0xe3, 0x6b, 0xd2, 0x87, 0xd1, 0xb9, 0x60, 0xbc, 0x73,- 0xca, 0xcb, 0x2e, 0x60, 0x5d, 0xbd, 0x5f, 0xd6, 0xad, 0xac, 0xe2, 0xe6, 0xaa, 0xd1, 0xde, 0x50, 0x19, 0xe6, 0x39, 0x5a,- 0x9b, 0x8b, 0x2e, 0x72, 0x0c, 0x75, 0x71, 0xe7, 0xa9, 0x7e, 0xab, 0xe3, 0xa3, 0x78, 0x8c, 0xf7, 0x1b, 0xd6, 0xb3, 0x20,- 0x99, 0x18, 0xe9, 0xaf, 0xed, 0xcf, 0xf6, 0x0d, 0xfb, 0xb6, 0xfd, 0xcb, 0xfe, 0x6d, 0x1f, 0xd9, 0x67, 0x56, 0xef, 0x22,- 0xe5, 0xe6, 0xe8, 0x27, 0xa5, 0x97, 0x0d, 0xa9, 0x38, 0x39, 0x9c, 0xba, 0x8c, 0xa7, 0xbe, 0xf7, 0xba, 0x5c, 0x9d, 0xde,- 0x3c, 0xf5, 0xe1, 0xca, 0x51, 0x7b, 0xc3, 0x25, 0x34, 0x47, 0xaa, 0x72, 0xa0, 0xba, 0xff, 0x47, 0xf1, 0x18, 0xc7, 0xbf,- 0x08, 0x43, 0x65, 0x7d, 0x8e, 0x7e, 0x61, 0x7f, 0xb7, 0xaf, 0xdb, 0x97, 0xec, 0x0b, 0xf6, 0x79, 0x7b, 0x5f, 0xc4, 0x4b,- 0xad, 0xed, 0x51, 0x06, 0xa5, 0xb8, 0x01, 0x7a, 0x8b, 0xc7, 0x7a, 0xfc, 0x6b, 0x9a, 0x1d, 0x60, 0xef, 0x9e, 0x0b, 0x73,- 0x75, 0xb6, 0x22, 0xcf, 0x7f, 0xf5, 0x13, 0x59, 0x3d, 0x53, 0x47, 0xf1, 0x98, 0x75, 0x28, 0x4c, 0xdc, 0x75, 0x7f, 0xb0,- 0x9f, 0xd9, 0x4f, 0xed, 0x7b, 0xf6, 0x2b, 0xfb, 0xc8, 0x9a, 0x7d, 0x33, 0xb8, 0xb6, 0x4b, 0xb8, 0xde, 0xa0, 0x4d, 0xde,- 0xff, 0x5d, 0xda, 0x77, 0xd7, 0x8e, 0xbf, 0xea, 0xb7, 0x3a, 0x3e, 0x8a, 0xc7, 0xac, 0x43, 0xa1, 0x5c, 0xc9, 0xf7, 0xed,- 0xc7, 0xf6, 0x81, 0xfd, 0xd2, 0x7e, 0x64, 0xdf, 0xb7, 0xdf, 0xd8, 0x97, 0x27, 0xc6, 0x66, 0xa1, 0xdf, 0xbd, 0xbc, 0xdf,- 0xca, 0xca, 0x20, 0xef, 0x54, 0x6e, 0x1e, 0xa1, 0x33, 0xde, 0x29, 0xce, 0x96, 0x78, 0xc4, 0x6d, 0x2c, 0xbd, 0x32, 0x7e,- 0x62, 0xbf, 0xb5, 0x3f, 0xd9, 0x07, 0xf6, 0x3b, 0xfb, 0xa3, 0xfd, 0xc5, 0xde, 0x73, 0x4c, 0xba, 0x68, 0xcd, 0xbc, 0x59,- 0xbf, 0xce, 0xe4, 0xef, 0x2a, 0xd9, 0xae, 0x51, 0xd6, 0x3b, 0x59, 0xa2, 0xbd, 0x34, 0x8a, 0xc7, 0xb5, 0xfc, 0x96, 0x99,- 0xac, 0x7b, 0x8f, 0xed, 0x79, 0xc1, 0x96, 0x58, 0xce, 0x59, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,- 0xc5, 0xfe, 0xf1, 0xdd, 0x9a, 0x65, 0x53, 0x76, 0x89, 0xb1, 0x15, 0x14, 0x71, 0x5a, 0x8a, 0xcc, 0x61, 0x51, 0x37, 0xd4,- 0xda, 0x2a, 0xa1, 0x91, 0xce, 0x1c, 0x1f, 0xf9, 0x3b, 0xfa, 0x78, 0x9e, 0x15, 0x35, 0xe3, 0x23, 0x45, 0x3f, 0x75, 0x6d,- 0x6e, 0xe5, 0x9e, 0x88, 0x85, 0xa2, 0x6b, 0x89, 0x99, 0x70, 0x34, 0x9a, 0xf0, 0x04, 0x9a, 0x3c, 0xcb, 0x5e, 0x76, 0x1e,- 0x4d, 0x66, 0xc4, 0x79, 0x92, 0xce, 0x8d, 0x3a, 0xfe, 0x9e, 0x8c, 0xf2, 0x93, 0xcc, 0xeb, 0xb3, 0x7e, 0x96, 0x3d, 0x1f,- 0xef, 0xa1, 0xbe, 0x99, 0x5b, 0x85, 0xcd, 0x9c, 0xb6, 0xb6, 0xe9, 0x13, 0xf3, 0x51, 0xfc, 0xb7, 0x7b, 0x12, 0x63, 0x0b,- 0xc5, 0xe4, 0x0e, 0xfe, 0xba, 0xa3, 0xa5, 0xb3, 0xed, 0xf8, 0x6d, 0xca, 0x9e, 0xf1, 0x73, 0x69, 0x69, 0x83, 0x23, 0xba,- 0x62, 0x54, 0x2c, 0x9b, 0x34, 0x99, 0x7c, 0x2b, 0xa6, 0x3a, 0xee, 0x83, 0x97, 0x91, 0xa8, 0x9d, 0x1a, 0xff, 0xb1, 0x85,- 0x12, 0x89, 0x7f, 0x77, 0x33, 0x24, 0x68, 0xbb, 0x64, 0x94, 0x11, 0x47, 0xbb, 0x58, 0x65, 0xea, 0xe9, 0x9b, 0xd3, 0xe2,- 0xdf, 0xe5, 0x4d, 0xee, 0x7d, 0x7b, 0xf3, 0x10, 0xcf, 0xff, 0xb2, 0x66, 0x71, 0x6c, 0x8f, 0xff, 0xd8, 0x42, 0x31, 0x51,- 0x03, 0x6f, 0xce, 0xc4, 0x8a, 0x65, 0x77, 0xf2, 0x57, 0xba, 0xce, 0xec, 0x74, 0x56, 0x8e, 0xbb, 0x99, 0x8c, 0x59, 0x9e,- 0x65, 0xb3, 0x6c, 0xcc, 0x01, 0x66, 0x03, 0x5b, 0x63, 0x7b, 0xfc, 0xc7, 0x16, 0x4a, 0xc4, 0x69, 0x19, 0x9b, 0x38, 0x25,- 0xb8, 0xab, 0xee, 0xf9, 0x45, 0x3a, 0x8f, 0xd0, 0x4c, 0x25, 0xc8, 0xb3, 0x5a, 0xbc, 0x79, 0x28, 0x1b, 0x23, 0xe7, 0xe7,- 0xd0, 0x89, 0xc4, 0x7f, 0x9f, 0x85, 0x12, 0x33, 0x08, 0xe2, 0xfe, 0xe6, 0xd8, 0x22, 0xea, 0x77, 0xcf, 0x71, 0x19, 0x7f,- 0x66, 0x74, 0xb9, 0x36, 0xb6, 0x1a, 0x13, 0xfe, 0x2b, 0x23, 0xf3, 0x7c, 0x96, 0x85, 0x32, 0x6b, 0xce, 0x94, 0x09, 0xbf,- 0xe4, 0xdc, 0xec, 0x87, 0xf1, 0x96, 0x3e, 0x88, 0x1d, 0xf9, 0x46, 0xb6, 0x3e, 0xe9, 0xe2, 0xbf, 0x1d, 0xdf, 0xbb, 0x65,- 0x64, 0xf5, 0x61, 0xd2, 0xec, 0xb7, 0xc8, 0x1e, 0x37, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19,- 0x2e, 0x4b, 0xb0, 0x86, 0x95, 0x6e, 0xd3, 0x47, 0x6b, 0x28, 0x6b, 0x8e, 0xe7, 0xdd, 0xdc, 0xdf, 0xef, 0x29, 0xee, 0x3e,- 0x5d, 0x5e, 0x9f, 0xbd, 0x4f, 0x80, 0xf3, 0x0c, 0x17, 0xcf, 0x7d, 0xa8, 0xa1, 0x77, 0xa9, 0xce, 0x3b, 0x3c, 0x89, 0x3d,- 0xaf, 0xb8, 0x77, 0x73, 0x7f, 0xbf, 0x47, 0x19, 0x1c, 0x55, 0x7a, 0x1f, 0x33, 0x7d, 0x1e, 0xad, 0x80, 0x2c, 0xc3, 0xc5,- 0xf3, 0xce, 0x62, 0xef, 0xd2, 0x44, 0x8b, 0xbe, 0xbe, 0xfe, 0x7c, 0xbf, 0x39, 0x19, 0x84, 0xee, 0xed, 0xf7, 0xe8, 0x6a,- 0x54, 0xca, 0xfb, 0xa8, 0x72, 0x05, 0xdc, 0x72, 0x5a, 0xd5, 0xe0, 0xd3, 0xff, 0x1c, 0x8f, 0x25, 0x9a, 0xd3, 0x4c, 0x1d,- 0xbf, 0x39, 0x6f, 0x3a, 0x5b, 0x51, 0x2c, 0xe7, 0xd0, 0xfd, 0xfd, 0x9e, 0xee, 0xe6, 0x9b, 0x3a, 0x7e, 0xaf, 0x60, 0x94,- 0x8f, 0xa7, 0x4f, 0x54, 0x64, 0x5c, 0xcf, 0x77, 0x64, 0xc2, 0xff, 0x88, 0x1d, 0x5f, 0x64, 0x46, 0x27, 0x73, 0x76, 0xc3,- 0xaf, 0xb0, 0x57, 0x1f, 0x8b, 0xcc, 0xcd, 0x72, 0xb0, 0x13, 0xe2, 0x5f, 0x9c, 0x7a, 0x68, 0x79, 0x2d, 0xcb, 0xa0, 0xee,- 0x5a, 0xd6, 0xf1, 0xeb, 0xee, 0xd5, 0x47, 0xe3, 0x6f, 0x27, 0xc5, 0xdf, 0x77, 0xdf, 0xb2, 0x5a, 0x88, 0x7f, 0x34, 0xfe,- 0xfd, 0xa4, 0xe7, 0xbf, 0x76, 0xdf, 0x32, 0x5b, 0xce, 0x88, 0xbf, 0xb9, 0x35, 0xf5, 0x1e, 0x2d, 0xfe, 0xe5, 0x14, 0x57,- 0x20, 0xbb, 0x8a, 0xa7, 0x9f, 0x4d, 0xee, 0xc8, 0xf8, 0xcf, 0x59, 0x1c, 0xe5, 0xce, 0x2d, 0x71, 0x5b, 0x25, 0xf3, 0x5d,- 0xf2, 0xab, 0x78, 0xfa, 0x2d, 0xc7, 0x1d, 0xdf, 0xf3, 0x1d, 0x07, 0xbb, 0x63, 0x4b, 0xdc, 0xcb, 0xcb, 0x7c, 0x17, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2d, 0xfe, 0x4f, 0xd4, 0xe5, 0x99, 0x31, 0x53, 0xaa, 0xeb, 0xe7, 0x5c, 0x35,- 0xc7, 0x8e, 0x97, 0x4f, 0x48, 0xb7, 0xdc, 0xdb, 0xa9, 0xaa, 0xa1, 0xe8, 0xc7, 0x5d, 0x1e, 0xed, 0x99, 0xd8, 0xc4, 0x0e,- 0xb8, 0xef, 0x06, 0xb5, 0x09, 0x07, 0xa7, 0x3a, 0x0e, 0x4e, 0x0b, 0xe5, 0xd8, 0xe8, 0x4e, 0x3e, 0x21, 0x73, 0x72, 0x17,- 0x64, 0x8e, 0x48, 0xf7, 0xbb, 0x89, 0x55, 0xd1, 0xc2, 0x9f, 0x33, 0x3e, 0x85, 0xf2, 0xe5, 0x68, 0xcf, 0x64, 0x76, 0x07,- 0x7c, 0xce, 0xc1, 0x69, 0x21, 0x07, 0xc7, 0xab, 0x22, 0x55, 0x07, 0x55, 0xba, 0xf4, 0x6e, 0x4b, 0xae, 0x53, 0x15, 0xeb,- 0xb7, 0x9e, 0x81, 0x8c, 0xfc, 0x6f, 0xd9, 0x3b, 0x60, 0x45, 0x98, 0x6e, 0x33, 0x4f, 0xd8, 0x99, 0x16, 0x9d, 0xff, 0xc1,- 0xab, 0xde, 0x37, 0x53, 0xc9, 0x28, 0xb7, 0xdf, 0x5e, 0x85, 0xbe, 0x12, 0xca, 0x64, 0x75, 0xdf, 0x6f, 0x38, 0x77, 0x51,- 0x39, 0x27, 0xb7, 0x22, 0x90, 0x6e, 0x29, 0x32, 0x27, 0x4a, 0x71, 0x6b, 0x52, 0xf5, 0x70, 0x7d, 0x9c, 0x6c, 0x77, 0xa8,- 0x38, 0x96, 0x60, 0xd9, 0x91, 0xfb, 0x69, 0xdf, 0xbd, 0xdc, 0x27, 0x72, 0xec, 0xf4, 0x89, 0xb8, 0x64, 0xb5, 0xd8, 0x54,- 0x7d, 0xa9, 0x71, 0x7e, 0x94, 0xe3, 0xb3, 0x06, 0x75, 0xc7, 0xb7, 0xb9, 0x47, 0xfc, 0xc7, 0xf3, 0x15, 0x7f, 0x32, 0x9c,- 0x73, 0x1f, 0x45, 0x57, 0xe0, 0x5c, 0x8e, 0x8d, 0x6c, 0xa7, 0xb2, 0x0c, 0xec, 0x8d, 0xb3, 0xe3, 0x5f, 0x06, 0xe7, 0xe8,- 0xac, 0x5d, 0x76, 0x57, 0x07, 0x23, 0xfe, 0xbc, 0xde, 0x93, 0x69, 0x26, 0xaf, 0xc5, 0xaf, 0xd0, 0xb7, 0x37, 0xfe, 0x67,- 0xd8, 0x2c, 0x57, 0x30, 0x50, 0x72, 0x33, 0x03, 0x9d, 0x37, 0xa2, 0xe8, 0x4a, 0xb3, 0x8b, 0xf6, 0xf5, 0xd3, 0x95, 0x19,- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xd1, 0xf3, 0xff, 0xd4, 0x70, 0xcb, 0x95, 0xb3, 0xec, 0xe4, 0xe5,- 0x1f, 0xca, 0x76, 0x78, 0xe6, 0x5c, 0xaa, 0xb9, 0x4c, 0x3f, 0xca, 0x47, 0xa9, 0x81, 0xfc, 0x2b, 0x37, 0xeb, 0x44, 0x55,- 0xaa, 0xaa, 0x27, 0xf8, 0x30, 0x33, 0x86, 0x8f, 0x3a, 0xea, 0xed, 0xfc, 0x9c, 0xe3, 0xf0, 0xe8, 0xab, 0xd9, 0xc0, 0xd9,- 0xc9, 0xc9, 0xef, 0xde, 0x9c, 0xb9, 0x99, 0x59, 0x31, 0xed, 0x92, 0x86, 0xcf, 0x8c, 0x5b, 0x91, 0xeb, 0xf0, 0xe8, 0x19,- 0x6d, 0xd2, 0x2f, 0xf0, 0xab, 0x2f, 0x66, 0x7d, 0x5a, 0x1d, 0xdd, 0x91, 0x6a, 0x61, 0x8b, 0xa2, 0xdc, 0xdd, 0x94, 0xe9,- 0xae, 0xc3, 0xd3, 0x43, 0x11, 0x9b, 0x69, 0x19, 0xed, 0xa5, 0x96, 0x44, 0x97, 0x2e, 0x6b, 0xb7, 0xd2, 0x82, 0x4f, 0xcc,- 0x6b, 0x67, 0xd9, 0x29, 0x4e, 0xf6, 0x93, 0x47, 0xac, 0xfc, 0x72, 0xaf, 0xf8, 0x3f, 0xe6, 0x8c, 0xf9, 0x39, 0x29, 0x1e,- 0x2d, 0xca, 0x36, 0xe9, 0xab, 0xe4, 0xc4, 0xff, 0xda, 0xf3, 0x92, 0x97, 0x65, 0xe3, 0x9c, 0x9e, 0xcd, 0x19, 0x61, 0x99,- 0xfb, 0xd5, 0xd1, 0xf8, 0x97, 0xe4, 0xd1, 0x9f, 0x61, 0xf8, 0xcc, 0x64, 0xd9, 0x38, 0xcb, 0x3d, 0x9a, 0xb5, 0x2c, 0x8e,- 0xbe, 0xff, 0x33, 0xef, 0x98, 0x7b, 0x1b, 0x3e, 0x57, 0x76, 0x78, 0xe2, 0x2e, 0x9d, 0xf6, 0xd5, 0xe1, 0xd1, 0xd0, 0xb1,- 0x7c, 0x3d, 0x95, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0xe6, 0xb9, 0xfd, 0x61, 0x1e, 0x88, 0x3f, 0xbc, 0xda, 0xf8, 0xff, 0x17 };--// Font glyphs rectangles data (on atlas)-static const Rectangle bluishFontRecs[189] = {- { 4, 4, 5 , 10 },- { 17, 4, 2 , 8 },- { 27, 4, 4 , 3 },- { 39, 4, 6 , 8 },- { 53, 4, 5 , 10 },- { 66, 4, 6 , 8 },- { 80, 4, 5 , 10 },- { 93, 4, 2 , 3 },- { 103, 4, 3 , 8 },- { 114, 4, 3 , 8 },- { 125, 4, 6 , 6 },- { 139, 4, 6 , 6 },- { 153, 4, 2 , 3 },- { 163, 4, 5 , 2 },- { 176, 4, 2 , 2 },- { 186, 4, 6 , 8 },- { 200, 4, 5 , 8 },- { 213, 4, 3 , 8 },- { 224, 4, 5 , 8 },- { 237, 4, 5 , 8 },- { 4, 22, 5 , 8 },- { 17, 22, 5 , 8 },- { 30, 22, 5 , 8 },- { 43, 22, 5 , 8 },- { 56, 22, 5 , 8 },- { 69, 22, 5 , 8 },- { 82, 22, 2 , 8 },- { 92, 22, 2 , 9 },- { 102, 22, 4 , 6 },- { 114, 22, 5 , 4 },- { 127, 22, 4 , 6 },- { 139, 22, 5 , 8 },- { 152, 22, 6 , 8 },- { 166, 22, 5 , 8 },- { 179, 22, 5 , 8 },- { 192, 22, 5 , 8 },- { 205, 22, 5 , 8 },- { 218, 22, 5 , 8 },- { 231, 22, 5 , 8 },- { 4, 40, 5 , 8 },- { 17, 40, 5 , 8 },- { 30, 40, 4 , 8 },- { 42, 40, 5 , 8 },- { 55, 40, 5 , 8 },- { 68, 40, 5 , 8 },- { 81, 40, 8 , 8 },- { 97, 40, 5 , 8 },- { 110, 40, 5 , 8 },- { 123, 40, 5 , 8 },- { 136, 40, 5 , 9 },- { 149, 40, 5 , 8 },- { 162, 40, 5 , 8 },- { 175, 40, 6 , 8 },- { 189, 40, 5 , 8 },- { 202, 40, 5 , 8 },- { 215, 40, 8 , 8 },- { 231, 40, 5 , 8 },- { 4, 58, 5 , 8 },- { 17, 58, 5 , 8 },- { 30, 58, 3 , 8 },- { 41, 58, 6 , 8 },- { 55, 58, 3 , 8 },- { 66, 58, 6 , 4 },- { 80, 58, 5 , 1 },- { 93, 58, 2 , 3 },- { 103, 58, 5 , 6 },- { 116, 58, 5 , 8 },- { 129, 58, 5 , 6 },- { 142, 58, 5 , 8 },- { 155, 58, 5 , 6 },- { 168, 58, 5 , 8 },- { 181, 58, 5 , 7 },- { 194, 58, 5 , 8 },- { 207, 58, 2 , 8 },- { 217, 58, 3 , 9 },- { 228, 58, 5 , 8 },- { 241, 58, 2 , 8 },- { 4, 76, 8 , 6 },- { 20, 76, 5 , 6 },- { 33, 76, 5 , 6 },- { 46, 76, 5 , 7 },- { 59, 76, 5 , 7 },- { 72, 76, 5 , 6 },- { 85, 76, 5 , 6 },- { 98, 76, 5 , 8 },- { 111, 76, 5 , 6 },- { 124, 76, 5 , 6 },- { 137, 76, 8 , 6 },- { 153, 76, 5 , 6 },- { 166, 76, 5 , 7 },- { 179, 76, 5 , 6 },- { 192, 76, 4 , 8 },- { 204, 76, 2 , 10 },- { 214, 76, 4 , 8 },- { 226, 76, 6 , 4 },- { 240, 76, 2 , 8 },- { 4, 94, 5 , 8 },- { 17, 94, 5 , 8 },- { 30, 94, 8 , 8 },- { 46, 94, 6 , 8 },- { 60, 94, 5 , 10 },- { 73, 94, 5 , 10 },- { 86, 94, 5 , 9 },- { 99, 94, 7 , 8 },- { 114, 94, 4 , 6 },- { 126, 94, 5 , 4 },- { 139, 94, 5 , 3 },- { 152, 94, 7 , 8 },- { 167, 94, 5 , 2 },- { 180, 94, 4 , 4 },- { 192, 94, 6 , 8 },- { 206, 94, 4 , 6 },- { 218, 94, 4 , 6 },- { 230, 94, 8 , 8 },- { 4, 112, 5 , 9 },- { 17, 112, 6 , 8 },- { 31, 112, 2 , 2 },- { 41, 112, 8 , 8 },- { 57, 112, 3 , 6 },- { 68, 112, 4 , 6 },- { 80, 112, 5 , 4 },- { 93, 112, 6 , 8 },- { 107, 112, 6 , 6 },- { 121, 112, 5 , 10 },- { 134, 112, 5 , 8 },- { 147, 112, 5 , 10 },- { 160, 112, 5 , 10 },- { 173, 112, 5 , 10 },- { 186, 112, 5 , 10 },- { 199, 112, 5 , 10 },- { 212, 112, 5 , 10 },- { 225, 112, 6 , 8 },- { 239, 112, 5 , 9 },- { 4, 130, 5 , 10 },- { 17, 130, 5 , 10 },- { 30, 130, 5 , 10 },- { 43, 130, 5 , 10 },- { 56, 130, 4 , 10 },- { 68, 130, 4 , 10 },- { 80, 130, 4 , 10 },- { 92, 130, 4 , 10 },- { 104, 130, 6 , 8 },- { 118, 130, 5 , 10 },- { 131, 130, 5 , 10 },- { 144, 130, 5 , 10 },- { 157, 130, 5 , 10 },- { 170, 130, 5 , 10 },- { 183, 130, 5 , 10 },- { 196, 130, 4 , 4 },- { 208, 130, 5 , 10 },- { 221, 130, 5 , 10 },- { 234, 130, 5 , 10 },- { 4, 148, 5 , 10 },- { 17, 148, 5 , 10 },- { 30, 148, 5 , 10 },- { 43, 148, 5 , 8 },- { 56, 148, 5 , 8 },- { 69, 148, 5 , 9 },- { 82, 148, 5 , 9 },- { 95, 148, 5 , 9 },- { 108, 148, 5 , 9 },- { 121, 148, 5 , 8 },- { 134, 148, 5 , 10 },- { 147, 148, 6 , 6 },- { 161, 148, 5 , 7 },- { 174, 148, 5 , 9 },- { 187, 148, 5 , 9 },- { 200, 148, 5 , 9 },- { 213, 148, 5 , 8 },- { 226, 148, 3 , 9 },- { 237, 148, 3 , 9 },- { 4, 166, 4 , 9 },- { 16, 166, 4 , 8 },- { 28, 166, 5 , 9 },- { 41, 166, 5 , 9 },- { 54, 166, 5 , 9 },- { 67, 166, 5 , 9 },- { 80, 166, 5 , 9 },- { 93, 166, 5 , 9 },- { 106, 166, 5 , 8 },- { 119, 166, 4 , 6 },- { 131, 166, 5 , 8 },- { 144, 166, 5 , 9 },- { 157, 166, 5 , 9 },- { 170, 166, 5 , 9 },- { 183, 166, 5 , 8 },- { 196, 166, 5 , 10 },- { 209, 166, 5 , 10 },- { 222, 166, 5 , 9 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo bluishFontGlyphs[189] = {- { 32, 0, 9, 5, { 0 }},- { 33, 0, 1, 2, { 0 }},- { 34, 0, 1, 4, { 0 }},- { 35, 0, 1, 6, { 0 }},- { 36, 0, 0, 5, { 0 }},- { 37, 0, 1, 6, { 0 }},- { 38, 0, 0, 5, { 0 }},- { 39, 0, 1, 2, { 0 }},- { 40, 0, 1, 3, { 0 }},- { 41, 0, 1, 3, { 0 }},- { 42, 0, 1, 6, { 0 }},- { 43, 0, 2, 6, { 0 }},- { 44, 0, 7, 2, { 0 }},- { 45, 0, 4, 5, { 0 }},- { 46, 0, 7, 2, { 0 }},- { 47, 0, 1, 6, { 0 }},- { 48, 0, 1, 5, { 0 }},- { 49, 0, 1, 3, { 0 }},- { 50, 0, 1, 5, { 0 }},- { 51, 0, 1, 5, { 0 }},- { 52, 0, 1, 5, { 0 }},- { 53, 0, 1, 5, { 0 }},- { 54, 0, 1, 5, { 0 }},- { 55, 0, 1, 5, { 0 }},- { 56, 0, 1, 5, { 0 }},- { 57, 0, 1, 5, { 0 }},- { 58, 0, 1, 2, { 0 }},- { 59, 0, 1, 2, { 0 }},- { 60, 0, 2, 4, { 0 }},- { 61, 0, 3, 5, { 0 }},- { 62, 0, 2, 4, { 0 }},- { 63, 0, 1, 5, { 0 }},- { 64, 0, 1, 6, { 0 }},- { 65, 0, 1, 5, { 0 }},- { 66, 0, 1, 5, { 0 }},- { 67, 0, 1, 5, { 0 }},- { 68, 0, 1, 5, { 0 }},- { 69, 0, 1, 5, { 0 }},- { 70, 0, 1, 5, { 0 }},- { 71, 0, 1, 5, { 0 }},- { 72, 0, 1, 5, { 0 }},- { 73, 0, 1, 4, { 0 }},- { 74, 0, 1, 5, { 0 }},- { 75, 0, 1, 5, { 0 }},- { 76, 0, 1, 5, { 0 }},- { 77, 0, 1, 8, { 0 }},- { 78, 0, 1, 5, { 0 }},- { 79, 0, 1, 5, { 0 }},- { 80, 0, 1, 5, { 0 }},- { 81, 0, 1, 5, { 0 }},- { 82, 0, 1, 5, { 0 }},- { 83, 0, 1, 5, { 0 }},- { 84, 0, 1, 6, { 0 }},- { 85, 0, 1, 5, { 0 }},- { 86, 0, 1, 5, { 0 }},- { 87, 0, 1, 8, { 0 }},- { 88, 0, 1, 5, { 0 }},- { 89, 0, 1, 5, { 0 }},- { 90, 0, 1, 5, { 0 }},- { 91, 0, 1, 3, { 0 }},- { 92, 0, 1, 6, { 0 }},- { 93, 0, 1, 3, { 0 }},- { 94, 0, 1, 6, { 0 }},- { 95, 0, 9, 5, { 0 }},- { 96, 0, 1, 2, { 0 }},- { 97, 0, 3, 5, { 0 }},- { 98, 0, 1, 5, { 0 }},- { 99, 0, 3, 5, { 0 }},- { 100, 0, 1, 5, { 0 }},- { 101, 0, 3, 5, { 0 }},- { 102, 0, 1, 5, { 0 }},- { 103, 0, 3, 5, { 0 }},- { 104, 0, 1, 5, { 0 }},- { 105, 0, 1, 2, { 0 }},- { 106, 0, 1, 3, { 0 }},- { 107, 0, 1, 5, { 0 }},- { 108, 0, 1, 2, { 0 }},- { 109, 0, 3, 8, { 0 }},- { 110, 0, 3, 5, { 0 }},- { 111, 0, 3, 5, { 0 }},- { 112, 0, 3, 5, { 0 }},- { 113, 0, 3, 5, { 0 }},- { 114, 0, 3, 5, { 0 }},- { 115, 0, 3, 5, { 0 }},- { 116, 0, 1, 5, { 0 }},- { 117, 0, 3, 5, { 0 }},- { 118, 0, 3, 5, { 0 }},- { 119, 0, 3, 8, { 0 }},- { 120, 0, 3, 5, { 0 }},- { 121, 0, 3, 5, { 0 }},- { 122, 0, 3, 5, { 0 }},- { 123, 0, 1, 4, { 0 }},- { 124, 0, 0, 2, { 0 }},- { 125, 0, 1, 4, { 0 }},- { 126, 0, 3, 6, { 0 }},- { 161, 0, 1, 2, { 0 }},- { 162, 0, 2, 5, { 0 }},- { 163, 0, 1, 5, { 0 }},- { 8364, 0, 1, 7, { 0 }},- { 165, 0, 1, 6, { 0 }},- { 352, 0, -1, 5, { 0 }},- { 167, 0, 0, 5, { 0 }},- { 353, 0, 0, 5, { 0 }},- { 169, 0, 1, 7, { 0 }},- { 170, 0, -1, 4, { 0 }},- { 171, 0, 3, 5, { 0 }},- { 172, 0, 4, 5, { 0 }},- { 174, 0, 1, 7, { 0 }},- { 175, 0, -1, 5, { 0 }},- { 176, 0, -1, 4, { 0 }},- { 177, 0, 1, 6, { 0 }},- { 178, 0, -1, 4, { 0 }},- { 179, 0, -1, 4, { 0 }},- { 381, 0, 1, 7, { 0 }},- { 181, 0, 1, 5, { 0 }},- { 182, 0, 1, 6, { 0 }},- { 183, 0, 4, 2, { 0 }},- { 382, 0, 1, 7, { 0 }},- { 185, 0, -1, 3, { 0 }},- { 186, 0, -1, 4, { 0 }},- { 187, 0, 3, 5, { 0 }},- { 338, 0, 1, 6, { 0 }},- { 339, 0, 3, 6, { 0 }},- { 376, 0, -1, 5, { 0 }},- { 191, 0, 1, 5, { 0 }},- { 192, 0, -1, 5, { 0 }},- { 193, 0, -1, 5, { 0 }},- { 194, 0, -1, 5, { 0 }},- { 195, 0, -1, 5, { 0 }},- { 196, 0, -1, 5, { 0 }},- { 197, 0, -1, 5, { 0 }},- { 198, 0, 1, 6, { 0 }},- { 199, 0, 1, 5, { 0 }},- { 200, 0, -1, 5, { 0 }},- { 201, 0, -1, 5, { 0 }},- { 202, 0, -1, 5, { 0 }},- { 203, 0, -1, 5, { 0 }},- { 204, 0, -1, 4, { 0 }},- { 205, 0, -1, 4, { 0 }},- { 206, 0, -1, 4, { 0 }},- { 207, 0, -1, 4, { 0 }},- { 208, 0, 1, 6, { 0 }},- { 209, 0, -1, 5, { 0 }},- { 210, 0, -1, 5, { 0 }},- { 211, 0, -1, 5, { 0 }},- { 212, 0, -1, 5, { 0 }},- { 213, 0, -1, 5, { 0 }},- { 214, 0, -1, 5, { 0 }},- { 215, 0, 3, 4, { 0 }},- { 216, 0, 0, 5, { 0 }},- { 217, 0, -1, 5, { 0 }},- { 218, 0, -1, 5, { 0 }},- { 219, 0, -1, 5, { 0 }},- { 220, 0, -1, 5, { 0 }},- { 221, 0, -1, 5, { 0 }},- { 222, 0, 1, 5, { 0 }},- { 223, 0, 1, 5, { 0 }},- { 224, 0, 0, 5, { 0 }},- { 225, 0, 0, 5, { 0 }},- { 226, 0, 0, 5, { 0 }},- { 227, 0, 0, 5, { 0 }},- { 228, 0, 1, 5, { 0 }},- { 229, 0, -1, 5, { 0 }},- { 230, 0, 3, 6, { 0 }},- { 231, 0, 3, 5, { 0 }},- { 232, 0, 0, 5, { 0 }},- { 233, 0, 0, 5, { 0 }},- { 234, 0, 0, 5, { 0 }},- { 235, 0, 1, 5, { 0 }},- { 236, 0, 0, 3, { 0 }},- { 237, 0, 0, 2, { 0 }},- { 238, 0, 0, 3, { 0 }},- { 239, 0, 1, 3, { 0 }},- { 240, 0, 0, 5, { 0 }},- { 241, 0, 0, 5, { 0 }},- { 242, 0, 0, 5, { 0 }},- { 243, 0, 0, 5, { 0 }},- { 244, 0, 0, 5, { 0 }},- { 245, 0, 0, 5, { 0 }},- { 246, 0, 1, 5, { 0 }},- { 247, 0, 2, 4, { 0 }},- { 248, 0, 2, 5, { 0 }},- { 249, 0, 0, 5, { 0 }},- { 250, 0, 0, 5, { 0 }},- { 251, 0, 0, 5, { 0 }},- { 252, 0, 1, 5, { 0 }},- { 253, 0, 0, 5, { 0 }},- { 254, 0, 0, 5, { 0 }},- { 255, 0, 1, 5, { 0 }},-};--// Style loading function: Bluish-static void GuiLoadStyleBluish(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < BLUISH_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(bluishStyleProps[i].controlId, bluishStyleProps[i].propertyId, bluishStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int bluishFontDataSize = 0;- unsigned char *data = DecompressData(bluishFontData, BLUISH_STYLE_FONT_ATLAS_COMP_SIZE, &bluishFontDataSize);- Image imFont = { data, 256, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 10;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, bluishFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, bluishFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 254, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_candy.h
@@ -1,589 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleCandy(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define CANDY_STYLE_PROPS_COUNT 17--// Custom style name: Candy-static const GuiStyleProp candyStyleProps[CANDY_STYLE_PROPS_COUNT] = {- { 0, 0, 0xe58b68ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0xfeda96ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xe59b5fff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xee813fff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xfcd85bff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xfc6955ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xb34848ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xeb7272ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0xbd4a4aff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x94795dff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0xc2a37aff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x9c8369ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0xd77575ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0xfff5e1ff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "v5easter.ttf" (size: 15, spacing: 0)--#define CANDY_STYLE_FONT_ATLAS_COMP_SIZE 2260--// Font atlas image pixels data: DEFLATE compressed-static unsigned char candyFontData[CANDY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x4d, 0x92, 0xd4, 0x38, 0x10, 0x06, 0x50, 0xdd, 0x80, 0xfb, 0xcc, 0x61, 0xe6, 0x4a, 0x73, 0x45, 0x8e, 0xc0, 0x86,- 0x25, 0xa1, 0x89, 0x61, 0x88, 0x20, 0x80, 0x2e, 0x4b, 0x4a, 0xa5, 0x6c, 0xd9, 0xf5, 0x78, 0x1b, 0xa2, 0xdd, 0x5d, 0x55,- 0xfe, 0xf9, 0x2c, 0xc9, 0x2e, 0xa5, 0x6b, 0x01, 0x00, 0x00, 0x00, 0xde, 0xdc, 0x7f, 0xff, 0xfe, 0xfc, 0x59, 0xf9, 0xe0,- 0xa7, 0x3f, 0x7f, 0xb7, 0x7e, 0xb8, 0xf4, 0x68, 0x49, 0xfc, 0x2f, 0x8f, 0x3f, 0x49, 0xdf, 0x2b, 0x94, 0x83, 0x25, 0xed,- 0xcf, 0xfc, 0xfb, 0xcf, 0x6a, 0xca, 0xbb, 0xbf, 0x7a, 0x9d, 0xd6, 0x27, 0x8a, 0x2c, 0x3b, 0x7a, 0xd5, 0x7a, 0xb0, 0x4e,- 0xa5, 0x63, 0x49, 0x0d, 0xad, 0x5d, 0x9d, 0xde, 0xab, 0x63, 0x7b, 0xa7, 0xbd, 0xfe, 0x65, 0x78, 0x1d, 0xcb, 0x82, 0x65,- 0x75, 0x72, 0x1f, 0xaf, 0xcc, 0xff, 0xef, 0xff, 0x32, 0xf3, 0x7f, 0xfc, 0x9a, 0x33, 0xc7, 0xc4, 0xcf, 0xb5, 0xa9, 0x09,- 0xf9, 0x1f, 0x3f, 0x8b, 0x1c, 0xaf, 0xc1, 0xeb, 0xa3, 0xb8, 0x0c, 0xff, 0x4d, 0xfb, 0xfc, 0x9a, 0xf9, 0xaa, 0x2b, 0x97,- 0xf5, 0xa5, 0x76, 0xfe, 0x38, 0x6f, 0x7d, 0x9a, 0xb9, 0x7d, 0x78, 0xe6, 0xb2, 0xdc, 0xfc, 0xb7, 0x7e, 0x37, 0x7a, 0x66,- 0x8f, 0xf7, 0x0e, 0x7a, 0x5b, 0xf3, 0x3a, 0x74, 0xec, 0xb7, 0x5b, 0xb1, 0x9c, 0x2d, 0x3c, 0xba, 0xc6, 0xc7, 0xe7, 0x92,- 0xd6, 0xd2, 0xf9, 0x36, 0x77, 0xe4, 0xd8, 0xb8, 0xe2, 0x28, 0x6e, 0xef, 0xcd, 0x8c, 0x76, 0xa9, 0xfe, 0xb2, 0xb5, 0xe5,- 0xbf, 0xf7, 0xa8, 0xad, 0x8b, 0x5b, 0xda, 0x32, 0xdc, 0xd2, 0xc6, 0xfa, 0x2c, 0x79, 0x5b, 0x38, 0x2b, 0xff, 0x75, 0x22,- 0xfd, 0x25, 0xd0, 0xe3, 0x3c, 0x3e, 0x6b, 0xb7, 0x3e, 0x7f, 0xf4, 0x28, 0xc9, 0x3d, 0x66, 0x67, 0xf3, 0x7f, 0xdc, 0x1f,- 0x2e, 0x87, 0xe7, 0x9b, 0xf3, 0x7a, 0x5c, 0x3b, 0xe5, 0x3f, 0xda, 0x43, 0xee, 0x1f, 0xdd, 0xe4, 0xb5, 0xff, 0xeb, 0xf3,- 0xdf, 0x4a, 0x64, 0x1d, 0x1c, 0xa9, 0xe6, 0xb6, 0xc6, 0x3d, 0xe3, 0xe9, 0xe8, 0x19, 0x7d, 0x7c, 0x8c, 0x7b, 0x7e, 0xff,- 0xbf, 0x3d, 0x6e, 0xac, 0xcb, 0x46, 0x4e, 0xf9, 0x09, 0xdb, 0xb7, 0xff, 0xdf, 0xd7, 0x2f, 0x58, 0xd3, 0xff, 0x6f, 0x8d,- 0xff, 0xcb, 0xe9, 0xad, 0x7f, 0x2b, 0x59, 0xf1, 0xbd, 0x5f, 0x43, 0x3d, 0xa0, 0xb9, 0xab, 0x0a, 0xb1, 0xfd, 0x39, 0x97,- 0xff, 0x15, 0x7d, 0x80, 0xd1, 0xd1, 0xdf, 0x33, 0xfa, 0xff, 0x91, 0x2d, 0x18, 0xbd, 0xce, 0x9c, 0xb5, 0x66, 0xe3, 0xd7,- 0xf9, 0xaf, 0xdb, 0x62, 0x79, 0xe7, 0xf9, 0xd9, 0x2d, 0x98, 0xff, 0xaa, 0xb1, 0x5e, 0xf5, 0xe8, 0x51, 0x5c, 0x2f, 0xbd,- 0x37, 0x56, 0x6f, 0x71, 0xe5, 0xf4, 0x8c, 0xf6, 0xbf, 0x75, 0xfd, 0x7f, 0xe6, 0xea, 0xc0, 0xd8, 0x9d, 0x8d, 0xba, 0xe1,- 0xb1, 0x22, 0xff, 0x77, 0x69, 0xc5, 0xb2, 0x7a, 0xd5, 0xae, 0xff, 0x45, 0xee, 0x69, 0x67, 0xf4, 0xe7, 0xee, 0x92, 0xff,- 0xda, 0x71, 0x36, 0xed, 0x5f, 0x12, 0xbf, 0xe3, 0xbe, 0xea, 0x5b, 0x05, 0xad, 0xbb, 0x8d, 0xe7, 0xdd, 0xc5, 0xde, 0x31,- 0xff, 0xf7, 0xb8, 0xff, 0xbf, 0xc7, 0xb6, 0x5c, 0x3b, 0x92, 0xdb, 0x31, 0xff, 0xf0, 0x1e, 0xdf, 0x26, 0x3c, 0xef, 0x5b,- 0x8b, 0xf2, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdd, 0x67, 0xe7, 0xc4, 0x2b,- 0x44, 0x8e, 0xcd, 0xb9, 0xa9, 0x4b, 0xea, 0x22, 0xc5, 0xe6, 0x46, 0x9f, 0x5b, 0xc3, 0x39, 0x5a, 0x35, 0x7b, 0x6e, 0x5e,- 0xf8, 0xeb, 0x7a, 0x42, 0x33, 0xaf, 0x7b, 0x3c, 0x17, 0x79, 0x64, 0x5e, 0x76, 0xb4, 0xd6, 0xf9, 0x68, 0x4d, 0xa0, 0x48,- 0xed, 0xa4, 0xd9, 0xda, 0xe9, 0xe3, 0x6b, 0x1c, 0x99, 0xc1, 0x3a, 0x3b, 0xe7, 0xed, 0xac, 0x8a, 0xcd, 0xd1, 0x9c, 0xf6,- 0x55, 0xbd, 0xad, 0xc3, 0x95, 0xea, 0x76, 0xab, 0xd3, 0x90, 0x5d, 0x35, 0x63, 0x65, 0xfe, 0x4b, 0x57, 0x6d, 0xec, 0xbe,- 0xf9, 0xce, 0x35, 0x71, 0x46, 0xfb, 0x79, 0x35, 0xf7, 0xca, 0xf4, 0x3e, 0x19, 0x6d, 0xa9, 0x9e, 0x9f, 0xff, 0xe8, 0xba,- 0xb7, 0xb6, 0x6a, 0xdd, 0xb6, 0x8a, 0xfd, 0x95, 0xf9, 0x8f, 0xf6, 0xed, 0x8e, 0x5b, 0xbe, 0xf1, 0x8a, 0x07, 0xe7, 0x54,- 0xb4, 0xa9, 0x1b, 0xe5, 0x7f, 0xfc, 0xdd, 0x56, 0xce, 0x61, 0x9f, 0x6b, 0x7b, 0x6b, 0x5a, 0xfe, 0xe3, 0x7d, 0x9f, 0xdd,- 0xda, 0xf8, 0xdc, 0xaa, 0x39, 0xeb, 0xf2, 0x5f, 0xd2, 0xab, 0x32, 0xed, 0x99, 0xff, 0x9e, 0xf6, 0x21, 0x32, 0x36, 0x18,- 0xff, 0xcb, 0xe8, 0x19, 0x77, 0xf4, 0xdd, 0x22, 0xed, 0xff, 0xf1, 0x5a, 0xde, 0xb9, 0xfd, 0xdf, 0x25, 0xff, 0x65, 0xab,- 0xfe, 0xff, 0xec, 0xd1, 0x38, 0x96, 0xf3, 0xeb, 0x6a, 0xb3, 0xed, 0xfe, 0x24, 0xa3, 0x91, 0x2d, 0x3e, 0x5b, 0x1d, 0x39,- 0x7a, 0xdd, 0x21, 0xf3, 0x89, 0x4d, 0xf7, 0xba, 0xc6, 0x55, 0xde, 0x72, 0xfc, 0x1f, 0xbf, 0xee, 0x2b, 0xff, 0xb3, 0xfd,- 0xe9, 0x72, 0x41, 0xfe, 0x57, 0x6d, 0xbb, 0x3b, 0xe7, 0x7f, 0xa6, 0xe7, 0x77, 0x56, 0xfe, 0xcb, 0xcb, 0xa7, 0x50, 0xcd,- 0xe6, 0x3f, 0xfe, 0x6c, 0x9c, 0xd1, 0x9c, 0xd7, 0x0b, 0xef, 0x6f, 0xad, 0x38, 0x07, 0xc6, 0xef, 0x37, 0x14, 0xf9, 0xbf,- 0x55, 0xfe, 0xaf, 0x6f, 0xff, 0x7b, 0x9f, 0xad, 0xf8, 0xde, 0xf9, 0x2f, 0x53, 0xd7, 0xf8, 0x56, 0xfc, 0xdd, 0x6e, 0xfd,- 0xff, 0xec, 0x73, 0xe7, 0xb9, 0xe7, 0xd3, 0x75, 0x7d, 0xdc, 0xd8, 0xf5, 0xa4, 0xd8, 0xd3, 0x0c, 0x62, 0x55, 0xb3, 0xd7,- 0x1c, 0x53, 0x25, 0xfc, 0x0c, 0xaf, 0x32, 0x7c, 0x06, 0x90, 0xff, 0x5f, 0x97, 0xac, 0x7b, 0x3a, 0x32, 0xac, 0xce, 0xd3,- 0xbd, 0xf2, 0x3f, 0xf7, 0x4d, 0x83, 0xfc, 0xa7, 0x0d, 0xd6, 0x0b, 0xda, 0x7f, 0x58, 0x7b, 0x97, 0x3d, 0xef, 0xf7, 0xc9,- 0xe8, 0xd3, 0x03, 0xef, 0xdb, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x38, 0x57,- 0xe0, 0xf5, 0x2c, 0xcf, 0xe3, 0x2a, 0x18, 0x25, 0x58, 0x05, 0xbb, 0x74, 0x54, 0x4e, 0xae, 0xc1, 0xf7, 0x1b, 0x99, 0xa5,- 0xbc, 0x5b, 0x2d, 0x82, 0xd1, 0xfa, 0x88, 0x23, 0xb5, 0xb1, 0xcb, 0x70, 0x9d, 0xaf, 0x68, 0x15, 0x9b, 0x32, 0x59, 0x73,- 0x34, 0x3e, 0xff, 0x2e, 0x3a, 0x83, 0xfa, 0x68, 0x7f, 0x7e, 0xaa, 0xdf, 0xea, 0x97, 0xef, 0xbe, 0xd6, 0x7f, 0x86, 0xdf,- 0xb5, 0x76, 0xcd, 0xf7, 0x9b, 0xdd, 0x27, 0x3d, 0x5b, 0x28, 0x92, 0xff, 0x1d, 0xab, 0xee, 0x65, 0x55, 0xf9, 0xb8, 0x53,- 0xbd, 0xed, 0x91, 0x3a, 0xbc, 0xed, 0x7a, 0x1e, 0xf3, 0xf9, 0xef, 0xad, 0x29, 0x50, 0x27, 0xab, 0x7e, 0x8e, 0x9e, 0x2b,- 0x8e, 0xb7, 0xcb, 0xd1, 0xdc, 0xe4, 0xd7, 0xad, 0xdc, 0xa7, 0xfa, 0xf9, 0xc7, 0xff, 0xfe, 0xfe, 0x30, 0xff, 0x35, 0x3c,- 0x1b, 0xa7, 0xfd, 0x89, 0x32, 0xe7, 0x57, 0xbf, 0x47, 0xfe, 0xc7, 0xcf, 0x99, 0x77, 0xa8, 0xb7, 0x5d, 0x12, 0x7e, 0x9a,- 0x39, 0xf3, 0x3d, 0x5a, 0x53, 0x24, 0x9a, 0xff, 0x91, 0x34, 0xbd, 0x3e, 0xcb, 0x95, 0x8e, 0x0a, 0x6a, 0xa3, 0xf9, 0x6f,- 0xbd, 0x6b, 0x24, 0xff, 0x75, 0xb8, 0xf6, 0x4a, 0xff, 0xb6, 0x1c, 0x6b, 0x5d, 0xf6, 0xcc, 0x7f, 0xa4, 0xc7, 0x59, 0x4f,- 0xcc, 0xff, 0x5c, 0x8d, 0xaf, 0x72, 0x7a, 0xfe, 0x73, 0x9f, 0x53, 0xd1, 0x37, 0x92, 0xe9, 0x4d, 0x76, 0xff, 0xef, 0xd6,- 0x46, 0x5b, 0xbc, 0x2e, 0xff, 0xf5, 0x83, 0xf7, 0x5f, 0xd5, 0xfe, 0xc7, 0xeb, 0xab, 0xd6, 0x83, 0x4f, 0xf8, 0x84, 0xfc,- 0x97, 0x4d, 0xfa, 0xff, 0xf9, 0xcf, 0x52, 0xdb, 0x33, 0xff, 0xe3, 0x3d, 0xae, 0xf1, 0x76, 0x7d, 0xac, 0xaf, 0xd0, 0x1e,- 0x01, 0xd4, 0xc0, 0x19, 0xa0, 0x27, 0xff, 0xb1, 0xf6, 0x3f, 0x3a, 0xfe, 0x8f, 0x27, 0xa3, 0x3e, 0xb6, 0xfd, 0xcf, 0x1d,- 0xff, 0xaf, 0xaa, 0x45, 0x98, 0xfb, 0xbc, 0xad, 0xac, 0x5a, 0x9b, 0xb1, 0xbe, 0x56, 0xb4, 0xfd, 0x6f, 0xf5, 0x0e, 0x66,- 0xf2, 0x5f, 0x26, 0x93, 0xf8, 0xf1, 0xf5, 0xbf, 0x55, 0xed, 0xff, 0xf9, 0xd7, 0xff, 0x6b, 0x20, 0x21, 0xab, 0xaa, 0x6e,- 0xd6, 0xe1, 0x6b, 0x31, 0xb3, 0x55, 0xd5, 0xfa, 0xef, 0x34, 0xf4, 0x9c, 0x9b, 0x5f, 0xdf, 0xa5, 0xe8, 0xd9, 0x2a, 0x19,- 0xa3, 0xbe, 0x5d, 0xfb, 0xff, 0xd7, 0xb4, 0xff, 0x3d, 0xad, 0x7f, 0xa4, 0x0e, 0xd9, 0xba, 0xeb, 0x7f, 0xd1, 0xf1, 0xd3,- 0xdc, 0xfd, 0xbf, 0xeb, 0xeb, 0x08, 0x66, 0x5f, 0xf9, 0x39, 0xf3, 0xb5, 0xae, 0xfa, 0x44, 0x3b, 0xf6, 0xff, 0xe3, 0x63,- 0xab, 0x91, 0x51, 0x7d, 0xde, 0xfd, 0xbf, 0x98, 0x56, 0xfe, 0xd7, 0xbc, 0xeb, 0xba, 0x63, 0x4e, 0xfe, 0xf7, 0xdc, 0x07,- 0x7b, 0xe5, 0xbf, 0xf7, 0x29, 0xe6, 0x35, 0xfd, 0x4e, 0xfc, 0x6e, 0x7b, 0xb0, 0x9d, 0xff, 0x7b, 0x7d, 0xff, 0xe7, 0xfc,- 0x27, 0x8f, 0x5e, 0x9d, 0xff, 0xdd, 0xce, 0x00, 0x59, 0x4f, 0xbc, 0x2e, 0x49, 0x7b, 0x32, 0x72, 0x17, 0x6f, 0xf7, 0xf3,- 0xa5, 0xfc, 0xf3, 0xfc, 0xef, 0x6f, 0xd6, 0xc7, 0xf7, 0x9b, 0xae, 0xef, 0x5b, 0xcb, 0x3f, 0xbc, 0xaf, 0xf6, 0xf7, 0x7f,- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x9e, 0x0f, 0x58, 0x27, 0xe7, 0x0a, 0xc6, 0x2a,- 0x0d, 0x95, 0xe6, 0x8c, 0xd3, 0x1a, 0xfe, 0x9d, 0x91, 0x75, 0x89, 0xd7, 0xb0, 0x88, 0xd4, 0xe0, 0x2e, 0x8d, 0xba, 0x35,- 0x39, 0xdb, 0xe6, 0x9c, 0xf5, 0x6c, 0xd7, 0xda, 0x1b, 0x3b, 0x2e, 0x46, 0xb6, 0x54, 0xbb, 0x86, 0xca, 0x79, 0xdb, 0x21,- 0xba, 0xbf, 0x6b, 0x63, 0x76, 0x77, 0x6d, 0x54, 0xae, 0xc9, 0xa9, 0x07, 0x50, 0x1b, 0x75, 0x54, 0xe2, 0xf3, 0xd5, 0x46,- 0xcf, 0x00, 0xf5, 0x8f, 0xda, 0x4e, 0x35, 0xf4, 0x3b, 0xa3, 0x7b, 0x3d, 0xb6, 0xac, 0xa7, 0xaa, 0x63, 0x5e, 0xa5, 0xe8,- 0xc8, 0xb6, 0x59, 0xbf, 0x9e, 0xe3, 0xc7, 0x45, 0x4d, 0x7a, 0x87, 0xde, 0xba, 0x24, 0xfb, 0xef, 0xef, 0x76, 0x05, 0xd9,- 0xba, 0xac, 0xfd, 0xcf, 0xc8, 0xff, 0x58, 0x0d, 0xd6, 0x91, 0x3a, 0x63, 0x99, 0xf9, 0xdf, 0xab, 0x3f, 0x16, 0x7f, 0x1e,- 0x44, 0x56, 0xc5, 0xfd, 0x7b, 0xcc, 0xda, 0x8d, 0x3f, 0x99, 0xe0, 0x3e, 0xfb, 0x7b, 0xf5, 0xfa, 0xf5, 0x9c, 0x29, 0xe7,- 0xea, 0x42, 0x5c, 0x95, 0xff, 0xbc, 0xfe, 0x7f, 0xb4, 0x3f, 0x1d, 0x79, 0x26, 0xd2, 0x6c, 0x2d, 0xc5, 0x99, 0x27, 0x8b,- 0x9c, 0xbd, 0x2e, 0x73, 0xa3, 0x82, 0x9e, 0x31, 0xeb, 0x0e, 0xdb, 0x61, 0x66, 0x1b, 0x95, 0xe0, 0x93, 0x17, 0xb2, 0xf2,- 0x9f, 0x51, 0xcf, 0x74, 0x7c, 0xfc, 0xd7, 0xde, 0x56, 0xb9, 0xe7, 0xc5, 0xd8, 0xeb, 0xed, 0xba, 0xac, 0x4e, 0x8c, 0x63,- 0xae, 0x7d, 0x92, 0x51, 0x4e, 0xfe, 0xfb, 0x7b, 0xb5, 0xbb, 0xef, 0xd3, 0xd2, 0x31, 0x4e, 0xde, 0x3f, 0xff, 0xa3, 0x9f,- 0x25, 0xb3, 0x8f, 0x3b, 0x5b, 0x5d, 0xfa, 0x9a, 0x65, 0xf3, 0x4f, 0x2a, 0xd9, 0xfd, 0xd8, 0xbe, 0x3a, 0xff, 0x6b, 0x9e,- 0x06, 0x93, 0xbd, 0x8d, 0x5a, 0xa3, 0x86, 0xac, 0xf6, 0xbf, 0x35, 0x02, 0xa9, 0x5b, 0x8c, 0x0b, 0xfb, 0xb2, 0x3d, 0x7e,- 0xfd, 0x7f, 0xee, 0x58, 0x59, 0xb1, 0x6c, 0xfe, 0xb8, 0xdd, 0x37, 0xe3, 0xbb, 0xe4, 0xff, 0x0e, 0xe7, 0xc8, 0x78, 0xab,- 0x9d, 0xd1, 0xf7, 0x3d, 0xbf, 0xfd, 0xcf, 0xc8, 0x7f, 0xfe, 0x15, 0xd0, 0x3b, 0x2e, 0x5b, 0x9f, 0xd5, 0xd9, 0x6b, 0x70,- 0xf2, 0x2f, 0xff, 0xf1, 0xbe, 0x4a, 0x4d, 0xaf, 0x70, 0xb9, 0xe2, 0xe9, 0x60, 0x57, 0x8d, 0xff, 0x73, 0xaf, 0x43, 0xdd,- 0xb5, 0xff, 0x7f, 0xf7, 0x7d, 0x3a, 0xd3, 0x6b, 0xa7, 0xbc, 0x55, 0xdf, 0x60, 0xf6, 0x6c, 0xff, 0xb4, 0xfc, 0x3f, 0x7b,- 0x9f, 0x4a, 0xbd, 0xfc, 0xe7, 0x9e, 0x01, 0xd6, 0x65, 0x7c, 0x24, 0xbb, 0xef, 0x97, 0xff, 0xbb, 0x3c, 0x35, 0x48, 0xfe,- 0x9f, 0x31, 0xe6, 0x3b, 0xf7, 0x7b, 0x0e, 0x39, 0xdf, 0xff, 0x2b, 0x27, 0x3e, 0x01, 0xef, 0xec, 0xfb, 0xff, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x33, 0x7e, 0x33, 0x2b, 0x3d, 0x1f, 0xfd, 0xe5, 0xa7, 0xfa,- 0xad, 0x7e, 0xf9, 0xee, 0x6b, 0xfd, 0xe7, 0xb0, 0xce, 0xc9, 0x19, 0x6b, 0xa1, 0x2e, 0xf7, 0xda, 0xba, 0xdc, 0xc7, 0x7b,- 0xfb, 0x2e, 0x55, 0xb9, 0x7b, 0x8f, 0xd9, 0x3a, 0xb8, 0x85, 0x57, 0xa6, 0x2f, 0xab, 0x9e, 0x43, 0x74, 0xee, 0xe1, 0xab,- 0xd7, 0xfc, 0x54, 0x3f, 0xff, 0xf8, 0xdf, 0xdf, 0x1f, 0x6e, 0xcb, 0xbe, 0x7a, 0x60, 0x79, 0x6b, 0xa1, 0x2e, 0xf7, 0xca,- 0xba, 0xdc, 0x7d, 0x7b, 0x7b, 0xf7, 0xaa, 0xdc, 0xfd, 0x6b, 0x51, 0x37, 0x49, 0xdf, 0xb5, 0xb3, 0xe4, 0xe2, 0xdb, 0x72,- 0xaf, 0x1a, 0xce, 0x35, 0x5c, 0x5b, 0x73, 0xae, 0x2e, 0xef, 0xf9, 0xeb, 0xb2, 0xaa, 0x87, 0xd9, 0x4a, 0xce, 0x6e, 0x47,- 0x74, 0x6c, 0x2d, 0xae, 0xd9, 0x9b, 0xfd, 0xef, 0xb8, 0xd3, 0xec, 0xe7, 0x99, 0xfc, 0xef, 0x54, 0xa7, 0xb9, 0xbd, 0xbd,- 0xe3, 0xcf, 0x51, 0x7a, 0x4e, 0x5d, 0xee, 0xd6, 0xde, 0x2e, 0x27, 0xcf, 0xbc, 0x8d, 0x6d, 0xa1, 0xfe, 0x3e, 0xeb, 0x1e,- 0x75, 0x96, 0xee, 0x9e, 0xff, 0x9d, 0xb6, 0x63, 0x0d, 0xd6, 0xe5, 0xdf, 0xab, 0xf6, 0xf6, 0xae, 0xf9, 0xbf, 0x47, 0xa5,- 0x95, 0x9e, 0xfc, 0xef, 0x76, 0xdc, 0x3e, 0xb1, 0xfd, 0x2f, 0x1d, 0xd5, 0xee, 0x33, 0x97, 0xe5, 0xd4, 0x8c, 0x7f, 0xe7,- 0xba, 0xbc, 0xef, 0x93, 0xff, 0x22, 0xff, 0xa7, 0xf4, 0xff, 0xcf, 0x5b, 0x36, 0xdf, 0x37, 0x58, 0x71, 0xfd, 0xff, 0x5e,- 0x75, 0x79, 0xdf, 0xa9, 0xfd, 0xdf, 0xa7, 0xce, 0xe2, 0x33, 0xf3, 0xbf, 0x63, 0x7b, 0xaa, 0x2e, 0xa7, 0xfc, 0xd7, 0xcd,- 0xd2, 0xb7, 0xcb, 0x11, 0x15, 0x3f, 0x22, 0x76, 0xaa, 0x57, 0x9d, 0x7d, 0x6d, 0xb0, 0xff, 0x0e, 0xfb, 0x13, 0xea, 0x72,- 0xde, 0x27, 0xff, 0x33, 0xd7, 0xff, 0xcf, 0x4f, 0x5f, 0x19, 0x7a, 0x0e, 0xf8, 0x15, 0x67, 0xa0, 0xd8, 0xfd, 0xff, 0xb3,- 0xaf, 0x8b, 0x67, 0x3d, 0x97, 0x28, 0xf7, 0x3b, 0x59, 0xcf, 0xa9, 0xcb, 0x79, 0x9f, 0xbb, 0x3d, 0x33, 0xf7, 0xff, 0xfb,- 0xee, 0x2c, 0x96, 0xe1, 0x1c, 0x67, 0x3c, 0xeb, 0xbf, 0x5c, 0x54, 0xc5, 0x38, 0xfa, 0xfd, 0x9f, 0x3b, 0x7d, 0xa3, 0x52,- 0x7d, 0xd7, 0xd5, 0xc9, 0xb1, 0x16, 0xeb, 0x8f, 0xd6, 0x35, 0x55, 0x8c, 0x5f, 0xe7, 0xbf, 0xf5, 0x5d, 0x4a, 0x9e, 0x94,- 0xff, 0x27, 0xec, 0x6d, 0xc7, 0x2c, 0xac, 0xf4, 0x97, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0xd0, 0x3d, 0x43, 0xf3, 0xf8, 0xbb, 0xcd, 0x3b, 0xd7, 0x20, 0x05, 0x66, 0xe7, 0xe3, 0x3c, 0x63, 0x3e, 0x1e, 0x90, 0x3d,- 0xb7, 0x71, 0xaf, 0x7a, 0xdc, 0x40, 0xee, 0xfc, 0x7f, 0xf9, 0x07, 0xf9, 0x97, 0x7f, 0x90, 0x7f, 0xf9, 0x07, 0xf9, 0xff,- 0xf9, 0x97, 0x55, 0xfe, 0xe1, 0xe6, 0xf9, 0xaf, 0x4b, 0x6a, 0x9b, 0x03, 0x77, 0x39, 0x03, 0x44, 0xf2, 0x5f, 0xf4, 0xff,- 0xe1, 0xb1, 0xdf, 0x01, 0x30, 0xfe, 0x07, 0xe3, 0x7f, 0xf9, 0x87, 0x77, 0xcc, 0x7f, 0xeb, 0xfb, 0xbf, 0x46, 0xff, 0xf0,- 0x8c, 0xf1, 0xbf, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xf2, 0xff, 0x3f, 0xdb, 0x01, 0xe4, 0x1f, 0x78, 0xbb, 0xfc, 0xff, 0x0b };--// Font glyphs rectangles data (on atlas)-static const Rectangle candyFontRecs[189] = {- { 4, 4, 3 , 15 },- { 15, 4, 2 , 9 },- { 25, 4, 3 , 2 },- { 36, 4, 8 , 9 },- { 52, 4, 6 , 11 },- { 66, 4, 7 , 9 },- { 81, 4, 7 , 9 },- { 96, 4, 1 , 2 },- { 105, 4, 3 , 11 },- { 116, 4, 3 , 11 },- { 127, 4, 7 , 7 },- { 142, 4, 6 , 5 },- { 156, 4, 2 , 3 },- { 166, 4, 5 , 1 },- { 179, 4, 2 , 2 },- { 189, 4, 5 , 10 },- { 202, 4, 6 , 9 },- { 216, 4, 4 , 9 },- { 228, 4, 6 , 9 },- { 242, 4, 6 , 9 },- { 256, 4, 7 , 9 },- { 271, 4, 6 , 9 },- { 285, 4, 6 , 9 },- { 299, 4, 6 , 9 },- { 313, 4, 6 , 9 },- { 327, 4, 6 , 9 },- { 341, 4, 2 , 6 },- { 351, 4, 2 , 7 },- { 361, 4, 4 , 6 },- { 373, 4, 5 , 3 },- { 386, 4, 4 , 6 },- { 398, 4, 6 , 9 },- { 412, 4, 8 , 7 },- { 428, 4, 6 , 9 },- { 442, 4, 6 , 9 },- { 456, 4, 6 , 9 },- { 470, 4, 6 , 9 },- { 484, 4, 6 , 9 },- { 4, 27, 6 , 9 },- { 18, 27, 6 , 9 },- { 32, 27, 6 , 9 },- { 46, 27, 2 , 9 },- { 56, 27, 6 , 9 },- { 70, 27, 6 , 9 },- { 84, 27, 6 , 9 },- { 98, 27, 8 , 9 },- { 114, 27, 6 , 9 },- { 128, 27, 6 , 9 },- { 142, 27, 6 , 9 },- { 156, 27, 6 , 9 },- { 170, 27, 6 , 9 },- { 184, 27, 6 , 9 },- { 198, 27, 6 , 9 },- { 212, 27, 6 , 9 },- { 226, 27, 6 , 9 },- { 240, 27, 8 , 9 },- { 256, 27, 6 , 9 },- { 270, 27, 6 , 9 },- { 284, 27, 6 , 9 },- { 298, 27, 3 , 11 },- { 309, 27, 5 , 10 },- { 322, 27, 3 , 11 },- { 333, 27, 6 , 4 },- { 347, 27, 6 , 1 },- { 361, 27, 3 , 2 },- { 372, 27, 6 , 7 },- { 386, 27, 6 , 10 },- { 400, 27, 6 , 7 },- { 414, 27, 6 , 10 },- { 428, 27, 6 , 7 },- { 442, 27, 5 , 10 },- { 455, 27, 7 , 10 },- { 470, 27, 6 , 10 },- { 484, 27, 2 , 10 },- { 494, 27, 2 , 12 },- { 4, 50, 6 , 10 },- { 18, 50, 3 , 10 },- { 29, 50, 8 , 7 },- { 45, 50, 6 , 7 },- { 59, 50, 6 , 7 },- { 73, 50, 6 , 10 },- { 87, 50, 6 , 10 },- { 101, 50, 6 , 7 },- { 115, 50, 6 , 7 },- { 129, 50, 3 , 10 },- { 140, 50, 6 , 7 },- { 154, 50, 6 , 7 },- { 168, 50, 8 , 7 },- { 184, 50, 6 , 7 },- { 198, 50, 6 , 10 },- { 212, 50, 6 , 7 },- { 226, 50, 4 , 11 },- { 238, 50, 1 , 11 },- { 247, 50, 4 , 11 },- { 259, 50, 6 , 2 },- { 273, 50, 2 , 10 },- { 283, 50, 6 , 11 },- { 297, 50, 8 , 9 },- { 313, 50, 7 , 9 },- { 328, 50, 6 , 9 },- { 342, 50, 0 , 0 },- { 350, 50, 6 , 11 },- { 364, 50, 0 , 0 },- { 372, 50, 8 , 8 },- { 388, 50, 5 , 7 },- { 401, 50, 7 , 6 },- { 416, 50, 7 , 12 },- { 431, 50, 8 , 8 },- { 447, 50, 6 , 1 },- { 461, 50, 4 , 5 },- { 473, 50, 6 , 7 },- { 487, 50, 3 , 5 },- { 498, 50, 3 , 5 },- { 4, 73, 0 , 0 },- { 12, 73, 6 , 9 },- { 26, 73, 6 , 9 },- { 40, 73, 4 , 4 },- { 52, 73, 0 , 0 },- { 60, 73, 2 , 5 },- { 70, 73, 4 , 7 },- { 82, 73, 7 , 6 },- { 97, 73, 10 , 9 },- { 115, 73, 10 , 7 },- { 133, 73, 0 , 0 },- { 141, 73, 6 , 9 },- { 155, 73, 6 , 12 },- { 169, 73, 6 , 12 },- { 183, 73, 6 , 12 },- { 197, 73, 6 , 12 },- { 211, 73, 6 , 11 },- { 225, 73, 6 , 12 },- { 239, 73, 10 , 9 },- { 257, 73, 6 , 12 },- { 271, 73, 6 , 12 },- { 285, 73, 6 , 12 },- { 299, 73, 6 , 12 },- { 313, 73, 6 , 11 },- { 327, 73, 3 , 12 },- { 338, 73, 3 , 12 },- { 349, 73, 4 , 12 },- { 361, 73, 4 , 11 },- { 373, 73, 8 , 9 },- { 389, 73, 6 , 12 },- { 403, 73, 6 , 12 },- { 417, 73, 6 , 12 },- { 431, 73, 6 , 12 },- { 445, 73, 6 , 12 },- { 459, 73, 6 , 11 },- { 473, 73, 5 , 5 },- { 486, 73, 9 , 10 },- { 4, 96, 6 , 12 },- { 18, 96, 6 , 12 },- { 32, 96, 6 , 12 },- { 46, 96, 6 , 11 },- { 60, 96, 6 , 12 },- { 74, 96, 7 , 12 },- { 89, 96, 6 , 10 },- { 103, 96, 6 , 10 },- { 117, 96, 6 , 10 },- { 131, 96, 6 , 10 },- { 145, 96, 6 , 10 },- { 159, 96, 6 , 9 },- { 173, 96, 6 , 11 },- { 187, 96, 10 , 7 },- { 205, 96, 6 , 10 },- { 219, 96, 6 , 10 },- { 233, 96, 6 , 10 },- { 247, 96, 6 , 10 },- { 261, 96, 6 , 9 },- { 275, 96, 3 , 10 },- { 286, 96, 3 , 10 },- { 297, 96, 4 , 10 },- { 309, 96, 4 , 9 },- { 321, 96, 7 , 12 },- { 336, 96, 6 , 13 },- { 350, 96, 6 , 10 },- { 364, 96, 6 , 10 },- { 378, 96, 6 , 10 },- { 392, 96, 6 , 10 },- { 406, 96, 6 , 9 },- { 420, 96, 7 , 12 },- { 435, 96, 8 , 8 },- { 451, 96, 6 , 10 },- { 465, 96, 6 , 10 },- { 479, 96, 6 , 10 },- { 493, 96, 6 , 9 },- { 4, 119, 6 , 13 },- { 18, 119, 7 , 12 },- { 33, 119, 6 , 12 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo candyFontGlyphs[189] = {- { 32, 0, 12, 3, { 0 }},- { 33, 0, 3, 3, { 0 }},- { 34, 0, 2, 4, { 0 }},- { 35, 0, 3, 9, { 0 }},- { 36, 0, 2, 7, { 0 }},- { 37, 0, 3, 8, { 0 }},- { 38, 0, 3, 8, { 0 }},- { 39, 0, 2, 2, { 0 }},- { 40, 1, 2, 5, { 0 }},- { 41, 1, 2, 5, { 0 }},- { 42, 0, 4, 8, { 0 }},- { 43, 0, 6, 7, { 0 }},- { 44, 0, 10, 3, { 0 }},- { 45, 0, 7, 6, { 0 }},- { 46, 0, 10, 3, { 0 }},- { 47, 1, 3, 7, { 0 }},- { 48, 0, 3, 7, { 0 }},- { 49, 0, 3, 5, { 0 }},- { 50, 0, 3, 7, { 0 }},- { 51, 0, 3, 7, { 0 }},- { 52, 0, 3, 8, { 0 }},- { 53, 0, 3, 7, { 0 }},- { 54, 0, 3, 7, { 0 }},- { 55, 0, 3, 7, { 0 }},- { 56, 0, 3, 7, { 0 }},- { 57, 0, 3, 7, { 0 }},- { 58, 0, 6, 3, { 0 }},- { 59, 0, 6, 3, { 0 }},- { 60, 1, 5, 6, { 0 }},- { 61, 1, 7, 7, { 0 }},- { 62, 1, 5, 6, { 0 }},- { 63, 0, 3, 7, { 0 }},- { 64, 0, 4, 9, { 0 }},- { 65, 0, 3, 7, { 0 }},- { 66, 0, 3, 7, { 0 }},- { 67, 0, 3, 7, { 0 }},- { 68, 0, 3, 7, { 0 }},- { 69, 0, 3, 7, { 0 }},- { 70, 0, 3, 7, { 0 }},- { 71, 0, 3, 7, { 0 }},- { 72, 0, 3, 7, { 0 }},- { 73, 0, 3, 3, { 0 }},- { 74, 0, 3, 7, { 0 }},- { 75, 0, 3, 7, { 0 }},- { 76, 0, 3, 7, { 0 }},- { 77, 0, 3, 9, { 0 }},- { 78, 0, 3, 7, { 0 }},- { 79, 0, 3, 7, { 0 }},- { 80, 0, 3, 7, { 0 }},- { 81, 0, 3, 7, { 0 }},- { 82, 0, 3, 7, { 0 }},- { 83, 0, 3, 7, { 0 }},- { 84, 0, 3, 7, { 0 }},- { 85, 0, 3, 7, { 0 }},- { 86, 0, 3, 7, { 0 }},- { 87, 0, 3, 9, { 0 }},- { 88, 0, 3, 7, { 0 }},- { 89, 0, 3, 7, { 0 }},- { 90, 0, 3, 7, { 0 }},- { 91, 1, 2, 5, { 0 }},- { 92, 1, 3, 7, { 0 }},- { 93, 1, 2, 5, { 0 }},- { 94, 0, 3, 7, { 0 }},- { 95, 0, 11, 7, { 0 }},- { 96, 0, 0, 4, { 0 }},- { 97, 0, 5, 7, { 0 }},- { 98, 0, 2, 7, { 0 }},- { 99, 0, 5, 7, { 0 }},- { 100, 0, 2, 7, { 0 }},- { 101, 0, 5, 7, { 0 }},- { 102, 0, 2, 6, { 0 }},- { 103, 0, 5, 7, { 0 }},- { 104, 0, 2, 7, { 0 }},- { 105, 0, 2, 3, { 0 }},- { 106, 0, 2, 3, { 0 }},- { 107, 0, 2, 7, { 0 }},- { 108, 0, 2, 4, { 0 }},- { 109, 0, 5, 9, { 0 }},- { 110, 0, 5, 7, { 0 }},- { 111, 0, 5, 7, { 0 }},- { 112, 0, 5, 7, { 0 }},- { 113, 0, 5, 7, { 0 }},- { 114, 0, 5, 7, { 0 }},- { 115, 0, 5, 7, { 0 }},- { 116, 0, 2, 4, { 0 }},- { 117, 0, 5, 7, { 0 }},- { 118, 0, 5, 7, { 0 }},- { 119, 0, 5, 9, { 0 }},- { 120, 0, 5, 7, { 0 }},- { 121, 0, 5, 7, { 0 }},- { 122, 0, 5, 7, { 0 }},- { 123, 1, 2, 6, { 0 }},- { 124, 1, 2, 3, { 0 }},- { 125, 1, 2, 6, { 0 }},- { 126, 0, 0, 7, { 0 }},- { 161, 0, 3, 3, { 0 }},- { 162, 0, 2, 7, { 0 }},- { 163, 0, 3, 9, { 0 }},- { 8364, 0, 3, 8, { 0 }},- { 165, 0, 3, 7, { 0 }},- { 352, 0, 12, 1, { 0 }},- { 167, 0, 2, 7, { 0 }},- { 353, 0, 12, 1, { 0 }},- { 169, 0, 0, 9, { 0 }},- { 170, 0, 0, 6, { 0 }},- { 171, 1, 5, 9, { 0 }},- { 172, 0, 0, 7, { 0 }},- { 174, 0, 0, 9, { 0 }},- { 175, 0, 0, 7, { 0 }},- { 176, 0, 0, 5, { 0 }},- { 177, 0, 4, 7, { 0 }},- { 178, 0, 0, 4, { 0 }},- { 179, 0, 0, 4, { 0 }},- { 381, 0, 12, 1, { 0 }},- { 181, 0, 5, 7, { 0 }},- { 182, 0, 3, 7, { 0 }},- { 183, 0, 6, 5, { 0 }},- { 382, 0, 12, 1, { 0 }},- { 185, 0, 0, 3, { 0 }},- { 186, 0, 0, 5, { 0 }},- { 187, 1, 5, 9, { 0 }},- { 338, 0, 3, 11, { 0 }},- { 339, 0, 5, 11, { 0 }},- { 376, 0, 12, 1, { 0 }},- { 191, 0, 4, 7, { 0 }},- { 192, 0, 0, 7, { 0 }},- { 193, 0, 0, 7, { 0 }},- { 194, 0, 0, 7, { 0 }},- { 195, 0, 0, 7, { 0 }},- { 196, 0, 1, 7, { 0 }},- { 197, 0, 0, 7, { 0 }},- { 198, 0, 3, 11, { 0 }},- { 199, 0, 3, 7, { 0 }},- { 200, 0, 0, 7, { 0 }},- { 201, 0, 0, 7, { 0 }},- { 202, 0, 0, 7, { 0 }},- { 203, 0, 1, 7, { 0 }},- { 204, -1, 0, 3, { 0 }},- { 205, 0, 0, 3, { 0 }},- { 206, -1, 0, 3, { 0 }},- { 207, -1, 1, 3, { 0 }},- { 208, 0, 3, 9, { 0 }},- { 209, 0, 0, 7, { 0 }},- { 210, 0, 0, 7, { 0 }},- { 211, 0, 0, 7, { 0 }},- { 212, 0, 0, 7, { 0 }},- { 213, 0, 0, 7, { 0 }},- { 214, 0, 1, 7, { 0 }},- { 215, 0, 7, 6, { 0 }},- { 216, 0, 3, 10, { 0 }},- { 217, 0, 0, 7, { 0 }},- { 218, 0, 0, 7, { 0 }},- { 219, 0, 0, 7, { 0 }},- { 220, 0, 1, 7, { 0 }},- { 221, 0, 0, 7, { 0 }},- { 222, 0, 0, 7, { 0 }},- { 223, 0, 3, 7, { 0 }},- { 224, 0, 2, 7, { 0 }},- { 225, 0, 2, 7, { 0 }},- { 226, 0, 2, 7, { 0 }},- { 227, 0, 2, 7, { 0 }},- { 228, 0, 3, 7, { 0 }},- { 229, 0, 1, 7, { 0 }},- { 230, 0, 5, 11, { 0 }},- { 231, 0, 5, 7, { 0 }},- { 232, 0, 2, 7, { 0 }},- { 233, 0, 2, 7, { 0 }},- { 234, 0, 2, 7, { 0 }},- { 235, 0, 3, 7, { 0 }},- { 236, 0, 2, 4, { 0 }},- { 237, 0, 2, 4, { 0 }},- { 238, 0, 2, 4, { 0 }},- { 239, 0, 3, 4, { 0 }},- { 240, 0, 0, 7, { 0 }},- { 241, 0, 2, 7, { 0 }},- { 242, 0, 2, 7, { 0 }},- { 243, 0, 2, 7, { 0 }},- { 244, 0, 2, 7, { 0 }},- { 245, 0, 2, 7, { 0 }},- { 246, 0, 3, 7, { 0 }},- { 247, 0, 0, 7, { 0 }},- { 248, 0, 5, 9, { 0 }},- { 249, 0, 2, 7, { 0 }},- { 250, 0, 2, 7, { 0 }},- { 251, 0, 2, 7, { 0 }},- { 252, 0, 3, 7, { 0 }},- { 253, 0, 2, 7, { 0 }},- { 254, 0, 0, 7, { 0 }},- { 255, 0, 3, 7, { 0 }},-};--// Style loading function: Candy-static void GuiLoadStyleCandy(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < CANDY_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(candyStyleProps[i].controlId, candyStyleProps[i].propertyId, candyStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int candyFontDataSize = 0;- unsigned char *data = DecompressData(candyFontData, CANDY_STYLE_FONT_ATLAS_COMP_SIZE, &candyFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 15;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, candyFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, candyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_cherry.h
@@ -1,617 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleCherry(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define CHERRY_STYLE_PROPS_COUNT 17--// Custom style name: Cherry-static const GuiStyleProp cherryStyleProps[CHERRY_STYLE_PROPS_COUNT] = {- { 0, 0, 0xda5757ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x753233ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xe17373ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xfaaa97ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xe06262ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xfdb4aaff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xe03c46ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0x5b1e20ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0xc2474fff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0xa19292ff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x706060ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x9e8585ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0xfb8170ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x3a1720ff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "Westington.ttf" (size: 15, spacing: 0)--#define CHERRY_STYLE_FONT_ATLAS_COMP_SIZE 2821--// Font atlas image pixels data: DEFLATE compressed-static unsigned char cherryFontData[CHERRY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x59, 0x92, 0xdc, 0xba, 0x11, 0x05, 0x50, 0xee, 0x7f, 0xd3, 0xd7, 0xe1, 0x70, 0x84, 0xed, 0x27, 0xa9, 0x09, 0x20,- 0x91, 0x20, 0xab, 0x5b, 0x47, 0xe7, 0xaf, 0xa1, 0x1a, 0x38, 0x24, 0x26, 0x16, 0x12, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xf2,- 0xef, 0x7f, 0x5f, 0xfd, 0xf5, 0xcf, 0x65, 0xff, 0xff, 0xaa, 0xdc, 0xbe, 0x73, 0xfd, 0xb3, 0xb3, 0xf8, 0xae, 0x59, 0xf8,- 0x7f, 0xf9, 0xf2, 0xbb, 0x64, 0xfa, 0x33, 0xd7, 0x8f, 0x7b, 0xfd, 0x58, 0xef, 0xce, 0xfd, 0xfa, 0x31, 0x5c, 0x37, 0x9f,- 0xbf, 0xf6, 0xdd, 0x2a, 0xaf, 0xb9, 0x2f, 0x59, 0xbf, 0x7b, 0x3a, 0xae, 0xc8, 0xdc, 0x35, 0xb8, 0x3f, 0xa7, 0xd7, 0xf0,- 0x95, 0xeb, 0xef, 0x9c, 0xe1, 0x59, 0x1c, 0x7f, 0xab, 0xb5, 0x1a, 0xe0, 0xeb, 0xbf, 0x8e, 0xee, 0xa6, 0x14, 0xee, 0xab,- 0xff, 0xbd, 0x22, 0x8b, 0x65, 0xa3, 0xd7, 0xec, 0xdd, 0x57, 0x59, 0xa8, 0xa5, 0x2a, 0x57, 0x21, 0x8b, 0xe7, 0x61, 0xf5,- 0xdc, 0xa5, 0x54, 0xff, 0x8c, 0xbe, 0x6d, 0x5a, 0x8e, 0xe7, 0xae, 0x24, 0xd3, 0x7f, 0x1d, 0xbf, 0xa2, 0xf2, 0x6e, 0x33,- 0xf7, 0xd5, 0xdd, 0xab, 0xfb, 0xdf, 0x39, 0x53, 0xf7, 0xef, 0xd9, 0xf8, 0x1f, 0xd5, 0x97, 0xf7, 0xe7, 0xfb, 0xee, 0x28,- 0xf2, 0xdf, 0xde, 0x45, 0xed, 0xbe, 0xdb, 0x89, 0xf4, 0xdc, 0xdc, 0x9d, 0x29, 0x9e, 0x8d, 0xfa, 0xff, 0xbb, 0x8f, 0x97,- 0x14, 0x7b, 0x5e, 0x59, 0xb8, 0x4f, 0xb3, 0x54, 0xeb, 0xcd, 0xf4, 0x26, 0x2a, 0x35, 0xdd, 0x6e, 0x2f, 0x6a, 0xbf, 0xa7,- 0xfb, 0xf5, 0x35, 0xb8, 0x3b, 0xdf, 0x99, 0x3c, 0x82, 0x94, 0xe2, 0xff, 0x5a, 0xac, 0xb1, 0x9f, 0x8a, 0xff, 0x71, 0xac,- 0x8c, 0xe2, 0x29, 0xc3, 0x2b, 0x9c, 0x96, 0xef, 0x9f, 0x52, 0x8d, 0x76, 0x6a, 0x9c, 0x55, 0xbf, 0x7f, 0x66, 0xcf, 0x5e,- 0x06, 0xa3, 0xb9, 0xee, 0x5e, 0xe8, 0x7c, 0xaf, 0x2f, 0xc5, 0xda, 0x75, 0xa5, 0x8f, 0x9f, 0xad, 0xde, 0xfa, 0x28, 0x7e,- 0xb3, 0x5c, 0x17, 0x67, 0xa2, 0x3f, 0x74, 0xa2, 0x4f, 0xf2, 0x09, 0xf1, 0x9f, 0xc2, 0x08, 0xae, 0x5a, 0xc7, 0xa7, 0xa9,- 0x6d, 0xce, 0xa1, 0xfa, 0xb5, 0x3b, 0xfe, 0xd7, 0xcb, 0xc6, 0x91, 0x91, 0xd6, 0x71, 0x58, 0x4a, 0x23, 0xe9, 0x7a, 0x1b,- 0xbe, 0xfb, 0xda, 0xbb, 0xb9, 0xa2, 0x4c, 0xd4, 0x9e, 0x59, 0x9e, 0x01, 0xd8, 0x89, 0xff, 0xfe, 0xf1, 0x7f, 0x4a, 0xaf,- 0x98, 0xab, 0x8d, 0x6b, 0x35, 0x71, 0x16, 0xbe, 0x59, 0x9a, 0x6a, 0xb6, 0x1c, 0x9d, 0x65, 0xbd, 0x1a, 0xe3, 0xbf, 0x36,- 0x72, 0x4a, 0xdb, 0xdc, 0x44, 0x7d, 0xec, 0x96, 0xa6, 0xfb, 0x35, 0xad, 0xaf, 0xb8, 0x8f, 0xff, 0xbb, 0xf6, 0x7f, 0xbf,- 0xff, 0xff, 0x7e, 0xfb, 0xdf, 0x3d, 0xfa, 0x9f, 0x9f, 0xc5, 0x18, 0x9f, 0xd3, 0xe7, 0xe2, 0xff, 0x64, 0xdf, 0xbf, 0x36,- 0x96, 0x4f, 0x71, 0x9e, 0x32, 0x4d, 0x23, 0xf6, 0x94, 0x47, 0xe7, 0x69, 0x99, 0xd5, 0xe9, 0xab, 0xab, 0x53, 0xfe, 0x8c,- 0xfa, 0x3c, 0xf6, 0x4f, 0x1d, 0xff, 0x67, 0xe9, 0xd9, 0xc0, 0xb8, 0x6f, 0x75, 0x77, 0x66, 0xd2, 0x3e, 0xff, 0xf7, 0xde,- 0x53, 0xd6, 0xb5, 0x5a, 0x27, 0x85, 0x31, 0x76, 0x65, 0xd6, 0xbc, 0xfa, 0x34, 0xb1, 0xf3, 0xd9, 0xe4, 0xfb, 0xd7, 0xa9,- 0x3a, 0xd7, 0x98, 0x72, 0xed, 0x9e, 0x89, 0x67, 0x3f, 0xeb, 0xb3, 0x0a, 0x4f, 0xf5, 0xa6, 0x66, 0xe6, 0x62, 0xae, 0xe2,- 0xbc, 0x69, 0x0a, 0x3d, 0x9c, 0x4f, 0x8f, 0xff, 0x4f, 0xaa, 0x89, 0x3e, 0xf1, 0xf7, 0x27, 0x69, 0x1e, 0xe9, 0x77, 0x45,- 0x40, 0x26, 0x46, 0xe2, 0x57, 0xa1, 0x9e, 0xfe, 0x0e, 0xcf, 0xff, 0xc7, 0xf1, 0x5f, 0x1d, 0xff, 0x67, 0xea, 0xf7, 0x18,- 0x6b, 0xcf, 0x01, 0xf2, 0xe1, 0xad, 0xbf, 0x1a, 0xa0, 0x67, 0x4e, 0xfe, 0xe9, 0xfa, 0x39, 0x87, 0xc7, 0x85, 0x7f, 0xe3,- 0x75, 0x05, 0xf7, 0x0f, 0x20, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x5e, 0x37,- 0xb8, 0xbe, 0x16, 0xb1, 0x3b, 0x4b, 0x6b, 0xe5, 0xfd, 0x7e, 0x2f, 0x1d, 0xbd, 0x47, 0xf5, 0x68, 0x2b, 0xb9, 0xa0, 0x33,- 0xf5, 0xdd, 0xb3, 0xbc, 0xa2, 0x73, 0x74, 0x34, 0xf9, 0xc7, 0x1a, 0xd5, 0x99, 0x73, 0xba, 0x73, 0x5d, 0xc6, 0x99, 0x77,- 0x57, 0xf2, 0xfb, 0xae, 0xad, 0x06, 0x5e, 0x5d, 0x21, 0xd0, 0x99, 0xed, 0x60, 0xf6, 0xfa, 0x56, 0xee, 0xa8, 0x95, 0x4f,- 0xdb, 0x59, 0x8b, 0x78, 0x9f, 0x81, 0xf9, 0x1a, 0x66, 0x88, 0xee, 0xca, 0x51, 0x97, 0x8d, 0x35, 0xfb, 0xbf, 0xdf, 0xc9,- 0x95, 0x55, 0xdb, 0xe3, 0x7b, 0xaa, 0x92, 0x77, 0xa9, 0x9a, 0xb3, 0x39, 0x2d, 0x9f, 0x3b, 0xf3, 0xcd, 0xe6, 0x32, 0xfa,- 0xd4, 0x33, 0xb6, 0x5f, 0x8b, 0xfb, 0x30, 0xac, 0xad, 0xe5, 0xce, 0xf2, 0x5a, 0xf8, 0xb4, 0xe5, 0x8b, 0x48, 0xf1, 0x3d,- 0x6b, 0xf7, 0xda, 0x99, 0xec, 0x3f, 0xd5, 0x2c, 0x59, 0x67, 0xe2, 0x3f, 0xe5, 0xef, 0x92, 0xdb, 0x7b, 0xe2, 0x1a, 0x66,- 0x28, 0xaa, 0x66, 0x5e, 0xca, 0x46, 0xbd, 0x96, 0x8d, 0xb5, 0xee, 0x5d, 0xf1, 0xbf, 0x13, 0xe1, 0xb3, 0xf9, 0x7b, 0xd3,- 0xb2, 0xba, 0x7f, 0x25, 0x1b, 0x7a, 0xb5, 0x1f, 0xdc, 0x19, 0x21, 0x77, 0xc7, 0x9e, 0x8d, 0x33, 0x73, 0x26, 0xfe, 0xf3,- 0x01, 0xf1, 0xbf, 0x53, 0x17, 0x7d, 0xcf, 0xf8, 0x4f, 0x43, 0xed, 0x9c, 0xd2, 0x15, 0xfa, 0x3d, 0x76, 0x2b, 0x7b, 0x59,- 0x5c, 0xe5, 0x8c, 0xce, 0x69, 0x6e, 0x8f, 0x3a, 0xd6, 0x14, 0x3f, 0x19, 0xff, 0xeb, 0xf5, 0xcd, 0xa9, 0xf8, 0xbf, 0xdb,- 0xad, 0x23, 0xa5, 0xdd, 0x9e, 0xfa, 0xf6, 0xc1, 0x5a, 0xa9, 0x8b, 0x32, 0x9d, 0x5b, 0xb4, 0x12, 0xff, 0x19, 0xee, 0xa0,- 0x51, 0xd9, 0xb7, 0xa0, 0x9a, 0x0d, 0xb9, 0x23, 0xfe, 0xe7, 0xf3, 0x9b, 0x67, 0xb2, 0xee, 0xed, 0x88, 0xf3, 0x77, 0xe2,- 0x7f, 0x74, 0x05, 0x53, 0xcc, 0xd6, 0xb7, 0x9e, 0xe5, 0x7b, 0xfc, 0x69, 0xbd, 0x59, 0xd4, 0x67, 0xf6, 0x9a, 0xc9, 0x37,- 0x68, 0xff, 0xcf, 0xc7, 0x7f, 0xe5, 0x5d, 0x67, 0xe7, 0x66, 0xf2, 0x5a, 0xfc, 0x67, 0xbb, 0x85, 0x4f, 0xf3, 0xe8, 0xf2,- 0x8d, 0xbc, 0x5f, 0x33, 0xf3, 0x05, 0xb5, 0x18, 0x4f, 0xeb, 0x78, 0xa3, 0xf6, 0x69, 0x27, 0x7a, 0x98, 0xeb, 0xf1, 0x9f,- 0xa3, 0xe3, 0xff, 0x95, 0x4f, 0xa8, 0xf7, 0xff, 0xef, 0x3e, 0xbb, 0x77, 0xfe, 0xaf, 0x6b, 0xee, 0x69, 0xa6, 0xed, 0x4e,- 0x43, 0x2f, 0xe2, 0x7c, 0xcd, 0x90, 0xd7, 0x9e, 0x91, 0x55, 0x3e, 0xff, 0x44, 0x44, 0x56, 0x63, 0xab, 0x1a, 0xff, 0xbd,- 0xf3, 0xff, 0x1d, 0xf3, 0xcc, 0x73, 0x47, 0x9f, 0x42, 0xa4, 0xa6, 0x38, 0xbe, 0xca, 0xd6, 0x0c, 0x79, 0x36, 0xe2, 0x3f,- 0x0d, 0xf1, 0x7f, 0xf7, 0xfc, 0x6e, 0x37, 0xfe, 0x33, 0x78, 0xbe, 0x91, 0x6f, 0x13, 0xff, 0x29, 0xc5, 0x7f, 0x9a, 0x23,- 0x32, 0xe5, 0xd8, 0xba, 0x96, 0x9f, 0x4f, 0x9e, 0x79, 0xfe, 0x3f, 0x7e, 0xca, 0xba, 0xf3, 0x24, 0x79, 0xf6, 0x3b, 0xd5,- 0x7f, 0xed, 0x30, 0x3a, 0x4b, 0x59, 0x8e, 0xb0, 0x94, 0x72, 0xf3, 0xcf, 0x8f, 0xf9, 0xb2, 0xd9, 0x4a, 0x8d, 0x6b, 0x88,- 0x6a, 0x4e, 0xea, 0xd5, 0x7d, 0xd5, 0xf3, 0xfa, 0xbe, 0x36, 0xcf, 0xbc, 0x72, 0x67, 0xaf, 0x06, 0x39, 0x89, 0xf9, 0x19,- 0xbf, 0x49, 0x73, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0x60,- 0xa6, 0x94, 0xd5, 0x6b, 0xf6, 0x7f, 0x55, 0x73, 0x90, 0xe5, 0x36, 0xcb, 0xf4, 0xda, 0x5a, 0xdf, 0x0c, 0x8f, 0xb1, 0x63,- 0xa5, 0xf4, 0xd9, 0x2c, 0xdc, 0xf3, 0xe7, 0xb6, 0x76, 0xf5, 0xb3, 0x98, 0xcf, 0x32, 0xed, 0x2b, 0xd3, 0xc7, 0xeb, 0xad,- 0xef, 0xd7, 0xd0, 0xd7, 0x5f, 0x77, 0x15, 0x56, 0x38, 0xaf, 0x5e, 0xad, 0x99, 0x5c, 0xf1, 0x6f, 0xd4, 0x15, 0xd7, 0x44,- 0x86, 0xbb, 0x9d, 0x1c, 0xfa, 0x77, 0xe7, 0xfe, 0xeb, 0xfb, 0xf5, 0xee, 0x7b, 0xf5, 0xe5, 0x2d, 0xbc, 0xb6, 0x33, 0xe8,- 0x5e, 0x8f, 0x64, 0xe1, 0xce, 0xe2, 0x7d, 0x38, 0xfb, 0x3f, 0x47, 0x59, 0x04, 0x53, 0xc8, 0xf4, 0x71, 0xee, 0x78, 0x67,- 0xf2, 0x3f, 0x8d, 0xf2, 0x3c, 0xfe, 0xf9, 0xef, 0x2b, 0xf7, 0x53, 0x2d, 0x67, 0x72, 0x06, 0xb9, 0x24, 0x7b, 0xd7, 0x5a,- 0xe7, 0xf6, 0x5e, 0x5d, 0xef, 0x47, 0x9c, 0xb9, 0xa2, 0xf5, 0xf8, 0x5f, 0x6f, 0x77, 0x4e, 0xc5, 0xff, 0x7e, 0x16, 0xde,- 0x9d, 0x1c, 0x3d, 0xfb, 0x7f, 0xbf, 0x6f, 0xfd, 0xaf, 0xe5, 0xde, 0xd9, 0xb5, 0x95, 0xeb, 0x76, 0x9c, 0x09, 0x67, 0x9c,- 0x61, 0x6a, 0xf5, 0x38, 0xae, 0xc5, 0xfc, 0xce, 0x9f, 0x13, 0xff, 0x57, 0x29, 0xfe, 0xaf, 0x0f, 0x8a, 0xff, 0xbb, 0x76,- 0xe7, 0x2a, 0xee, 0x27, 0x72, 0xd7, 0x33, 0xbb, 0x1a, 0xdb, 0x9c, 0xdf, 0x6b, 0xd5, 0x94, 0xfa, 0xc3, 0x29, 0x67, 0x4f,- 0x7c, 0x2b, 0x07, 0xd7, 0x78, 0x77, 0x93, 0x71, 0xdf, 0xbf, 0x56, 0x53, 0xd6, 0x32, 0x31, 0xdd, 0x8f, 0x28, 0xb2, 0xb4,- 0x3b, 0x41, 0x3d, 0x2f, 0x58, 0x0e, 0x64, 0x47, 0x59, 0xad, 0xe9, 0x53, 0xe8, 0xff, 0x5f, 0x5b, 0xfb, 0x48, 0x54, 0xf3,- 0x1e, 0xd7, 0x72, 0xac, 0xa7, 0xd0, 0xee, 0xcc, 0xc4, 0xdf, 0x5e, 0x16, 0xde, 0x4c, 0x8e, 0xb2, 0xae, 0xc5, 0x3a, 0xf2,- 0x6a, 0xab, 0x31, 0xd6, 0x7a, 0x98, 0xd9, 0x1a, 0x6d, 0xcd, 0xd4, 0x0d, 0x59, 0xdc, 0xab, 0xa1, 0xde, 0x5e, 0x54, 0xf2,- 0xc9, 0xd5, 0x6b, 0x80, 0xbc, 0x36, 0xff, 0x77, 0x15, 0x32, 0xd5, 0xaf, 0xe5, 0xe6, 0xab, 0xcc, 0xbd, 0x55, 0x8e, 0xaf,- 0x96, 0x73, 0x6f, 0x26, 0x6b, 0x7b, 0x4f, 0xfe, 0xe2, 0xd5, 0xf3, 0x73, 0x4d, 0xcd, 0x6a, 0xe5, 0xa5, 0xf6, 0x7f, 0x3d,- 0x02, 0xe6, 0x76, 0xa5, 0xdc, 0xe9, 0xd5, 0x54, 0x33, 0x76, 0xf7, 0xf7, 0x7e, 0xde, 0x9f, 0xff, 0x5f, 0xcb, 0xe0, 0xfd,- 0x59, 0xd9, 0x59, 0xd3, 0xf0, 0x3f, 0xfa, 0x3e, 0xeb, 0xed, 0x67, 0x38, 0x39, 0x5a, 0xfb, 0xf7, 0xc6, 0x7f, 0x8a, 0xe3,- 0xc9, 0xd9, 0x7a, 0x38, 0x4b, 0x39, 0x87, 0xc7, 0xf3, 0x5b, 0xe7, 0xc6, 0x3f, 0x9f, 0x78, 0x3f, 0xed, 0xe4, 0xb2, 0x7f,- 0xf6, 0x7b, 0xe6, 0xb1, 0x1e, 0xd3, 0x89, 0xd9, 0x97, 0xe7, 0xce, 0xc4, 0xda, 0x31, 0xa5, 0xf1, 0x8e, 0xad, 0xcd, 0xff,- 0x65, 0x63, 0x8e, 0x6f, 0x77, 0xbf, 0xde, 0x14, 0x66, 0x15, 0xff, 0x86, 0x5f, 0x0a, 0x7c, 0x3d, 0x03, 0x91, 0xbf, 0x22,- 0xf7, 0xf0, 0x4f, 0x3c, 0xc6, 0x8e, 0xe7, 0xff, 0xd5, 0x7e, 0x53, 0x6d, 0xe7, 0x80, 0xb9, 0x79, 0x9f, 0xca, 0xfc, 0x6e,- 0x75, 0xcc, 0x08, 0x54, 0x9e, 0x31, 0x57, 0x76, 0x0e, 0xe8, 0x18, 0xc1, 0x65, 0xf9, 0xf9, 0x3f, 0xf0, 0x53, 0x6a, 0xa2,- 0xda, 0xbc, 0x22, 0xf0, 0xfd, 0x47, 0x3b, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,- 0x9e, 0xbf, 0x88, 0x5e, 0x5f, 0xeb, 0xba, 0x9e, 0xeb, 0xb0, 0x9e, 0x71, 0x65, 0x76, 0x7d, 0xea, 0x55, 0xca, 0x1a, 0xb9,- 0x97, 0x9b, 0x66, 0x2e, 0x5b, 0x73, 0x3d, 0x5b, 0x5d, 0x35, 0x43, 0xd6, 0x5e, 0xe9, 0xf8, 0x95, 0xf5, 0x57, 0x5f, 0xd3,- 0xe7, 0x2d, 0xaf, 0x1c, 0x77, 0x16, 0x73, 0x18, 0xac, 0xdc, 0x53, 0xfd, 0xc7, 0xba, 0x77, 0x2e, 0xae, 0x62, 0x46, 0x9f,- 0x4a, 0xb6, 0xe3, 0x4a, 0xbc, 0xde, 0xe5, 0x3b, 0xcd, 0xe2, 0x67, 0x65, 0x39, 0xa7, 0xf3, 0xa8, 0x16, 0xc9, 0x60, 0xc5,- 0x68, 0x26, 0xd6, 0x9c, 0xee, 0xe5, 0x1b, 0xa8, 0x96, 0x8d, 0xaf, 0x7a, 0x3d, 0xcf, 0x49, 0x16, 0xeb, 0x8f, 0xb5, 0x1c,- 0x7d, 0x27, 0x8f, 0x7b, 0x7d, 0x0d, 0x73, 0x96, 0x73, 0x64, 0x5d, 0x8b, 0xad, 0x4d, 0x26, 0xda, 0x87, 0xea, 0xb9, 0x98,- 0x6d, 0x01, 0x57, 0xdb, 0xcd, 0xd5, 0x9a, 0xa4, 0x1a, 0xff, 0xd5, 0xcf, 0x3a, 0x13, 0xff, 0x77, 0xc7, 0x96, 0xdb, 0x9c,- 0x13, 0xd9, 0xcc, 0x6f, 0xf8, 0x6c, 0xaf, 0xb0, 0xa7, 0xfd, 0x4d, 0x71, 0x8d, 0xfe, 0xf9, 0x75, 0x81, 0xa7, 0x56, 0x07,- 0xd6, 0x73, 0x47, 0xbf, 0x71, 0x0f, 0xa4, 0x2d, 0x6b, 0xe4, 0x5c, 0x3e, 0xd6, 0xf5, 0xf8, 0x5f, 0x1d, 0x2f, 0xac, 0xe6,- 0x33, 0xcc, 0x44, 0xeb, 0x34, 0xdb, 0xfe, 0x67, 0xeb, 0xea, 0x3f, 0xdf, 0xff, 0xbf, 0x36, 0xda, 0xd0, 0xb9, 0xd1, 0xc1,- 0x6c, 0x1e, 0x8e, 0xd5, 0xbb, 0xa9, 0x5e, 0x3a, 0xce, 0x0d, 0xbc, 0xf7, 0xd7, 0xf1, 0xfd, 0x77, 0xf7, 0x4e, 0x95, 0x91,- 0x52, 0xb6, 0x33, 0x36, 0x65, 0xf9, 0x6c, 0xdc, 0x1f, 0xf5, 0x7a, 0xce, 0xe5, 0xd5, 0xf8, 0x1f, 0xd5, 0x26, 0x6b, 0x23,- 0xb8, 0x71, 0xfb, 0x3f, 0x93, 0x6b, 0x72, 0x6f, 0xb7, 0x8a, 0x1c, 0x89, 0xc3, 0x7a, 0xe9, 0xce, 0x4e, 0x27, 0x7f, 0xaa,- 0x13, 0x53, 0xae, 0x99, 0x72, 0xac, 0xf4, 0xc4, 0xf8, 0x7f, 0x9c, 0x71, 0x24, 0x85, 0x7c, 0x25, 0x3b, 0xa3, 0xa8, 0xdd,- 0xf6, 0xa5, 0xe3, 0xdd, 0xb2, 0xb5, 0x97, 0xc3, 0xb9, 0x6f, 0xdd, 0x31, 0xfe, 0x3f, 0x3b, 0xff, 0xb7, 0xbf, 0xe3, 0x58,- 0xcf, 0x6e, 0x45, 0xab, 0xb5, 0xd9, 0xaf, 0xe7, 0x22, 0x1f, 0xd2, 0xab, 0xa9, 0xd5, 0x0e, 0xfb, 0x7f, 0x1d, 0xcf, 0x59,- 0xe7, 0xa5, 0xf8, 0xef, 0x1d, 0x09, 0xe5, 0xc0, 0xfc, 0xe4, 0xf3, 0xd1, 0xbf, 0x32, 0xfe, 0xef, 0x98, 0x31, 0xab, 0xee,- 0x38, 0x72, 0xb6, 0xb4, 0xb2, 0xe3, 0xea, 0xfc, 0x3d, 0xf9, 0x44, 0x0b, 0xdf, 0xb5, 0x4f, 0xc2, 0x4f, 0x8d, 0xff, 0x37,- 0xf7, 0x18, 0xd9, 0x89, 0xff, 0xf3, 0x59, 0x9a, 0xf3, 0x87, 0x79, 0xbd, 0xdd, 0x4f, 0x1c, 0xed, 0x11, 0x9b, 0xf6, 0x38,- 0xdc, 0x8f, 0xe1, 0x9d, 0xd2, 0xb9, 0x7d, 0x78, 0x6a, 0x51, 0xba, 0x53, 0xfa, 0x56, 0xfb, 0x3f, 0x33, 0x0b, 0xf5, 0x74,- 0xfc, 0x77, 0xce, 0x86, 0xe6, 0x50, 0xeb, 0xb8, 0x3e, 0x9a, 0xe8, 0x9f, 0x1b, 0xed, 0xf8, 0xc4, 0x6a, 0xcb, 0xf0, 0x4e,- 0xff, 0xbf, 0xfe, 0xfb, 0x8b, 0x7f, 0xce, 0x66, 0xa5, 0x38, 0xab, 0xf5, 0x93, 0xc6, 0xff, 0xd7, 0xd4, 0xae, 0x51, 0x79,- 0x69, 0xfc, 0xff, 0x19, 0xaf, 0xff, 0x7b, 0x7f, 0x81, 0x75, 0x1d, 0x6e, 0x87, 0x9f, 0x2e, 0x3d, 0xdf, 0x63, 0xdc, 0x2b,- 0xcd, 0x2b, 0xed, 0xff, 0xdc, 0x48, 0xf4, 0xbd, 0xf8, 0xef, 0xea, 0x2f, 0xab, 0x09, 0x3a, 0xe7, 0x59, 0xde, 0x6d, 0xc3,- 0x6b, 0xbb, 0x38, 0xee, 0xfd, 0xda, 0x66, 0x76, 0x74, 0x50, 0x2b, 0xcd, 0xe1, 0xf1, 0xff, 0xee, 0x55, 0xae, 0x1c, 0xcf,- 0xa7, 0xc4, 0xbf, 0xbc, 0xea, 0xa7, 0xea, 0x8c, 0x4a, 0x1c, 0x3e, 0x15, 0xc3, 0xcf, 0xdf, 0x4d, 0x7b, 0xcf, 0xff, 0xd7,- 0xeb, 0xe8, 0xb5, 0xe7, 0xff, 0x3b, 0x2d, 0xc3, 0xd3, 0xcf, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x80, 0xef, 0xb7, 0xfe, 0x6c, 0x9c, 0x99, 0xa6, 0x9e, 0xd5, 0x7b, 0x37, 0x2b, 0xc0, 0xde, 0x11, 0xa5, 0xb4, 0xf6,- 0x6c, 0x36, 0xb7, 0x75, 0xf7, 0xfa, 0xb4, 0x7a, 0x7e, 0xf0, 0x6c, 0xac, 0x3a, 0xac, 0xff, 0xba, 0xfc, 0xd4, 0x71, 0x9e,- 0xca, 0xc2, 0x55, 0xb9, 0x1f, 0x9e, 0xbb, 0x96, 0x69, 0xbf, 0xc2, 0xb3, 0xef, 0x51, 0xcd, 0x05, 0x9d, 0xa5, 0x1c, 0x10,- 0xab, 0x71, 0x96, 0xcd, 0x0c, 0xf5, 0xf5, 0xb5, 0x67, 0xb3, 0xb5, 0x4e, 0x6f, 0xe6, 0xea, 0x6c, 0xe4, 0x87, 0xae, 0x9f,- 0xa3, 0x9d, 0xd5, 0xa5, 0xdd, 0xc7, 0xb9, 0x7e, 0xc5, 0x3a, 0x72, 0x73, 0x67, 0xe3, 0xcc, 0x67, 0xf9, 0xcc, 0x64, 0x50,- 0x3b, 0xe5, 0x91, 0x75, 0xa5, 0xbd, 0x99, 0x0b, 0x56, 0x57, 0x34, 0x3e, 0xb7, 0xd6, 0xb6, 0xbe, 0x0a, 0x6c, 0x37, 0xbf,- 0xd5, 0x73, 0xfd, 0xb7, 0x6a, 0x5f, 0xe4, 0xd7, 0xa3, 0xcc, 0x07, 0xe4, 0x74, 0x38, 0xbb, 0x9a, 0xed, 0xcc, 0x5e, 0x23,- 0xe7, 0xbf, 0xe1, 0xde, 0xde, 0x21, 0x3b, 0x6b, 0x08, 0x53, 0xec, 0x51, 0x8d, 0x32, 0x1a, 0xdc, 0xc7, 0xe7, 0x6e, 0xf9,- 0x5c, 0x0e, 0xb8, 0x6b, 0x22, 0x33, 0x6d, 0x0a, 0xd9, 0x2f, 0x32, 0x58, 0xd7, 0xde, 0x5d, 0x56, 0xbb, 0x47, 0x67, 0xf2,- 0x96, 0xe7, 0xc0, 0x1d, 0x75, 0xbd, 0x98, 0x9b, 0xeb, 0x5a, 0x6e, 0x93, 0x53, 0x6c, 0x7b, 0x3b, 0x4b, 0x3a, 0xea, 0xe7,- 0x6a, 0x2f, 0x6f, 0xa6, 0x6c, 0x3d, 0xa3, 0xe1, 0x4c, 0xcf, 0xf2, 0x99, 0xf2, 0xf5, 0x5c, 0xe6, 0xb3, 0xd9, 0x6f, 0xf2,- 0x58, 0x59, 0xca, 0x77, 0xdb, 0x35, 0x91, 0x87, 0xff, 0xd4, 0x5d, 0xf3, 0x7c, 0x36, 0x8b, 0x4a, 0x0d, 0x5a, 0xcb, 0x91,- 0xf8, 0x5c, 0xc9, 0x6c, 0xae, 0x83, 0x13, 0x57, 0xeb, 0x2a, 0xde, 0x39, 0x9f, 0x11, 0xff, 0xb9, 0xbd, 0xe6, 0xd7, 0x56,- 0xdd, 0xd6, 0xdd, 0x2e, 0xce, 0xb4, 0x99, 0xf5, 0x7a, 0xa3, 0xfa, 0xb9, 0xb5, 0xac, 0x34, 0x73, 0xd9, 0x79, 0xae, 0xe9,- 0x91, 0x7e, 0x65, 0x8f, 0xca, 0x95, 0x4f, 0xad, 0xb4, 0x03, 0x4f, 0x95, 0x54, 0x46, 0x30, 0x4f, 0xc5, 0xff, 0x67, 0xb4,- 0xef, 0xb5, 0xdd, 0x0d, 0xc7, 0xe3, 0xff, 0x94, 0x7b, 0x45, 0xfd, 0x65, 0x29, 0xcf, 0xde, 0x74, 0xcc, 0x0b, 0xa5, 0xb5,- 0xec, 0x6a, 0x9a, 0x9f, 0xaf, 0xec, 0x66, 0xf7, 0xb9, 0xf1, 0x5f, 0xdd, 0x3b, 0xe6, 0xad, 0xf8, 0xcf, 0xc7, 0xb7, 0xff,- 0xeb, 0xbb, 0x9b, 0xfe, 0xf9, 0x19, 0x55, 0x4a, 0x3d, 0x8b, 0xce, 0xb2, 0xab, 0xb8, 0xef, 0xda, 0x6e, 0xaf, 0xf9, 0xc4,- 0xf8, 0x66, 0x36, 0x27, 0xf0, 0x93, 0xf1, 0x5f, 0xb9, 0x2a, 0xbd, 0x25, 0xbb, 0x33, 0x43, 0x6f, 0xb4, 0xff, 0xf3, 0xcf,- 0x0d, 0xde, 0x8a, 0xff, 0xea, 0xf3, 0xff, 0x99, 0xbd, 0x3c, 0x4f, 0xb4, 0x8c, 0x95, 0x96, 0xfc, 0xec, 0x3e, 0x09, 0x27,- 0xc6, 0x39, 0xa7, 0xdb, 0xff, 0xca, 0x78, 0xe4, 0x1a, 0xee, 0xfc, 0x7e, 0xba, 0xe4, 0xda, 0x9e, 0xf9, 0xfd, 0xb4, 0x19,- 0x99, 0xa7, 0xc6, 0xf7, 0x9f, 0xb5, 0xdf, 0xea, 0xf5, 0xda, 0xf3, 0xb4, 0x9f, 0x70, 0xac, 0x1d, 0x33, 0x00, 0xcf, 0x3f,- 0x73, 0xfc, 0xb4, 0x73, 0x57, 0xdd, 0x89, 0xe5, 0xb9, 0xef, 0xd3, 0x51, 0x3e, 0xf3, 0xbd, 0xe5, 0x4c, 0xe5, 0x6f, 0xfa,- 0xf5, 0xef, 0x67, 0xe5, 0x10, 0x1e, 0xff, 0x86, 0x76, 0xaf, 0xfc, 0xb9, 0xdf, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa9, 0xdf, 0xde, 0xd7, 0xd7, 0xbd, 0x57, 0xd7, 0x7c, 0xf7, 0x67, 0xe2, 0x8e, 0x35,- 0x3c, 0xd0, 0xb6, 0x16, 0x34, 0x93, 0xb9, 0xe0, 0xba, 0x63, 0x31, 0x5b, 0x99, 0x4d, 0x80, 0xf9, 0x36, 0xff, 0x8d, 0x75,- 0x7e, 0xd5, 0xcf, 0xcd, 0x30, 0xf3, 0x82, 0x55, 0x7c, 0x30, 0x1f, 0xff, 0x19, 0xe6, 0x32, 0xea, 0x2e, 0xbd, 0x26, 0xb2,- 0x0b, 0x5c, 0x85, 0xfc, 0x55, 0xd1, 0x47, 0x80, 0xa5, 0xf8, 0x9f, 0xc9, 0xc8, 0xfd, 0x49, 0xa5, 0x29, 0xef, 0x3e, 0x06,- 0xfc, 0x79, 0x94, 0xfd, 0xbd, 0xe2, 0x7f, 0x27, 0x7f, 0x3d, 0xf0, 0x7e, 0xfc, 0xa7, 0x58, 0x5a, 0xcf, 0x15, 0x0b, 0xfc,- 0xda, 0xfb, 0x9f, 0x99, 0xfd, 0x4f, 0x7b, 0xe9, 0xd5, 0xb0, 0xc7, 0x44, 0xf5, 0xa9, 0x24, 0xd0, 0xf1, 0x7c, 0x70, 0xa7,- 0xb4, 0xfe, 0x9b, 0x84, 0x99, 0xe7, 0x19, 0xae, 0x1c, 0x7c, 0xff, 0xe7, 0x92, 0xb5, 0xfa, 0xca, 0x19, 0x84, 0xef, 0xdf,- 0xef, 0x70, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x79, 0xff, 0xf9, 0xe7, 0x3c, 0x80, 0xf8, 0x07, 0xfe, 0xba, 0xf8, 0xff, 0x17 };--// Font glyphs rectangles data (on atlas)-static const Rectangle cherryFontRecs[189] = {- { 4, 4, 5 , 15 },- { 17, 4, 3 , 10 },- { 28, 4, 5 , 2 },- { 41, 4, 10 , 10 },- { 59, 4, 7 , 11 },- { 74, 4, 7 , 10 },- { 89, 4, 8 , 10 },- { 105, 4, 1 , 2 },- { 114, 4, 3 , 10 },- { 125, 4, 3 , 10 },- { 136, 4, 3 , 3 },- { 147, 4, 7 , 7 },- { 162, 4, 2 , 2 },- { 172, 4, 6 , 3 },- { 186, 4, 1 , 1 },- { 195, 4, 4 , 10 },- { 207, 4, 5 , 8 },- { 220, 4, 5 , 8 },- { 233, 4, 5 , 8 },- { 246, 4, 5 , 8 },- { 259, 4, 5 , 8 },- { 272, 4, 5 , 8 },- { 285, 4, 5 , 8 },- { 298, 4, 5 , 8 },- { 311, 4, 5 , 8 },- { 324, 4, 5 , 8 },- { 337, 4, 3 , 10 },- { 348, 4, 3 , 12 },- { 359, 4, 6 , 7 },- { 373, 4, 6 , 4 },- { 387, 4, 6 , 7 },- { 401, 4, 5 , 10 },- { 414, 4, 8 , 10 },- { 430, 4, 7 , 9 },- { 445, 4, 7 , 9 },- { 460, 4, 6 , 9 },- { 474, 4, 6 , 9 },- { 488, 4, 7 , 9 },- { 4, 27, 6 , 9 },- { 18, 27, 6 , 9 },- { 32, 27, 7 , 9 },- { 47, 27, 3 , 9 },- { 58, 27, 6 , 9 },- { 72, 27, 7 , 9 },- { 87, 27, 7 , 9 },- { 102, 27, 11 , 9 },- { 121, 27, 8 , 9 },- { 137, 27, 6 , 9 },- { 151, 27, 6 , 9 },- { 165, 27, 7 , 9 },- { 180, 27, 7 , 9 },- { 195, 27, 6 , 9 },- { 209, 27, 7 , 9 },- { 224, 27, 8 , 9 },- { 240, 27, 9 , 9 },- { 257, 27, 11 , 9 },- { 276, 27, 7 , 9 },- { 291, 27, 7 , 9 },- { 306, 27, 7 , 9 },- { 321, 27, 3 , 9 },- { 332, 27, 4 , 10 },- { 344, 27, 3 , 9 },- { 355, 27, 3 , 3 },- { 366, 27, 7 , 2 },- { 381, 27, 2 , 2 },- { 391, 27, 6 , 6 },- { 405, 27, 6 , 9 },- { 419, 27, 6 , 6 },- { 433, 27, 6 , 9 },- { 447, 27, 6 , 6 },- { 461, 27, 5 , 9 },- { 474, 27, 5 , 9 },- { 487, 27, 7 , 9 },- { 4, 50, 3 , 7 },- { 15, 50, 3 , 8 },- { 26, 50, 6 , 9 },- { 40, 50, 4 , 9 },- { 52, 50, 11 , 6 },- { 71, 50, 7 , 6 },- { 86, 50, 5 , 6 },- { 99, 50, 6 , 8 },- { 113, 50, 6 , 8 },- { 127, 50, 5 , 6 },- { 140, 50, 5 , 6 },- { 153, 50, 5 , 9 },- { 166, 50, 7 , 6 },- { 181, 50, 7 , 6 },- { 196, 50, 11 , 6 },- { 215, 50, 7 , 6 },- { 230, 50, 7 , 8 },- { 245, 50, 6 , 6 },- { 259, 50, 5 , 9 },- { 272, 50, 1 , 9 },- { 281, 50, 5 , 9 },- { 294, 50, 7 , 3 },- { 309, 50, 3 , 10 },- { 320, 50, 7 , 10 },- { 335, 50, 7 , 10 },- { 350, 50, 6 , 9 },- { 364, 50, 7 , 9 },- { 379, 50, 6 , 12 },- { 393, 50, 7 , 11 },- { 408, 50, 5 , 9 },- { 421, 50, 5 , 5 },- { 434, 50, 4 , 5 },- { 446, 50, 6 , 7 },- { 460, 50, 6 , 3 },- { 474, 50, 5 , 5 },- { 487, 50, 6 , 1 },- { 4, 73, 3 , 3 },- { 15, 73, 7 , 10 },- { 30, 73, 3 , 5 },- { 41, 73, 3 , 5 },- { 52, 73, 7 , 12 },- { 67, 73, 6 , 8 },- { 81, 73, 7 , 9 },- { 96, 73, 2 , 3 },- { 106, 73, 6 , 9 },- { 120, 73, 3 , 5 },- { 131, 73, 3 , 5 },- { 142, 73, 6 , 7 },- { 156, 73, 13 , 9 },- { 177, 73, 10 , 6 },- { 195, 73, 7 , 11 },- { 210, 73, 5 , 10 },- { 223, 73, 7 , 12 },- { 238, 73, 7 , 12 },- { 253, 73, 7 , 12 },- { 268, 73, 7 , 12 },- { 283, 73, 7 , 11 },- { 298, 73, 7 , 11 },- { 313, 73, 12 , 9 },- { 333, 73, 6 , 11 },- { 347, 73, 7 , 12 },- { 362, 73, 7 , 12 },- { 377, 73, 7 , 12 },- { 392, 73, 7 , 11 },- { 407, 73, 3 , 12 },- { 418, 73, 3 , 12 },- { 429, 73, 3 , 12 },- { 440, 73, 3 , 11 },- { 451, 73, 7 , 9 },- { 466, 73, 8 , 12 },- { 482, 73, 6 , 12 },- { 496, 73, 6 , 12 },- { 4, 96, 6 , 12 },- { 18, 96, 6 , 12 },- { 32, 96, 6 , 11 },- { 46, 96, 5 , 5 },- { 59, 96, 8 , 9 },- { 75, 96, 8 , 12 },- { 91, 96, 8 , 12 },- { 107, 96, 8 , 12 },- { 123, 96, 8 , 11 },- { 139, 96, 7 , 12 },- { 154, 96, 7 , 9 },- { 169, 96, 8 , 9 },- { 185, 96, 6 , 9 },- { 199, 96, 6 , 9 },- { 213, 96, 6 , 9 },- { 227, 96, 6 , 9 },- { 241, 96, 6 , 8 },- { 255, 96, 6 , 10 },- { 269, 96, 10 , 6 },- { 287, 96, 6 , 8 },- { 301, 96, 6 , 9 },- { 315, 96, 6 , 9 },- { 329, 96, 6 , 9 },- { 343, 96, 6 , 8 },- { 357, 96, 3 , 10 },- { 368, 96, 3 , 10 },- { 379, 96, 3 , 10 },- { 390, 96, 3 , 9 },- { 401, 96, 6 , 10 },- { 415, 96, 7 , 9 },- { 430, 96, 5 , 9 },- { 443, 96, 5 , 9 },- { 456, 96, 5 , 9 },- { 469, 96, 5 , 9 },- { 482, 96, 5 , 8 },- { 495, 96, 7 , 9 },- { 4, 119, 8 , 8 },- { 20, 119, 7 , 9 },- { 35, 119, 7 , 9 },- { 50, 119, 7 , 9 },- { 65, 119, 7 , 8 },- { 80, 119, 7 , 11 },- { 95, 119, 5 , 8 },- { 108, 119, 7 , 10 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo cherryFontGlyphs[189] = {- { 32, 0, 12, 5, { 0 }},- { 33, 0, 2, 4, { 0 }},- { 34, 0, 2, 6, { 0 }},- { 35, 0, 2, 11, { 0 }},- { 36, 0, 2, 8, { 0 }},- { 37, 0, 2, 8, { 0 }},- { 38, 0, 2, 9, { 0 }},- { 39, 0, 2, 2, { 0 }},- { 40, 0, 2, 4, { 0 }},- { 41, 0, 2, 4, { 0 }},- { 42, 0, 2, 4, { 0 }},- { 43, 0, 4, 8, { 0 }},- { 44, 0, 11, 3, { 0 }},- { 45, 0, 6, 7, { 0 }},- { 46, 0, 11, 2, { 0 }},- { 47, 0, 2, 5, { 0 }},- { 48, 0, 4, 6, { 0 }},- { 49, 0, 4, 6, { 0 }},- { 50, 0, 4, 6, { 0 }},- { 51, 0, 4, 6, { 0 }},- { 52, 0, 4, 6, { 0 }},- { 53, 0, 4, 6, { 0 }},- { 54, 0, 4, 6, { 0 }},- { 55, 0, 4, 6, { 0 }},- { 56, 0, 4, 6, { 0 }},- { 57, 0, 4, 6, { 0 }},- { 58, 0, 2, 4, { 0 }},- { 59, 0, 2, 4, { 0 }},- { 60, 0, 4, 7, { 0 }},- { 61, 0, 5, 7, { 0 }},- { 62, 0, 4, 7, { 0 }},- { 63, 0, 2, 6, { 0 }},- { 64, 0, 2, 9, { 0 }},- { 65, 0, 3, 8, { 0 }},- { 66, 0, 3, 8, { 0 }},- { 67, 0, 3, 7, { 0 }},- { 68, 0, 3, 7, { 0 }},- { 69, 0, 3, 8, { 0 }},- { 70, 0, 3, 7, { 0 }},- { 71, 0, 3, 7, { 0 }},- { 72, 0, 3, 8, { 0 }},- { 73, 0, 3, 4, { 0 }},- { 74, 0, 3, 7, { 0 }},- { 75, 0, 3, 8, { 0 }},- { 76, 0, 3, 8, { 0 }},- { 77, 0, 3, 12, { 0 }},- { 78, 0, 3, 9, { 0 }},- { 79, 0, 3, 7, { 0 }},- { 80, 0, 3, 7, { 0 }},- { 81, 0, 3, 8, { 0 }},- { 82, 0, 3, 8, { 0 }},- { 83, 0, 3, 7, { 0 }},- { 84, 0, 3, 8, { 0 }},- { 85, 0, 3, 9, { 0 }},- { 86, 0, 3, 10, { 0 }},- { 87, 0, 3, 12, { 0 }},- { 88, 0, 3, 8, { 0 }},- { 89, 0, 3, 8, { 0 }},- { 90, 0, 3, 8, { 0 }},- { 91, 0, 3, 4, { 0 }},- { 92, 0, 2, 5, { 0 }},- { 93, 0, 3, 4, { 0 }},- { 94, 0, 3, 4, { 0 }},- { 95, 0, 10, 8, { 0 }},- { 96, 0, 2, 3, { 0 }},- { 97, 0, 6, 7, { 0 }},- { 98, 0, 3, 7, { 0 }},- { 99, 0, 6, 7, { 0 }},- { 100, 0, 3, 7, { 0 }},- { 101, 0, 6, 7, { 0 }},- { 102, 0, 3, 6, { 0 }},- { 103, 0, 5, 6, { 0 }},- { 104, 0, 3, 8, { 0 }},- { 105, 0, 5, 4, { 0 }},- { 106, 0, 5, 4, { 0 }},- { 107, 0, 3, 7, { 0 }},- { 108, 0, 3, 5, { 0 }},- { 109, 0, 6, 12, { 0 }},- { 110, 0, 6, 8, { 0 }},- { 111, 0, 6, 6, { 0 }},- { 112, 0, 6, 7, { 0 }},- { 113, 0, 6, 7, { 0 }},- { 114, 0, 6, 6, { 0 }},- { 115, 0, 6, 6, { 0 }},- { 116, 0, 3, 6, { 0 }},- { 117, 0, 6, 8, { 0 }},- { 118, 0, 6, 8, { 0 }},- { 119, 0, 6, 12, { 0 }},- { 120, 0, 6, 8, { 0 }},- { 121, 0, 6, 8, { 0 }},- { 122, 0, 6, 7, { 0 }},- { 123, 0, 3, 6, { 0 }},- { 124, 0, 3, 2, { 0 }},- { 125, 0, 3, 6, { 0 }},- { 126, 0, 6, 8, { 0 }},- { 161, 0, 4, 4, { 0 }},- { 162, 0, 4, 8, { 0 }},- { 163, 0, 2, 8, { 0 }},- { 8364, 0, 3, 7, { 0 }},- { 165, 0, 3, 8, { 0 }},- { 352, 0, 0, 7, { 0 }},- { 167, 0, 2, 8, { 0 }},- { 353, 0, 3, 6, { 0 }},- { 169, 0, 1, 6, { 0 }},- { 170, 0, 2, 5, { 0 }},- { 171, 0, 5, 7, { 0 }},- { 172, 0, 6, 7, { 0 }},- { 174, 0, 1, 6, { 0 }},- { 175, 0, 2, 7, { 0 }},- { 176, 0, 2, 4, { 0 }},- { 177, 0, 3, 8, { 0 }},- { 178, 0, 2, 4, { 0 }},- { 179, 0, 2, 4, { 0 }},- { 381, 0, 0, 8, { 0 }},- { 181, 0, 6, 7, { 0 }},- { 182, 0, 3, 8, { 0 }},- { 183, 0, 6, 3, { 0 }},- { 382, 0, 3, 7, { 0 }},- { 185, 0, 2, 4, { 0 }},- { 186, 0, 2, 4, { 0 }},- { 187, 0, 5, 7, { 0 }},- { 338, 0, 3, 14, { 0 }},- { 339, 0, 6, 11, { 0 }},- { 376, 0, 1, 8, { 0 }},- { 191, 0, 4, 6, { 0 }},- { 192, 0, 0, 8, { 0 }},- { 193, 0, 0, 8, { 0 }},- { 194, 0, 0, 8, { 0 }},- { 195, 0, 0, 8, { 0 }},- { 196, 0, 1, 8, { 0 }},- { 197, 0, 1, 8, { 0 }},- { 198, 0, 3, 13, { 0 }},- { 199, 0, 3, 7, { 0 }},- { 200, 0, 0, 8, { 0 }},- { 201, 0, 0, 8, { 0 }},- { 202, 0, 0, 8, { 0 }},- { 203, 0, 1, 8, { 0 }},- { 204, 0, 0, 4, { 0 }},- { 205, 0, 0, 4, { 0 }},- { 206, 0, 0, 4, { 0 }},- { 207, 0, 1, 4, { 0 }},- { 208, 0, 3, 8, { 0 }},- { 209, 0, 0, 9, { 0 }},- { 210, 0, 0, 7, { 0 }},- { 211, 0, 0, 7, { 0 }},- { 212, 0, 0, 7, { 0 }},- { 213, 0, 0, 7, { 0 }},- { 214, 0, 1, 7, { 0 }},- { 215, 1, 5, 7, { 0 }},- { 216, 0, 3, 9, { 0 }},- { 217, 0, 0, 9, { 0 }},- { 218, 0, 0, 9, { 0 }},- { 219, 0, 0, 9, { 0 }},- { 220, 0, 1, 9, { 0 }},- { 221, 0, 0, 8, { 0 }},- { 222, 0, 2, 8, { 0 }},- { 223, 0, 3, 9, { 0 }},- { 224, 0, 3, 7, { 0 }},- { 225, 0, 3, 7, { 0 }},- { 226, 0, 3, 7, { 0 }},- { 227, 0, 3, 7, { 0 }},- { 228, 0, 4, 7, { 0 }},- { 229, 0, 2, 7, { 0 }},- { 230, 0, 6, 11, { 0 }},- { 231, 0, 6, 7, { 0 }},- { 232, 0, 3, 7, { 0 }},- { 233, 0, 3, 7, { 0 }},- { 234, 0, 3, 7, { 0 }},- { 235, 0, 4, 7, { 0 }},- { 236, 0, 2, 4, { 0 }},- { 237, 0, 2, 4, { 0 }},- { 238, 0, 2, 4, { 0 }},- { 239, 0, 3, 4, { 0 }},- { 240, 0, 2, 7, { 0 }},- { 241, 0, 3, 8, { 0 }},- { 242, 0, 3, 6, { 0 }},- { 243, 0, 3, 6, { 0 }},- { 244, 0, 3, 6, { 0 }},- { 245, 0, 3, 6, { 0 }},- { 246, 0, 4, 6, { 0 }},- { 247, 0, 3, 8, { 0 }},- { 248, 0, 4, 9, { 0 }},- { 249, 0, 3, 8, { 0 }},- { 250, 0, 3, 8, { 0 }},- { 251, 0, 3, 8, { 0 }},- { 252, 0, 4, 8, { 0 }},- { 253, 0, 3, 8, { 0 }},- { 254, 0, 4, 6, { 0 }},- { 255, 0, 4, 8, { 0 }},-};--// Style loading function: Cherry-static void GuiLoadStyleCherry(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < CHERRY_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(cherryStyleProps[i].controlId, cherryStyleProps[i].propertyId, cherryStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int cherryFontDataSize = 0;- unsigned char *data = DecompressData(cherryFontData, CHERRY_STYLE_FONT_ATLAS_COMP_SIZE, &cherryFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 15;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, cherryFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, cherryFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_cyber.h
@@ -1,591 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleCyber(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define CYBER_STYLE_PROPS_COUNT 17--// Custom style name: Cyber-static const GuiStyleProp cyberStyleProps[CYBER_STYLE_PROPS_COUNT] = {- { 0, 0, 0x2f7486ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x024658ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0x51bfd3ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0x82cde0ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0x3299b4ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xb6e1eaff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xeb7630ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xffbc51ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0xd86f36ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x134b5aff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x02313dff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x17505fff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x0000000e }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0x81c0d0ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x00222bff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000015 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "Kyrou 7 Wide.ttf" (size: 14, spacing: 0)--#define CYBER_STYLE_FONT_ATLAS_COMP_SIZE 2286--// Font atlas image pixels data: DEFLATE compressed-static unsigned char cyberFontData[CYBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x81, 0x6e, 0xdb, 0x36, 0x10, 0x06, 0x60, 0x21, 0xef, 0xff, 0xc6, 0x99, 0xf6, 0x0f, 0xe8, 0xd0, 0x2d, 0x45, 0x6b,- 0x89, 0x3c, 0x92, 0xb2, 0xec, 0x7c, 0xfd, 0x80, 0x61, 0x88, 0x62, 0x5b, 0xa2, 0x78, 0xe4, 0x49, 0x0a, 0xcf, 0xd9, 0x00,- 0x00, 0x00, 0x00, 0x26, 0xcb, 0xc5, 0x9f, 0x96, 0xe6, 0x9f, 0xce, 0x3b, 0xa2, 0x9f, 0xff, 0x9e, 0x7b, 0xec, 0xfa, 0x57,- 0x7f, 0xbb, 0xe7, 0xe1, 0xb9, 0xd3, 0x9e, 0x5f, 0x7f, 0x92, 0xc3, 0xdf, 0x4d, 0xa9, 0x75, 0x73, 0x7a, 0xc6, 0x8e, 0xcf,- 0x4c, 0x5f, 0xbc, 0x3d, 0xde, 0x87, 0x74, 0xbf, 0x62, 0xe5, 0xc8, 0xf8, 0xf3, 0xdf, 0xde, 0xd5, 0xdf, 0x8f, 0x7b, 0x71,- 0x5b, 0x2f, 0xcf, 0xc9, 0x1e, 0xa5, 0xe1, 0x37, 0xce, 0x5e, 0xbf, 0x0d, 0xec, 0xfd, 0x7e, 0xe9, 0x5c, 0x94, 0xd3, 0x31,- 0x63, 0x5b, 0x70, 0x34, 0x19, 0x3c, 0x97, 0x19, 0x1e, 0xd1, 0xda, 0xe3, 0xff, 0xac, 0x5f, 0xe4, 0xb7, 0xff, 0x6e, 0xa5,- 0x48, 0xcb, 0xc2, 0xf8, 0xdf, 0xba, 0xc6, 0x97, 0xf5, 0x79, 0x51, 0x1a, 0x22, 0xbd, 0xff, 0x35, 0xad, 0x47, 0x5b, 0x1b,- 0xf1, 0xd2, 0xfc, 0xbb, 0x29, 0x1d, 0xf1, 0xac, 0x33, 0xd2, 0x3b, 0x72, 0x9e, 0xb5, 0xc6, 0x8a, 0xa3, 0xf9, 0xfa, 0xb3,- 0xcf, 0xc1, 0xd7, 0xef, 0xcb, 0xc7, 0xc8, 0xbd, 0xa1, 0xa5, 0xf6, 0xf2, 0x27, 0xa6, 0x90, 0xcd, 0xcd, 0x3a, 0xfb, 0xab,- 0xf3, 0xc2, 0x94, 0x63, 0x29, 0x43, 0x67, 0xef, 0xf8, 0x73, 0xab, 0xf3, 0xf7, 0xda, 0x11, 0xaf, 0x3f, 0xd7, 0xcf, 0xa4,- 0xd1, 0xbc, 0x36, 0x9a, 0xfd, 0x6c, 0xa9, 0x2c, 0x88, 0xdf, 0x79, 0x63, 0xf1, 0xcc, 0x1c, 0x69, 0x24, 0xef, 0x3c, 0xda,- 0xf6, 0xf9, 0x43, 0xfb, 0x5e, 0xbd, 0xca, 0xfc, 0x9f, 0x81, 0xf3, 0x97, 0x52, 0x3b, 0x9f, 0xe5, 0x94, 0xad, 0x47, 0x7c,- 0xfc, 0xe9, 0x7b, 0xe1, 0x98, 0x3f, 0xb2, 0xff, 0x67, 0x9b, 0x92, 0xd3, 0x66, 0xe2, 0xb9, 0x4c, 0xf7, 0xb5, 0xd2, 0xbf,- 0x71, 0x5b, 0xcf, 0x99, 0x93, 0xbf, 0x7f, 0xd8, 0x17, 0xe7, 0x62, 0x57, 0xc4, 0xff, 0xff, 0xa3, 0x58, 0x06, 0x22, 0x36,- 0x83, 0x33, 0xcc, 0xdc, 0xeb, 0xff, 0x71, 0xfb, 0xd0, 0xf9, 0xcb, 0xf4, 0xab, 0xda, 0xff, 0xa3, 0x37, 0xa5, 0xfc, 0x21,- 0xd3, 0x46, 0xd9, 0x7d, 0xe1, 0xbd, 0xe4, 0x2c, 0xca, 0xd2, 0x1e, 0xcd, 0xff, 0xd7, 0x65, 0x3b, 0x6b, 0xae, 0x96, 0x7a,- 0xee, 0x9d, 0x56, 0xaf, 0xff, 0xd3, 0x38, 0xba, 0xac, 0x8b, 0xff, 0xeb, 0xfd, 0x35, 0x78, 0xfe, 0x72, 0xf1, 0xf5, 0xf9,- 0x9c, 0x2b, 0xf4, 0x7a, 0xc6, 0xb3, 0xf6, 0xfa, 0xff, 0xaa, 0x11, 0x63, 0x45, 0xfe, 0x9f, 0x17, 0xcf, 0xff, 0x7b, 0xee,- 0xff, 0xe7, 0x4d, 0xe2, 0x3f, 0xc3, 0x4f, 0xa4, 0x32, 0xfd, 0xfe, 0x7c, 0x5b, 0xb6, 0x3b, 0xf6, 0x7c, 0x21, 0x43, 0x47,- 0x3c, 0xeb, 0x5e, 0x4c, 0x26, 0xfd, 0x6e, 0x1a, 0x67, 0xc5, 0xda, 0xfd, 0xdd, 0xe7, 0xde, 0xff, 0xf7, 0xfc, 0x1f, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9e, 0xd5, 0x9d, 0xb9, 0xe0, 0x75, 0x95,- 0x55, 0xb4, 0x23, 0xab, 0x6e, 0x47, 0xd6, 0xec, 0x56, 0x5f, 0x79, 0x5e, 0x87, 0xa8, 0xbe, 0xce, 0xb8, 0x7d, 0x95, 0x73,- 0xdf, 0xba, 0xe1, 0xb1, 0xea, 0x28, 0x39, 0x5d, 0x47, 0xdf, 0x56, 0x8f, 0xe0, 0xbc, 0x76, 0xeb, 0x59, 0x25, 0xab, 0xf5,- 0xb5, 0x5f, 0x57, 0xd6, 0xa6, 0x4c, 0xb9, 0x05, 0x7b, 0x56, 0xbf, 0xa7, 0xab, 0x3e, 0x41, 0x75, 0x1d, 0xfa, 0x75, 0x55,- 0x01, 0xc7, 0x57, 0xc8, 0x1f, 0xbf, 0xf3, 0xbe, 0xfc, 0x28, 0xda, 0xf7, 0x38, 0x13, 0xce, 0xd9, 0x8a, 0xf8, 0xcf, 0x61,- 0x45, 0x80, 0x5c, 0x58, 0xdb, 0x75, 0x5d, 0x25, 0xdc, 0x75, 0x95, 0x76, 0xce, 0xe3, 0xbf, 0xbd, 0x66, 0x73, 0x26, 0x47,- 0x6b, 0xca, 0xd1, 0x33, 0x6b, 0x04, 0xa8, 0x8c, 0x5b, 0x33, 0xe2, 0xbf, 0x9a, 0x3b, 0xbc, 0x76, 0xfc, 0x57, 0xeb, 0x89,- 0xe5, 0xe0, 0xbc, 0xa7, 0xb1, 0x6f, 0xdf, 0x61, 0xfb, 0x76, 0xd3, 0xf8, 0x3f, 0x8f, 0xa9, 0x0c, 0x57, 0x29, 0x9e, 0xd7,- 0x9f, 0xe6, 0xd9, 0x9b, 0xa2, 0xb4, 0x56, 0xd3, 0x73, 0x2f, 0x8f, 0x2c, 0xab, 0xf2, 0xff, 0x9c, 0x5c, 0x79, 0xa4, 0x29,- 0x97, 0x9d, 0x3b, 0xc6, 0xb6, 0x8e, 0x5a, 0x8f, 0x2b, 0x8a, 0x9d, 0xd5, 0x2b, 0x7c, 0xfe, 0xfc, 0x3e, 0x56, 0x4f, 0xf9,- 0x9a, 0xf8, 0x1f, 0x8f, 0xc4, 0x3c, 0x65, 0xce, 0x9a, 0x73, 0x6f, 0x22, 0xc5, 0x79, 0x6b, 0xcd, 0x6b, 0xaf, 0x98, 0xff,- 0xf3, 0x52, 0xf3, 0x7f, 0xcb, 0xf5, 0x7f, 0x26, 0x5c, 0xbd, 0xd6, 0x5a, 0x6d, 0x6f, 0x3e, 0x97, 0x2b, 0xf2, 0xff, 0x96,- 0x99, 0x7d, 0x7c, 0xfe, 0x1f, 0xd9, 0x9a, 0xe6, 0x59, 0xf8, 0xfa, 0xf8, 0x6f, 0x3b, 0xa6, 0x5c, 0xfa, 0xda, 0xd7, 0x8b,- 0xff, 0xdc, 0xe2, 0xfe, 0x5f, 0x16, 0xd6, 0x66, 0xce, 0x94, 0xd1, 0x6d, 0x4d, 0xfc, 0xb7, 0xd5, 0x43, 0x1f, 0xb9, 0xfe,- 0x1f, 0x8b, 0xf0, 0xf3, 0x08, 0xf8, 0x4b, 0xfc, 0x4f, 0xca, 0xff, 0x67, 0xbd, 0xba, 0xff, 0x5e, 0xc9, 0xc8, 0x0c, 0xda,- 0x7e, 0x4c, 0x99, 0x9e, 0x7f, 0x8f, 0xd6, 0xf6, 0x5d, 0x9d, 0xff, 0xcf, 0x7a, 0xfd, 0x56, 0x3e, 0xef, 0xe7, 0x5b, 0xc6,- 0x7a, 0xe5, 0xf6, 0x84, 0x6f, 0x73, 0x58, 0xfd, 0x7c, 0xcf, 0x77, 0x94, 0xbe, 0xdf, 0x53, 0x6c, 0x6d, 0x70, 0xef, 0xe7,- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x5e, 0x65, 0x75, 0xbf, 0x15,- 0x53, 0x69, 0x58, 0x1f, 0xda, 0x52, 0x3f, 0xf3, 0xb8, 0xfa, 0xe6, 0xa3, 0x1a, 0x12, 0x7b, 0x53, 0xed, 0xcd, 0x59, 0xad,- 0xd9, 0x5a, 0x07, 0x61, 0xb4, 0x4e, 0x67, 0xe5, 0xdd, 0x5b, 0x5a, 0xf9, 0x7c, 0xcd, 0x63, 0x4e, 0xd6, 0x01, 0x6f, 0x13,- 0x7b, 0xe0, 0xf9, 0x9a, 0xe7, 0x0c, 0xd4, 0x5c, 0x18, 0xa9, 0x22, 0x98, 0x85, 0x2b, 0x4c, 0x53, 0x6a, 0x95, 0xf6, 0x0a,- 0x1c, 0xad, 0x5b, 0x33, 0xa9, 0xca, 0xc3, 0xea, 0x7e, 0x3d, 0x63, 0x6b, 0x7f, 0x1d, 0x85, 0x67, 0xc4, 0xff, 0x71, 0x0f,- 0xc9, 0xe4, 0xb3, 0xdd, 0xf7, 0xd3, 0xb3, 0xd8, 0x7f, 0x5c, 0x5b, 0xf9, 0xa3, 0xb1, 0xdf, 0xf4, 0x6c, 0xcf, 0xf0, 0x59,- 0xce, 0x60, 0x25, 0x84, 0xbd, 0x73, 0xbe, 0x69, 0x8f, 0xfe, 0xb1, 0x9e, 0xb7, 0x6e, 0x05, 0xfc, 0x3b, 0xc5, 0xff, 0x56,- 0xac, 0x58, 0xb8, 0x3a, 0xfe, 0xb7, 0xa6, 0x7d, 0xca, 0xb4, 0x23, 0x9a, 0x57, 0x7d, 0xfb, 0xa3, 0x3b, 0xc7, 0x9a, 0x53,- 0xcb, 0x2a, 0x17, 0xd6, 0x7a, 0x48, 0x47, 0xef, 0xaa, 0x8e, 0x00, 0x29, 0xce, 0xff, 0xfd, 0x2d, 0x3d, 0x2b, 0xc7, 0x78,- 0xcd, 0xf8, 0xaf, 0xb5, 0x66, 0x06, 0xce, 0xf0, 0xda, 0xf9, 0x7f, 0x66, 0xe5, 0xee, 0x4a, 0x74, 0xec, 0x0f, 0xde, 0x65,- 0x2f, 0xcf, 0xce, 0xf5, 0xab, 0x83, 0xad, 0xe9, 0x3b, 0x19, 0xf6, 0xee, 0xd7, 0xe5, 0x97, 0xf8, 0xcc, 0x92, 0x6b, 0xf4,- 0x1c, 0xb4, 0x70, 0xb5, 0x1a, 0x69, 0x6f, 0xfc, 0xe7, 0xd2, 0xf9, 0x7f, 0x6b, 0xfc, 0xf6, 0x8c, 0xad, 0x74, 0xbe, 0xb6,- 0xe2, 0xbb, 0xd6, 0x5f, 0x99, 0xd3, 0x1e, 0xbb, 0xa6, 0x1e, 0xed, 0xcc, 0x6f, 0xe8, 0xc8, 0x84, 0x7e, 0x9b, 0x93, 0x4f,- 0x48, 0x31, 0x07, 0xef, 0xcd, 0xfc, 0x7b, 0xc6, 0xd9, 0x74, 0xdc, 0x19, 0xc8, 0xc1, 0x18, 0x98, 0x45, 0x39, 0xf8, 0xcc,- 0x79, 0x30, 0x53, 0xf3, 0xb5, 0x75, 0x77, 0x17, 0x57, 0x66, 0x74, 0xd7, 0xbc, 0xdb, 0xb3, 0xda, 0xe4, 0xca, 0xf9, 0x3f,- 0xdd, 0xd9, 0xee, 0xc8, 0xfc, 0x9f, 0xe1, 0x3a, 0x99, 0x67, 0xb9, 0xdf, 0x76, 0xbb, 0xf9, 0xbf, 0x2d, 0x36, 0x73, 0x79,- 0xfe, 0x2f, 0xfe, 0xaf, 0x7e, 0xd2, 0xb2, 0xbd, 0x44, 0xfc, 0xaf, 0xbd, 0xfe, 0x9f, 0x33, 0x82, 0x54, 0x67, 0xd9, 0x6d,- 0xf1, 0x33, 0x82, 0xfa, 0xab, 0xd6, 0xc5, 0xff, 0xf6, 0xad, 0xaa, 0x35, 0xbe, 0x5b, 0x6d, 0xca, 0x67, 0xc4, 0x7f, 0x4b,- 0xfe, 0x9f, 0xe2, 0xfd, 0xff, 0xf6, 0x6f, 0xd8, 0x4a, 0x57, 0xce, 0xd2, 0x9e, 0x77, 0xbc, 0x67, 0x8f, 0xe0, 0x9d, 0x47,- 0xb4, 0xb1, 0xe7, 0xff, 0x77, 0x1b, 0x83, 0xc7, 0xbe, 0x53, 0xe5, 0x3b, 0xf7, 0x7f, 0x75, 0x97, 0xf1, 0xd7, 0x72, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x5e, 0xb7, 0x90, 0x4b, 0xd7, 0xcb, 0x57, 0xeb,- 0xd6, 0xf5, 0xaf, 0x58, 0xcd, 0xa4, 0x96, 0xc9, 0xa4, 0xb3, 0xb5, 0x37, 0xac, 0xce, 0xcf, 0x60, 0xbb, 0x67, 0xf8, 0x77,- 0xd2, 0xb0, 0x22, 0x2c, 0xa5, 0x33, 0x7c, 0xbf, 0x75, 0xab, 0x23, 0xab, 0x06, 0x33, 0xb5, 0x75, 0x67, 0x9e, 0xef, 0x9c,- 0x56, 0xc3, 0xfe, 0x6a, 0x2f, 0x56, 0x5f, 0x49, 0x69, 0xc5, 0x64, 0xca, 0xb5, 0x09, 0x7a, 0xc7, 0xbb, 0x74, 0xb6, 0x59,- 0xef, 0xb9, 0xfe, 0xda, 0xc6, 0xad, 0x55, 0x66, 0xbe, 0x6e, 0xdf, 0xcb, 0x3d, 0xfb, 0x73, 0xa8, 0xdf, 0xa7, 0x3c, 0x42,- 0x6f, 0x53, 0xea, 0x7a, 0xb7, 0x54, 0xe3, 0xd8, 0x1b, 0xd6, 0xd0, 0x67, 0xb8, 0x36, 0x58, 0xca, 0xed, 0x30, 0xb3, 0xe7,- 0x8d, 0x7d, 0xda, 0xd9, 0x5a, 0xed, 0x0c, 0xcc, 0xa0, 0x29, 0xd6, 0xbf, 0xcb, 0x60, 0x65, 0x88, 0x1c, 0xac, 0xf1, 0xce,- 0xb2, 0xf5, 0xed, 0xe9, 0x8c, 0xfe, 0xf6, 0xe3, 0x4d, 0x73, 0x9b, 0xb6, 0xd5, 0xab, 0xfe, 0xb8, 0x7d, 0x56, 0xba, 0x97,- 0x66, 0x9b, 0x5a, 0x9b, 0x5e, 0x9d, 0x6f, 0xdc, 0xbd, 0xb6, 0xc7, 0x79, 0xf5, 0xb1, 0xf5, 0xd7, 0x06, 0x95, 0x5a, 0x2c,- 0xf3, 0xe2, 0x3f, 0xdd, 0x15, 0xa5, 0xf6, 0xa1, 0xab, 0x8e, 0xbe, 0xf8, 0x6f, 0x7b, 0xdf, 0x94, 0xe6, 0xff, 0xb3, 0xf8,- 0x5b, 0xbb, 0x7d, 0xb4, 0xda, 0x7e, 0x35, 0xfe, 0xfb, 0xfb, 0x40, 0x16, 0xd4, 0x48, 0x3d, 0xcb, 0x4a, 0x2a, 0x5b, 0xc6,- 0xaf, 0xb1, 0xd7, 0xc5, 0xff, 0x51, 0xeb, 0x8d, 0xe6, 0x1b, 0xb3, 0xe6, 0xff, 0x0c, 0xe7, 0xff, 0xad, 0x7d, 0x35, 0xcd,- 0xdf, 0x2f, 0xd4, 0x92, 0x53, 0x1d, 0x55, 0x77, 0xde, 0x4f, 0xbf, 0x29, 0x63, 0x2b, 0x7e, 0x1b, 0xc6, 0xea, 0xed, 0x3d,- 0xe3, 0xf6, 0x9c, 0xca, 0x9d, 0xd7, 0x6f, 0x9d, 0x31, 0xf6, 0xdd, 0x23, 0xfe, 0xb3, 0x28, 0xd3, 0xc9, 0x50, 0xbb, 0xa6,- 0x6b, 0xdf, 0xaf, 0xb9, 0xbb, 0x94, 0xcb, 0xaa, 0x8a, 0xce, 0xf9, 0x2e, 0x8c, 0x75, 0xdb, 0x5b, 0xc7, 0xc1, 0xfd, 0x82,- 0xf9, 0x7f, 0xe5, 0x1d, 0xd0, 0x7a, 0x55, 0xf8, 0x6b, 0xe2, 0xff, 0x59, 0xd7, 0x46, 0xeb, 0xfa, 0x76, 0x4f, 0xfc, 0xe7,- 0xe2, 0xe3, 0xb8, 0x3e, 0xfe, 0x3f, 0xfe, 0x18, 0x41, 0xe9, 0xc8, 0x6b, 0xd7, 0x6c, 0x9f, 0x39, 0xbe, 0x8c, 0x8e, 0x75,- 0xcf, 0xc9, 0xff, 0x9f, 0x1f, 0xff, 0x77, 0xbe, 0x43, 0x91, 0x37, 0xba, 0x43, 0x93, 0x5f, 0xee, 0xb2, 0x5c, 0xf7, 0x3c,- 0xb6, 0x7e, 0xfd, 0xfd, 0x5a, 0xdb, 0xc7, 0xee, 0xff, 0x7f, 0xdf, 0xfc, 0xff, 0xce, 0x7f, 0xb3, 0xe0, 0xef, 0x36, 0x56,- 0xb6, 0xd3, 0xfd, 0xe3, 0x7b, 0xfe, 0xc8, 0xfc, 0xe8, 0x6e, 0xc8, 0xf7, 0xcd, 0xff, 0xef, 0xff, 0x17, 0x4b, 0xaa, 0xad,- 0x5e, 0x71, 0x4d, 0x72, 0xc7, 0xfb, 0x7b, 0xb3, 0xfb, 0xfb, 0xd1, 0xbd, 0xd0, 0x55, 0xf9, 0xff, 0x76, 0xf3, 0xfb, 0xff,- 0xf0, 0x9a, 0xe3, 0x13, 0x20, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0xaf, 0x29,- 0x53, 0x5e, 0x37, 0x91, 0x1f, 0x6b, 0xc8, 0x3f, 0x06, 0x56, 0x23, 0xad, 0xab, 0x22, 0x7b, 0x5c, 0x03, 0xeb, 0x73, 0xe0,- 0xef, 0x47, 0xd7, 0x1e, 0x57, 0x26, 0xad, 0x1f, 0x7d, 0xc6, 0x91, 0xa5, 0x78, 0xae, 0xc6, 0xd7, 0x32, 0xe7, 0xb7, 0xff,- 0x9f, 0xbb, 0xd6, 0xf7, 0x71, 0xbd, 0x84, 0xb1, 0x33, 0xd2, 0xb3, 0xf2, 0xf0, 0x5e, 0x15, 0x0a, 0xf7, 0x1f, 0xed, 0x91,- 0xc3, 0x3a, 0x92, 0x77, 0xae, 0x22, 0xbb, 0x97, 0xaa, 0xcb, 0xac, 0x3f, 0xae, 0xb1, 0x78, 0xc8, 0x49, 0x5d, 0xcf, 0xe7,- 0x54, 0xbb, 0x3d, 0x3b, 0x57, 0xc7, 0xb5, 0xb0, 0xf7, 0xc6, 0xf5, 0xf2, 0xc7, 0x55, 0x91, 0x33, 0x38, 0xfa, 0x9d, 0x47,- 0x7f, 0x4a, 0x47, 0xf7, 0xa7, 0x33, 0x96, 0xe6, 0x4f, 0xc8, 0xa4, 0xea, 0x5c, 0xc7, 0xad, 0xb1, 0xbf, 0xf0, 0x4a, 0xe1,- 0xbd, 0x2b, 0xfe, 0xf3, 0x25, 0x43, 0xc8, 0x0b, 0xae, 0x6e, 0x69, 0x1d, 0x8f, 0x5f, 0x6b, 0xe5, 0x4c, 0x9a, 0x57, 0x84,- 0x8f, 0x54, 0xdc, 0xb1, 0x9e, 0xaa, 0xbd, 0x27, 0x9e, 0xf7, 0xd3, 0x7b, 0x57, 0x91, 0xfd, 0x3c, 0x39, 0xae, 0xbc, 0x6c,- 0xf5, 0x9b, 0xb6, 0x56, 0x49, 0x21, 0x3b, 0x78, 0xd6, 0xd6, 0xe3, 0x2c, 0xee, 0x4f, 0xf3, 0x7f, 0x2d, 0xb3, 0x79, 0xd6,- 0xb1, 0xb7, 0xee, 0x6b, 0x96, 0x5c, 0x09, 0xb6, 0xf4, 0x84, 0x1c, 0x66, 0x5b, 0xaf, 0x18, 0x27, 0x2d, 0x99, 0xe8, 0x3d,- 0xf7, 0x3b, 0x8d, 0xbd, 0x21, 0x07, 0x79, 0xf8, 0x5d, 0xeb, 0xde, 0x8e, 0x8c, 0x4a, 0x69, 0xb8, 0xc2, 0x6f, 0xc9, 0x0e,- 0xf6, 0x4b, 0xb7, 0xde, 0x35, 0xfe, 0x5b, 0xe6, 0xff, 0xbc, 0x69, 0xfc, 0xef, 0x37, 0xdf, 0xef, 0xfa, 0xf7, 0x9f, 0xb5,- 0xce, 0xff, 0xf7, 0xda, 0x3a, 0x33, 0x83, 0x7f, 0x7c, 0xbf, 0x6d, 0x5d, 0xa5, 0xcf, 0xfe, 0xfb, 0x8e, 0xaf, 0x11, 0xff,- 0x77, 0x9e, 0x27, 0xeb, 0xf1, 0xff, 0xf9, 0x02, 0xfb, 0x9d, 0xd2, 0x1d, 0x9d, 0xb3, 0xf8, 0xdf, 0x6f, 0xb9, 0x75, 0x66,- 0x65, 0xab, 0xea, 0xb3, 0xaa, 0x95, 0x95, 0x3e, 0xef, 0x1b, 0xff, 0x2d, 0xf9, 0xd2, 0xab, 0x5e, 0x27, 0x6f, 0xc3, 0x11,- 0x74, 0xd7, 0xf8, 0x3f, 0x7f, 0xf2, 0x50, 0x7f, 0x42, 0xf6, 0x8c, 0xad, 0xfb, 0x45, 0x77, 0xf0, 0x9e, 0x77, 0xec, 0xcf,- 0x8b, 0xff, 0x91, 0x0a, 0x85, 0xc7, 0xf7, 0x5d, 0xee, 0x70, 0x9d, 0xbc, 0xa2, 0x1e, 0xe2, 0x3d, 0xf6, 0x3b, 0x8b, 0xe6,- 0xa2, 0x7b, 0x3f, 0xc9, 0x71, 0x07, 0xff, 0x9e, 0x4f, 0x0d, 0x6a, 0xfd, 0x78, 0xf5, 0xf6, 0x67, 0xf5, 0xc6, 0x2b, 0xf6,- 0x5b, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xa7, 0x95, 0x3c, 0x39, 0x59,- 0x05, 0xbc, 0x75, 0xd5, 0x2e, 0xfa, 0x55, 0xb5, 0x66, 0x6a, 0x26, 0x54, 0xc9, 0x7c, 0xb4, 0xf6, 0x66, 0xbf, 0xfc, 0x68,- 0xb6, 0xc1, 0x77, 0x86, 0xab, 0x56, 0xf3, 0xfd, 0x69, 0xbd, 0x78, 0xb5, 0xcf, 0x57, 0x6b, 0xa6, 0x8e, 0xd5, 0x8b, 0x3d,- 0x5b, 0x29, 0xfd, 0x59, 0x1c, 0xcf, 0x56, 0x55, 0x80, 0x3d, 0x7a, 0xe7, 0xf3, 0x7a, 0xbe, 0xd6, 0x03, 0x32, 0x1e, 0xfd,- 0xdf, 0xa1, 0x07, 0x65, 0x59, 0x5e, 0xb1, 0x72, 0x9f, 0x3f, 0xf4, 0x50, 0x9e, 0x94, 0x03, 0xb4, 0xad, 0x65, 0xdf, 0x6f,- 0xb5, 0xf5, 0xf1, 0x3e, 0xa7, 0xb1, 0xb2, 0xdf, 0xbd, 0xb6, 0x8e, 0xd4, 0xf3, 0x85, 0x96, 0x2b, 0xe2, 0xf3, 0xaa, 0xa8,- 0xaf, 0xb3, 0xb5, 0xe5, 0x68, 0xb7, 0x37, 0x39, 0x56, 0xf1, 0xcf, 0xac, 0x39, 0xff, 0x9d, 0x7a, 0x7d, 0x86, 0xda, 0x42,- 0xfc, 0x23, 0xfe, 0xbf, 0x5b, 0xaf, 0x17, 0xff, 0x7c, 0xdf, 0xfc, 0x7f, 0x1f, 0xaa, 0x17, 0xbf, 0xdd, 0x6a, 0xeb, 0xf8,- 0xb5, 0xd0, 0x7d, 0xb6, 0xde, 0xb5, 0x0a, 0x22, 0x70, 0xc5, 0x1d, 0xd8, 0xb1, 0x27, 0xb8, 0xc0, 0x6b, 0xe4, 0x60, 0x95,- 0xb8, 0x36, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xe2, 0xdf, 0x7f, 0xda, 0x01, 0xc4, 0x3f,- 0xf0, 0xed, 0xe2, 0xff, 0x1f };--// Font glyphs rectangles data (on atlas)-static const Rectangle cyberFontRecs[189] = {- { 4, 4, 4 , 14 },- { 16, 4, 1 , 8 },- { 25, 4, 4 , 3 },- { 37, 4, 8 , 8 },- { 53, 4, 8 , 9 },- { 69, 4, 8 , 8 },- { 85, 4, 8 , 8 },- { 101, 4, 1 , 3 },- { 110, 4, 4 , 9 },- { 122, 4, 4 , 9 },- { 134, 4, 5 , 6 },- { 147, 4, 5 , 6 },- { 160, 4, 2 , 2 },- { 170, 4, 4 , 1 },- { 182, 4, 1 , 1 },- { 191, 4, 8 , 8 },- { 207, 4, 8 , 8 },- { 223, 4, 2 , 8 },- { 233, 4, 8 , 8 },- { 249, 4, 8 , 8 },- { 265, 4, 8 , 8 },- { 281, 4, 8 , 8 },- { 297, 4, 8 , 8 },- { 313, 4, 7 , 8 },- { 328, 4, 8 , 8 },- { 344, 4, 8 , 8 },- { 360, 4, 1 , 4 },- { 369, 4, 2 , 5 },- { 379, 4, 4 , 8 },- { 391, 4, 5 , 3 },- { 404, 4, 4 , 8 },- { 416, 4, 7 , 8 },- { 431, 4, 8 , 8 },- { 447, 4, 8 , 8 },- { 463, 4, 8 , 8 },- { 479, 4, 8 , 8 },- { 495, 4, 8 , 8 },- { 4, 26, 7 , 8 },- { 19, 26, 7 , 8 },- { 34, 26, 8 , 8 },- { 50, 26, 8 , 8 },- { 66, 26, 5 , 8 },- { 79, 26, 7 , 8 },- { 94, 26, 8 , 8 },- { 110, 26, 7 , 8 },- { 125, 26, 8 , 8 },- { 141, 26, 8 , 8 },- { 157, 26, 8 , 8 },- { 173, 26, 8 , 8 },- { 189, 26, 8 , 9 },- { 205, 26, 8 , 8 },- { 221, 26, 8 , 8 },- { 237, 26, 8 , 8 },- { 253, 26, 8 , 8 },- { 269, 26, 8 , 8 },- { 285, 26, 9 , 8 },- { 302, 26, 8 , 8 },- { 318, 26, 8 , 8 },- { 334, 26, 8 , 8 },- { 350, 26, 4 , 9 },- { 362, 26, 8 , 8 },- { 378, 26, 4 , 9 },- { 390, 26, 4 , 3 },- { 402, 26, 7 , 1 },- { 417, 26, 2 , 3 },- { 427, 26, 7 , 5 },- { 442, 26, 7 , 8 },- { 457, 26, 7 , 5 },- { 472, 26, 7 , 8 },- { 487, 26, 7 , 5 },- { 4, 48, 4 , 8 },- { 16, 48, 7 , 7 },- { 31, 48, 7 , 8 },- { 46, 48, 1 , 8 },- { 55, 48, 3 , 10 },- { 66, 48, 7 , 8 },- { 81, 48, 4 , 8 },- { 93, 48, 9 , 5 },- { 110, 48, 7 , 5 },- { 125, 48, 7 , 5 },- { 140, 48, 7 , 7 },- { 155, 48, 7 , 7 },- { 170, 48, 5 , 5 },- { 183, 48, 7 , 5 },- { 198, 48, 5 , 8 },- { 211, 48, 7 , 5 },- { 226, 48, 7 , 5 },- { 241, 48, 9 , 5 },- { 258, 48, 7 , 5 },- { 273, 48, 7 , 7 },- { 288, 48, 7 , 5 },- { 303, 48, 4 , 9 },- { 315, 48, 1 , 9 },- { 324, 48, 4 , 9 },- { 336, 48, 8 , 2 },- { 352, 48, 1 , 8 },- { 361, 48, 7 , 8 },- { 376, 48, 7 , 8 },- { 391, 48, 8 , 9 },- { 407, 48, 8 , 9 },- { 423, 48, 8 , 10 },- { 439, 48, 4 , 9 },- { 451, 48, 7 , 8 },- { 466, 48, 8 , 8 },- { 482, 48, 7 , 6 },- { 497, 48, 5 , 3 },- { 4, 70, 5 , 3 },- { 17, 70, 8 , 8 },- { 33, 70, 0 , 0 },- { 41, 70, 4 , 3 },- { 53, 70, 8 , 6 },- { 69, 70, 4 , 5 },- { 81, 70, 4 , 5 },- { 93, 70, 8 , 10 },- { 109, 70, 7 , 7 },- { 124, 70, 5 , 7 },- { 137, 70, 1 , 1 },- { 146, 70, 7 , 8 },- { 161, 70, 2 , 5 },- { 171, 70, 4 , 5 },- { 183, 70, 5 , 3 },- { 196, 70, 14 , 8 },- { 218, 70, 13 , 5 },- { 239, 70, 8 , 9 },- { 255, 70, 7 , 8 },- { 270, 70, 8 , 10 },- { 286, 70, 8 , 10 },- { 302, 70, 8 , 10 },- { 318, 70, 8 , 10 },- { 334, 70, 8 , 9 },- { 350, 70, 8 , 12 },- { 366, 70, 14 , 8 },- { 388, 70, 8 , 10 },- { 404, 70, 7 , 10 },- { 419, 70, 7 , 10 },- { 434, 70, 7 , 10 },- { 449, 70, 7 , 9 },- { 464, 70, 5 , 10 },- { 477, 70, 5 , 10 },- { 490, 70, 5 , 10 },- { 4, 92, 5 , 9 },- { 17, 92, 8 , 8 },- { 33, 92, 8 , 10 },- { 49, 92, 8 , 10 },- { 65, 92, 8 , 10 },- { 81, 92, 8 , 10 },- { 97, 92, 8 , 10 },- { 113, 92, 8 , 9 },- { 129, 92, 4 , 4 },- { 141, 92, 8 , 8 },- { 157, 92, 8 , 10 },- { 173, 92, 8 , 10 },- { 189, 92, 8 , 10 },- { 205, 92, 8 , 9 },- { 221, 92, 8 , 10 },- { 237, 92, 7 , 9 },- { 252, 92, 7 , 9 },- { 267, 92, 7 , 8 },- { 282, 92, 7 , 8 },- { 297, 92, 7 , 8 },- { 312, 92, 7 , 8 },- { 327, 92, 7 , 8 },- { 342, 92, 7 , 9 },- { 357, 92, 13 , 5 },- { 378, 92, 7 , 7 },- { 393, 92, 7 , 8 },- { 408, 92, 7 , 8 },- { 423, 92, 7 , 8 },- { 438, 92, 7 , 8 },- { 453, 92, 3 , 8 },- { 464, 92, 2 , 8 },- { 474, 92, 3 , 8 },- { 485, 92, 3 , 8 },- { 4, 114, 8 , 8 },- { 20, 114, 7 , 8 },- { 35, 114, 7 , 8 },- { 50, 114, 7 , 8 },- { 65, 114, 7 , 8 },- { 80, 114, 7 , 8 },- { 95, 114, 7 , 8 },- { 110, 114, 5 , 6 },- { 123, 114, 7 , 5 },- { 138, 114, 7 , 8 },- { 153, 114, 7 , 8 },- { 168, 114, 7 , 8 },- { 183, 114, 7 , 8 },- { 198, 114, 7 , 10 },- { 213, 114, 7 , 10 },- { 228, 114, 7 , 10 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo cyberFontGlyphs[189] = {- { 32, 0, 11, 4, { 0 }},- { 33, 0, 3, 2, { 0 }},- { 34, 0, 3, 4, { 0 }},- { 35, 0, 3, 8, { 0 }},- { 36, 0, 3, 8, { 0 }},- { 37, 0, 3, 8, { 0 }},- { 38, 0, 3, 8, { 0 }},- { 39, 0, 3, 2, { 0 }},- { 40, 0, 3, 4, { 0 }},- { 41, 0, 3, 4, { 0 }},- { 42, 0, 4, 6, { 0 }},- { 43, 0, 4, 6, { 0 }},- { 44, 0, 10, 3, { 0 }},- { 45, 0, 7, 5, { 0 }},- { 46, 0, 10, 2, { 0 }},- { 47, 0, 3, 8, { 0 }},- { 48, 0, 3, 8, { 0 }},- { 49, 0, 3, 3, { 0 }},- { 50, 0, 3, 8, { 0 }},- { 51, 0, 3, 8, { 0 }},- { 52, 0, 3, 8, { 0 }},- { 53, 0, 3, 8, { 0 }},- { 54, 0, 3, 8, { 0 }},- { 55, 0, 3, 7, { 0 }},- { 56, 0, 3, 8, { 0 }},- { 57, 0, 3, 8, { 0 }},- { 58, 0, 6, 2, { 0 }},- { 59, 0, 6, 3, { 0 }},- { 60, 0, 3, 5, { 0 }},- { 61, 0, 6, 6, { 0 }},- { 62, 0, 3, 5, { 0 }},- { 63, 0, 3, 7, { 0 }},- { 64, 0, 3, 8, { 0 }},- { 65, 0, 3, 8, { 0 }},- { 66, 0, 3, 8, { 0 }},- { 67, 0, 3, 8, { 0 }},- { 68, 0, 3, 8, { 0 }},- { 69, 0, 3, 7, { 0 }},- { 70, 0, 3, 7, { 0 }},- { 71, 0, 3, 8, { 0 }},- { 72, 0, 3, 8, { 0 }},- { 73, 0, 3, 6, { 0 }},- { 74, 0, 3, 7, { 0 }},- { 75, 0, 3, 8, { 0 }},- { 76, 0, 3, 7, { 0 }},- { 77, 0, 3, 9, { 0 }},- { 78, 0, 3, 8, { 0 }},- { 79, 0, 3, 8, { 0 }},- { 80, 0, 3, 8, { 0 }},- { 81, 0, 3, 8, { 0 }},- { 82, 0, 3, 8, { 0 }},- { 83, 0, 3, 8, { 0 }},- { 84, 0, 3, 8, { 0 }},- { 85, 0, 3, 8, { 0 }},- { 86, 0, 3, 8, { 0 }},- { 87, 0, 3, 10, { 0 }},- { 88, 0, 3, 8, { 0 }},- { 89, 0, 3, 8, { 0 }},- { 90, 0, 3, 8, { 0 }},- { 91, 0, 3, 4, { 0 }},- { 92, 0, 3, 8, { 0 }},- { 93, 0, 3, 4, { 0 }},- { 94, 0, 3, 4, { 0 }},- { 95, 0, 11, 7, { 0 }},- { 96, 0, 3, 3, { 0 }},- { 97, 0, 6, 7, { 0 }},- { 98, 0, 3, 7, { 0 }},- { 99, 0, 6, 7, { 0 }},- { 100, 0, 3, 7, { 0 }},- { 101, 0, 6, 7, { 0 }},- { 102, 0, 3, 5, { 0 }},- { 103, 0, 6, 7, { 0 }},- { 104, 0, 3, 7, { 0 }},- { 105, 0, 3, 2, { 0 }},- { 106, -2, 3, 2, { 0 }},- { 107, 0, 3, 7, { 0 }},- { 108, 0, 3, 4, { 0 }},- { 109, 0, 6, 10, { 0 }},- { 110, 0, 6, 7, { 0 }},- { 111, 0, 6, 7, { 0 }},- { 112, 0, 6, 7, { 0 }},- { 113, 0, 6, 7, { 0 }},- { 114, 0, 6, 6, { 0 }},- { 115, 0, 6, 7, { 0 }},- { 116, 0, 3, 6, { 0 }},- { 117, 0, 6, 7, { 0 }},- { 118, 0, 6, 7, { 0 }},- { 119, 0, 6, 10, { 0 }},- { 120, 0, 6, 7, { 0 }},- { 121, 0, 6, 7, { 0 }},- { 122, 0, 6, 7, { 0 }},- { 123, 0, 3, 5, { 0 }},- { 124, 0, 3, 2, { 0 }},- { 125, 0, 3, 5, { 0 }},- { 126, 0, 6, 8, { 0 }},- { 161, 0, 3, 2, { 0 }},- { 162, 0, 4, 7, { 0 }},- { 163, 0, 3, 7, { 0 }},- { 8364, 0, 3, 9, { 0 }},- { 165, 0, 3, 8, { 0 }},- { 352, 0, 1, 8, { 0 }},- { 167, 0, 4, 5, { 0 }},- { 353, 0, 3, 7, { 0 }},- { 169, 0, 3, 9, { 0 }},- { 170, 0, 3, 7, { 0 }},- { 171, 0, 6, 6, { 0 }},- { 172, 0, 7, 6, { 0 }},- { 174, 0, 3, 9, { 0 }},- { 175, 0, 11, 3, { 0 }},- { 176, 0, 3, 4, { 0 }},- { 177, 0, 6, 8, { 0 }},- { 178, 0, 3, 4, { 0 }},- { 179, 0, 3, 4, { 0 }},- { 381, 0, 1, 8, { 0 }},- { 181, 0, 6, 7, { 0 }},- { 182, 0, 4, 6, { 0 }},- { 183, 0, 7, 2, { 0 }},- { 382, 0, 3, 7, { 0 }},- { 185, 0, 3, 4, { 0 }},- { 186, 0, 3, 5, { 0 }},- { 187, 0, 6, 6, { 0 }},- { 338, 0, 3, 14, { 0 }},- { 339, 0, 6, 13, { 0 }},- { 376, 0, 2, 8, { 0 }},- { 191, 0, 3, 7, { 0 }},- { 192, 0, 1, 8, { 0 }},- { 193, 0, 1, 8, { 0 }},- { 194, 0, 1, 8, { 0 }},- { 195, 0, 1, 8, { 0 }},- { 196, 0, 2, 8, { 0 }},- { 197, 0, -1, 8, { 0 }},- { 198, 0, 3, 14, { 0 }},- { 199, 0, 3, 8, { 0 }},- { 200, 0, 1, 7, { 0 }},- { 201, 0, 1, 7, { 0 }},- { 202, 0, 1, 7, { 0 }},- { 203, 0, 2, 7, { 0 }},- { 204, 0, 1, 6, { 0 }},- { 205, 0, 1, 6, { 0 }},- { 206, 0, 1, 6, { 0 }},- { 207, 0, 2, 6, { 0 }},- { 208, 0, 3, 9, { 0 }},- { 209, 0, 1, 8, { 0 }},- { 210, 0, 1, 8, { 0 }},- { 211, 0, 1, 8, { 0 }},- { 212, 0, 1, 8, { 0 }},- { 213, 0, 1, 8, { 0 }},- { 214, 0, 2, 8, { 0 }},- { 215, 1, 6, 6, { 0 }},- { 216, 0, 3, 8, { 0 }},- { 217, 0, 1, 8, { 0 }},- { 218, 0, 1, 8, { 0 }},- { 219, 0, 1, 8, { 0 }},- { 220, 0, 2, 8, { 0 }},- { 221, 0, 1, 8, { 0 }},- { 222, 0, 3, 7, { 0 }},- { 223, 0, 3, 7, { 0 }},- { 224, 0, 3, 7, { 0 }},- { 225, 0, 3, 7, { 0 }},- { 226, 0, 3, 7, { 0 }},- { 227, 0, 3, 7, { 0 }},- { 228, 0, 3, 7, { 0 }},- { 229, 0, 2, 7, { 0 }},- { 230, 0, 6, 13, { 0 }},- { 231, 0, 6, 7, { 0 }},- { 232, 0, 3, 7, { 0 }},- { 233, 0, 3, 7, { 0 }},- { 234, 0, 3, 7, { 0 }},- { 235, 0, 3, 7, { 0 }},- { 236, -1, 3, 2, { 0 }},- { 237, 0, 3, 2, { 0 }},- { 238, -1, 3, 2, { 0 }},- { 239, -1, 3, 2, { 0 }},- { 240, 0, 3, 8, { 0 }},- { 241, 0, 3, 7, { 0 }},- { 242, 0, 3, 7, { 0 }},- { 243, 0, 3, 7, { 0 }},- { 244, 0, 3, 7, { 0 }},- { 245, 0, 3, 7, { 0 }},- { 246, 0, 3, 7, { 0 }},- { 247, 0, 4, 6, { 0 }},- { 248, 0, 6, 7, { 0 }},- { 249, 0, 3, 7, { 0 }},- { 250, 0, 3, 7, { 0 }},- { 251, 0, 3, 7, { 0 }},- { 252, 0, 3, 7, { 0 }},- { 253, 0, 3, 7, { 0 }},- { 254, 0, 3, 7, { 0 }},- { 255, 0, 3, 7, { 0 }},-};--// Style loading function: Cyber-static void GuiLoadStyleCyber(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < CYBER_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(cyberStyleProps[i].controlId, cyberStyleProps[i].propertyId, cyberStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int cyberFontDataSize = 0;- unsigned char *data = DecompressData(cyberFontData, CYBER_STYLE_FONT_ATLAS_COMP_SIZE, &cyberFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 14;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, cyberFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, cyberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_dark.h
@@ -1,589 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleDark(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define DARK_STYLE_PROPS_COUNT 23--// Custom style name: Dark-static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = {- { 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING - { 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED - { 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED - { 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED - { 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED - { 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED - { 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED -};--// WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0)--#define DARK_STYLE_FONT_ATLAS_COMP_SIZE 2126--// Font atlas image pixels data: DEFLATE compressed-static unsigned char darkFontData[DARK_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0xdb, 0x72, 0xa4, 0x3a, 0x12, 0x05, 0x50, 0xfd, 0xff, 0x4f, 0xe7, 0x3c, 0x4c, 0x4c, 0x4c, 0x74, 0x9c, 0xd3, 0x20,- 0xa5, 0x52, 0x17, 0xec, 0xd5, 0xeb, 0xcd, 0xe5, 0x76, 0x51, 0xa0, 0x94, 0x84, 0x28, 0x36, 0xd1, 0x00, 0x00, 0x00, 0x80,- 0x5f, 0x2f, 0xfe, 0xf5, 0x27, 0xf1, 0xd7, 0xdf, 0x8c, 0xee, 0xbf, 0xf3, 0xfc, 0xf3, 0xff, 0xbd, 0x1a, 0x0f, 0xef, 0xd5,- 0xb7, 0xad, 0xa3, 0xef, 0x1b, 0x03, 0x7b, 0xe2, 0xdf, 0xb7, 0x2f, 0xba, 0xff, 0xee, 0xdf, 0x3e, 0xdf, 0xf8, 0xef, 0x3f,- 0xfd, 0xa5, 0xe7, 0xad, 0x8f, 0xa1, 0xfd, 0x3e, 0xfe, 0x7f, 0xc6, 0x8e, 0x62, 0x2c, 0xd9, 0xf7, 0xef, 0x5b, 0x37, 0xbe,- 0xed, 0x95, 0xff, 0x27, 0x1e, 0x3e, 0x4f, 0xe6, 0x28, 0xf5, 0xd4, 0xd6, 0x0d, 0xf5, 0x1f, 0x5d, 0x95, 0x18, 0xa5, 0x2d,- 0xe7, 0xff, 0xef, 0x1a, 0x85, 0x3d, 0x55, 0x76, 0x4f, 0x3e, 0x55, 0xfa, 0xf8, 0xfe, 0x78, 0x6a, 0xfd, 0xe3, 0x3d, 0x60,- 0x94, 0x7c, 0x96, 0xf9, 0xd6, 0x18, 0xd3, 0xbf, 0xdd, 0xd7, 0x92, 0x6a, 0x3e, 0xd5, 0xcc, 0x2b, 0xad, 0xe4, 0x28, 0x9d,- 0xa8, 0xff, 0x48, 0xf7, 0x54, 0x31, 0x58, 0xd1, 0x15, 0x7b, 0x30, 0xd3, 0x0f, 0xb7, 0x8d, 0xf5, 0x1f, 0xa5, 0x73, 0x97,- 0x28, 0x6b, 0x73, 0x27, 0xea, 0xff, 0x79, 0xd4, 0x6e, 0x25, 0xed, 0x26, 0x5e, 0xf6, 0x51, 0x6d, 0x2d, 0xaf, 0x9d, 0xa7,- 0xae, 0xae, 0xff, 0xe7, 0xdf, 0x1c, 0x1d, 0x6f, 0x63, 0x70, 0xec, 0xae, 0xd8, 0x4f, 0xb9, 0xf1, 0xbf, 0x7e, 0x3f, 0xc6,- 0x5f, 0xc7, 0xe6, 0xec, 0x3c, 0x64, 0x64, 0x0f, 0xc7, 0xe0, 0xd9, 0xd5, 0xec, 0x08, 0x7b, 0x72, 0xfc, 0xef, 0x9b, 0x0b,- 0xaa, 0xff, 0xb5, 0xf5, 0x9f, 0xf9, 0x24, 0xd1, 0xb9, 0x05, 0x99, 0x31, 0xb1, 0x5d, 0x50, 0xff, 0xa3, 0xfd, 0xd0, 0xf3,- 0xbe, 0xaa, 0x9a, 0xcb, 0x8f, 0xae, 0x4b, 0xf4, 0x9d, 0x61, 0xef, 0x6b, 0x85, 0xe3, 0x73, 0xa3, 0xf1, 0xfa, 0x1f, 0xef,- 0x3d, 0xdf, 0xfe, 0xda, 0xe8, 0x5e, 0xfd, 0xfb, 0x99, 0xdd, 0xfc, 0x1e, 0xdf, 0x57, 0xff, 0x91, 0x18, 0x53, 0xce, 0xd7,- 0x73, 0x4d, 0xfd, 0x47, 0x62, 0xe5, 0xa2, 0x95, 0xad, 0xf2, 0xe5, 0xd6, 0x25, 0xea, 0xd6, 0x0c, 0xce, 0x1f, 0x81, 0xf7,- 0xfa, 0x7f, 0x3b, 0x1f, 0x3c, 0x3f, 0xfe, 0xc7, 0x15, 0xe3, 0x7f, 0xa4, 0xd7, 0x86, 0x5b, 0xa2, 0xf7, 0xfd, 0x5a, 0xfd,- 0x47, 0xa2, 0x66, 0xa2, 0xe4, 0xbc, 0xbc, 0x2d, 0x59, 0xcb, 0xab, 0x5d, 0x33, 0xdc, 0x73, 0xb4, 0xde, 0x46, 0xd1, 0xaa,- 0xb3, 0x9a, 0x9f, 0x55, 0xff, 0xad, 0x60, 0xfc, 0xef, 0x9b, 0x03, 0xcc, 0x7e, 0x8e, 0xf8, 0xd8, 0xe8, 0x5f, 0x59, 0xff,- 0xbb, 0x56, 0xec, 0xd7, 0xb7, 0xc6, 0xb8, 0xe2, 0xc8, 0x58, 0xff, 0xaf, 0x9c, 0xff, 0xe7, 0xd7, 0x00, 0xc6, 0xce, 0x63,- 0xe2, 0xd2, 0xea, 0xcf, 0x9c, 0x33, 0x57, 0x5d, 0xb1, 0xaf, 0xfd, 0x36, 0x41, 0x24, 0xbe, 0xab, 0x51, 0xb3, 0x8a, 0xb3,- 0xfa, 0x18, 0x8c, 0x8f, 0xff, 0xbb, 0xae, 0xff, 0xbf, 0xcf, 0xb9, 0xef, 0x18, 0xff, 0xdb, 0xeb, 0xe8, 0x7e, 0xcb, 0xf6,- 0x00, 0x7b, 0x7b, 0x80, 0x50, 0xfd, 0xe0, 0x7b, 0xc4, 0x80, 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x0a, 0xbf, 0x9f, 0x5f, 0x9f, 0x63, 0x30, 0x9e, 0x84, 0xbd, 0x3e, 0x81, 0x7d, 0x26, 0x13, 0x38, 0xbb,- 0x87, 0xaa, 0xfe, 0xe2, 0x73, 0x76, 0xfc, 0x48, 0xd2, 0x42, 0x7f, 0xcb, 0x88, 0xe1, 0xa7, 0x1f, 0x54, 0x26, 0x0a, 0x64,- 0x32, 0x0d, 0xda, 0x60, 0x9b, 0xa8, 0xcd, 0x52, 0x1a, 0xdb, 0xfa, 0x3d, 0x2d, 0xfe, 0x0b, 0xf5, 0x7f, 0xfe, 0x95, 0x96,- 0xc8, 0xef, 0xd9, 0x59, 0xff, 0xa3, 0x6d, 0x2f, 0x97, 0x8f, 0x3b, 0x37, 0x96, 0xec, 0x4e, 0x14, 0x8b, 0xc2, 0x63, 0xb8,- 0x6f, 0x5c, 0xfd, 0x33, 0x43, 0x67, 0x47, 0xbb, 0x9e, 0xa9, 0xff, 0xd1, 0xec, 0xd3, 0x78, 0xe8, 0x85, 0xef, 0xa9, 0xff,- 0xb6, 0xa5, 0xfe, 0xe3, 0x23, 0xf5, 0x5f, 0x9d, 0x24, 0x53, 0x95, 0x42, 0x9e, 0x49, 0xbe, 0x19, 0x3f, 0x86, 0xf9, 0x84,- 0xdf, 0x6c, 0x8b, 0xfb, 0x4e, 0xfd, 0x67, 0xda, 0xd6, 0x73, 0xce, 0xaa, 0xfa, 0x7f, 0xdf, 0xb7, 0x99, 0xd1, 0x64, 0xfe,- 0xe7, 0x35, 0x95, 0xbf, 0x27, 0x47, 0xf7, 0xed, 0x39, 0x5a, 0x6b, 0xdb, 0xca, 0xec, 0x58, 0xf9, 0x95, 0xfa, 0x8f, 0xe4,- 0x5f, 0x89, 0x97, 0x1e, 0xa5, 0x36, 0x81, 0xbd, 0x26, 0xb5, 0x6d, 0x6f, 0xfd, 0x57, 0x3f, 0xf7, 0xe7, 0x8e, 0xfa, 0x3f,- 0x9f, 0xa3, 0xbb, 0xea, 0x1c, 0xae, 0x76, 0xac, 0xfc, 0xd9, 0xe3, 0xff, 0x7b, 0x2f, 0xb9, 0xa3, 0x7d, 0xcc, 0x8c, 0xf4,- 0x27, 0xc7, 0xff, 0x73, 0x3f, 0x3f, 0x5b, 0xff, 0x55, 0xad, 0x3d, 0x36, 0xce, 0x4c, 0xb2, 0x63, 0xe5, 0xce, 0x55, 0xb2,- 0xdd, 0xe7, 0xff, 0xab, 0x3e, 0x59, 0x1b, 0x9e, 0x4d, 0xc4, 0xb5, 0xf5, 0x3f, 0xb3, 0x0a, 0xb9, 0x6e, 0xbe, 0x70, 0x66,- 0xfe, 0x9f, 0x7b, 0xbe, 0x6d, 0xe6, 0xa9, 0x80, 0xb7, 0x8d, 0xff, 0xbb, 0xae, 0x92, 0xb5, 0xcd, 0x35, 0xb9, 0xf7, 0xbd,- 0x2a, 0x9f, 0x52, 0x37, 0x9e, 0xdf, 0x1f, 0xc5, 0x33, 0xbc, 0xaf, 0xd7, 0x7f, 0x7e, 0x95, 0xbf, 0x15, 0xad, 0x4a, 0x9e,- 0x9b, 0xff, 0xef, 0x7e, 0xd2, 0x49, 0xe6, 0x5d, 0x6a, 0xfa, 0xdf, 0xbe, 0xab, 0xc2, 0xb5, 0xa3, 0xc0, 0xdf, 0xaf, 0x36,- 0x44, 0xd1, 0xc8, 0x51, 0x95, 0xdf, 0xff, 0xe7, 0xb6, 0x8d, 0x3f, 0xf1, 0x6c, 0xfc, 0x4a, 0x7c, 0x0c, 0x3e, 0x4f, 0xff,- 0x44, 0xfd, 0x67, 0xde, 0x39, 0xf3, 0xbf, 0x46, 0x8f, 0x61, 0x65, 0xfd, 0x9f, 0xeb, 0x01, 0xe4, 0x6e, 0xc2, 0x8d, 0xb3,- 0x18, 0xe0, 0xe7, 0xf4, 0x00, 0x9e, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0xec, 0xbe, 0x13, 0xfb, 0xef, 0xd9, 0x5c, 0x99, 0xd4, 0xf8, 0xf1, 0xfb, 0xa4, 0x77, 0x26, 0xe6, 0xb7, 0x97, 0x14, 0xb2,- 0xe7, 0xdf, 0xfa, 0xf3, 0x95, 0x8a, 0x3c, 0xde, 0x28, 0xbc, 0x6b, 0xfd, 0x29, 0x93, 0xe4, 0x39, 0x4b, 0x71, 0x34, 0x77,- 0xe0, 0x7d, 0x0f, 0x8f, 0x1f, 0x97, 0x99, 0xd7, 0x5a, 0x61, 0x9a, 0x42, 0x24, 0xd2, 0x5e, 0xde, 0xf6, 0x7a, 0x7f, 0x36,- 0x70, 0x94, 0x6d, 0xf1, 0x58, 0x1d, 0x55, 0x65, 0x27, 0xdf, 0x9e, 0x98, 0x3f, 0x9f, 0xbc, 0x13, 0x2f, 0xad, 0xae, 0xbf,- 0xfe, 0x7b, 0x92, 0x23, 0xd6, 0xe7, 0x18, 0xf5, 0xfc, 0x34, 0x93, 0x7a, 0x31, 0x96, 0xc1, 0x36, 0xd7, 0x06, 0x56, 0x8f,- 0x50, 0x6d, 0xb2, 0x42, 0x62, 0xaa, 0xa5, 0xcc, 0x67, 0xff, 0xbd, 0x6f, 0x69, 0x1b, 0x1c, 0xb9, 0x6e, 0x48, 0xcc, 0x8c,- 0xce, 0xfa, 0xaa, 0xfe, 0x69, 0x1b, 0xec, 0x6f, 0x32, 0x79, 0x75, 0x51, 0x9a, 0x44, 0x91, 0xff, 0x3f, 0x91, 0x48, 0x6d,- 0x6e, 0xc9, 0x2c, 0xbe, 0x7c, 0x46, 0x7c, 0x26, 0xa7, 0x2a, 0x16, 0xef, 0xd9, 0x4c, 0xfd, 0xb7, 0x43, 0xf5, 0x9f, 0x49,- 0x3d, 0x38, 0x9f, 0x98, 0x1d, 0xa9, 0xda, 0xdd, 0x5b, 0xff, 0xd1, 0xd1, 0x7f, 0x65, 0x66, 0xd7, 0x51, 0x78, 0xce, 0xf0,- 0x3e, 0xe3, 0xad, 0x1e, 0xff, 0xdb, 0xe3, 0x7e, 0x1a, 0x4f, 0x75, 0x5b, 0x3f, 0x42, 0x65, 0x7a, 0x93, 0xb1, 0xfa, 0x5f,- 0xdd, 0x63, 0xcd, 0x3c, 0x07, 0x29, 0x3e, 0x37, 0xfe, 0x9f, 0x49, 0xcc, 0x8e, 0xc4, 0xd9, 0x75, 0xe6, 0x7d, 0xeb, 0xd7,- 0x5e, 0xa2, 0xb0, 0xfe, 0x33, 0x3d, 0x40, 0xbe, 0xfe, 0x77, 0xce, 0xa6, 0xb3, 0x79, 0x93, 0x31, 0xdd, 0x86, 0xce, 0xd4,- 0x7f, 0xe5, 0xd3, 0x96, 0x56, 0x24, 0xe6, 0x8e, 0x3f, 0xd9, 0xf1, 0xd4, 0xf8, 0xdf, 0x52, 0xe3, 0x7f, 0x6e, 0x9c, 0xa8,- 0x3b, 0xf6, 0xb5, 0x73, 0xe5, 0xf7, 0xfa, 0x8f, 0x0d, 0xef, 0xb6, 0xaf, 0xfe, 0x33, 0x3d, 0x61, 0x2c, 0x9b, 0xff, 0x67,- 0xab, 0x25, 0x86, 0xe7, 0xd7, 0x3b, 0x13, 0x73, 0x33, 0xeb, 0xcc, 0xf7, 0xd7, 0x7f, 0xe5, 0x33, 0x4c, 0xda, 0x54, 0xfa,- 0x72, 0x94, 0x8e, 0xc8, 0xfb, 0xc6, 0xff, 0x15, 0xb3, 0xe9, 0x4c, 0xfa, 0xfe, 0x3d, 0xeb, 0x7f, 0xad, 0xf8, 0x88, 0xb5,- 0xe3, 0x79, 0x88, 0x2b, 0x66, 0x85, 0x27, 0xce, 0xff, 0xab, 0x12, 0xd8, 0x73, 0xe7, 0xff, 0xd5, 0x2b, 0xf2, 0x73, 0xc7,- 0xf2, 0xde, 0xf1, 0x3f, 0xd7, 0x42, 0x62, 0x68, 0x7c, 0x6e, 0x9f, 0xaa, 0xff, 0x5b, 0xbe, 0xd1, 0x50, 0xd1, 0x6f, 0x45,- 0x49, 0xef, 0x96, 0x79, 0x6e, 0x4b, 0xe5, 0x3c, 0xaa, 0x72, 0xfd, 0x6a, 0xe6, 0xfa, 0xff, 0xcc, 0xb7, 0x53, 0x56, 0xbf,- 0x5b, 0xfe, 0xfa, 0xff, 0xda, 0xfa, 0x8f, 0xe2, 0x2d, 0xe6, 0x9e, 0x5e, 0xea, 0xe6, 0xf7, 0xd3, 0x7e, 0xee, 0x38, 0x82,- 0x6a, 0x59, 0xeb, 0x39, 0x71, 0x3e, 0xc4, 0xef, 0x9a, 0x33, 0xf3, 0xd3, 0xbf, 0xe1, 0x6d, 0x3f, 0x18, 0x9b, 0x01, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xde, 0xc3, 0x14, 0xaf, 0x77, 0x38, 0xbc, 0x65, 0x4b,- 0x64, 0x72, 0x29, 0x5b, 0x69, 0xce, 0x5d, 0x4b, 0x24, 0xf3, 0x67, 0xb7, 0xae, 0x77, 0xaf, 0xac, 0xff, 0x64, 0xb3, 0x69,- 0xe6, 0x99, 0xc4, 0xf9, 0xcc, 0x3e, 0x3e, 0x7b, 0x34, 0xdf, 0x32, 0x3c, 0x22, 0x91, 0xc6, 0x5a, 0x79, 0xbc, 0x5a, 0x6a,- 0xdf, 0x65, 0x5b, 0x59, 0x6f, 0x0f, 0xd0, 0x9f, 0x0f, 0x53, 0x7f, 0x8f, 0x69, 0xa4, 0xf6, 0x79, 0x4d, 0x32, 0xff, 0x4c,- 0x5b, 0x6a, 0xe9, 0x04, 0xe2, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0x31, 0xfd, 0x97, 0xdf, 0xb3, 0x5a, 0xe3, 0x73, 0x47, 0x33,- 0x9b, 0x17, 0x5f, 0x7d, 0xbc, 0x6a, 0xd3, 0xdb, 0x6a, 0x7a, 0x80, 0x8a, 0xfa, 0xaf, 0xdb, 0xca, 0xfd, 0xf7, 0xc6, 0x46,- 0xf2, 0x7e, 0xfa, 0xf8, 0xfc, 0xfd, 0xa7, 0xf1, 0xd1, 0x24, 0x81, 0x5c, 0xca, 0xe4, 0xae, 0x4f, 0x95, 0xcb, 0xe5, 0xca,- 0xa7, 0xb7, 0xed, 0x1c, 0xff, 0x33, 0x49, 0x52, 0x99, 0xb4, 0xd0, 0xea, 0x57, 0xb2, 0xbd, 0x65, 0xae, 0xfe, 0x33, 0x99,- 0x4d, 0x51, 0x94, 0x67, 0x5c, 0xf7, 0xdc, 0x93, 0x48, 0xce, 0xaf, 0x4f, 0x1e, 0xcd, 0x78, 0x4d, 0x25, 0xaf, 0xca, 0xd8,- 0xdd, 0xfb, 0x4a, 0x4c, 0x26, 0x3e, 0x44, 0xd7, 0xf1, 0x8e, 0xe9, 0xb1, 0x70, 0xd7, 0xd3, 0x02, 0x33, 0xcf, 0xa4, 0x68,- 0xc9, 0xd4, 0xcc, 0x28, 0x9b, 0xe1, 0x57, 0xbf, 0xb2, 0xa2, 0xfe, 0xe3, 0xe1, 0x3c, 0xb9, 0xfa, 0x99, 0x65, 0xd5, 0x47,- 0xb3, 0xa7, 0x67, 0xf8, 0x62, 0xfd, 0xaf, 0x9d, 0xa7, 0xd5, 0x9c, 0xff, 0x47, 0xfa, 0x59, 0x3c, 0x77, 0xb6, 0x98, 0xe8,- 0x4c, 0x77, 0xfe, 0x69, 0xf5, 0xbf, 0x77, 0x1f, 0x57, 0xf7, 0xe6, 0xcf, 0x33, 0xec, 0xf6, 0xd1, 0xfa, 0x9f, 0x49, 0x8b,- 0xaf, 0x39, 0x5f, 0x79, 0x5f, 0xff, 0xaf, 0x5c, 0xd9, 0xb8, 0xa3, 0xfe, 0x6f, 0xa9, 0xf2, 0xb1, 0x7d, 0xbe, 0xb6, 0xfe,- 0xcf, 0xd7, 0xd0, 0x6c, 0xf2, 0xfb, 0xf9, 0x6d, 0x8f, 0xb2, 0xf3, 0xff, 0x9a, 0x75, 0xa1, 0xea, 0x79, 0xc4, 0x6d, 0x3d,- 0xe8, 0xaa, 0xa7, 0xab, 0xbd, 0xcd, 0x1d, 0xaa, 0xcf, 0x77, 0xef, 0x18, 0xff, 0x43, 0xfd, 0x2f, 0x58, 0x0b, 0xaf, 0x1d,- 0x25, 0xf3, 0x2b, 0xcc, 0x33, 0xfd, 0xc9, 0xf8, 0xb3, 0xec, 0x6b, 0x57, 0xc9, 0x32, 0x7d, 0x68, 0xcf, 0x2b, 0xf9, 0x27,- 0x6e, 0x7c, 0x75, 0xfe, 0xdf, 0xf3, 0x54, 0xa0, 0x6f, 0xd5, 0x7f, 0x24, 0xd7, 0xb7, 0xee, 0xa8, 0xff, 0xb5, 0x57, 0x06,- 0xd6, 0x5f, 0xcb, 0xbf, 0x79, 0xfe, 0xbf, 0xa2, 0xcf, 0xfb, 0x76, 0xfd, 0x7f, 0x61, 0x0e, 0xbd, 0xe6, 0x5b, 0x28, 0xe7,- 0xea, 0x7f, 0x6e, 0xdc, 0x56, 0xff, 0x2b, 0x56, 0x8c, 0xf3, 0x9f, 0x7a, 0xc5, 0xf9, 0x7f, 0xef, 0x4c, 0xe3, 0xe7, 0xd7,- 0x7f, 0x7d, 0xd2, 0xf9, 0x9a, 0xf3, 0xcd, 0x76, 0xe9, 0x77, 0x61, 0xee, 0xfa, 0x4e, 0xf2, 0x9e, 0x16, 0xb3, 0x66, 0xed,- 0x23, 0xf3, 0x94, 0xde, 0xda, 0xa7, 0x39, 0xc5, 0xa2, 0x4a, 0xcf, 0x5d, 0xe5, 0xdd, 0x73, 0xfd, 0x7f, 0xef, 0x37, 0x8a,- 0xaa, 0xb7, 0x50, 0xfd, 0x7f, 0xa3, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdb,- 0xee, 0xd0, 0xdb, 0x9b, 0xa8, 0x5f, 0x9f, 0x82, 0x71, 0x7b, 0xa2, 0xfe, 0xdb, 0x5d, 0x33, 0xed, 0xda, 0x44, 0xfd, 0xd6,- 0x95, 0x4c, 0xf4, 0xbd, 0x44, 0xfd, 0xdf, 0x78, 0xc7, 0xc7, 0x6d, 0x89, 0xfa, 0x75, 0x77, 0x4e, 0xdf, 0x9e, 0xa8, 0xdf,- 0x5e, 0xf2, 0x87, 0x6e, 0x4e, 0xd4, 0xcf, 0xdf, 0x3b, 0x75, 0x6b, 0xa2, 0x3e, 0x6b, 0xef, 0x98, 0xec, 0xed, 0xfb, 0xe3,- 0xe0, 0x31, 0x5b, 0x75, 0x77, 0x69, 0x7c, 0xf4, 0xce, 0xcf, 0xf1, 0x8c, 0xa6, 0x15, 0x3d, 0x4a, 0xe5, 0x5d, 0x9a, 0xeb,- 0x13, 0xf5, 0x7f, 0x4a, 0xbd, 0xee, 0x4a, 0xd4, 0x7f, 0xcf, 0x19, 0x8b, 0x4d, 0xdb, 0x1f, 0x43, 0xf3, 0xc6, 0xb5, 0x89,- 0x5a, 0xcf, 0xfd, 0xe8, 0xbd, 0xcf, 0x47, 0xf8, 0x76, 0xa2, 0xf6, 0x6f, 0xab, 0xff, 0x55, 0xfb, 0x29, 0x8a, 0xaa, 0xae,- 0xf7, 0x95, 0x7d, 0x59, 0x41, 0x75, 0xf5, 0x1f, 0xe5, 0xaf, 0xed, 0x4d, 0xd4, 0xca, 0xae, 0x27, 0xa8, 0xff, 0xef, 0xac,- 0x01, 0xe4, 0xd6, 0xad, 0xe6, 0x12, 0x75, 0x4f, 0xb6, 0x80, 0x9d, 0x89, 0x5a, 0x5f, 0xaf, 0xff, 0xcc, 0xac, 0x5c, 0xfd,- 0xdf, 0x39, 0xff, 0x8f, 0xb2, 0x57, 0x32, 0xbd, 0x46, 0x7e, 0xfd, 0xff, 0xcb, 0x4f, 0xd4, 0xfa, 0x99, 0xf5, 0x7f, 0x47,- 0xa2, 0xae, 0xfa, 0x3f, 0x33, 0xff, 0x5f, 0xf7, 0x54, 0x82, 0x9d, 0x89, 0xba, 0xc6, 0xff, 0x55, 0x15, 0x71, 0x77, 0x95,- 0xdf, 0x95, 0x9b, 0xfb, 0xcd, 0xf3, 0xff, 0xdc, 0x93, 0x40, 0xb3, 0x3d, 0xc0, 0xbe, 0x84, 0xd6, 0x13, 0x89, 0xfa, 0x12,- 0x75, 0x67, 0x8e, 0xd7, 0xf3, 0xec, 0xef, 0x9b, 0xd7, 0x63, 0x6e, 0x9f, 0xff, 0xd7, 0x5e, 0xab, 0xf9, 0xe7, 0x9a, 0xd2,- 0xea, 0x15, 0xef, 0x55, 0xf3, 0xff, 0xda, 0x2b, 0x5b, 0x12, 0x75, 0xab, 0x8f, 0xda, 0x6f, 0x5f, 0xff, 0x3b, 0xdb, 0xd3,- 0xc0, 0xee, 0x79, 0xed, 0xf9, 0x9e, 0x10, 0xf8, 0xda, 0x37, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf9, 0xef, 0x3f, 0xfb, 0x01, 0xd4, 0x3f,- 0xf0, 0xeb, 0xea, 0xff, 0x3f };--// Font glyphs rectangles data (on atlas)-static const Rectangle darkFontRecs[189] = {- { 4, 4, 4 , 16 },- { 16, 4, 1 , 9 },- { 25, 4, 3 , 3 },- { 36, 4, 6 , 9 },- { 50, 4, 5 , 13 },- { 63, 4, 7 , 9 },- { 78, 4, 5 , 9 },- { 91, 4, 1 , 3 },- { 100, 4, 3 , 9 },- { 111, 4, 3 , 9 },- { 122, 4, 5 , 5 },- { 135, 4, 5 , 5 },- { 148, 4, 2 , 3 },- { 158, 4, 4 , 1 },- { 170, 4, 1 , 1 },- { 179, 4, 3 , 9 },- { 190, 4, 5 , 9 },- { 203, 4, 3 , 9 },- { 214, 4, 5 , 9 },- { 227, 4, 5 , 9 },- { 240, 4, 5 , 9 },- { 253, 4, 5 , 9 },- { 266, 4, 5 , 9 },- { 279, 4, 5 , 9 },- { 292, 4, 5 , 9 },- { 305, 4, 5 , 9 },- { 318, 4, 1 , 7 },- { 327, 4, 2 , 9 },- { 337, 4, 3 , 5 },- { 348, 4, 4 , 3 },- { 360, 4, 3 , 5 },- { 371, 4, 5 , 9 },- { 384, 4, 7 , 9 },- { 399, 4, 5 , 9 },- { 412, 4, 5 , 9 },- { 425, 4, 5 , 9 },- { 438, 4, 5 , 9 },- { 451, 4, 5 , 9 },- { 464, 4, 5 , 9 },- { 477, 4, 5 , 9 },- { 490, 4, 5 , 9 },- { 4, 28, 1 , 9 },- { 13, 28, 5 , 9 },- { 26, 28, 5 , 9 },- { 39, 28, 5 , 9 },- { 52, 28, 7 , 9 },- { 67, 28, 5 , 9 },- { 80, 28, 5 , 9 },- { 93, 28, 5 , 9 },- { 106, 28, 5 , 9 },- { 119, 28, 5 , 9 },- { 132, 28, 5 , 9 },- { 145, 28, 5 , 9 },- { 158, 28, 5 , 9 },- { 171, 28, 5 , 9 },- { 184, 28, 7 , 9 },- { 199, 28, 5 , 9 },- { 212, 28, 5 , 9 },- { 225, 28, 5 , 9 },- { 238, 28, 3 , 9 },- { 249, 28, 3 , 9 },- { 260, 28, 3 , 9 },- { 271, 28, 5 , 3 },- { 284, 28, 5 , 1 },- { 297, 28, 2 , 2 },- { 307, 28, 5 , 7 },- { 320, 28, 5 , 9 },- { 333, 28, 5 , 7 },- { 346, 28, 5 , 9 },- { 359, 28, 5 , 7 },- { 372, 28, 4 , 9 },- { 384, 28, 5 , 9 },- { 397, 28, 5 , 9 },- { 410, 28, 1 , 9 },- { 419, 28, 5 , 11 },- { 432, 28, 5 , 9 },- { 445, 28, 2 , 9 },- { 455, 28, 7 , 7 },- { 470, 28, 5 , 7 },- { 483, 28, 5 , 7 },- { 496, 28, 5 , 9 },- { 4, 52, 5 , 9 },- { 17, 52, 5 , 7 },- { 30, 52, 5 , 7 },- { 43, 52, 4 , 8 },- { 55, 52, 5 , 7 },- { 68, 52, 5 , 7 },- { 81, 52, 7 , 7 },- { 96, 52, 5 , 7 },- { 109, 52, 5 , 9 },- { 122, 52, 5 , 7 },- { 135, 52, 4 , 9 },- { 147, 52, 1 , 9 },- { 156, 52, 4 , 9 },- { 168, 52, 6 , 2 },- { 182, 52, 1 , 9 },- { 191, 52, 5 , 11 },- { 204, 52, 6 , 9 },- { 218, 52, 6 , 9 },- { 232, 52, 5 , 9 },- { 245, 52, 5 , 12 },- { 258, 52, 5 , 9 },- { 271, 52, 5 , 10 },- { 284, 52, 7 , 9 },- { 299, 52, 5 , 9 },- { 312, 52, 6 , 5 },- { 326, 52, 5 , 3 },- { 339, 52, 7 , 9 },- { 354, 52, 5 , 9 },- { 367, 52, 4 , 4 },- { 379, 52, 5 , 7 },- { 392, 52, 5 , 9 },- { 405, 52, 5 , 9 },- { 418, 52, 5 , 12 },- { 431, 52, 5 , 9 },- { 444, 52, 7 , 9 },- { 459, 52, 1 , 1 },- { 468, 52, 5 , 10 },- { 481, 52, 5 , 9 },- { 494, 52, 5 , 9 },- { 4, 76, 6 , 5 },- { 18, 76, 9 , 9 },- { 35, 76, 9 , 7 },- { 52, 76, 5 , 11 },- { 65, 76, 5 , 9 },- { 78, 76, 5 , 12 },- { 91, 76, 5 , 12 },- { 104, 76, 5 , 12 },- { 117, 76, 6 , 12 },- { 131, 76, 5 , 11 },- { 144, 76, 5 , 13 },- { 157, 76, 9 , 9 },- { 174, 76, 5 , 12 },- { 187, 76, 5 , 12 },- { 200, 76, 5 , 12 },- { 213, 76, 5 , 12 },- { 226, 76, 5 , 11 },- { 239, 76, 2 , 12 },- { 249, 76, 2 , 12 },- { 259, 76, 3 , 12 },- { 270, 76, 3 , 11 },- { 281, 76, 6 , 9 },- { 295, 76, 6 , 12 },- { 309, 76, 5 , 12 },- { 322, 76, 5 , 12 },- { 335, 76, 5 , 12 },- { 348, 76, 6 , 12 },- { 362, 76, 5 , 11 },- { 375, 76, 5 , 5 },- { 388, 76, 7 , 9 },- { 403, 76, 5 , 12 },- { 416, 76, 5 , 12 },- { 429, 76, 5 , 12 },- { 442, 76, 5 , 11 },- { 455, 76, 5 , 12 },- { 468, 76, 5 , 9 },- { 481, 76, 5 , 9 },- { 494, 76, 5 , 10 },- { 4, 100, 5 , 10 },- { 17, 100, 5 , 10 },- { 30, 100, 6 , 10 },- { 44, 100, 5 , 9 },- { 57, 100, 5 , 11 },- { 70, 100, 9 , 7 },- { 87, 100, 5 , 10 },- { 100, 100, 5 , 10 },- { 113, 100, 5 , 10 },- { 126, 100, 5 , 10 },- { 139, 100, 5 , 9 },- { 152, 100, 2 , 10 },- { 162, 100, 2 , 10 },- { 172, 100, 3 , 10 },- { 183, 100, 3 , 9 },- { 194, 100, 6 , 9 },- { 208, 100, 6 , 10 },- { 222, 100, 5 , 10 },- { 235, 100, 5 , 10 },- { 248, 100, 5 , 10 },- { 261, 100, 6 , 10 },- { 275, 100, 5 , 9 },- { 288, 100, 5 , 5 },- { 301, 100, 7 , 7 },- { 316, 100, 5 , 10 },- { 329, 100, 5 , 10 },- { 342, 100, 5 , 10 },- { 355, 100, 5 , 9 },- { 368, 100, 5 , 12 },- { 381, 100, 5 , 11 },- { 394, 100, 5 , 11 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo darkFontGlyphs[189] = {- { 32, 0, 13, 4, { 0 }},- { 33, 2, 4, 5, { 0 }},- { 34, 2, 4, 7, { 0 }},- { 35, 1, 4, 8, { 0 }},- { 36, 1, 2, 7, { 0 }},- { 37, 1, 4, 9, { 0 }},- { 38, 1, 4, 7, { 0 }},- { 39, 2, 4, 5, { 0 }},- { 40, 3, 4, 7, { 0 }},- { 41, 1, 4, 7, { 0 }},- { 42, 1, 4, 7, { 0 }},- { 43, 1, 6, 7, { 0 }},- { 44, 1, 12, 5, { 0 }},- { 45, 1, 8, 6, { 0 }},- { 46, 2, 12, 5, { 0 }},- { 47, 1, 4, 5, { 0 }},- { 48, 1, 4, 7, { 0 }},- { 49, 2, 4, 7, { 0 }},- { 50, 1, 4, 7, { 0 }},- { 51, 1, 4, 7, { 0 }},- { 52, 1, 4, 7, { 0 }},- { 53, 1, 4, 7, { 0 }},- { 54, 1, 4, 7, { 0 }},- { 55, 1, 4, 7, { 0 }},- { 56, 1, 4, 7, { 0 }},- { 57, 1, 4, 7, { 0 }},- { 58, 2, 6, 5, { 0 }},- { 59, 1, 6, 5, { 0 }},- { 60, 1, 6, 5, { 0 }},- { 61, 1, 7, 6, { 0 }},- { 62, 1, 6, 5, { 0 }},- { 63, 1, 4, 7, { 0 }},- { 64, 1, 4, 9, { 0 }},- { 65, 1, 4, 7, { 0 }},- { 66, 1, 4, 7, { 0 }},- { 67, 1, 4, 7, { 0 }},- { 68, 1, 4, 7, { 0 }},- { 69, 1, 4, 7, { 0 }},- { 70, 1, 4, 7, { 0 }},- { 71, 1, 4, 7, { 0 }},- { 72, 1, 4, 7, { 0 }},- { 73, 2, 4, 5, { 0 }},- { 74, 1, 4, 7, { 0 }},- { 75, 1, 4, 7, { 0 }},- { 76, 1, 4, 7, { 0 }},- { 77, 1, 4, 9, { 0 }},- { 78, 1, 4, 7, { 0 }},- { 79, 1, 4, 7, { 0 }},- { 80, 1, 4, 7, { 0 }},- { 81, 1, 4, 7, { 0 }},- { 82, 1, 4, 7, { 0 }},- { 83, 1, 4, 7, { 0 }},- { 84, 1, 4, 7, { 0 }},- { 85, 1, 4, 7, { 0 }},- { 86, 1, 4, 7, { 0 }},- { 87, 1, 4, 9, { 0 }},- { 88, 1, 4, 7, { 0 }},- { 89, 1, 4, 7, { 0 }},- { 90, 1, 4, 7, { 0 }},- { 91, 3, 4, 7, { 0 }},- { 92, 1, 4, 5, { 0 }},- { 93, 1, 4, 7, { 0 }},- { 94, 1, 4, 7, { 0 }},- { 95, 0, 14, 5, { 0 }},- { 96, 1, 4, 5, { 0 }},- { 97, 1, 6, 7, { 0 }},- { 98, 1, 4, 7, { 0 }},- { 99, 1, 6, 7, { 0 }},- { 100, 1, 4, 7, { 0 }},- { 101, 1, 6, 7, { 0 }},- { 102, 1, 4, 6, { 0 }},- { 103, 1, 6, 7, { 0 }},- { 104, 1, 4, 7, { 0 }},- { 105, 2, 4, 5, { 0 }},- { 106, 1, 4, 7, { 0 }},- { 107, 1, 4, 7, { 0 }},- { 108, 2, 4, 5, { 0 }},- { 109, 1, 6, 9, { 0 }},- { 110, 1, 6, 7, { 0 }},- { 111, 1, 6, 7, { 0 }},- { 112, 1, 6, 7, { 0 }},- { 113, 1, 6, 7, { 0 }},- { 114, 1, 6, 7, { 0 }},- { 115, 1, 6, 7, { 0 }},- { 116, 1, 5, 6, { 0 }},- { 117, 1, 6, 7, { 0 }},- { 118, 1, 6, 7, { 0 }},- { 119, 1, 6, 9, { 0 }},- { 120, 1, 6, 7, { 0 }},- { 121, 1, 6, 7, { 0 }},- { 122, 1, 6, 7, { 0 }},- { 123, 2, 4, 7, { 0 }},- { 124, 2, 4, 5, { 0 }},- { 125, 1, 4, 7, { 0 }},- { 126, 1, 4, 8, { 0 }},- { 161, 2, 6, 5, { 0 }},- { 162, 1, 4, 7, { 0 }},- { 163, 1, 4, 8, { 0 }},- { 8364, 1, 4, 8, { 0 }},- { 165, 1, 4, 7, { 0 }},- { 352, 1, 1, 7, { 0 }},- { 167, 2, 4, 9, { 0 }},- { 353, 1, 3, 7, { 0 }},- { 169, 1, 4, 9, { 0 }},- { 170, 2, 4, 9, { 0 }},- { 171, 1, 6, 8, { 0 }},- { 172, 1, 8, 7, { 0 }},- { 174, 1, 4, 9, { 0 }},- { 175, 2, 4, 9, { 0 }},- { 176, 1, 4, 6, { 0 }},- { 177, 1, 6, 7, { 0 }},- { 178, 2, 4, 9, { 0 }},- { 179, 2, 4, 9, { 0 }},- { 381, 1, 1, 7, { 0 }},- { 181, 1, 6, 7, { 0 }},- { 182, 1, 4, 9, { 0 }},- { 183, 2, 8, 5, { 0 }},- { 382, 1, 3, 7, { 0 }},- { 185, 2, 4, 9, { 0 }},- { 186, 2, 4, 9, { 0 }},- { 187, 1, 6, 8, { 0 }},- { 338, 1, 4, 11, { 0 }},- { 339, 1, 6, 11, { 0 }},- { 376, 1, 2, 7, { 0 }},- { 191, 1, 6, 7, { 0 }},- { 192, 1, 1, 7, { 0 }},- { 193, 1, 1, 7, { 0 }},- { 194, 1, 1, 7, { 0 }},- { 195, 1, 1, 7, { 0 }},- { 196, 1, 2, 7, { 0 }},- { 197, 1, 0, 7, { 0 }},- { 198, 1, 4, 11, { 0 }},- { 199, 1, 4, 7, { 0 }},- { 200, 1, 1, 7, { 0 }},- { 201, 1, 1, 7, { 0 }},- { 202, 1, 1, 7, { 0 }},- { 203, 1, 2, 7, { 0 }},- { 204, 1, 1, 5, { 0 }},- { 205, 2, 1, 5, { 0 }},- { 206, 1, 1, 5, { 0 }},- { 207, 1, 2, 5, { 0 }},- { 208, 0, 4, 7, { 0 }},- { 209, 1, 1, 7, { 0 }},- { 210, 1, 1, 7, { 0 }},- { 211, 1, 1, 7, { 0 }},- { 212, 1, 1, 7, { 0 }},- { 213, 1, 1, 7, { 0 }},- { 214, 1, 2, 7, { 0 }},- { 215, 1, 6, 7, { 0 }},- { 216, 0, 4, 7, { 0 }},- { 217, 1, 1, 7, { 0 }},- { 218, 1, 1, 7, { 0 }},- { 219, 1, 1, 7, { 0 }},- { 220, 1, 2, 7, { 0 }},- { 221, 1, 1, 7, { 0 }},- { 222, 1, 4, 7, { 0 }},- { 223, 1, 4, 7, { 0 }},- { 224, 1, 3, 7, { 0 }},- { 225, 1, 3, 7, { 0 }},- { 226, 1, 3, 7, { 0 }},- { 227, 1, 3, 7, { 0 }},- { 228, 1, 4, 7, { 0 }},- { 229, 1, 2, 7, { 0 }},- { 230, 1, 6, 11, { 0 }},- { 231, 1, 6, 7, { 0 }},- { 232, 1, 3, 7, { 0 }},- { 233, 1, 3, 7, { 0 }},- { 234, 1, 3, 7, { 0 }},- { 235, 1, 4, 7, { 0 }},- { 236, 1, 3, 5, { 0 }},- { 237, 2, 3, 5, { 0 }},- { 238, 1, 3, 5, { 0 }},- { 239, 1, 4, 5, { 0 }},- { 240, 1, 4, 7, { 0 }},- { 241, 1, 3, 7, { 0 }},- { 242, 1, 3, 7, { 0 }},- { 243, 1, 3, 7, { 0 }},- { 244, 1, 3, 7, { 0 }},- { 245, 1, 3, 7, { 0 }},- { 246, 1, 4, 7, { 0 }},- { 247, 1, 6, 7, { 0 }},- { 248, 0, 6, 7, { 0 }},- { 249, 1, 3, 7, { 0 }},- { 250, 1, 3, 7, { 0 }},- { 251, 1, 3, 7, { 0 }},- { 252, 1, 4, 7, { 0 }},- { 253, 1, 3, 7, { 0 }},- { 254, 1, 4, 7, { 0 }},- { 255, 1, 4, 7, { 0 }},-};--// Style loading function: Dark-static void GuiLoadStyleDark(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int darkFontDataSize = 0;- unsigned char *data = DecompressData(darkFontData, DARK_STYLE_FONT_ATLAS_COMP_SIZE, &darkFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, darkFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, darkFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_enefete.h
@@ -1,600 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleEnefete(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define ENEFETE_STYLE_PROPS_COUNT 17--// Custom style name: Enefete-static const GuiStyleProp enefeteStyleProps[ENEFETE_STYLE_PROPS_COUNT] = {- { 0, 0, 0x1980d5ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x4df3ebff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0x103e60ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xe7e2f7ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0x23d4ddff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xf1f1f1ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0x6413a6ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xea66d9ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x9f00bbff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x4b909eff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x73c7d0ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x448894ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0x1d3f6cff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x29c9e5ff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)--#define ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE 2462--// Font atlas image pixels data: DEFLATE compressed-static unsigned char enefeteFontData[ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,- 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,- 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,- 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,- 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,- 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,- 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,- 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,- 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,- 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,- 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,- 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,- 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,- 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,- 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,- 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,- 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,- 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,- 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,- 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,- 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,- 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,- 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,- 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,- 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,- 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,- 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,- 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,- 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,- 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,- 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,- 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,- 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,- 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,- 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,- 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,- 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,- 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,- 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,- 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,- 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,- 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,- 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,- 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,- 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,- 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,- 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,- 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,- 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,- 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,- 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,- 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,- 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,- 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,- 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,- 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,- 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,- 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,- 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,- 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,- 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,- 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,- 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,- 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,- 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,- 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,- 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,- 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,- 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,- 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,- 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,- 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,- 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,- 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,- 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,- 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,- 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,- 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,- 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,- 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,- 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,- 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,- 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,- 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,- 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,- 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,- 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,- 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,- 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,- 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,- 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,- 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,- 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,- 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,- 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,- 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,- 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,- 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,- 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,- 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,- 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,- 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,- 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,- 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,- 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,- 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,- 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,- 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,- 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,- 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,- 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,- 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,- 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,- 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,- 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,- 0x0f };--// Font glyphs rectangles data (on atlas)-static const Rectangle enefeteFontRecs[189] = {- { 4, 4, 4 , 16 },- { 16, 4, 2 , 10 },- { 26, 4, 5 , 3 },- { 39, 4, 7 , 10 },- { 54, 4, 7 , 13 },- { 69, 4, 7 , 10 },- { 84, 4, 7 , 10 },- { 99, 4, 2 , 3 },- { 109, 4, 3 , 12 },- { 120, 4, 3 , 12 },- { 131, 4, 5 , 6 },- { 144, 4, 6 , 5 },- { 158, 4, 2 , 4 },- { 168, 4, 5 , 1 },- { 181, 4, 2 , 2 },- { 191, 4, 4 , 10 },- { 203, 4, 6 , 10 },- { 217, 4, 4 , 10 },- { 229, 4, 6 , 10 },- { 243, 4, 6 , 10 },- { 257, 4, 6 , 10 },- { 271, 4, 6 , 10 },- { 285, 4, 6 , 10 },- { 299, 4, 6 , 10 },- { 313, 4, 6 , 10 },- { 327, 4, 6 , 10 },- { 341, 4, 2 , 6 },- { 351, 4, 2 , 8 },- { 361, 4, 7 , 7 },- { 376, 4, 5 , 3 },- { 389, 4, 7 , 7 },- { 404, 4, 6 , 10 },- { 418, 4, 7 , 12 },- { 433, 4, 7 , 10 },- { 448, 4, 7 , 10 },- { 463, 4, 7 , 10 },- { 478, 4, 7 , 10 },- { 493, 4, 7 , 10 },- { 4, 28, 7 , 10 },- { 19, 28, 7 , 10 },- { 34, 28, 7 , 10 },- { 49, 28, 2 , 10 },- { 59, 28, 5 , 10 },- { 72, 28, 7 , 10 },- { 87, 28, 6 , 10 },- { 101, 28, 9 , 10 },- { 118, 28, 7 , 10 },- { 133, 28, 7 , 10 },- { 148, 28, 7 , 10 },- { 163, 28, 7 , 12 },- { 178, 28, 7 , 10 },- { 193, 28, 7 , 10 },- { 208, 28, 6 , 10 },- { 222, 28, 7 , 10 },- { 237, 28, 7 , 10 },- { 252, 28, 8 , 10 },- { 268, 28, 7 , 10 },- { 283, 28, 6 , 10 },- { 297, 28, 7 , 10 },- { 312, 28, 4 , 12 },- { 324, 28, 4 , 10 },- { 336, 28, 4 , 12 },- { 348, 28, 6 , 3 },- { 362, 28, 7 , 1 },- { 377, 28, 4 , 3 },- { 389, 28, 6 , 7 },- { 403, 28, 6 , 10 },- { 417, 28, 6 , 7 },- { 431, 28, 6 , 10 },- { 445, 28, 6 , 7 },- { 459, 28, 4 , 10 },- { 471, 28, 6 , 9 },- { 485, 28, 6 , 10 },- { 499, 28, 2 , 10 },- { 4, 52, 5 , 12 },- { 17, 52, 6 , 10 },- { 31, 52, 3 , 10 },- { 42, 52, 8 , 7 },- { 58, 52, 6 , 7 },- { 72, 52, 6 , 7 },- { 86, 52, 6 , 9 },- { 100, 52, 6 , 9 },- { 114, 52, 5 , 7 },- { 127, 52, 6 , 7 },- { 141, 52, 4 , 10 },- { 153, 52, 6 , 7 },- { 167, 52, 6 , 7 },- { 181, 52, 8 , 7 },- { 197, 52, 6 , 7 },- { 211, 52, 6 , 9 },- { 225, 52, 6 , 7 },- { 239, 52, 5 , 12 },- { 252, 52, 2 , 12 },- { 262, 52, 5 , 12 },- { 275, 52, 7 , 3 },- { 290, 52, 2 , 9 },- { 300, 52, 6 , 11 },- { 314, 52, 7 , 10 },- { 329, 52, 7 , 9 },- { 344, 52, 6 , 10 },- { 358, 52, 7 , 11 },- { 373, 52, 6 , 12 },- { 387, 52, 6 , 10 },- { 401, 52, 7 , 10 },- { 416, 52, 5 , 5 },- { 429, 52, 7 , 6 },- { 444, 52, 6 , 3 },- { 458, 52, 7 , 10 },- { 473, 52, 9 , 10 },- { 490, 52, 4 , 4 },- { 4, 76, 6 , 7 },- { 18, 76, 4 , 5 },- { 30, 76, 4 , 5 },- { 42, 76, 7 , 11 },- { 57, 76, 6 , 9 },- { 71, 76, 7 , 12 },- { 86, 76, 2 , 2 },- { 96, 76, 6 , 10 },- { 110, 76, 3 , 5 },- { 121, 76, 4 , 5 },- { 133, 76, 7 , 6 },- { 148, 76, 9 , 10 },- { 165, 76, 8 , 7 },- { 181, 76, 6 , 11 },- { 195, 76, 6 , 11 },- { 209, 76, 7 , 11 },- { 224, 76, 7 , 11 },- { 239, 76, 7 , 11 },- { 254, 76, 7 , 11 },- { 269, 76, 7 , 11 },- { 284, 76, 7 , 11 },- { 299, 76, 9 , 10 },- { 316, 76, 7 , 12 },- { 331, 76, 7 , 11 },- { 346, 76, 7 , 11 },- { 361, 76, 7 , 11 },- { 376, 76, 7 , 11 },- { 391, 76, 3 , 11 },- { 402, 76, 3 , 11 },- { 413, 76, 5 , 11 },- { 426, 76, 5 , 11 },- { 439, 76, 8 , 10 },- { 455, 76, 7 , 11 },- { 470, 76, 7 , 11 },- { 485, 76, 7 , 11 },- { 4, 100, 7 , 11 },- { 19, 100, 7 , 11 },- { 34, 100, 7 , 11 },- { 49, 100, 7 , 7 },- { 64, 100, 7 , 13 },- { 79, 100, 7 , 11 },- { 94, 100, 7 , 11 },- { 109, 100, 7 , 11 },- { 124, 100, 7 , 11 },- { 139, 100, 6 , 11 },- { 153, 100, 7 , 10 },- { 168, 100, 7 , 10 },- { 183, 100, 6 , 10 },- { 197, 100, 6 , 10 },- { 211, 100, 6 , 10 },- { 225, 100, 6 , 10 },- { 239, 100, 6 , 10 },- { 253, 100, 6 , 11 },- { 267, 100, 8 , 7 },- { 283, 100, 6 , 9 },- { 297, 100, 6 , 10 },- { 311, 100, 6 , 10 },- { 325, 100, 6 , 10 },- { 339, 100, 6 , 10 },- { 353, 100, 3 , 10 },- { 364, 100, 3 , 10 },- { 375, 100, 5 , 10 },- { 388, 100, 5 , 10 },- { 401, 100, 6 , 10 },- { 415, 100, 6 , 10 },- { 429, 100, 6 , 10 },- { 443, 100, 6 , 10 },- { 457, 100, 6 , 10 },- { 471, 100, 6 , 10 },- { 485, 100, 6 , 10 },- { 4, 124, 6 , 7 },- { 18, 124, 7 , 11 },- { 33, 124, 6 , 10 },- { 47, 124, 6 , 10 },- { 61, 124, 6 , 10 },- { 75, 124, 6 , 10 },- { 89, 124, 6 , 12 },- { 103, 124, 6 , 12 },- { 117, 124, 6 , 12 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo enefeteFontGlyphs[189] = {- { 32, 0, 12, 4, { 0 }},- { 33, 0, 2, 3, { 0 }},- { 34, 0, 2, 6, { 0 }},- { 35, 0, 2, 8, { 0 }},- { 36, 0, 1, 8, { 0 }},- { 37, 0, 2, 8, { 0 }},- { 38, 0, 2, 8, { 0 }},- { 39, 0, 2, 3, { 0 }},- { 40, 0, 2, 4, { 0 }},- { 41, 0, 2, 4, { 0 }},- { 42, 0, 4, 6, { 0 }},- { 43, 0, 6, 7, { 0 }},- { 44, 0, 10, 3, { 0 }},- { 45, 0, 8, 6, { 0 }},- { 46, 0, 10, 3, { 0 }},- { 47, 0, 2, 5, { 0 }},- { 48, 0, 2, 7, { 0 }},- { 49, 0, 2, 7, { 0 }},- { 50, 0, 2, 7, { 0 }},- { 51, 0, 2, 7, { 0 }},- { 52, 0, 2, 7, { 0 }},- { 53, 0, 2, 7, { 0 }},- { 54, 0, 2, 7, { 0 }},- { 55, 0, 2, 7, { 0 }},- { 56, 0, 2, 7, { 0 }},- { 57, 0, 2, 7, { 0 }},- { 58, 0, 4, 3, { 0 }},- { 59, 0, 4, 3, { 0 }},- { 60, 0, 4, 8, { 0 }},- { 61, 0, 6, 6, { 0 }},- { 62, 0, 4, 8, { 0 }},- { 63, 0, 2, 7, { 0 }},- { 64, 0, 2, 8, { 0 }},- { 65, 0, 2, 8, { 0 }},- { 66, 0, 2, 8, { 0 }},- { 67, 0, 2, 8, { 0 }},- { 68, 0, 2, 8, { 0 }},- { 69, 0, 2, 8, { 0 }},- { 70, 0, 2, 8, { 0 }},- { 71, 0, 2, 8, { 0 }},- { 72, 0, 2, 8, { 0 }},- { 73, 0, 2, 3, { 0 }},- { 74, 0, 2, 6, { 0 }},- { 75, 0, 2, 8, { 0 }},- { 76, 0, 2, 7, { 0 }},- { 77, 0, 2, 10, { 0 }},- { 78, 0, 2, 8, { 0 }},- { 79, 0, 2, 8, { 0 }},- { 80, 0, 2, 8, { 0 }},- { 81, 0, 2, 8, { 0 }},- { 82, 0, 2, 8, { 0 }},- { 83, 0, 2, 8, { 0 }},- { 84, 0, 2, 7, { 0 }},- { 85, 0, 2, 8, { 0 }},- { 86, 0, 2, 8, { 0 }},- { 87, 0, 2, 9, { 0 }},- { 88, 0, 2, 8, { 0 }},- { 89, 0, 2, 7, { 0 }},- { 90, 0, 2, 8, { 0 }},- { 91, 0, 2, 5, { 0 }},- { 92, 0, 2, 5, { 0 }},- { 93, 0, 2, 5, { 0 }},- { 94, 0, 2, 7, { 0 }},- { 95, 0, 14, 8, { 0 }},- { 96, 0, 2, 5, { 0 }},- { 97, 0, 5, 7, { 0 }},- { 98, 0, 2, 7, { 0 }},- { 99, 0, 5, 7, { 0 }},- { 100, 0, 2, 7, { 0 }},- { 101, 0, 5, 7, { 0 }},- { 102, 0, 2, 5, { 0 }},- { 103, 0, 5, 7, { 0 }},- { 104, 0, 2, 7, { 0 }},- { 105, 0, 2, 3, { 0 }},- { 106, 0, 2, 6, { 0 }},- { 107, 0, 2, 7, { 0 }},- { 108, 0, 2, 4, { 0 }},- { 109, 0, 5, 9, { 0 }},- { 110, 0, 5, 7, { 0 }},- { 111, 0, 5, 7, { 0 }},- { 112, 0, 5, 7, { 0 }},- { 113, 0, 5, 7, { 0 }},- { 114, 0, 5, 6, { 0 }},- { 115, 0, 5, 7, { 0 }},- { 116, 0, 2, 5, { 0 }},- { 117, 0, 5, 7, { 0 }},- { 118, 0, 5, 7, { 0 }},- { 119, 0, 5, 9, { 0 }},- { 120, 0, 5, 7, { 0 }},- { 121, 0, 5, 7, { 0 }},- { 122, 0, 5, 7, { 0 }},- { 123, 0, 2, 6, { 0 }},- { 124, 0, 2, 3, { 0 }},- { 125, 0, 2, 6, { 0 }},- { 126, 0, 6, 8, { 0 }},- { 161, 0, 5, 3, { 0 }},- { 162, 0, 3, 7, { 0 }},- { 163, 0, 2, 8, { 0 }},- { 8364, 0, 3, 8, { 0 }},- { 165, 0, 2, 7, { 0 }},- { 352, 0, 1, 8, { 0 }},- { 167, 0, 2, 7, { 0 }},- { 353, 0, 2, 7, { 0 }},- { 169, 0, 2, 8, { 0 }},- { 170, 0, 2, 6, { 0 }},- { 171, 0, 6, 8, { 0 }},- { 172, 0, 7, 7, { 0 }},- { 174, 0, 2, 8, { 0 }},- { 175, 1, 3, 14, { 0 }},- { 176, 0, 2, 5, { 0 }},- { 177, 0, 4, 7, { 0 }},- { 178, 0, 2, 5, { 0 }},- { 179, 0, 2, 5, { 0 }},- { 381, 0, 1, 8, { 0 }},- { 181, 0, 5, 7, { 0 }},- { 182, 0, 2, 8, { 0 }},- { 183, 0, 6, 3, { 0 }},- { 382, 0, 2, 7, { 0 }},- { 185, 0, 2, 4, { 0 }},- { 186, 0, 2, 5, { 0 }},- { 187, 0, 6, 8, { 0 }},- { 338, 0, 2, 10, { 0 }},- { 339, 0, 5, 9, { 0 }},- { 376, 0, 1, 7, { 0 }},- { 191, 0, 3, 7, { 0 }},- { 192, 0, 1, 8, { 0 }},- { 193, 0, 1, 8, { 0 }},- { 194, 0, 1, 8, { 0 }},- { 195, 0, 1, 8, { 0 }},- { 196, 0, 1, 8, { 0 }},- { 197, 0, 1, 8, { 0 }},- { 198, 0, 2, 10, { 0 }},- { 199, 0, 2, 8, { 0 }},- { 200, 0, 1, 8, { 0 }},- { 201, 0, 1, 8, { 0 }},- { 202, 0, 1, 8, { 0 }},- { 203, 0, 1, 8, { 0 }},- { 204, 0, 1, 4, { 0 }},- { 205, 0, 1, 4, { 0 }},- { 206, 0, 1, 6, { 0 }},- { 207, 0, 1, 6, { 0 }},- { 208, 0, 2, 9, { 0 }},- { 209, 0, 1, 8, { 0 }},- { 210, 0, 1, 8, { 0 }},- { 211, 0, 1, 8, { 0 }},- { 212, 0, 1, 8, { 0 }},- { 213, 0, 1, 8, { 0 }},- { 214, 0, 1, 8, { 0 }},- { 215, 0, 5, 8, { 0 }},- { 216, 0, 1, 8, { 0 }},- { 217, 0, 1, 8, { 0 }},- { 218, 0, 1, 8, { 0 }},- { 219, 0, 1, 8, { 0 }},- { 220, 0, 1, 8, { 0 }},- { 221, 0, 1, 7, { 0 }},- { 222, 0, 2, 8, { 0 }},- { 223, 0, 2, 8, { 0 }},- { 224, 0, 2, 7, { 0 }},- { 225, 0, 2, 7, { 0 }},- { 226, 0, 2, 7, { 0 }},- { 227, 0, 2, 7, { 0 }},- { 228, 0, 2, 7, { 0 }},- { 229, 0, 1, 7, { 0 }},- { 230, 0, 5, 9, { 0 }},- { 231, 0, 5, 7, { 0 }},- { 232, 0, 2, 7, { 0 }},- { 233, 0, 2, 7, { 0 }},- { 234, 0, 2, 7, { 0 }},- { 235, 0, 2, 7, { 0 }},- { 236, 0, 2, 4, { 0 }},- { 237, 0, 2, 4, { 0 }},- { 238, 0, 2, 6, { 0 }},- { 239, 0, 2, 6, { 0 }},- { 240, 0, 2, 7, { 0 }},- { 241, 0, 2, 7, { 0 }},- { 242, 0, 2, 7, { 0 }},- { 243, 0, 2, 7, { 0 }},- { 244, 0, 2, 7, { 0 }},- { 245, 0, 2, 7, { 0 }},- { 246, 0, 2, 7, { 0 }},- { 247, 0, 4, 7, { 0 }},- { 248, 0, 3, 8, { 0 }},- { 249, 0, 2, 7, { 0 }},- { 250, 0, 2, 7, { 0 }},- { 251, 0, 2, 7, { 0 }},- { 252, 0, 2, 7, { 0 }},- { 253, 0, 2, 7, { 0 }},- { 254, 0, 2, 7, { 0 }},- { 255, 0, 2, 7, { 0 }},-};--// Style loading function: Enefete-static void GuiLoadStyleEnefete(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < ENEFETE_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(enefeteStyleProps[i].controlId, enefeteStyleProps[i].propertyId, enefeteStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int enefeteFontDataSize = 0;- unsigned char *data = DecompressData(enefeteFontData, ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE, &enefeteFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, enefeteFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, enefeteFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_jungle.h
@@ -1,578 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleJungle(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define JUNGLE_STYLE_PROPS_COUNT 17--// Custom style name: Jungle-static const GuiStyleProp jungleStyleProps[JUNGLE_STYLE_PROPS_COUNT] = {- { 0, 0, 0x60827dff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x2c3334ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0x82a29fff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0x5f9aa8ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0x334e57ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0x6aa9b8ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xa9cb8dff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0x3b6357ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x97af81ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x5b6462ff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x2c3334ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x666b69ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x0000000c }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0x638465ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x2b3a3aff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000012 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "Pixel Intv.otf" (size: 12, spacing: 0)--#define JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE 2030--// Font atlas image pixels data: DEFLATE compressed-static unsigned char jungleFontData[JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0x9d, 0x3d, 0x8e, 0x25, 0x35, 0x14, 0x85, 0x8d, 0xe9, 0x8c, 0x10, 0x11, 0x80, 0x84, 0x20, 0x41, 0x22, 0x21, 0x61, 0x34,- 0x12, 0x64, 0xb3, 0x00, 0x62, 0x84, 0x08, 0x10, 0x11, 0x09, 0xb0, 0x07, 0x66, 0x65, 0x93, 0x90, 0xb3, 0x01, 0x76, 0xc1,- 0x02, 0x2e, 0x9a, 0xbf, 0x9e, 0x9f, 0xae, 0xb2, 0x7d, 0x8f, 0xaf, 0xcb, 0xae, 0x7a, 0x5f, 0x7f, 0x9a, 0xd1, 0xcc, 0xf3,- 0x73, 0x95, 0xcb, 0xc7, 0xd7, 0x55, 0xaf, 0x7d, 0xde, 0xb5, 0x25, 0x00, 0x00, 0x00, 0x80, 0x07, 0x3c, 0xff, 0xd9, 0x7e,- 0x6d, 0xab, 0x24, 0xbd, 0x2a, 0x69, 0x3f, 0xd6, 0xeb, 0xd7, 0x5f, 0x96, 0xe4, 0xdd, 0x77, 0x6c, 0x1f, 0x31, 0xef, 0xb4,- 0x61, 0xaf, 0xd5, 0xfb, 0x2d, 0x4b, 0xae, 0x92, 0xfd, 0xe3, 0xef, 0xf7, 0x57, 0x72, 0x5c, 0xc3, 0xbb, 0x3f, 0xc9, 0x71,- 0x2d, 0xe5, 0x7a, 0xa3, 0xf5, 0x2f, 0xf7, 0xc1, 0x7e, 0xd9, 0xcb, 0x3f, 0xcf, 0x7b, 0x22, 0x3b, 0x8e, 0xb9, 0xff, 0xfe,- 0xe4, 0x1a, 0x81, 0xfe, 0x91, 0xe1, 0xeb, 0xdd, 0xd2, 0xbb, 0x6b, 0xd7, 0x60, 0xce, 0x16, 0xbc, 0x7e, 0x7d, 0xa4, 0xfe,- 0xe9, 0xfe, 0x1c, 0xed, 0xf1, 0x5f, 0x53, 0xc5, 0xec, 0x6e, 0xb3, 0x27, 0x52, 0x51, 0x9b, 0x2c, 0x9c, 0x29, 0x62, 0x34,- 0xa7, 0xa0, 0xde, 0xcd, 0xc5, 0x6b, 0x30, 0x41, 0x7f, 0x6d, 0x84, 0x46, 0x1d, 0x47, 0x8b, 0xff, 0xe7, 0xdc, 0xbd, 0x18,- 0x01, 0xe5, 0xa3, 0xf6, 0xb7, 0x38, 0x2a, 0xfe, 0xd3, 0x50, 0xf5, 0x7b, 0xf4, 0x3f, 0x62, 0xfe, 0x2f, 0xbf, 0xbf, 0xdc,- 0x67, 0xdb, 0xc7, 0xcb, 0xaf, 0xe2, 0xdf, 0x7f, 0xf7, 0x8c, 0xd0, 0xdf, 0x7f, 0xff, 0x1f, 0xab, 0x7e, 0xc4, 0xfc, 0xbf,- 0xe2, 0x73, 0x64, 0xed, 0x3e, 0xbe, 0x3d, 0x76, 0x6c, 0x78, 0xfc, 0xcf, 0xa0, 0xa4, 0x7e, 0xed, 0xf9, 0xcf, 0x3a, 0xe6,- 0xd9, 0xd1, 0xf1, 0xaf, 0x1c, 0xeb, 0x75, 0x4f, 0x98, 0x10, 0x9f, 0x67, 0xd5, 0xbf, 0xa4, 0x3e, 0x44, 0xcc, 0x35, 0x9e,- 0xbb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x35, 0x57, 0x4c, 0xca, 0xeb, 0xef,- 0x91, 0x2b, 0x91, 0xa3, 0xca, 0xda, 0xdd, 0x06, 0x1e, 0xe7, 0x4a, 0x16, 0x7a, 0x6c, 0x56, 0xbf, 0x8c, 0x72, 0xfb, 0x25,- 0xb7, 0x37, 0xa3, 0xa5, 0x35, 0xea, 0xf9, 0x7a, 0xf4, 0xcf, 0xce, 0xb5, 0xd7, 0xb2, 0x43, 0x6f, 0xcf, 0xcf, 0xb8, 0xbf,- 0x72, 0xdd, 0x7b, 0x7d, 0xde, 0x32, 0xdf, 0x0c, 0x90, 0x0e, 0x89, 0xff, 0x36, 0x0f, 0xd3, 0x18, 0x77, 0xe3, 0xb6, 0xcf,- 0xac, 0xd4, 0xd6, 0x3b, 0xb7, 0xa3, 0xf0, 0xcd, 0x6a, 0xf3, 0xd8, 0xf1, 0x1d, 0xed, 0xfa, 0x54, 0x1d, 0x25, 0xca, 0x98,- 0x54, 0x1c, 0xac, 0x11, 0xf3, 0x7f, 0x4c, 0xfc, 0x97, 0xc6, 0xa9, 0xbd, 0xf7, 0x27, 0x66, 0x1e, 0x9f, 0xa5, 0xff, 0x88,- 0xb9, 0x3a, 0x35, 0xcc, 0x0a, 0x6a, 0x5b, 0xb4, 0xfb, 0xbf, 0xe2, 0xd4, 0x29, 0xb9, 0x95, 0xf4, 0xe7, 0xa9, 0x19, 0xf1,- 0xdf, 0x13, 0xe3, 0xda, 0xfc, 0x5f, 0xd6, 0x3f, 0xce, 0xdd, 0x66, 0x53, 0x9e, 0xa6, 0x5b, 0x62, 0x6c, 0xad, 0xfb, 0x3f,- 0x44, 0xfa, 0x19, 0xe7, 0x7d, 0x9e, 0x42, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x18, 0xeb, 0xc7, 0x3b, 0xca, 0x53, 0x62, 0x8d, 0x59, 0x7c, 0xf6, 0xfd, 0x5a, 0x47, 0xb9, 0xf5, 0x8e, 0xef, 0xef, 0x68,- 0xdf, 0x47, 0xc4, 0x9a, 0xb4, 0x92, 0xc1, 0xac, 0xdf, 0x8b, 0x68, 0x4b, 0x38, 0xf2, 0x46, 0xf4, 0xdb, 0x4c, 0xfd, 0x95,- 0xf6, 0xe8, 0xfa, 0x9b, 0x98, 0x61, 0xb0, 0x96, 0x19, 0x66, 0x2d, 0xfd, 0x15, 0xd7, 0x41, 0x8f, 0xfe, 0xf5, 0xb9, 0x2a,- 0x15, 0xf4, 0xf0, 0xcf, 0xf1, 0xaa, 0xfe, 0x26, 0xe6, 0x7d, 0x1c, 0x73, 0x17, 0x1b, 0xa3, 0xbf, 0xd2, 0x6f, 0x57, 0x99,- 0xff, 0xeb, 0xc7, 0xcc, 0xe2, 0xfc, 0x6f, 0xd5, 0x59, 0xc5, 0xc2, 0xdd, 0xa8, 0xfe, 0x98, 0x6a, 0xed, 0x9f, 0xdb, 0xd5,- 0x3f, 0x0d, 0xd1, 0x7f, 0xcc, 0x19, 0xcf, 0x73, 0xff, 0x57, 0xb2, 0x57, 0xcf, 0xf0, 0xb9, 0xf5, 0x79, 0xc3, 0x6b, 0xa5,- 0x47, 0xf4, 0xcc, 0xb8, 0xf9, 0x1f, 0x17, 0xe0, 0x79, 0x5c, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x47, 0xac, 0x51, 0xe8, 0x6b, 0x67, 0x23, 0x56, 0x00, 0x1f, 0xbe, 0x9e, 0x1b, 0xd6, 0x30, 0xdf, 0x7f,- 0x3d, 0xef, 0x38, 0x46, 0xcc, 0x99, 0xf3, 0x4f, 0xdb, 0x8f, 0xb7, 0x35, 0x0f, 0x9a, 0xee, 0x20, 0x8c, 0x58, 0x07, 0x3c,- 0x5e, 0xff, 0xd4, 0xb4, 0x1e, 0xfb, 0x50, 0xc9, 0x2c, 0x78, 0x86, 0xb2, 0x33, 0xe3, 0x53, 0x29, 0x43, 0x94, 0xdf, 0xcd,- 0x54, 0xef, 0x05, 0x25, 0xd7, 0x5d, 0xed, 0x68, 0xda, 0x0e, 0xc5, 0x25, 0x77, 0x4c, 0xcd, 0xcb, 0xe2, 0xbf, 0xf2, 0xec,- 0xbe, 0xb6, 0xdc, 0x30, 0x07, 0x8c, 0xf7, 0x48, 0x27, 0x77, 0x3c, 0xf6, 0xf9, 0xee, 0xc6, 0xeb, 0x9f, 0x1a, 0x3c, 0x7e,- 0xd1, 0x8e, 0x14, 0xab, 0xec, 0x7e, 0xab, 0x8c, 0x80, 0xd1, 0xfa, 0xd7, 0xae, 0x55, 0x77, 0x09, 0xa5, 0xd0, 0x71, 0x13,- 0xad, 0x7f, 0xcb, 0x38, 0x8d, 0x1e, 0xc1, 0xca, 0x08, 0x38, 0x26, 0xfe, 0xcd, 0xad, 0x7f, 0x79, 0x6e, 0x88, 0xef, 0x3d,- 0xc5, 0x05, 0xa4, 0xcd, 0x28, 0xbd, 0x6e, 0x35, 0x45, 0xc5, 0x2c, 0xcd, 0x1c, 0x47, 0x3c, 0x41, 0x6b, 0x7b, 0x55, 0x47,- 0x3b, 0x36, 0xb5, 0x9e, 0x38, 0x5e, 0x7f, 0x93, 0x77, 0xfc, 0xce, 0xcb, 0xed, 0x7e, 0xad, 0x45, 0x9d, 0xee, 0xd8, 0x8b,- 0x8f, 0xff, 0xf5, 0xbe, 0x8d, 0x76, 0x44, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,- 0xdb, 0xcc, 0x51, 0xe0, 0xcf, 0x54, 0x53, 0xaf, 0xa1, 0xee, 0x9d, 0x75, 0xe4, 0xde, 0xb9, 0xa3, 0xf6, 0xb7, 0xd3, 0xf3,- 0x82, 0xd9, 0x90, 0x1d, 0xe0, 0xe2, 0xd7, 0xcd, 0xfa, 0xb2, 0x98, 0xd5, 0x7a, 0x48, 0xcd, 0xb8, 0xe5, 0xf5, 0x60, 0xf4,- 0xf8, 0x7a, 0x54, 0xcf, 0x47, 0xbc, 0x0f, 0x2f, 0xc6, 0xdb, 0xa6, 0xc5, 0xbf, 0xe6, 0x0b, 0x59, 0x4d, 0xff, 0x74, 0x90,- 0x3f, 0xaf, 0x47, 0xff, 0xde, 0xdd, 0x9f, 0x75, 0x47, 0x96, 0xbf, 0x57, 0xaf, 0xa0, 0x7f, 0x9b, 0x7b, 0x57, 0xf1, 0x11,- 0x46, 0xfb, 0xf0, 0x66, 0xe9, 0x6f, 0xd2, 0xde, 0xb9, 0x3d, 0xfa, 0xf7, 0xf9, 0xe5, 0x8f, 0x8b, 0x7f, 0xfd, 0x8c, 0x69,- 0xc8, 0xce, 0xe8, 0xbd, 0xd1, 0xea, 0xcb, 0xd4, 0x38, 0xc3, 0xa9, 0x15, 0xef, 0x97, 0x1b, 0xe5, 0xec, 0x9a, 0xeb, 0x5e,- 0x8c, 0xf2, 0xaf, 0xf6, 0x66, 0xff, 0x9e, 0xa1, 0x3f, 0xde, 0xb1, 0x6b, 0x8f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5b, 0x5b, 0xc7, 0x89, 0xdb, 0x8f, 0xca, 0x9b, 0xd5, 0xcd, 0x36, 0x33, 0x7a, 0xa8,- 0xb9, 0x63, 0xbc, 0xde, 0x8a, 0xd2, 0x5a, 0xe5, 0x77, 0xf6, 0xe5, 0x3d, 0x8f, 0xec, 0x13, 0x57, 0xef, 0xd4, 0xea, 0xe6,- 0xb7, 0xea, 0x66, 0x77, 0xed, 0xd7, 0x59, 0x50, 0xb2, 0x70, 0x66, 0xbf, 0x03, 0xc0, 0x97, 0xab, 0xcd, 0xf7, 0x6a, 0x2e,- 0x3a, 0x45, 0x62, 0x5c, 0x17, 0x6a, 0x86, 0xbe, 0xc7, 0xef, 0xf4, 0xc1, 0xa3, 0xe0, 0xba, 0xf9, 0x1d, 0x25, 0x7d, 0xb5,- 0xf3, 0x7d, 0x66, 0xc3, 0xec, 0xae, 0xeb, 0xd3, 0x3f, 0xbb, 0x73, 0xb5, 0xf9, 0xd5, 0x89, 0xf1, 0x15, 0x6a, 0x59, 0x71,- 0x4a, 0xc7, 0xfc, 0xb2, 0xf0, 0xbf, 0xda, 0x35, 0xd5, 0xeb, 0xbe, 0x3d, 0xf3, 0xfa, 0x6b, 0xdf, 0xdd, 0xff, 0xed, 0xad,- 0xeb, 0x75, 0xf2, 0x68, 0x2e, 0xae, 0xde, 0x11, 0x10, 0x99, 0x4d, 0x51, 0x75, 0x64, 0xb5, 0xe8, 0xbf, 0x77, 0xce, 0x36,- 0xfd, 0xdf, 0xfc, 0xdb, 0x57, 0xbb, 0x14, 0xff, 0x9a, 0xfe, 0x71, 0x3e, 0xf7, 0xb1, 0xf1, 0x3f, 0x22, 0x2b, 0xde, 0x5e,- 0x49, 0x6b, 0xfc, 0x6b, 0x63, 0xa7, 0x27, 0xfe, 0x4b, 0xf7, 0x7f, 0xbf, 0xfe, 0xaa, 0x0b, 0xee, 0x68, 0xfd, 0x93, 0xec,- 0x53, 0xd5, 0x9e, 0x1a, 0xeb, 0x3d, 0xd9, 0x33, 0x77, 0x94, 0xee, 0xff, 0xaa, 0x86, 0xd1, 0xf1, 0xbf, 0x9e, 0xfe, 0xa9,- 0xc3, 0x59, 0xeb, 0x1d, 0x53, 0xad, 0x3d, 0x69, 0xe2, 0x0c, 0xbe, 0xff, 0xfc, 0x7f, 0xac, 0xfe, 0xb1, 0xce, 0x4a, 0x2d,- 0xab, 0xe3, 0x8a, 0xfc, 0xf2, 0xd6, 0x27, 0xa9, 0xc7, 0xf6, 0xbd, 0x6b, 0xfe, 0xaf, 0xd5, 0xed, 0x3b, 0xf3, 0xa8, 0xba,- 0x10, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xa3, 0xd7, 0x89, 0xf6, 0xe9,- 0xa6, 0x43, 0xa4, 0x56, 0x6f, 0x74, 0x79, 0xcd, 0xd3, 0xf6, 0x95, 0x7d, 0x63, 0x9f, 0x3f, 0x78, 0xf5, 0x99, 0x3d, 0xb3,- 0x5f, 0x27, 0xb4, 0x35, 0xef, 0xee, 0x70, 0xbc, 0xf5, 0xa3, 0xbc, 0xa7, 0xb4, 0x8a, 0xd1, 0xe3, 0x44, 0xfb, 0xc1, 0x9e,- 0xd8, 0x1f, 0x1b, 0x47, 0xad, 0xd5, 0x1b, 0x5d, 0x5e, 0xd2, 0xff, 0x33, 0xfb, 0xd7, 0xfe, 0xb1, 0xa7, 0xf6, 0xc5, 0x66,- 0xad, 0xbf, 0x0e, 0x6f, 0x6b, 0xc9, 0xcd, 0xe3, 0xd9, 0x47, 0x59, 0xcb, 0x03, 0xd5, 0xe7, 0x44, 0xf9, 0xd9, 0x3e, 0xb0,- 0x1f, 0x37, 0x7c, 0x68, 0xb5, 0x7a, 0xa3, 0xcb, 0x4b, 0xfa, 0xff, 0x69, 0x66, 0x7f, 0xdb, 0x6f, 0xf6, 0xe1, 0x83, 0x92,- 0x27, 0xf6, 0x64, 0x42, 0x5b, 0x93, 0xdd, 0xbd, 0x68, 0xe7, 0x5d, 0xe7, 0x3e, 0xda, 0x6a, 0xfc, 0xf7, 0x38, 0xd1, 0x3e,- 0xb6, 0x9f, 0xec, 0x5b, 0xc1, 0x85, 0x30, 0x53, 0xff, 0xaf, 0xed, 0xbf, 0x1d, 0xfd, 0x35, 0x47, 0x45, 0x6f, 0x79, 0x6b,- 0xfc, 0xdb, 0xa0, 0xfc, 0x6f, 0x3d, 0xfa, 0xcf, 0xea, 0xb3, 0x76, 0x6f, 0xe6, 0x56, 0x9f, 0x7c, 0x64, 0x4f, 0x17, 0xd2,- 0xbf, 0x76, 0xff, 0x4f, 0x8e, 0x8c, 0xb3, 0xd1, 0xf7, 0xff, 0x33, 0xeb, 0x5f, 0x6a, 0xdf, 0xef, 0x0b, 0xe9, 0xdf, 0xe2,- 0xb0, 0x1a, 0xe7, 0x31, 0x19, 0xe3, 0x44, 0x43, 0xff, 0x38, 0xfd, 0xf5, 0xd8, 0x1e, 0xef, 0x81, 0x53, 0xeb, 0x8d, 0x2e,- 0xaf, 0xe1, 0xd1, 0x7f, 0x76, 0x5b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb4,- 0xe4, 0x8b, 0x2b, 0xaf, 0x3e, 0xe7, 0xe2, 0xda, 0x62, 0x69, 0xd5, 0x31, 0x17, 0x4a, 0x14, 0xa7, 0x43, 0xdb, 0xce, 0xc2,- 0x26, 0xe6, 0x3a, 0x8c, 0xbd, 0xce, 0xfa, 0xb5, 0xc4, 0x9e, 0x6f, 0x0f, 0x7f, 0xbe, 0xb8, 0xd6, 0xb6, 0xa4, 0x62, 0xf6,- 0xb0, 0xbc, 0xab, 0x71, 0x4f, 0x9f, 0x99, 0xbc, 0x8a, 0x5e, 0x7b, 0x4f, 0xfc, 0x75, 0x1e, 0x7b, 0xbe, 0x9e, 0x7c, 0x31,- 0x67, 0xcf, 0x70, 0xe1, 0xd1, 0xff, 0xd6, 0x68, 0x75, 0x52, 0x79, 0x33, 0xa0, 0xac, 0x5a, 0xa6, 0xe6, 0x0f, 0x3d, 0xdb,- 0x75, 0x46, 0xea, 0xaf, 0xc4, 0xd5, 0x59, 0xca, 0x3c, 0xd7, 0x79, 0x54, 0xd9, 0xc8, 0xe3, 0xaa, 0xfa, 0x9f, 0x59, 0xe3,- 0xde, 0xfb, 0xff, 0xad, 0xeb, 0x7f, 0xf6, 0xb9, 0xaf, 0xc5, 0x21, 0x6f, 0xe2, 0x3e, 0xe1, 0x23, 0xca, 0x8e, 0xd4, 0xbf,- 0xc7, 0x9d, 0x76, 0xb6, 0x18, 0x6f, 0xbd, 0x9e, 0x5b, 0x8a, 0xff, 0x51, 0xcf, 0xd5, 0xe7, 0xd3, 0xdf, 0xd0, 0xff, 0xa6,- 0xf5, 0x4f, 0x37, 0xf9, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0xf6, 0x3b, 0x55,- 0xab, 0xec, 0x0c, 0x6a, 0x8b, 0xfb, 0x02, 0xdb, 0xae, 0x6f, 0x0d, 0xcf, 0x5f, 0x96, 0xf6, 0xce, 0xec, 0xfb, 0x9d, 0xaf,- 0xde, 0x77, 0x65, 0xaf, 0xe1, 0x3a, 0xbe, 0x40, 0x3d, 0x73, 0xd6, 0xd1, 0x9e, 0xbf, 0xd2, 0x4e, 0xbb, 0xca, 0x0e, 0xd6,- 0x31, 0xeb, 0x1e, 0xd7, 0xf1, 0xff, 0x6d, 0xbd, 0x9e, 0x4f, 0xb0, 0x5e, 0x32, 0x72, 0xdd, 0x4b, 0x1d, 0x5b, 0x56, 0xe8,- 0xdb, 0xb5, 0xd6, 0xbd, 0x6a, 0x25, 0xf9, 0x02, 0xde, 0xa6, 0xbe, 0x11, 0xac, 0xf8, 0xa6, 0x29, 0xbb, 0x1d, 0xdf, 0xcb,- 0x7e, 0xcc, 0x9d, 0xbb, 0x0f, 0xce, 0xa4, 0xf1, 0xc8, 0xfb, 0x7f, 0xdd, 0xdf, 0x1d, 0x79, 0xdf, 0x58, 0x4b, 0xff, 0x33,- 0x5c, 0x43, 0xdd, 0xef, 0x63, 0x43, 0xf4, 0xaf, 0xd7, 0x39, 0xb7, 0xfe, 0xab, 0xcd, 0x0d, 0xb3, 0xbc, 0x3b, 0xba, 0xfe,- 0xd7, 0xf5, 0x7e, 0xcd, 0x68, 0xe7, 0x2c, 0xed, 0x95, 0x71, 0x67, 0x85, 0xac, 0xd1, 0x57, 0xf0, 0xbd, 0xcd, 0x68, 0x27,- 0xbe, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x46, 0xf3, 0x39, 0xcd, 0xce, 0xe1, 0xb7, 0xba,- 0x9b, 0xef, 0xd8, 0xf3, 0xf5, 0x79, 0x00, 0x95, 0x96, 0x1e, 0x9b, 0xc3, 0xaf, 0x7f, 0x75, 0xe5, 0xec, 0x19, 0xfc, 0xea,- 0xab, 0x5c, 0x57, 0x5e, 0x3f, 0x68, 0x8b, 0xff, 0x5b, 0x76, 0x71, 0x6b, 0x33, 0xc0, 0xd1, 0xb9, 0x8d, 0x7a, 0xca, 0xfa,- 0xb2, 0xa2, 0xcc, 0x70, 0x1d, 0x7a, 0x33, 0xcd, 0xa8, 0x65, 0xbd, 0x2e, 0xc0, 0xf5, 0x33, 0xe3, 0xf5, 0xdd, 0xff, 0x57,- 0x5b, 0xcd, 0x8f, 0x2e, 0xd3, 0xf5, 0x3f, 0x4b, 0xfc, 0x47, 0x39, 0xd9, 0xd6, 0x58, 0xcd, 0x5f, 0x4b, 0xff, 0x24, 0xcc,- 0xb9, 0x47, 0x97, 0x79, 0xbe, 0xaf, 0x30, 0x7f, 0x0e, 0x9b, 0xa1, 0xbf, 0x75, 0xc6, 0xff, 0x95, 0xf3, 0x57, 0x5d, 0x25,- 0x8b, 0x25, 0xd9, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xcd, 0xfb, 0x67, 0x15,- 0x3f, 0xda, 0x3a, 0xde, 0x40, 0xc5, 0xfb, 0x12, 0x7d, 0x05, 0x3d, 0x59, 0xfc, 0x4c, 0xf0, 0xb5, 0x8d, 0x76, 0x0e, 0x95,- 0xf3, 0xf8, 0xad, 0xe4, 0x0d, 0xdc, 0xef, 0xbb, 0x1c, 0xee, 0xfb, 0x8c, 0xcf, 0xe2, 0x97, 0x96, 0xd4, 0xff, 0x7c, 0x0e,- 0xb7, 0xed, 0x92, 0x7c, 0x82, 0xbe, 0x5b, 0x71, 0xfd, 0xf6, 0xfc, 0x2b, 0xdc, 0x6a, 0x76, 0xbc, 0x51, 0x65, 0x4a, 0xcd,- 0x99, 0x99, 0x36, 0xcf, 0x93, 0xc7, 0x4d, 0xf3, 0x76, 0x1d, 0xeb, 0x52, 0x9a, 0xe5, 0x7d, 0xba, 0x05, 0xfd, 0xd3, 0xf2,- 0xee, 0x36, 0xf4, 0x47, 0x7f, 0x6b, 0xf0, 0x30, 0x9f, 0x47, 0xff, 0x73, 0x3b, 0xdc, 0xe6, 0x65, 0x1b, 0x36, 0xf9, 0x1b,- 0x0a, 0x3c, 0xeb, 0x5f, 0xe3, 0xd3, 0x8a, 0xf2, 0xfd, 0x2c, 0xf4, 0xbf, 0xee, 0xe7, 0xd4, 0xf3, 0x7d, 0x36, 0x04, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xb2,- 0x0c, 0xa2, 0x3f, 0xfa, 0xdf, 0xb8, 0xfe, 0xff, 0x03 };--// Font glyphs rectangles data (on atlas)-static const Rectangle jungleFontRecs[189] = {- { 4, 4, 5 , 12 },- { 17, 4, 2 , 7 },- { 27, 4, 5 , 3 },- { 40, 4, 5 , 5 },- { 53, 4, 6 , 7 },- { 67, 4, 7 , 7 },- { 82, 4, 5 , 7 },- { 95, 4, 3 , 3 },- { 106, 4, 4 , 8 },- { 118, 4, 4 , 8 },- { 130, 4, 5 , 5 },- { 143, 4, 5 , 5 },- { 156, 4, 2 , 3 },- { 166, 4, 5 , 1 },- { 179, 4, 2 , 2 },- { 189, 4, 7 , 7 },- { 204, 4, 7 , 6 },- { 219, 4, 6 , 6 },- { 233, 4, 6 , 6 },- { 4, 24, 6 , 6 },- { 18, 24, 6 , 6 },- { 32, 24, 6 , 6 },- { 46, 24, 6 , 6 },- { 60, 24, 6 , 6 },- { 74, 24, 6 , 6 },- { 88, 24, 6 , 6 },- { 102, 24, 2 , 5 },- { 112, 24, 2 , 6 },- { 122, 24, 3 , 5 },- { 133, 24, 5 , 3 },- { 146, 24, 3 , 5 },- { 157, 24, 6 , 7 },- { 171, 24, 7 , 7 },- { 186, 24, 6 , 7 },- { 200, 24, 6 , 7 },- { 214, 24, 6 , 7 },- { 228, 24, 6 , 7 },- { 4, 44, 6 , 7 },- { 18, 44, 6 , 7 },- { 32, 44, 6 , 7 },- { 46, 44, 6 , 7 },- { 60, 44, 6 , 7 },- { 74, 44, 6 , 7 },- { 88, 44, 6 , 7 },- { 102, 44, 6 , 7 },- { 116, 44, 7 , 7 },- { 131, 44, 6 , 7 },- { 145, 44, 6 , 7 },- { 159, 44, 6 , 7 },- { 173, 44, 7 , 8 },- { 188, 44, 6 , 7 },- { 202, 44, 6 , 7 },- { 216, 44, 6 , 7 },- { 230, 44, 6 , 7 },- { 4, 64, 6 , 7 },- { 18, 64, 7 , 7 },- { 33, 64, 6 , 7 },- { 47, 64, 6 , 7 },- { 61, 64, 6 , 7 },- { 75, 64, 4 , 8 },- { 87, 64, 7 , 7 },- { 102, 64, 4 , 8 },- { 114, 64, 4 , 2 },- { 126, 64, 6 , 1 },- { 140, 64, 2 , 2 },- { 150, 64, 6 , 5 },- { 164, 64, 6 , 7 },- { 178, 64, 6 , 5 },- { 192, 64, 6 , 7 },- { 206, 64, 6 , 5 },- { 220, 64, 6 , 7 },- { 234, 64, 6 , 7 },- { 4, 84, 6 , 7 },- { 18, 84, 6 , 7 },- { 32, 84, 5 , 8 },- { 45, 84, 6 , 7 },- { 59, 84, 6 , 7 },- { 73, 84, 7 , 5 },- { 88, 84, 6 , 5 },- { 102, 84, 6 , 5 },- { 116, 84, 6 , 7 },- { 130, 84, 6 , 7 },- { 144, 84, 6 , 5 },- { 158, 84, 6 , 5 },- { 172, 84, 6 , 6 },- { 186, 84, 6 , 5 },- { 200, 84, 6 , 5 },- { 214, 84, 7 , 5 },- { 229, 84, 6 , 5 },- { 4, 104, 6 , 7 },- { 18, 104, 6 , 5 },- { 32, 104, 4 , 8 },- { 44, 104, 2 , 8 },- { 54, 104, 4 , 8 },- { 66, 104, 5 , 2 },- { 79, 104, 2 , 7 },- { 89, 104, 6 , 6 },- { 103, 104, 6 , 7 },- { 117, 104, 6 , 7 },- { 131, 104, 6 , 7 },- { 145, 104, 8 , 8 },- { 161, 104, 6 , 9 },- { 175, 104, 8 , 8 },- { 191, 104, 7 , 7 },- { 206, 104, 8 , 8 },- { 222, 104, 6 , 5 },- { 236, 104, 8 , 8 },- { 4, 124, 7 , 7 },- { 19, 124, 8 , 8 },- { 35, 124, 4 , 4 },- { 47, 124, 8 , 8 },- { 63, 124, 8 , 8 },- { 79, 124, 8 , 8 },- { 95, 124, 8 , 8 },- { 111, 124, 6 , 7 },- { 125, 124, 5 , 8 },- { 138, 124, 3 , 3 },- { 149, 124, 8 , 8 },- { 165, 124, 8 , 8 },- { 181, 124, 8 , 8 },- { 197, 124, 6 , 5 },- { 211, 124, 10 , 7 },- { 229, 124, 10 , 5 },- { 4, 144, 8 , 8 },- { 20, 144, 6 , 7 },- { 34, 144, 6 , 10 },- { 48, 144, 6 , 10 },- { 62, 144, 6 , 10 },- { 76, 144, 6 , 10 },- { 90, 144, 6 , 10 },- { 104, 144, 6 , 10 },- { 118, 144, 10 , 7 },- { 136, 144, 6 , 9 },- { 150, 144, 6 , 10 },- { 164, 144, 6 , 10 },- { 178, 144, 6 , 10 },- { 192, 144, 6 , 10 },- { 206, 144, 6 , 10 },- { 220, 144, 6 , 10 },- { 234, 144, 6 , 10 },- { 4, 164, 6 , 10 },- { 18, 164, 6 , 7 },- { 32, 164, 6 , 10 },- { 46, 164, 6 , 10 },- { 60, 164, 6 , 10 },- { 74, 164, 6 , 10 },- { 88, 164, 6 , 10 },- { 102, 164, 6 , 10 },- { 116, 164, 6 , 5 },- { 130, 164, 6 , 7 },- { 144, 164, 6 , 10 },- { 158, 164, 6 , 10 },- { 172, 164, 6 , 10 },- { 186, 164, 6 , 10 },- { 200, 164, 6 , 10 },- { 214, 164, 6 , 7 },- { 228, 164, 6 , 7 },- { 4, 184, 6 , 8 },- { 18, 184, 6 , 8 },- { 32, 184, 6 , 8 },- { 46, 184, 6 , 8 },- { 60, 184, 6 , 8 },- { 74, 184, 6 , 8 },- { 88, 184, 9 , 5 },- { 105, 184, 6 , 7 },- { 119, 184, 6 , 8 },- { 133, 184, 6 , 8 },- { 147, 184, 6 , 8 },- { 161, 184, 6 , 8 },- { 175, 184, 6 , 8 },- { 189, 184, 6 , 8 },- { 203, 184, 6 , 8 },- { 217, 184, 6 , 8 },- { 231, 184, 6 , 7 },- { 4, 204, 6 , 8 },- { 18, 204, 6 , 8 },- { 32, 204, 6 , 8 },- { 46, 204, 6 , 8 },- { 60, 204, 6 , 8 },- { 74, 204, 6 , 8 },- { 88, 204, 5 , 5 },- { 101, 204, 6 , 5 },- { 115, 204, 6 , 8 },- { 129, 204, 6 , 8 },- { 143, 204, 6 , 8 },- { 157, 204, 6 , 8 },- { 171, 204, 6 , 10 },- { 185, 204, 6 , 9 },- { 199, 204, 6 , 10 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo jungleFontGlyphs[189] = {- { 32, 0, 9, 5, { 0 }},- { 33, 0, 2, 3, { 0 }},- { 34, 0, 2, 6, { 0 }},- { 35, 0, 3, 6, { 0 }},- { 36, 0, 2, 7, { 0 }},- { 37, 0, 2, 8, { 0 }},- { 38, 0, 2, 6, { 0 }},- { 39, 0, 2, 4, { 0 }},- { 40, 0, 2, 5, { 0 }},- { 41, 0, 2, 5, { 0 }},- { 42, 0, 2, 6, { 0 }},- { 43, 0, 3, 6, { 0 }},- { 44, 0, 7, 3, { 0 }},- { 45, 0, 5, 6, { 0 }},- { 46, 0, 7, 3, { 0 }},- { 47, 0, 2, 8, { 0 }},- { 48, 0, 3, 8, { 0 }},- { 49, 0, 3, 7, { 0 }},- { 50, 0, 3, 7, { 0 }},- { 51, 0, 3, 7, { 0 }},- { 52, 0, 3, 7, { 0 }},- { 53, 0, 3, 7, { 0 }},- { 54, 0, 3, 7, { 0 }},- { 55, 0, 3, 7, { 0 }},- { 56, 0, 3, 7, { 0 }},- { 57, 0, 3, 7, { 0 }},- { 58, 0, 4, 3, { 0 }},- { 59, 0, 4, 3, { 0 }},- { 60, 0, 3, 4, { 0 }},- { 61, 0, 4, 6, { 0 }},- { 62, 0, 3, 4, { 0 }},- { 63, 0, 2, 7, { 0 }},- { 64, 0, 2, 8, { 0 }},- { 65, 0, 2, 7, { 0 }},- { 66, 0, 2, 7, { 0 }},- { 67, 0, 2, 7, { 0 }},- { 68, 0, 2, 7, { 0 }},- { 69, 0, 2, 7, { 0 }},- { 70, 0, 2, 7, { 0 }},- { 71, 0, 2, 7, { 0 }},- { 72, 0, 2, 7, { 0 }},- { 73, 0, 2, 7, { 0 }},- { 74, 0, 2, 7, { 0 }},- { 75, 0, 2, 7, { 0 }},- { 76, 0, 2, 7, { 0 }},- { 77, 0, 2, 8, { 0 }},- { 78, 0, 2, 7, { 0 }},- { 79, 0, 2, 7, { 0 }},- { 80, 0, 2, 7, { 0 }},- { 81, 0, 2, 7, { 0 }},- { 82, 0, 2, 7, { 0 }},- { 83, 0, 2, 7, { 0 }},- { 84, 0, 2, 7, { 0 }},- { 85, 0, 2, 7, { 0 }},- { 86, 0, 2, 7, { 0 }},- { 87, 0, 2, 8, { 0 }},- { 88, 0, 2, 7, { 0 }},- { 89, 0, 2, 7, { 0 }},- { 90, 0, 2, 7, { 0 }},- { 91, 0, 2, 5, { 0 }},- { 92, 0, 2, 8, { 0 }},- { 93, 0, 2, 5, { 0 }},- { 94, 0, -1, 5, { 0 }},- { 95, 0, 10, 7, { 0 }},- { 96, 0, -1, 3, { 0 }},- { 97, 0, 4, 7, { 0 }},- { 98, 0, 2, 7, { 0 }},- { 99, 0, 4, 7, { 0 }},- { 100, 0, 2, 7, { 0 }},- { 101, 0, 4, 7, { 0 }},- { 102, 0, 2, 7, { 0 }},- { 103, 0, 4, 7, { 0 }},- { 104, 0, 2, 7, { 0 }},- { 105, 0, 2, 7, { 0 }},- { 106, 0, 2, 6, { 0 }},- { 107, 0, 2, 7, { 0 }},- { 108, 0, 2, 7, { 0 }},- { 109, 0, 4, 8, { 0 }},- { 110, 0, 4, 7, { 0 }},- { 111, 0, 4, 7, { 0 }},- { 112, 0, 4, 7, { 0 }},- { 113, 0, 4, 7, { 0 }},- { 114, 0, 4, 7, { 0 }},- { 115, 0, 4, 7, { 0 }},- { 116, 0, 3, 7, { 0 }},- { 117, 0, 4, 7, { 0 }},- { 118, 0, 4, 7, { 0 }},- { 119, 0, 4, 8, { 0 }},- { 120, 0, 4, 7, { 0 }},- { 121, 0, 4, 7, { 0 }},- { 122, 0, 4, 7, { 0 }},- { 123, 0, 2, 5, { 0 }},- { 124, 0, 2, 3, { 0 }},- { 125, 0, 2, 5, { 0 }},- { 126, 0, -1, 6, { 0 }},- { 161, 0, 2, 3, { 0 }},- { 162, 0, 3, 7, { 0 }},- { 163, 0, 2, 7, { 0 }},- { 8364, 0, 2, 7, { 0 }},- { 165, 0, 2, 7, { 0 }},- { 352, 0, 1, 8, { 0 }},- { 167, 0, 1, 7, { 0 }},- { 353, 0, 1, 8, { 0 }},- { 169, 0, 2, 8, { 0 }},- { 170, 0, 1, 8, { 0 }},- { 171, 0, 3, 7, { 0 }},- { 172, 0, 1, 8, { 0 }},- { 174, 0, 2, 8, { 0 }},- { 175, 0, 1, 8, { 0 }},- { 176, 0, 1, 2, { 0 }},- { 177, 0, 1, 8, { 0 }},- { 178, 0, 1, 8, { 0 }},- { 179, 0, 1, 8, { 0 }},- { 381, 0, 1, 8, { 0 }},- { 181, 0, 4, 7, { 0 }},- { 182, 0, 1, 4, { 0 }},- { 183, 0, 4, 4, { 0 }},- { 382, 0, 1, 8, { 0 }},- { 185, 0, 1, 8, { 0 }},- { 186, 0, 1, 8, { 0 }},- { 187, 0, 3, 7, { 0 }},- { 338, 0, 2, 11, { 0 }},- { 339, 0, 4, 11, { 0 }},- { 376, 0, 1, 8, { 0 }},- { 191, 0, 2, 7, { 0 }},- { 192, 0, -1, 7, { 0 }},- { 193, 0, -1, 7, { 0 }},- { 194, 0, -1, 7, { 0 }},- { 195, 0, -1, 7, { 0 }},- { 196, 0, -1, 7, { 0 }},- { 197, 0, -1, 7, { 0 }},- { 198, 0, 2, 11, { 0 }},- { 199, 0, 2, 7, { 0 }},- { 200, 0, -1, 7, { 0 }},- { 201, 0, -1, 7, { 0 }},- { 202, 0, -1, 7, { 0 }},- { 203, 0, -1, 7, { 0 }},- { 204, 0, -1, 7, { 0 }},- { 205, 0, -1, 7, { 0 }},- { 206, 0, -1, 7, { 0 }},- { 207, 0, -1, 7, { 0 }},- { 208, 0, 2, 7, { 0 }},- { 209, 0, -1, 7, { 0 }},- { 210, 0, -1, 7, { 0 }},- { 211, 0, -1, 7, { 0 }},- { 212, 0, -1, 7, { 0 }},- { 213, 0, -1, 7, { 0 }},- { 214, 0, -1, 7, { 0 }},- { 215, 0, 3, 7, { 0 }},- { 216, 0, 2, 7, { 0 }},- { 217, 0, -1, 7, { 0 }},- { 218, 0, -1, 7, { 0 }},- { 219, 0, -1, 7, { 0 }},- { 220, 0, -1, 7, { 0 }},- { 221, 0, -1, 7, { 0 }},- { 222, 0, 2, 7, { 0 }},- { 223, 0, 2, 7, { 0 }},- { 224, 0, 1, 7, { 0 }},- { 225, 0, 1, 7, { 0 }},- { 226, 0, 1, 7, { 0 }},- { 227, 0, 1, 7, { 0 }},- { 228, 0, 1, 7, { 0 }},- { 229, 0, 1, 7, { 0 }},- { 230, 0, 4, 10, { 0 }},- { 231, 0, 4, 7, { 0 }},- { 232, 0, 1, 7, { 0 }},- { 233, 0, 1, 7, { 0 }},- { 234, 0, 1, 7, { 0 }},- { 235, 0, 1, 7, { 0 }},- { 236, 0, 1, 7, { 0 }},- { 237, 0, 1, 7, { 0 }},- { 238, 0, 1, 7, { 0 }},- { 239, 0, 1, 7, { 0 }},- { 240, 0, 2, 7, { 0 }},- { 241, 0, 1, 7, { 0 }},- { 242, 0, 1, 7, { 0 }},- { 243, 0, 1, 7, { 0 }},- { 244, 0, 1, 7, { 0 }},- { 245, 0, 1, 7, { 0 }},- { 246, 0, 1, 7, { 0 }},- { 247, 0, 3, 6, { 0 }},- { 248, 0, 4, 7, { 0 }},- { 249, 0, 1, 7, { 0 }},- { 250, 0, 1, 7, { 0 }},- { 251, 0, 1, 7, { 0 }},- { 252, 0, 1, 7, { 0 }},- { 253, 0, 1, 7, { 0 }},- { 254, 0, 2, 7, { 0 }},- { 255, 0, 1, 7, { 0 }},-};--// Style loading function: Jungle-static void GuiLoadStyleJungle(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < JUNGLE_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(jungleStyleProps[i].controlId, jungleStyleProps[i].propertyId, jungleStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int jungleFontDataSize = 0;- unsigned char *data = DecompressData(jungleFontData, JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE, &jungleFontDataSize);- Image imFont = { data, 256, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 12;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, jungleFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, jungleFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 254, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_lavanda.h
@@ -1,607 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleLavanda(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define LAVANDA_STYLE_PROPS_COUNT 16--// Custom style name: Lavanda-static const GuiStyleProp lavandaStyleProps[LAVANDA_STYLE_PROPS_COUNT] = {- { 0, 0, 0xab9bd3ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x3e4350ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xdadaf4ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xee84a0ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xf4b7c7ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xb7657bff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xd5c8dbff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0x966ec0ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0xd7ccf7ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x8fa2bdff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x6b798dff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x8292a9ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x5b5b81ff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "Cartridge.ttf" (size: 16, spacing: 1)--#define LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE 2636--// Font atlas image pixels data: DEFLATE compressed-static unsigned char lavandaFontData[LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0xdb, 0xd2, 0xa4, 0xba, 0x0d, 0x06, 0x50, 0xde, 0xff, 0xa5, 0xbf, 0x5c, 0xa4, 0x52, 0x49, 0xaa, 0x66, 0x63, 0x24,- 0x0b, 0x9a, 0xee, 0x59, 0xb3, 0xee, 0x7e, 0xa6, 0x4f, 0x06, 0xf9, 0x04, 0x96, 0x73, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7f,- 0xfc, 0x4b, 0x4e, 0xfe, 0x6f, 0x2e, 0xbf, 0xd3, 0x7f, 0xfe, 0x9e, 0xc5, 0xff, 0xf8, 0xff, 0xff, 0x75, 0xed, 0x7d, 0x73,- 0xf9, 0xf3, 0x3b, 0x47, 0xf2, 0xc7, 0xef, 0x97, 0x8d, 0xd7, 0xff, 0xd3, 0x3b, 0xd4, 0xff, 0xff, 0x7f, 0xff, 0x55, 0xca,- 0xf1, 0xfc, 0x35, 0x47, 0xf1, 0x73, 0xb2, 0xf8, 0x9c, 0xab, 0xbf, 0xb0, 0x56, 0xfa, 0xb5, 0x73, 0x9e, 0xd3, 0x2b, 0xb2,- 0xf3, 0xca, 0xf3, 0xd7, 0x1d, 0xe5, 0xb2, 0x3a, 0x96, 0x25, 0x5c, 0x3d, 0xcb, 0xef, 0x8b, 0xff, 0x5c, 0x78, 0xe5, 0xf9,- 0xf1, 0x6c, 0xd4, 0x09, 0xeb, 0x72, 0xac, 0xd6, 0x18, 0x3b, 0xa5, 0x7a, 0xf6, 0x1d, 0x2b, 0xff, 0xff, 0x5a, 0x6d, 0xbb,- 0x5f, 0x3b, 0xae, 0x4a, 0xbf, 0xfe, 0xad, 0xaf, 0x94, 0x5c, 0x06, 0xfe, 0x7f, 0x5a, 0xdf, 0x7e, 0xe2, 0xfa, 0xcf, 0xf6,- 0xb5, 0x7d, 0xa5, 0xad, 0x9c, 0xb8, 0x46, 0xab, 0xf1, 0x9f, 0x56, 0x8b, 0x90, 0x45, 0x99, 0xde, 0x1d, 0xff, 0x9d, 0x76,- 0x34, 0x37, 0x95, 0x6a, 0xb5, 0xbe, 0xad, 0x5f, 0x37, 0x29, 0xb6, 0xb4, 0xbd, 0xf8, 0x5f, 0x7f, 0x4e, 0xc6, 0xca, 0x6d,- 0xdd, 0x7b, 0xa9, 0x97, 0x76, 0xef, 0xb7, 0x75, 0x6b, 0x95, 0x34, 0x7a, 0x40, 0xfd, 0xfa, 0x7a, 0xaa, 0xc4, 0x6b, 0x51,- 0x7a, 0xa5, 0x75, 0xcb, 0x58, 0xbd, 0x9f, 0x72, 0x6b, 0x95, 0x47, 0xca, 0xf2, 0x68, 0xb7, 0x3a, 0xd5, 0x5f, 0x94, 0x72,- 0x5c, 0x56, 0xfa, 0xe5, 0xfd, 0xab, 0x30, 0xa5, 0xd1, 0x59, 0x6e, 0x6b, 0xff, 0xd7, 0xad, 0x71, 0x9a, 0x57, 0x72, 0xca,- 0x7d, 0x83, 0x94, 0x47, 0x95, 0xeb, 0x73, 0xbc, 0x1e, 0x8b, 0xcc, 0xc7, 0x7f, 0xaf, 0x1f, 0xf3, 0xa7, 0x72, 0xef, 0xf6,- 0x12, 0xe6, 0xeb, 0xc6, 0xb7, 0xc7, 0x7f, 0x1a, 0x7d, 0x8c, 0xea, 0x6b, 0x52, 0x9e, 0x7b, 0x39, 0x6f, 0x23, 0xaf, 0x5f,- 0x99, 0x19, 0xba, 0x26, 0x3b, 0xad, 0x41, 0x1a, 0xe3, 0xc5, 0xdd, 0x96, 0x7c, 0x7a, 0xce, 0xea, 0xc9, 0xf8, 0xcf, 0x85,- 0x19, 0x89, 0xd5, 0x95, 0x97, 0x65, 0x29, 0xe4, 0x86, 0xf6, 0xff, 0x0d, 0x73, 0xaa, 0x4f, 0xc5, 0x7f, 0x96, 0x73, 0x5b,- 0x13, 0xd7, 0x74, 0x46, 0xce, 0x43, 0x3e, 0x70, 0x16, 0xae, 0xc4, 0xff, 0xd1, 0x6c, 0xc9, 0x7f, 0x3b, 0xfe, 0x8f, 0x8b,- 0xbd, 0xf8, 0xa3, 0x31, 0x0b, 0xf8, 0x5b, 0xf1, 0x9f, 0x46, 0xcc, 0x64, 0x6c, 0x64, 0xde, 0xeb, 0x33, 0xcc, 0xc6, 0xff,- 0x7b, 0x6b, 0xe1, 0x55, 0xff, 0x3f, 0x17, 0xef, 0x30, 0xfd, 0x4e, 0xfc, 0x1f, 0xa3, 0xfd, 0xff, 0xf5, 0x15, 0x33, 0x31,- 0x6b, 0xf4, 0x77, 0xc4, 0x7f, 0x9a, 0xf5, 0x70, 0x06, 0x67, 0x6e, 0xbe, 0x39, 0xfe, 0x3b, 0xd1, 0x93, 0x76, 0x5d, 0x79,- 0xde, 0xba, 0xe5, 0xa4, 0xc7, 0x56, 0xad, 0x19, 0xee, 0x9e, 0xff, 0xef, 0xdf, 0xb7, 0xc9, 0xf6, 0xab, 0xf3, 0xf0, 0xf8,- 0xff, 0xb9, 0xf8, 0x3f, 0xca, 0x33, 0xd8, 0xe7, 0xf7, 0x5a, 0xea, 0xf5, 0x4f, 0x1a, 0xf7, 0xbb, 0x8f, 0x91, 0xdf, 0xf2,- 0xb6, 0xf3, 0x70, 0xed, 0x35, 0x29, 0xcf, 0x6d, 0x9c, 0xdf, 0x01, 0xfb, 0xe7, 0xd9, 0x88, 0xce, 0xbc, 0xec, 0xfb, 0xea,- 0xd8, 0xbc, 0xa6, 0x8d, 0xfd, 0x5b, 0x4a, 0x81, 0x67, 0x9e, 0x31, 0x40, 0xfc, 0x8b, 0x7f, 0x78, 0xfb, 0x73, 0xcb, 0xe2,- 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdf, 0x5a, 0xa1, 0x57, 0x5b, 0x15, 0xbe,- 0x93, 0xcb, 0xb8, 0x93, 0x9d, 0x6e, 0xbd, 0x42, 0x3d, 0xad, 0x9c, 0x04, 0xbd, 0xd7, 0xe5, 0x34, 0x0b, 0x5a, 0x46, 0xf2,- 0x13, 0x74, 0xf3, 0x4e, 0x55, 0x32, 0x08, 0x54, 0xf7, 0x32, 0xe8, 0xee, 0x1b, 0x50, 0xfb, 0x8c, 0xce, 0x6a, 0xfd, 0x0c,- 0x65, 0x41, 0xe8, 0xe4, 0x16, 0xde, 0x5b, 0x95, 0x5a, 0xcf, 0xd1, 0xb6, 0x93, 0xf5, 0x23, 0xad, 0x55, 0x73, 0x93, 0xf1,- 0x9f, 0x4b, 0xb9, 0x0e, 0x3a, 0x19, 0x6a, 0x3a, 0x59, 0x6a, 0x32, 0x9c, 0x5f, 0xe7, 0x5a, 0x94, 0x5e, 0xcb, 0x39, 0x95,- 0xe2, 0x77, 0xaa, 0xef, 0xca, 0x90, 0x46, 0xa4, 0xd5, 0xca, 0xb0, 0xb3, 0x3e, 0x72, 0xa7, 0x55, 0xd9, 0xbb, 0x7a, 0x53,- 0xca, 0x45, 0x7c, 0x77, 0xde, 0x9d, 0x94, 0xe3, 0xe7, 0xd9, 0xf8, 0x4f, 0xe3, 0x17, 0xe5, 0x52, 0xce, 0xe5, 0x6e, 0x46,- 0xb6, 0x6e, 0x26, 0xa7, 0x5e, 0x16, 0x81, 0x7e, 0xfc, 0x5f, 0x3b, 0x03, 0xbf, 0x1d, 0xff, 0x3b, 0xfb, 0xc7, 0x4c, 0xc4,- 0x7f, 0xb6, 0x3f, 0x39, 0x23, 0xe5, 0x5a, 0x79, 0x97, 0x55, 0xfc, 0x3c, 0x19, 0xff, 0xfd, 0x8c, 0x85, 0x67, 0xbf, 0x38,- 0x5b, 0xf1, 0x3f, 0xf9, 0xba, 0xa3, 0x99, 0x5f, 0x6b, 0x3f, 0xfe, 0xd3, 0xec, 0xb9, 0xce, 0xf5, 0x3d, 0xa7, 0xf2, 0x06,- 0x77, 0xae, 0xcf, 0x5c, 0xc8, 0xd7, 0xbb, 0xdb, 0x33, 0xa8, 0xe5, 0xae, 0xce, 0xb2, 0x35, 0xde, 0x8d, 0xff, 0x3c, 0xd8,- 0xff, 0xaf, 0x8c, 0xc8, 0x32, 0xde, 0xfe, 0x7f, 0x57, 0xfc, 0xdf, 0xd5, 0xff, 0xbf, 0xd2, 0x92, 0x75, 0xf7, 0xf5, 0x7a,- 0x3a, 0xfe, 0xef, 0x98, 0x97, 0xca, 0x48, 0xcb, 0xd5, 0xaf, 0x31, 0xae, 0xf6, 0xff, 0x33, 0xb4, 0x2b, 0x55, 0x6f, 0xdc,- 0x92, 0x9b, 0xdb, 0xff, 0x34, 0x46, 0x4a, 0xbb, 0xf1, 0x7f, 0x5c, 0xca, 0x83, 0x9a, 0xe6, 0xb9, 0xae, 0xd4, 0xe1, 0x3b,- 0x3b, 0xef, 0xed, 0xf4, 0xe0, 0xd3, 0xdc, 0x79, 0x2e, 0x8d, 0x91, 0xea, 0x6f, 0xc4, 0xff, 0xce, 0x2e, 0x5d, 0x4f, 0xf5,- 0xdc, 0x8f, 0x0b, 0x6d, 0xde, 0x1b, 0xe3, 0x7f, 0x7e, 0xfe, 0x6f, 0xfd, 0x1d, 0xf2, 0xf0, 0xf8, 0x3f, 0x8d, 0x28, 0x7e,- 0x5f, 0xfc, 0xd7, 0xdb, 0xa3, 0x99, 0xfd, 0x90, 0xa7, 0x6b, 0x80, 0xce, 0xee, 0x99, 0x9d, 0x9d, 0x53, 0x53, 0xda, 0x89,- 0x6c, 0xae, 0x47, 0x32, 0xd5, 0xff, 0x7f, 0x2e, 0xfe, 0xd3, 0xba, 0x0e, 0x3b, 0xdf, 0xbf, 0xbf, 0x3b, 0x40, 0xb6, 0x5a,- 0x95, 0x8c, 0xc6, 0xff, 0xc4, 0x2c, 0x5d, 0xb7, 0x4e, 0x7a, 0x7e, 0x3f, 0xf4, 0xe7, 0xee, 0x59, 0xa7, 0xb9, 0xab, 0x5b,- 0x46, 0xee, 0x8c, 0x67, 0x64, 0x2e, 0x2d, 0x5b, 0xf1, 0xbf, 0x7f, 0x2e, 0xaa, 0xfb, 0x32, 0xae, 0xfb, 0xc6, 0xf5, 0x79,- 0x91, 0x6e, 0xfc, 0xf7, 0x32, 0xd4, 0x5f, 0xfd, 0x1d, 0xff, 0x3c, 0x57, 0x72, 0x8c, 0xdf, 0x91, 0x4e, 0xab, 0xae, 0xea,- 0xf6, 0x2c, 0xd2, 0xda, 0x35, 0xff, 0x7d, 0xf1, 0xff, 0x44, 0xad, 0x31, 0x33, 0xf3, 0xd9, 0xb9, 0x17, 0x99, 0xf2, 0x35,- 0x3d, 0x3d, 0xc2, 0xfa, 0xfc, 0x19, 0xbd, 0x6f, 0x47, 0xa3, 0x37, 0x65, 0xe3, 0x9d, 0x88, 0xff, 0xa3, 0x71, 0xbf, 0x62,- 0xff, 0x4e, 0xdf, 0x77, 0x66, 0x35, 0xce, 0x8d, 0x4f, 0x25, 0xcc, 0xbd, 0xbf, 0x67, 0x10, 0x3f, 0x17, 0x75, 0x7f, 0x6b,- 0xa9, 0xfd, 0x1d, 0xf1, 0xff, 0x4c, 0x8d, 0x3d, 0x3d, 0x12, 0x81, 0x4f, 0x8e, 0xa9, 0x33, 0x32, 0x02, 0xe7, 0xb7, 0xda,- 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa9, 0xf5, 0x63, 0x33, 0xf9, 0x89, 0xd6,- 0x6b, 0x9a, 0x6b, 0x2b, 0x21, 0xd2, 0x58, 0xaf, 0xbc, 0x97, 0x47, 0xbf, 0x9a, 0xd5, 0xe5, 0x7c, 0xbd, 0x4c, 0x2e, 0xae,- 0xa1, 0x59, 0xad, 0x10, 0xc9, 0xf6, 0x5a, 0xbc, 0xee, 0xae, 0x06, 0xab, 0x4f, 0xeb, 0x64, 0x65, 0x38, 0xdf, 0x4d, 0xa0,- 0xbb, 0x0f, 0xc0, 0x59, 0x96, 0x83, 0x94, 0x3f, 0xef, 0xec, 0x95, 0x29, 0xe7, 0x0a, 0x4b, 0x61, 0xed, 0x54, 0x5a, 0x57,- 0x68, 0x27, 0xa3, 0xc3, 0xff, 0x7e, 0x5e, 0xe5, 0x6c, 0x65, 0x79, 0xa5, 0x55, 0xb2, 0xf1, 0xd5, 0xf3, 0x9d, 0xac, 0x32,- 0x10, 0xf6, 0xf3, 0xe8, 0x67, 0x70, 0x05, 0x7e, 0x86, 0xfe, 0x5a, 0x59, 0x25, 0x96, 0xad, 0x3a, 0x3e, 0x43, 0x75, 0xed,- 0x6e, 0x79, 0xa5, 0x51, 0x73, 0xa7, 0x5d, 0xe3, 0x1f, 0xad, 0x0c, 0x09, 0x19, 0xc8, 0x08, 0x90, 0x56, 0x09, 0x9d, 0xb5,- 0x42, 0x69, 0xaf, 0x42, 0xac, 0x67, 0x39, 0x4a, 0xf9, 0x3b, 0x1e, 0x8d, 0x3c, 0xa8, 0xb3, 0xd9, 0x97, 0x76, 0xf6, 0xfd,- 0x98, 0xc9, 0x98, 0x39, 0xb5, 0x86, 0xbe, 0x97, 0x9b, 0xa9, 0xfe, 0xd9, 0x9d, 0xab, 0x2a, 0x1b, 0xbd, 0xd0, 0x14, 0x7f,- 0x5d, 0x2e, 0xb7, 0x71, 0x7f, 0x6e, 0xf5, 0xea, 0x71, 0x53, 0xcf, 0xa9, 0x34, 0x95, 0x3b, 0xe9, 0xae, 0xf8, 0x3f, 0xc6,- 0xb3, 0x9c, 0xf5, 0x7a, 0x21, 0xbb, 0x3d, 0xf5, 0xbd, 0xf8, 0x5f, 0xef, 0x52, 0xb4, 0x5f, 0xe3, 0xdf, 0x19, 0xff, 0xbd,- 0x5c, 0x88, 0x59, 0xf6, 0xba, 0xbb, 0x7b, 0xaf, 0xd5, 0xfa, 0xf1, 0x69, 0x67, 0x97, 0xed, 0xe5, 0xd1, 0xc8, 0x22, 0xb7,- 0x6c, 0x6f, 0xdd, 0xfe, 0x7e, 0xff, 0x7f, 0xdd, 0x8f, 0x3f, 0xab, 0x1b, 0xef, 0xc8, 0xff, 0x77, 0x7f, 0xfc, 0xd7, 0xb2,- 0x26, 0xf7, 0xda, 0xf0, 0x6b, 0x79, 0x74, 0x27, 0xb3, 0xdf, 0x7d, 0x2a, 0xfe, 0xeb, 0xe3, 0xea, 0xe9, 0x31, 0x45, 0xe7,- 0x0c, 0xe5, 0x42, 0x2e, 0xc3, 0xb4, 0xf2, 0xa7, 0x9e, 0x8f, 0x7a, 0x67, 0xb3, 0xf0, 0xdc, 0xf9, 0x3e, 0x57, 0xc6, 0x62,- 0xcf, 0xc5, 0x7f, 0x36, 0x46, 0xe0, 0x7b, 0xed, 0x56, 0x2e, 0xb7, 0x22, 0xf7, 0xc7, 0xff, 0xdc, 0x9e, 0x95, 0xfb, 0x79,- 0xfa, 0x7a, 0x7d, 0xfc, 0x6c, 0xcc, 0x82, 0x75, 0xce, 0xe8, 0xb5, 0xb9, 0x8e, 0x3c, 0x32, 0xeb, 0x9d, 0xad, 0xb8, 0xb9,- 0x7f, 0x4e, 0xbe, 0x36, 0x1b, 0x34, 0x1f, 0xff, 0x47, 0x71, 0xfc, 0x7d, 0x5c, 0xdc, 0xab, 0x63, 0x77, 0xdc, 0x9a, 0xad,- 0xfe, 0xf8, 0xec, 0x9c, 0x55, 0xfd, 0xbb, 0x3f, 0xdf, 0xff, 0xdf, 0xcb, 0x1a, 0x9b, 0x56, 0x3f, 0x38, 0x1b, 0x75, 0x69,- 0x27, 0xf3, 0xf2, 0x4e, 0x8c, 0x4d, 0xee, 0x53, 0x36, 0xf1, 0x1d, 0xcf, 0x47, 0x11, 0xd3, 0xf1, 0x5f, 0x2f, 0x85, 0x7c,- 0xb4, 0x1f, 0xd4, 0xbf, 0x5a, 0xfb, 0x11, 0x98, 0xc1, 0xb3, 0xf8, 0xfc, 0xfc, 0x5f, 0xda, 0x75, 0x5f, 0x36, 0x33, 0x9e,- 0x57, 0xdb, 0x8e, 0x67, 0xf3, 0x09, 0xe6, 0xa5, 0xf9, 0x0b, 0xfb, 0xb9, 0xff, 0xf3, 0x48, 0xa4, 0x4d, 0xe7, 0x9c, 0xbe,- 0xbf, 0x1e, 0xd9, 0xbb, 0x77, 0x96, 0xdb, 0xcf, 0x62, 0x6e, 0x7f, 0xf7, 0x2c, 0x9f, 0x33, 0xe8, 0xde, 0xdf, 0xc8, 0xe0,- 0xfd, 0x44, 0x8e, 0xad, 0x79, 0x9a, 0x7c, 0xf8, 0x3b, 0x1e, 0xce, 0xef, 0x43, 0xf1, 0xff, 0xe9, 0x72, 0xef, 0xcf, 0xd5,- 0xc9, 0x7a, 0xfb, 0xfd, 0xf1, 0xcf, 0x3b, 0xe3, 0xff, 0x78, 0x49, 0xfc, 0xf3, 0x7c, 0x0d, 0x2e, 0xfe, 0xdf, 0x77, 0x2e,- 0x77, 0x9f, 0xff, 0x7d, 0xfb, 0xaf, 0xd3, 0x96, 0xdf, 0x55, 0xaa, 0xca, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x58, 0xaf, 0x1c, 0xca, 0x50, 0x46, 0xa0, 0xe3, 0xff, 0x72, 0x97, 0xac, 0x73, 0x4d, 0x76, 0xf2,- 0xc6, 0xf7, 0x57, 0x53, 0xa5, 0x7d, 0x6c, 0x27, 0x17, 0x4b, 0x2e, 0xad, 0x00, 0xc9, 0xc8, 0x7e, 0x09, 0xfd, 0x52, 0x4a,- 0x29, 0x9b, 0x68, 0x25, 0x7f, 0x5b, 0x1a, 0x2b, 0x83, 0x7b, 0x59, 0x9f, 0x3e, 0x75, 0x9e, 0x57, 0x19, 0x57, 0xfa, 0xbf,- 0x26, 0x37, 0xac, 0x1e, 0xbc, 0xfa, 0x3d, 0x7a, 0x59, 0x58, 0x73, 0x69, 0xa5, 0x5b, 0xda, 0xb9, 0x5c, 0xfb, 0xeb, 0x29,- 0xd3, 0x5c, 0x4f, 0x99, 0xed, 0xd2, 0x5e, 0x45, 0x63, 0x2f, 0x5f, 0x6a, 0xb7, 0x8e, 0xdc, 0xcf, 0xf0, 0x9d, 0xed, 0x77,- 0xbe, 0xb2, 0x47, 0x41, 0xbe, 0xe8, 0x3c, 0x77, 0xeb, 0x86, 0xfe, 0xef, 0xcc, 0xed, 0xb1, 0xb3, 0x9b, 0xf9, 0xef, 0xca,- 0x55, 0xdf, 0xdb, 0x87, 0xe6, 0x8d, 0xab, 0x38, 0x77, 0xea, 0xf0, 0x6e, 0x1e, 0xb3, 0x6f, 0x58, 0xdf, 0x9b, 0x8f, 0xfe,- 0xae, 0xe7, 0xce, 0xf3, 0x3a, 0xcf, 0xe1, 0x1b, 0x7e, 0x6b, 0x25, 0xc3, 0x6b, 0xa7, 0xfd, 0xcf, 0xa5, 0xf2, 0xba, 0x92,- 0xdd, 0xb4, 0xb7, 0xeb, 0xd5, 0x67, 0x8e, 0x1e, 0x9b, 0xd9, 0xb6, 0x3a, 0xd9, 0xae, 0xcf, 0x77, 0xac, 0xaa, 0x1f, 0xd9,- 0x6d, 0xff, 0xbb, 0x7f, 0xed, 0xec, 0x43, 0xf4, 0x89, 0xf3, 0xdc, 0xdb, 0x1d, 0x2d, 0x8b, 0x51, 0xf7, 0x95, 0x32, 0xae,- 0x1d, 0xdb, 0xed, 0x25, 0xef, 0x8d, 0xff, 0xab, 0xed, 0xff, 0x51, 0xbe, 0xea, 0x77, 0x7a, 0xda, 0x6f, 0x3b, 0xba, 0x93,- 0x71, 0xf3, 0xa9, 0x23, 0x77, 0xc4, 0x7f, 0x4e, 0xb3, 0xf1, 0xe7, 0xd2, 0x2c, 0xc3, 0x4e, 0x66, 0xe7, 0xfa, 0xd1, 0x5c,- 0x2a, 0x8f, 0xf3, 0x36, 0xf4, 0xfb, 0xe2, 0x7f, 0xef, 0xbd, 0xd7, 0xf1, 0x5d, 0xcf, 0x50, 0x7b, 0xb4, 0xe7, 0xe1, 0xee,- 0x8b, 0xe1, 0xa3, 0xfd, 0xad, 0xf2, 0x9a, 0x28, 0xaf, 0xe5, 0x04, 0xbd, 0xbb, 0xfd, 0xbf, 0x96, 0xdd, 0xfc, 0x3d, 0x47,- 0xaf, 0xb5, 0x49, 0xef, 0x88, 0xff, 0xdc, 0x3a, 0x26, 0x4c, 0x69, 0xa6, 0xf5, 0x28, 0xee, 0x7d, 0x94, 0xd7, 0xb5, 0x0b,- 0xeb, 0x3d, 0x35, 0xae, 0xb4, 0x29, 0xb3, 0x11, 0xdb, 0x3b, 0xf2, 0xa6, 0xfe, 0xff, 0x2f, 0xc5, 0xff, 0x1d, 0x31, 0xfe,- 0x4c, 0xfc, 0xef, 0xf5, 0x00, 0xfa, 0xfb, 0x2d, 0x75, 0x6a, 0x86, 0x9d, 0xbd, 0x6d, 0x76, 0x8f, 0x76, 0x6b, 0x87, 0xfc,- 0xa1, 0x36, 0xec, 0xcd, 0xb4, 0x7e, 0x5b, 0xff, 0xff, 0xfc, 0xfe, 0x4f, 0xda, 0xf3, 0xcb, 0xef, 0x8b, 0xff, 0x7e, 0x0b,- 0x70, 0x4f, 0xfc, 0xe7, 0xc1, 0x79, 0xd2, 0xb4, 0x67, 0x3d, 0xd3, 0xb8, 0x6f, 0xfc, 0xc6, 0x71, 0x61, 0xe5, 0xec, 0x77,- 0xf6, 0xd0, 0xfc, 0xee, 0xf8, 0x5f, 0xcf, 0x2f, 0xfd, 0x4a, 0xff, 0x3f, 0x1b, 0xb3, 0xa0, 0xd3, 0xf1, 0xff, 0x3d, 0xf9,- 0x46, 0x33, 0x36, 0xee, 0xf8, 0xbe, 0x56, 0xa3, 0x1b, 0x57, 0x3b, 0xa3, 0x89, 0xeb, 0x73, 0xae, 0xcf, 0xec, 0x76, 0x92,- 0x57, 0x9d, 0xab, 0x3b, 0xee, 0x58, 0x7e, 0x66, 0xfe, 0xef, 0x5b, 0x22, 0x5f, 0xfc, 0xaf, 0xe6, 0xd0, 0xcf, 0xc7, 0xcf,- 0xb5, 0x23, 0x95, 0xe7, 0x0c, 0x3f, 0x17, 0xff, 0x9f, 0x9b, 0xe7, 0xb9, 0x67, 0x37, 0x93, 0xce, 0x33, 0x36, 0xc7, 0x2d,- 0xcf, 0xce, 0xbd, 0xef, 0x59, 0x8b, 0xe3, 0x0b, 0xe2, 0x7f, 0x66, 0x36, 0xb4, 0x53, 0x12, 0x59, 0xec, 0x8b, 0x9c, 0xe2,- 0x33, 0xd7, 0x77, 0xf5, 0xff, 0x67, 0x5b, 0xc5, 0x4f, 0x3e, 0xe7, 0xf1, 0xfc, 0x95, 0xde, 0x3d, 0x06, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf6, 0xda, 0xba, 0x7a, 0xd6, 0xbd, 0x34, 0xd7, 0xef, 0xf6, 0xd7,- 0xa9, 0xd6, 0x77, 0x0d, 0xb8, 0xf2, 0x9e, 0x29, 0xaf, 0xbf, 0xa9, 0x7d, 0x52, 0xe5, 0x5b, 0xdf, 0x93, 0x75, 0xff, 0x58,- 0xe4, 0x18, 0xc8, 0xc8, 0x35, 0x91, 0x72, 0x4e, 0x87, 0xa3, 0x99, 0x95, 0x28, 0xe5, 0xab, 0x2e, 0x8d, 0xbf, 0xa7, 0xbc,- 0x32, 0xf3, 0x68, 0x7c, 0xef, 0x37, 0xaf, 0xb9, 0xef, 0x66, 0xf2, 0xec, 0xef, 0x50, 0x31, 0xbd, 0xea, 0x31, 0xcd, 0x3c,- 0xdc, 0x19, 0x5b, 0xef, 0x9a, 0x8d, 0x15, 0xcd, 0x9d, 0x48, 0xaf, 0xd4, 0xd7, 0x69, 0xc7, 0x46, 0xad, 0x3e, 0xcb, 0xe8,- 0x75, 0x3a, 0xb7, 0x43, 0x4c, 0x46, 0x33, 0x69, 0xbe, 0x79, 0x5d, 0x5e, 0x9a, 0xd9, 0x35, 0xf2, 0x05, 0xeb, 0x90, 0xb3,- 0xb1, 0x5b, 0x4a, 0x1a, 0x3b, 0x9d, 0x7c, 0x66, 0xa5, 0xf3, 0xde, 0x95, 0xf9, 0xce, 0x55, 0xa3, 0xd5, 0x7c, 0x6e, 0x4f,- 0x5d, 0x75, 0xbd, 0x9c, 0x1f, 0x19, 0x7f, 0xc7, 0x67, 0xe2, 0xbf, 0x93, 0x77, 0x37, 0xcb, 0x3e, 0xe5, 0xb3, 0xab, 0x9e,- 0xbb, 0xd9, 0xc6, 0xd2, 0xda, 0x6d, 0x60, 0xff, 0xef, 0x9f, 0xc8, 0xba, 0x73, 0x6f, 0xfb, 0x3f, 0xdf, 0xc7, 0xae, 0x66,- 0x38, 0xe8, 0x5d, 0xdd, 0xdd, 0x9d, 0x2e, 0xf2, 0x33, 0xf1, 0xbf, 0xce, 0xba, 0x98, 0x91, 0xd9, 0x84, 0x4f, 0x1c, 0x4b,- 0x73, 0xd7, 0xa7, 0x0c, 0x8d, 0x17, 0xd6, 0xb9, 0x2e, 0x9f, 0x88, 0xff, 0x9c, 0xf4, 0xce, 0xd3, 0xd8, 0xd9, 0x62, 0xea,- 0xef, 0x93, 0xb3, 0x15, 0xfd, 0x5d, 0x6b, 0xe6, 0xe2, 0x3f, 0xc3, 0x3b, 0xb0, 0xbd, 0x3d, 0xfe, 0xa7, 0x67, 0x00, 0xfa,- 0x31, 0x9e, 0xf6, 0x68, 0x6d, 0x62, 0x94, 0xdb, 0xf9, 0xfb, 0x73, 0x59, 0xf7, 0xcf, 0xf2, 0x2a, 0xa7, 0x75, 0x45, 0x64,- 0x60, 0x1e, 0x25, 0xed, 0x1e, 0xf6, 0xfd, 0xf1, 0xbf, 0xb3, 0xe7, 0x4f, 0xbe, 0x2e, 0xfe, 0x57, 0x35, 0x5a, 0x3d, 0xbf,- 0x6d, 0x5a, 0xb1, 0xda, 0x3b, 0x96, 0x8d, 0xd9, 0x9f, 0x2c, 0xb3, 0xe6, 0xdf, 0xd3, 0xfb, 0xaf, 0x7d, 0xdb, 0x99, 0xf8,- 0x9f, 0x89, 0xce, 0x4f, 0xc6, 0x7f, 0x36, 0xf6, 0x8e, 0x99, 0x6c, 0xdd, 0xd2, 0xcc, 0x14, 0x9a, 0x97, 0xce, 0xff, 0x75,- 0x46, 0x34, 0xf3, 0x7b, 0x75, 0xdc, 0x71, 0x6c, 0x6f, 0xe6, 0x2b, 0x37, 0x8e, 0x7d, 0x8f, 0x0f, 0xb4, 0xff, 0x13, 0x35,- 0xc3, 0x67, 0xdb, 0xff, 0x63, 0xf4, 0x7a, 0x5c, 0xff, 0xfa, 0x3c, 0xd0, 0xa3, 0x7c, 0x4b, 0xfc, 0xe7, 0x4b, 0xe3, 0xff,- 0xb8, 0xb0, 0xa3, 0xdc, 0x5b, 0x6b, 0x80, 0x3c, 0x3a, 0xfe, 0x7f, 0x57, 0xfc, 0xcf, 0xde, 0x01, 0xc9, 0xf2, 0x1e, 0x67,- 0x2d, 0xca, 0xd3, 0xb8, 0xd3, 0x98, 0xe2, 0x6e, 0x6a, 0xef, 0x79, 0xfe, 0x27, 0xcd, 0xd1, 0x49, 0x35, 0x1e, 0xef, 0x39,- 0x76, 0xcf, 0xac, 0x6b, 0xca, 0x73, 0x8a, 0x19, 0xb9, 0xce, 0x9f, 0xcc, 0xba, 0xbb, 0x1a, 0xc5, 0x3d, 0xff, 0xeb, 0x77,- 0xef, 0xa7, 0x66, 0xe8, 0xc8, 0xe4, 0xb3, 0x44, 0x6f, 0x79, 0x3a, 0x60, 0xfa, 0x1e, 0xda, 0x37, 0xe4, 0x21, 0xce, 0xcf,- 0x67, 0x4c, 0xbf, 0xef, 0xa9, 0x01, 0xee, 0xed, 0xe9, 0x7d, 0xcf, 0xb3, 0xc1, 0x88, 0x7e, 0xd6, 0xcf, 0xa8, 0xfc, 0xe6,- 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0xa6, 0xfd, 0xfb, 0x9f, 0x72, 0x00, 0xf1, 0x0f, 0xfc, 0x75, 0xf1, 0xff, 0x2f };--// Font glyphs rectangles data (on atlas)-static const Rectangle lavandaFontRecs[189] = {- { 4, 4, 5 , 16 },- { 17, 4, 1 , 9 },- { 26, 4, 3 , 3 },- { 37, 4, 7 , 8 },- { 52, 4, 5 , 11 },- { 65, 4, 10 , 8 },- { 83, 4, 7 , 9 },- { 98, 4, 1 , 3 },- { 107, 4, 3 , 12 },- { 118, 4, 3 , 12 },- { 129, 4, 5 , 4 },- { 142, 4, 5 , 5 },- { 155, 4, 2 , 3 },- { 165, 4, 3 , 1 },- { 176, 4, 1 , 1 },- { 185, 4, 4 , 12 },- { 197, 4, 5 , 9 },- { 210, 4, 3 , 9 },- { 221, 4, 5 , 9 },- { 234, 4, 5 , 9 },- { 247, 4, 5 , 9 },- { 260, 4, 5 , 9 },- { 273, 4, 5 , 9 },- { 286, 4, 5 , 9 },- { 299, 4, 5 , 9 },- { 312, 4, 5 , 9 },- { 325, 4, 1 , 4 },- { 334, 4, 2 , 6 },- { 344, 4, 4 , 5 },- { 356, 4, 4 , 3 },- { 368, 4, 4 , 5 },- { 380, 4, 5 , 9 },- { 393, 4, 7 , 10 },- { 408, 4, 7 , 9 },- { 423, 4, 6 , 9 },- { 437, 4, 5 , 9 },- { 450, 4, 6 , 9 },- { 464, 4, 5 , 9 },- { 477, 4, 5 , 9 },- { 490, 4, 6 , 9 },- { 4, 28, 5 , 10 },- { 17, 28, 1 , 9 },- { 26, 28, 6 , 9 },- { 40, 28, 6 , 9 },- { 54, 28, 5 , 9 },- { 67, 28, 8 , 11 },- { 83, 28, 6 , 10 },- { 97, 28, 7 , 9 },- { 112, 28, 5 , 9 },- { 125, 28, 7 , 11 },- { 140, 28, 5 , 9 },- { 153, 28, 6 , 9 },- { 167, 28, 7 , 9 },- { 182, 28, 6 , 9 },- { 196, 28, 6 , 10 },- { 210, 28, 9 , 10 },- { 227, 28, 6 , 11 },- { 241, 28, 5 , 10 },- { 254, 28, 5 , 9 },- { 267, 28, 3 , 12 },- { 278, 28, 4 , 12 },- { 290, 28, 3 , 12 },- { 301, 28, 5 , 4 },- { 314, 28, 6 , 1 },- { 328, 28, 3 , 3 },- { 339, 28, 6 , 7 },- { 353, 28, 5 , 9 },- { 366, 28, 4 , 7 },- { 378, 28, 5 , 10 },- { 391, 28, 4 , 7 },- { 403, 28, 3 , 10 },- { 414, 28, 4 , 11 },- { 426, 28, 5 , 11 },- { 439, 28, 1 , 9 },- { 448, 28, 5 , 12 },- { 461, 28, 5 , 9 },- { 474, 28, 1 , 9 },- { 483, 28, 8 , 9 },- { 4, 52, 5 , 9 },- { 17, 52, 4 , 7 },- { 29, 52, 5 , 10 },- { 42, 52, 5 , 10 },- { 55, 52, 5 , 7 },- { 68, 52, 5 , 7 },- { 81, 52, 3 , 9 },- { 92, 52, 5 , 7 },- { 105, 52, 5 , 8 },- { 118, 52, 9 , 8 },- { 135, 52, 5 , 9 },- { 148, 52, 6 , 9 },- { 162, 52, 4 , 7 },- { 174, 52, 5 , 12 },- { 187, 52, 1 , 12 },- { 196, 52, 5 , 12 },- { 209, 52, 6 , 2 },- { 223, 52, 1 , 9 },- { 232, 52, 5 , 10 },- { 245, 52, 6 , 9 },- { 259, 52, 7 , 9 },- { 274, 52, 5 , 9 },- { 287, 52, 6 , 12 },- { 301, 52, 5 , 10 },- { 314, 52, 5 , 10 },- { 327, 52, 8 , 8 },- { 343, 52, 4 , 7 },- { 355, 52, 6 , 5 },- { 369, 52, 6 , 3 },- { 383, 52, 8 , 8 },- { 399, 52, 5 , 1 },- { 412, 52, 4 , 4 },- { 424, 52, 5 , 7 },- { 437, 52, 3 , 4 },- { 448, 52, 3 , 4 },- { 459, 52, 5 , 12 },- { 472, 52, 5 , 10 },- { 485, 52, 7 , 11 },- { 500, 52, 1 , 1 },- { 4, 76, 4 , 10 },- { 16, 76, 2 , 4 },- { 26, 76, 4 , 7 },- { 38, 76, 6 , 5 },- { 52, 76, 11 , 9 },- { 71, 76, 7 , 7 },- { 86, 76, 5 , 12 },- { 99, 76, 5 , 9 },- { 112, 76, 7 , 12 },- { 127, 76, 7 , 12 },- { 142, 76, 7 , 12 },- { 157, 76, 7 , 12 },- { 172, 76, 7 , 11 },- { 187, 76, 7 , 12 },- { 202, 76, 10 , 9 },- { 220, 76, 5 , 12 },- { 233, 76, 5 , 12 },- { 246, 76, 5 , 12 },- { 259, 76, 5 , 12 },- { 272, 76, 5 , 11 },- { 285, 76, 2 , 12 },- { 295, 76, 2 , 12 },- { 305, 76, 3 , 12 },- { 316, 76, 3 , 11 },- { 327, 76, 7 , 9 },- { 342, 76, 6 , 12 },- { 356, 76, 7 , 12 },- { 371, 76, 7 , 12 },- { 386, 76, 7 , 12 },- { 401, 76, 7 , 12 },- { 416, 76, 7 , 11 },- { 431, 76, 5 , 5 },- { 444, 76, 7 , 9 },- { 459, 76, 6 , 12 },- { 473, 76, 6 , 12 },- { 487, 76, 6 , 12 },- { 4, 100, 6 , 11 },- { 18, 100, 5 , 13 },- { 31, 100, 5 , 9 },- { 44, 100, 5 , 11 },- { 57, 100, 6 , 10 },- { 71, 100, 6 , 10 },- { 85, 100, 6 , 10 },- { 99, 100, 6 , 10 },- { 113, 100, 6 , 9 },- { 127, 100, 6 , 11 },- { 141, 100, 7 , 7 },- { 156, 100, 4 , 10 },- { 168, 100, 4 , 10 },- { 180, 100, 4 , 10 },- { 192, 100, 4 , 10 },- { 204, 100, 4 , 9 },- { 216, 100, 2 , 10 },- { 226, 100, 2 , 10 },- { 236, 100, 3 , 10 },- { 247, 100, 3 , 9 },- { 258, 100, 5 , 9 },- { 271, 100, 5 , 12 },- { 284, 100, 4 , 10 },- { 296, 100, 4 , 10 },- { 308, 100, 4 , 10 },- { 320, 100, 5 , 10 },- { 333, 100, 4 , 9 },- { 345, 100, 5 , 5 },- { 358, 100, 6 , 7 },- { 372, 100, 5 , 10 },- { 385, 100, 5 , 10 },- { 398, 100, 5 , 10 },- { 411, 100, 5 , 9 },- { 424, 100, 6 , 12 },- { 438, 100, 5 , 12 },- { 451, 100, 6 , 11 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo lavandaFontGlyphs[189] = {- { 32, 0, 12, 5, { 0 }},- { 33, 0, 3, 2, { 0 }},- { 34, 0, 3, 4, { 0 }},- { 35, 0, 3, 8, { 0 }},- { 36, 0, 2, 6, { 0 }},- { 37, 0, 4, 11, { 0 }},- { 38, 0, 3, 8, { 0 }},- { 39, 0, 3, 2, { 0 }},- { 40, 0, 2, 4, { 0 }},- { 41, 0, 2, 4, { 0 }},- { 42, 0, 3, 6, { 0 }},- { 43, 0, 5, 6, { 0 }},- { 44, 0, 10, 3, { 0 }},- { 45, 0, 7, 4, { 0 }},- { 46, 0, 11, 2, { 0 }},- { 47, 0, 2, 5, { 0 }},- { 48, 0, 3, 6, { 0 }},- { 49, 0, 3, 4, { 0 }},- { 50, 0, 3, 6, { 0 }},- { 51, 0, 3, 6, { 0 }},- { 52, 0, 3, 6, { 0 }},- { 53, 0, 3, 6, { 0 }},- { 54, 0, 3, 6, { 0 }},- { 55, 0, 3, 6, { 0 }},- { 56, 0, 3, 6, { 0 }},- { 57, 0, 3, 6, { 0 }},- { 58, 0, 7, 2, { 0 }},- { 59, 0, 7, 3, { 0 }},- { 60, 0, 5, 5, { 0 }},- { 61, 0, 6, 5, { 0 }},- { 62, 0, 5, 5, { 0 }},- { 63, 0, 3, 6, { 0 }},- { 64, 0, 4, 8, { 0 }},- { 65, 0, 3, 8, { 0 }},- { 66, 0, 3, 7, { 0 }},- { 67, 0, 3, 6, { 0 }},- { 68, 0, 3, 7, { 0 }},- { 69, 0, 3, 6, { 0 }},- { 70, 0, 3, 6, { 0 }},- { 71, 0, 3, 7, { 0 }},- { 72, 0, 2, 6, { 0 }},- { 73, 0, 3, 2, { 0 }},- { 74, 0, 3, 7, { 0 }},- { 75, 0, 3, 7, { 0 }},- { 76, 0, 3, 6, { 0 }},- { 77, 0, 3, 9, { 0 }},- { 78, 0, 2, 7, { 0 }},- { 79, 0, 3, 8, { 0 }},- { 80, 0, 3, 6, { 0 }},- { 81, 0, 3, 8, { 0 }},- { 82, 0, 3, 6, { 0 }},- { 83, 0, 3, 7, { 0 }},- { 84, 0, 3, 8, { 0 }},- { 85, 0, 3, 7, { 0 }},- { 86, 0, 2, 7, { 0 }},- { 87, 0, 2, 10, { 0 }},- { 88, 0, 3, 7, { 0 }},- { 89, 0, 3, 6, { 0 }},- { 90, 0, 3, 6, { 0 }},- { 91, 0, 2, 4, { 0 }},- { 92, 0, 2, 5, { 0 }},- { 93, 0, 2, 4, { 0 }},- { 94, 0, 3, 6, { 0 }},- { 95, 0, 13, 7, { 0 }},- { 96, 0, 3, 4, { 0 }},- { 97, 0, 5, 7, { 0 }},- { 98, 0, 3, 6, { 0 }},- { 99, 0, 5, 5, { 0 }},- { 100, 0, 2, 6, { 0 }},- { 101, 0, 5, 5, { 0 }},- { 102, 0, 2, 4, { 0 }},- { 103, 0, 4, 5, { 0 }},- { 104, 0, 3, 6, { 0 }},- { 105, 0, 3, 2, { 0 }},- { 106, -1, 3, 5, { 0 }},- { 107, 0, 3, 6, { 0 }},- { 108, 0, 3, 2, { 0 }},- { 109, 0, 5, 9, { 0 }},- { 110, 0, 5, 6, { 0 }},- { 111, 0, 5, 5, { 0 }},- { 112, 0, 5, 6, { 0 }},- { 113, 0, 5, 6, { 0 }},- { 114, 0, 5, 6, { 0 }},- { 115, 0, 5, 6, { 0 }},- { 116, 0, 3, 4, { 0 }},- { 117, 0, 5, 6, { 0 }},- { 118, 0, 4, 6, { 0 }},- { 119, 0, 4, 10, { 0 }},- { 120, 0, 5, 6, { 0 }},- { 121, -1, 5, 6, { 0 }},- { 122, 0, 5, 5, { 0 }},- { 123, 0, 2, 6, { 0 }},- { 124, 0, 2, 2, { 0 }},- { 125, 0, 2, 6, { 0 }},- { 126, 0, 7, 7, { 0 }},- { 161, 0, 5, 2, { 0 }},- { 162, 0, 4, 6, { 0 }},- { 163, 0, 3, 7, { 0 }},- { 8364, 0, 3, 8, { 0 }},- { 165, 0, 3, 6, { 0 }},- { 352, 0, 0, 7, { 0 }},- { 167, 0, 3, 6, { 0 }},- { 353, 0, 2, 6, { 0 }},- { 169, 0, 4, 9, { 0 }},- { 170, 0, 3, 5, { 0 }},- { 171, 0, 6, 7, { 0 }},- { 172, 0, 6, 7, { 0 }},- { 174, 0, 4, 9, { 0 }},- { 175, 0, 2, 6, { 0 }},- { 176, 0, 3, 5, { 0 }},- { 177, 0, 5, 6, { 0 }},- { 178, 0, 3, 4, { 0 }},- { 179, 0, 3, 4, { 0 }},- { 381, 0, 0, 6, { 0 }},- { 181, 0, 5, 6, { 0 }},- { 182, 0, 3, 8, { 0 }},- { 183, 0, 7, 2, { 0 }},- { 382, 0, 2, 5, { 0 }},- { 185, 0, 3, 3, { 0 }},- { 186, 0, 3, 5, { 0 }},- { 187, 0, 6, 7, { 0 }},- { 338, 0, 3, 12, { 0 }},- { 339, 0, 5, 8, { 0 }},- { 376, 0, 1, 6, { 0 }},- { 191, 0, 5, 6, { 0 }},- { 192, 0, 0, 8, { 0 }},- { 193, 0, 0, 8, { 0 }},- { 194, 0, 0, 8, { 0 }},- { 195, 0, 0, 8, { 0 }},- { 196, 0, 1, 8, { 0 }},- { 197, 0, 0, 8, { 0 }},- { 198, 0, 3, 11, { 0 }},- { 199, 0, 3, 6, { 0 }},- { 200, 0, 0, 6, { 0 }},- { 201, 0, 0, 6, { 0 }},- { 202, 0, 0, 6, { 0 }},- { 203, 0, 1, 6, { 0 }},- { 204, -1, 0, 2, { 0 }},- { 205, 0, 0, 3, { 0 }},- { 206, -1, 0, 3, { 0 }},- { 207, -1, 1, 3, { 0 }},- { 208, -1, 3, 7, { 0 }},- { 209, 0, 0, 7, { 0 }},- { 210, 0, 0, 8, { 0 }},- { 211, 0, 0, 8, { 0 }},- { 212, 0, 0, 8, { 0 }},- { 213, 0, 0, 8, { 0 }},- { 214, 0, 1, 8, { 0 }},- { 215, 0, 5, 6, { 0 }},- { 216, 0, 3, 8, { 0 }},- { 217, 0, 0, 7, { 0 }},- { 218, 0, 0, 7, { 0 }},- { 219, 0, 0, 7, { 0 }},- { 220, 0, 1, 7, { 0 }},- { 221, 0, 0, 6, { 0 }},- { 222, 0, 3, 6, { 0 }},- { 223, 0, 3, 6, { 0 }},- { 224, 0, 2, 7, { 0 }},- { 225, 0, 2, 7, { 0 }},- { 226, 0, 2, 7, { 0 }},- { 227, 0, 2, 7, { 0 }},- { 228, 0, 3, 7, { 0 }},- { 229, 0, 1, 7, { 0 }},- { 230, 0, 5, 8, { 0 }},- { 231, 0, 5, 5, { 0 }},- { 232, 0, 2, 5, { 0 }},- { 233, 0, 2, 5, { 0 }},- { 234, 0, 2, 5, { 0 }},- { 235, 0, 3, 5, { 0 }},- { 236, -1, 2, 2, { 0 }},- { 237, 0, 2, 3, { 0 }},- { 238, -1, 2, 3, { 0 }},- { 239, -1, 3, 3, { 0 }},- { 240, 0, 3, 6, { 0 }},- { 241, 0, 2, 6, { 0 }},- { 242, 0, 2, 5, { 0 }},- { 243, 0, 2, 5, { 0 }},- { 244, 0, 2, 5, { 0 }},- { 245, 0, 2, 6, { 0 }},- { 246, 0, 3, 5, { 0 }},- { 247, 0, 5, 6, { 0 }},- { 248, -1, 5, 6, { 0 }},- { 249, 0, 2, 6, { 0 }},- { 250, 0, 2, 6, { 0 }},- { 251, 0, 2, 6, { 0 }},- { 252, 0, 3, 6, { 0 }},- { 253, -1, 2, 6, { 0 }},- { 254, 0, 3, 6, { 0 }},- { 255, -1, 3, 6, { 0 }},-};--// Style loading function: Lavanda-static void GuiLoadStyleLavanda(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < LAVANDA_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(lavandaStyleProps[i].controlId, lavandaStyleProps[i].propertyId, lavandaStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int lavandaFontDataSize = 0;- unsigned char *data = DecompressData(lavandaFontData, LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE, &lavandaFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, lavandaFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, lavandaFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_sunny.h
@@ -1,616 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleSunny(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define SUNNY_STYLE_PROPS_COUNT 33--// Custom style name: Sunny-static const GuiStyleProp sunnyStyleProps[SUNNY_STYLE_PROPS_COUNT] = {- { 0, 0, 0x9c760aff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x594006ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0xf6d519ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xf6ee89ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0xf5f3d1ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xf4cd19ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0xf7e580ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0xf7f2c1ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x52470aff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0xc0be92ff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0xd3d3a1ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0xbcbc89ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0x725706ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0xf0be4bff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING - { 1, 2, 0x504506ff }, // LABEL_TEXT_COLOR_NORMAL - { 1, 5, 0xfdeb9bff }, // LABEL_TEXT_COLOR_FOCUSED - { 1, 8, 0xf5e8a4ff }, // LABEL_TEXT_COLOR_PRESSED - { 2, 2, 0xebc21fff }, // BUTTON_TEXT_COLOR_NORMAL - { 3, 2, 0xebc21fff }, // TOGGLE_TEXT_COLOR_NORMAL - { 4, 2, 0x81700fff }, // SLIDER_TEXT_COLOR_NORMAL - { 4, 5, 0xf4e49aff }, // SLIDER_TEXT_COLOR_FOCUSED - { 7, 2, 0xebc21fff }, // COMBOBOX_TEXT_COLOR_NORMAL - { 8, 2, 0xefd87bff }, // DROPDOWNBOX_TEXT_COLOR_NORMAL - { 8, 5, 0xd4b219ff }, // DROPDOWNBOX_TEXT_COLOR_FOCUSED - { 9, 2, 0x7a680bff }, // TEXTBOX_TEXT_COLOR_NORMAL - { 9, 5, 0xad931fff }, // TEXTBOX_TEXT_COLOR_FOCUSED - { 10, 2, 0x62570eff }, // VALUEBOX_TEXT_COLOR_NORMAL - { 10, 5, 0xf2df88ff }, // VALUEBOX_TEXT_COLOR_FOCUSED - { 12, 2, 0xf4e798ff }, // LISTVIEW_TEXT_COLOR_NORMAL - { 15, 2, 0xebc21fff }, // STATUSBAR_TEXT_COLOR_NORMAL -};--// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)--#define SUNNY_STYLE_FONT_ATLAS_COMP_SIZE 2462--// Font atlas image pixels data: DEFLATE compressed-static unsigned char sunnyFontData[SUNNY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,- 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,- 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,- 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,- 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,- 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,- 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,- 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,- 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,- 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,- 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,- 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,- 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,- 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,- 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,- 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,- 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,- 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,- 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,- 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,- 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,- 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,- 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,- 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,- 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,- 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,- 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,- 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,- 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,- 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,- 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,- 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,- 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,- 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,- 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,- 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,- 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,- 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,- 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,- 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,- 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,- 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,- 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,- 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,- 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,- 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,- 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,- 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,- 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,- 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,- 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,- 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,- 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,- 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,- 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,- 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,- 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,- 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,- 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,- 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,- 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,- 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,- 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,- 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,- 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,- 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,- 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,- 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,- 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,- 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,- 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,- 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,- 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,- 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,- 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,- 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,- 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,- 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,- 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,- 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,- 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,- 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,- 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,- 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,- 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,- 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,- 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,- 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,- 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,- 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,- 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,- 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,- 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,- 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,- 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,- 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,- 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,- 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,- 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,- 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,- 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,- 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,- 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,- 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,- 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,- 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,- 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,- 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,- 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,- 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,- 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,- 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,- 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,- 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,- 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,- 0x0f };--// Font glyphs rectangles data (on atlas)-static const Rectangle sunnyFontRecs[189] = {- { 4, 4, 4 , 16 },- { 16, 4, 2 , 10 },- { 26, 4, 5 , 3 },- { 39, 4, 7 , 10 },- { 54, 4, 7 , 13 },- { 69, 4, 7 , 10 },- { 84, 4, 7 , 10 },- { 99, 4, 2 , 3 },- { 109, 4, 3 , 12 },- { 120, 4, 3 , 12 },- { 131, 4, 5 , 6 },- { 144, 4, 6 , 5 },- { 158, 4, 2 , 4 },- { 168, 4, 5 , 1 },- { 181, 4, 2 , 2 },- { 191, 4, 4 , 10 },- { 203, 4, 6 , 10 },- { 217, 4, 4 , 10 },- { 229, 4, 6 , 10 },- { 243, 4, 6 , 10 },- { 257, 4, 6 , 10 },- { 271, 4, 6 , 10 },- { 285, 4, 6 , 10 },- { 299, 4, 6 , 10 },- { 313, 4, 6 , 10 },- { 327, 4, 6 , 10 },- { 341, 4, 2 , 6 },- { 351, 4, 2 , 8 },- { 361, 4, 7 , 7 },- { 376, 4, 5 , 3 },- { 389, 4, 7 , 7 },- { 404, 4, 6 , 10 },- { 418, 4, 7 , 12 },- { 433, 4, 7 , 10 },- { 448, 4, 7 , 10 },- { 463, 4, 7 , 10 },- { 478, 4, 7 , 10 },- { 493, 4, 7 , 10 },- { 4, 28, 7 , 10 },- { 19, 28, 7 , 10 },- { 34, 28, 7 , 10 },- { 49, 28, 2 , 10 },- { 59, 28, 5 , 10 },- { 72, 28, 7 , 10 },- { 87, 28, 6 , 10 },- { 101, 28, 9 , 10 },- { 118, 28, 7 , 10 },- { 133, 28, 7 , 10 },- { 148, 28, 7 , 10 },- { 163, 28, 7 , 12 },- { 178, 28, 7 , 10 },- { 193, 28, 7 , 10 },- { 208, 28, 6 , 10 },- { 222, 28, 7 , 10 },- { 237, 28, 7 , 10 },- { 252, 28, 8 , 10 },- { 268, 28, 7 , 10 },- { 283, 28, 6 , 10 },- { 297, 28, 7 , 10 },- { 312, 28, 4 , 12 },- { 324, 28, 4 , 10 },- { 336, 28, 4 , 12 },- { 348, 28, 6 , 3 },- { 362, 28, 7 , 1 },- { 377, 28, 4 , 3 },- { 389, 28, 6 , 7 },- { 403, 28, 6 , 10 },- { 417, 28, 6 , 7 },- { 431, 28, 6 , 10 },- { 445, 28, 6 , 7 },- { 459, 28, 4 , 10 },- { 471, 28, 6 , 9 },- { 485, 28, 6 , 10 },- { 499, 28, 2 , 10 },- { 4, 52, 5 , 12 },- { 17, 52, 6 , 10 },- { 31, 52, 3 , 10 },- { 42, 52, 8 , 7 },- { 58, 52, 6 , 7 },- { 72, 52, 6 , 7 },- { 86, 52, 6 , 9 },- { 100, 52, 6 , 9 },- { 114, 52, 5 , 7 },- { 127, 52, 6 , 7 },- { 141, 52, 4 , 10 },- { 153, 52, 6 , 7 },- { 167, 52, 6 , 7 },- { 181, 52, 8 , 7 },- { 197, 52, 6 , 7 },- { 211, 52, 6 , 9 },- { 225, 52, 6 , 7 },- { 239, 52, 5 , 12 },- { 252, 52, 2 , 12 },- { 262, 52, 5 , 12 },- { 275, 52, 7 , 3 },- { 290, 52, 2 , 9 },- { 300, 52, 6 , 11 },- { 314, 52, 7 , 10 },- { 329, 52, 7 , 9 },- { 344, 52, 6 , 10 },- { 358, 52, 7 , 11 },- { 373, 52, 6 , 12 },- { 387, 52, 6 , 10 },- { 401, 52, 7 , 10 },- { 416, 52, 5 , 5 },- { 429, 52, 7 , 6 },- { 444, 52, 6 , 3 },- { 458, 52, 7 , 10 },- { 473, 52, 9 , 10 },- { 490, 52, 4 , 4 },- { 4, 76, 6 , 7 },- { 18, 76, 4 , 5 },- { 30, 76, 4 , 5 },- { 42, 76, 7 , 11 },- { 57, 76, 6 , 9 },- { 71, 76, 7 , 12 },- { 86, 76, 2 , 2 },- { 96, 76, 6 , 10 },- { 110, 76, 3 , 5 },- { 121, 76, 4 , 5 },- { 133, 76, 7 , 6 },- { 148, 76, 9 , 10 },- { 165, 76, 8 , 7 },- { 181, 76, 6 , 11 },- { 195, 76, 6 , 11 },- { 209, 76, 7 , 11 },- { 224, 76, 7 , 11 },- { 239, 76, 7 , 11 },- { 254, 76, 7 , 11 },- { 269, 76, 7 , 11 },- { 284, 76, 7 , 11 },- { 299, 76, 9 , 10 },- { 316, 76, 7 , 12 },- { 331, 76, 7 , 11 },- { 346, 76, 7 , 11 },- { 361, 76, 7 , 11 },- { 376, 76, 7 , 11 },- { 391, 76, 3 , 11 },- { 402, 76, 3 , 11 },- { 413, 76, 5 , 11 },- { 426, 76, 5 , 11 },- { 439, 76, 8 , 10 },- { 455, 76, 7 , 11 },- { 470, 76, 7 , 11 },- { 485, 76, 7 , 11 },- { 4, 100, 7 , 11 },- { 19, 100, 7 , 11 },- { 34, 100, 7 , 11 },- { 49, 100, 7 , 7 },- { 64, 100, 7 , 13 },- { 79, 100, 7 , 11 },- { 94, 100, 7 , 11 },- { 109, 100, 7 , 11 },- { 124, 100, 7 , 11 },- { 139, 100, 6 , 11 },- { 153, 100, 7 , 10 },- { 168, 100, 7 , 10 },- { 183, 100, 6 , 10 },- { 197, 100, 6 , 10 },- { 211, 100, 6 , 10 },- { 225, 100, 6 , 10 },- { 239, 100, 6 , 10 },- { 253, 100, 6 , 11 },- { 267, 100, 8 , 7 },- { 283, 100, 6 , 9 },- { 297, 100, 6 , 10 },- { 311, 100, 6 , 10 },- { 325, 100, 6 , 10 },- { 339, 100, 6 , 10 },- { 353, 100, 3 , 10 },- { 364, 100, 3 , 10 },- { 375, 100, 5 , 10 },- { 388, 100, 5 , 10 },- { 401, 100, 6 , 10 },- { 415, 100, 6 , 10 },- { 429, 100, 6 , 10 },- { 443, 100, 6 , 10 },- { 457, 100, 6 , 10 },- { 471, 100, 6 , 10 },- { 485, 100, 6 , 10 },- { 4, 124, 6 , 7 },- { 18, 124, 7 , 11 },- { 33, 124, 6 , 10 },- { 47, 124, 6 , 10 },- { 61, 124, 6 , 10 },- { 75, 124, 6 , 10 },- { 89, 124, 6 , 12 },- { 103, 124, 6 , 12 },- { 117, 124, 6 , 12 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo sunnyFontGlyphs[189] = {- { 32, 0, 12, 4, { 0 }},- { 33, 0, 2, 3, { 0 }},- { 34, 0, 2, 6, { 0 }},- { 35, 0, 2, 8, { 0 }},- { 36, 0, 1, 8, { 0 }},- { 37, 0, 2, 8, { 0 }},- { 38, 0, 2, 8, { 0 }},- { 39, 0, 2, 3, { 0 }},- { 40, 0, 2, 4, { 0 }},- { 41, 0, 2, 4, { 0 }},- { 42, 0, 4, 6, { 0 }},- { 43, 0, 6, 7, { 0 }},- { 44, 0, 10, 3, { 0 }},- { 45, 0, 8, 6, { 0 }},- { 46, 0, 10, 3, { 0 }},- { 47, 0, 2, 5, { 0 }},- { 48, 0, 2, 7, { 0 }},- { 49, 0, 2, 7, { 0 }},- { 50, 0, 2, 7, { 0 }},- { 51, 0, 2, 7, { 0 }},- { 52, 0, 2, 7, { 0 }},- { 53, 0, 2, 7, { 0 }},- { 54, 0, 2, 7, { 0 }},- { 55, 0, 2, 7, { 0 }},- { 56, 0, 2, 7, { 0 }},- { 57, 0, 2, 7, { 0 }},- { 58, 0, 4, 3, { 0 }},- { 59, 0, 4, 3, { 0 }},- { 60, 0, 4, 8, { 0 }},- { 61, 0, 6, 6, { 0 }},- { 62, 0, 4, 8, { 0 }},- { 63, 0, 2, 7, { 0 }},- { 64, 0, 2, 8, { 0 }},- { 65, 0, 2, 8, { 0 }},- { 66, 0, 2, 8, { 0 }},- { 67, 0, 2, 8, { 0 }},- { 68, 0, 2, 8, { 0 }},- { 69, 0, 2, 8, { 0 }},- { 70, 0, 2, 8, { 0 }},- { 71, 0, 2, 8, { 0 }},- { 72, 0, 2, 8, { 0 }},- { 73, 0, 2, 3, { 0 }},- { 74, 0, 2, 6, { 0 }},- { 75, 0, 2, 8, { 0 }},- { 76, 0, 2, 7, { 0 }},- { 77, 0, 2, 10, { 0 }},- { 78, 0, 2, 8, { 0 }},- { 79, 0, 2, 8, { 0 }},- { 80, 0, 2, 8, { 0 }},- { 81, 0, 2, 8, { 0 }},- { 82, 0, 2, 8, { 0 }},- { 83, 0, 2, 8, { 0 }},- { 84, 0, 2, 7, { 0 }},- { 85, 0, 2, 8, { 0 }},- { 86, 0, 2, 8, { 0 }},- { 87, 0, 2, 9, { 0 }},- { 88, 0, 2, 8, { 0 }},- { 89, 0, 2, 7, { 0 }},- { 90, 0, 2, 8, { 0 }},- { 91, 0, 2, 5, { 0 }},- { 92, 0, 2, 5, { 0 }},- { 93, 0, 2, 5, { 0 }},- { 94, 0, 2, 7, { 0 }},- { 95, 0, 14, 8, { 0 }},- { 96, 0, 2, 5, { 0 }},- { 97, 0, 5, 7, { 0 }},- { 98, 0, 2, 7, { 0 }},- { 99, 0, 5, 7, { 0 }},- { 100, 0, 2, 7, { 0 }},- { 101, 0, 5, 7, { 0 }},- { 102, 0, 2, 5, { 0 }},- { 103, 0, 5, 7, { 0 }},- { 104, 0, 2, 7, { 0 }},- { 105, 0, 2, 3, { 0 }},- { 106, 0, 2, 6, { 0 }},- { 107, 0, 2, 7, { 0 }},- { 108, 0, 2, 4, { 0 }},- { 109, 0, 5, 9, { 0 }},- { 110, 0, 5, 7, { 0 }},- { 111, 0, 5, 7, { 0 }},- { 112, 0, 5, 7, { 0 }},- { 113, 0, 5, 7, { 0 }},- { 114, 0, 5, 6, { 0 }},- { 115, 0, 5, 7, { 0 }},- { 116, 0, 2, 5, { 0 }},- { 117, 0, 5, 7, { 0 }},- { 118, 0, 5, 7, { 0 }},- { 119, 0, 5, 9, { 0 }},- { 120, 0, 5, 7, { 0 }},- { 121, 0, 5, 7, { 0 }},- { 122, 0, 5, 7, { 0 }},- { 123, 0, 2, 6, { 0 }},- { 124, 0, 2, 3, { 0 }},- { 125, 0, 2, 6, { 0 }},- { 126, 0, 6, 8, { 0 }},- { 161, 0, 5, 3, { 0 }},- { 162, 0, 3, 7, { 0 }},- { 163, 0, 2, 8, { 0 }},- { 8364, 0, 3, 8, { 0 }},- { 165, 0, 2, 7, { 0 }},- { 352, 0, 1, 8, { 0 }},- { 167, 0, 2, 7, { 0 }},- { 353, 0, 2, 7, { 0 }},- { 169, 0, 2, 8, { 0 }},- { 170, 0, 2, 6, { 0 }},- { 171, 0, 6, 8, { 0 }},- { 172, 0, 7, 7, { 0 }},- { 174, 0, 2, 8, { 0 }},- { 175, 1, 3, 14, { 0 }},- { 176, 0, 2, 5, { 0 }},- { 177, 0, 4, 7, { 0 }},- { 178, 0, 2, 5, { 0 }},- { 179, 0, 2, 5, { 0 }},- { 381, 0, 1, 8, { 0 }},- { 181, 0, 5, 7, { 0 }},- { 182, 0, 2, 8, { 0 }},- { 183, 0, 6, 3, { 0 }},- { 382, 0, 2, 7, { 0 }},- { 185, 0, 2, 4, { 0 }},- { 186, 0, 2, 5, { 0 }},- { 187, 0, 6, 8, { 0 }},- { 338, 0, 2, 10, { 0 }},- { 339, 0, 5, 9, { 0 }},- { 376, 0, 1, 7, { 0 }},- { 191, 0, 3, 7, { 0 }},- { 192, 0, 1, 8, { 0 }},- { 193, 0, 1, 8, { 0 }},- { 194, 0, 1, 8, { 0 }},- { 195, 0, 1, 8, { 0 }},- { 196, 0, 1, 8, { 0 }},- { 197, 0, 1, 8, { 0 }},- { 198, 0, 2, 10, { 0 }},- { 199, 0, 2, 8, { 0 }},- { 200, 0, 1, 8, { 0 }},- { 201, 0, 1, 8, { 0 }},- { 202, 0, 1, 8, { 0 }},- { 203, 0, 1, 8, { 0 }},- { 204, 0, 1, 4, { 0 }},- { 205, 0, 1, 4, { 0 }},- { 206, 0, 1, 6, { 0 }},- { 207, 0, 1, 6, { 0 }},- { 208, 0, 2, 9, { 0 }},- { 209, 0, 1, 8, { 0 }},- { 210, 0, 1, 8, { 0 }},- { 211, 0, 1, 8, { 0 }},- { 212, 0, 1, 8, { 0 }},- { 213, 0, 1, 8, { 0 }},- { 214, 0, 1, 8, { 0 }},- { 215, 0, 5, 8, { 0 }},- { 216, 0, 1, 8, { 0 }},- { 217, 0, 1, 8, { 0 }},- { 218, 0, 1, 8, { 0 }},- { 219, 0, 1, 8, { 0 }},- { 220, 0, 1, 8, { 0 }},- { 221, 0, 1, 7, { 0 }},- { 222, 0, 2, 8, { 0 }},- { 223, 0, 2, 8, { 0 }},- { 224, 0, 2, 7, { 0 }},- { 225, 0, 2, 7, { 0 }},- { 226, 0, 2, 7, { 0 }},- { 227, 0, 2, 7, { 0 }},- { 228, 0, 2, 7, { 0 }},- { 229, 0, 1, 7, { 0 }},- { 230, 0, 5, 9, { 0 }},- { 231, 0, 5, 7, { 0 }},- { 232, 0, 2, 7, { 0 }},- { 233, 0, 2, 7, { 0 }},- { 234, 0, 2, 7, { 0 }},- { 235, 0, 2, 7, { 0 }},- { 236, 0, 2, 4, { 0 }},- { 237, 0, 2, 4, { 0 }},- { 238, 0, 2, 6, { 0 }},- { 239, 0, 2, 6, { 0 }},- { 240, 0, 2, 7, { 0 }},- { 241, 0, 2, 7, { 0 }},- { 242, 0, 2, 7, { 0 }},- { 243, 0, 2, 7, { 0 }},- { 244, 0, 2, 7, { 0 }},- { 245, 0, 2, 7, { 0 }},- { 246, 0, 2, 7, { 0 }},- { 247, 0, 4, 7, { 0 }},- { 248, 0, 3, 8, { 0 }},- { 249, 0, 2, 7, { 0 }},- { 250, 0, 2, 7, { 0 }},- { 251, 0, 2, 7, { 0 }},- { 252, 0, 2, 7, { 0 }},- { 253, 0, 2, 7, { 0 }},- { 254, 0, 2, 7, { 0 }},- { 255, 0, 2, 7, { 0 }},-};--// Style loading function: Sunny-static void GuiLoadStyleSunny(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < SUNNY_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(sunnyStyleProps[i].controlId, sunnyStyleProps[i].propertyId, sunnyStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int sunnyFontDataSize = 0;- unsigned char *data = DecompressData(sunnyFontData, SUNNY_STYLE_FONT_ATLAS_COMP_SIZE, &sunnyFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, sunnyFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, sunnyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
− raygui/examples/styles/style_terminal.h
@@ -1,569 +0,0 @@-//////////////////////////////////////////////////////////////////////////////////-// //-// StyleAsCode exporter v2.0 - Style data exported as a values array //-// //-// USAGE: On init call: GuiLoadStyleTerminal(); //-// //-// more info and bugs-report: github.com/raysan5/raygui //-// feedback and support: ray[at]raylibtech.com //-// //-// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //-// //-//////////////////////////////////////////////////////////////////////////////////--#define TERMINAL_STYLE_PROPS_COUNT 17--// Custom style name: Terminal-static const GuiStyleProp terminalStyleProps[TERMINAL_STYLE_PROPS_COUNT] = {- { 0, 0, 0x1c8d00ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, 0x161313ff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, 0x38f620ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, 0xc3fbc6ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, 0x43bf2eff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, 0xdcfadcff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, 0x1f5b19ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, 0x43ff28ff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, 0x1e6f15ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, 0x223b22ff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, 0x182c18ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, 0x244125ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, 0xe6fce3ff }, // DEFAULT_LINE_COLOR - { 0, 19, 0x0c1505ff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING -};--// WARNING: This style uses a custom font: "Mecha.ttf" (size: 16, spacing: 0)--#define TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE 1860--// Font atlas image pixels data: DEFLATE compressed-static unsigned char terminalFontData[TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,- 0xdd, 0x41, 0x92, 0xa4, 0x36, 0x10, 0x05, 0x50, 0xee, 0x7f, 0xe9, 0xf4, 0x62, 0x62, 0x16, 0x76, 0xb8, 0x1b, 0x94, 0x4a,- 0x89, 0x04, 0x9e, 0x5f, 0x78, 0xd3, 0xd5, 0x53, 0x4d, 0x01, 0xbf, 0x24, 0x84, 0x94, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x7c,- 0x5e, 0xfc, 0xef, 0x4f, 0xe2, 0xc7, 0xdf, 0x8c, 0xcb, 0xef, 0xf3, 0xe7, 0xa7, 0xf1, 0xe3, 0x5f, 0xf9, 0xfb, 0xdf, 0x95,- 0x77, 0xba, 0xfe, 0x5b, 0x31, 0xb4, 0x75, 0x73, 0x5b, 0x95, 0x7b, 0x9f, 0xd1, 0xdf, 0xfe, 0x7d, 0x7b, 0xaa, 0xde, 0xad,- 0xf6, 0x95, 0xb1, 0xb3, 0x23, 0xbf, 0xe7, 0xae, 0x6e, 0x61, 0x6c, 0xdf, 0x2b, 0xc7, 0xa6, 0x7d, 0x1c, 0x0d, 0xf2, 0x7f,- 0x7e, 0xcc, 0x46, 0xf2, 0x14, 0xe9, 0xf4, 0x8e, 0x7f, 0x3b, 0xad, 0xfc, 0x0e, 0x1d, 0xdd, 0xc6, 0xdc, 0x3e, 0x89, 0x92,- 0xf7, 0x9f, 0xf9, 0x3b, 0x51, 0xb6, 0xd7, 0x72, 0xff, 0x26, 0x86, 0xdb, 0x88, 0xf9, 0x4f, 0x78, 0xbe, 0x8f, 0x63, 0xd1,- 0x71, 0xef, 0x99, 0xff, 0xfc, 0x51, 0xcb, 0x9f, 0x29, 0x57, 0xb7, 0x3c, 0xd7, 0xa6, 0xaf, 0x3a, 0x27, 0xe5, 0xff, 0xec,- 0x9b, 0xfa, 0xe7, 0x16, 0xb4, 0xa2, 0xdd, 0x90, 0xff, 0x5c, 0x06, 0x62, 0x22, 0x47, 0xbb, 0xf2, 0x5f, 0xdb, 0xd6, 0xc8,- 0xff, 0x33, 0xda, 0xff, 0xb3, 0x6d, 0xff, 0xf7, 0x79, 0x2b, 0xff, 0xd9, 0xa3, 0x90, 0x6d, 0xff, 0x63, 0x7a, 0xfb, 0x3b,- 0xe7, 0x7f, 0x74, 0xdc, 0x43, 0xfe, 0xcf, 0xaf, 0xe8, 0x73, 0xbf, 0x7d, 0xb6, 0x27, 0xe4, 0x7f, 0x5d, 0xfe, 0x7f, 0xeb,- 0xb3, 0x9d, 0xf5, 0xf4, 0x76, 0xe4, 0xff, 0xd8, 0x9e, 0xff, 0xb3, 0xeb, 0xa8, 0xeb, 0xfb, 0x62, 0xc7, 0x08, 0xd4, 0x91,- 0x1c, 0xdb, 0x89, 0xc1, 0x0c, 0xdf, 0xd3, 0x0b, 0x3b, 0xcb, 0x7f, 0x66, 0x4f, 0x66, 0xf2, 0x7f, 0x76, 0x5c, 0x8e, 0x5f,- 0x7a, 0x30, 0xab, 0xf6, 0x7e, 0x45, 0xfe, 0x67, 0x46, 0xe4, 0x9e, 0x9d, 0xff, 0x38, 0xd9, 0x57, 0x31, 0x31, 0xbe, 0xb9,- 0xb3, 0xcf, 0x30, 0xd3, 0x4f, 0xeb, 0x7b, 0x1c, 0xde, 0xd3, 0xff, 0x8f, 0xd6, 0xed, 0xbf, 0xfc, 0xcf, 0x5d, 0xff, 0xbf,- 0x2d, 0xff, 0xb1, 0xfd, 0x58, 0xc5, 0x85, 0x33, 0x56, 0xfe, 0xe7, 0xf6, 0xf0, 0x79, 0x8f, 0x23, 0x16, 0x5d, 0xbf, 0x74,- 0xcd, 0x7f, 0xee, 0xd3, 0x7d, 0xb1, 0xfd, 0x8f, 0x1b, 0x8f, 0x8f, 0xfc, 0xaf, 0xd8, 0x9b, 0x23, 0x77, 0xd8, 0x66, 0xe7,- 0x2f, 0xc8, 0xbf, 0xfc, 0xcb, 0x7f, 0xef, 0xfe, 0x7f, 0x0c, 0x8e, 0xdc, 0xc6, 0xe3, 0xc7, 0xff, 0xe2, 0x52, 0x6f, 0x69,- 0x7e, 0xb6, 0xe0, 0x78, 0x9f, 0x2b, 0xf7, 0x6e, 0xf9, 0xd9, 0x75, 0x4f, 0xb9, 0xfe, 0xdf, 0x39, 0x93, 0xf2, 0x28, 0x99,- 0x87, 0xb2, 0x7e, 0xfe, 0xdf, 0x33, 0xe7, 0x28, 0x77, 0xcf, 0x3f, 0xb0, 0x7a, 0x95, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x65, 0x0d, 0x4d, 0x94, 0xad, 0x7b, 0x8c, 0x16, 0x95, 0xe7, 0xf7, 0xd4, 0x58,- 0xbf, 0xb6, 0x87, 0xaa, 0xde, 0x71, 0xec, 0x59, 0x02, 0x63, 0xeb, 0x30, 0x73, 0x2b, 0xff, 0x56, 0xaf, 0x6e, 0x9b, 0x59,- 0xdd, 0x58, 0xb3, 0x65, 0x15, 0xb5, 0x2d, 0xee, 0x49, 0xc7, 0xca, 0x75, 0xe2, 0x71, 0x69, 0x75, 0x70, 0x6d, 0x92, 0x56,- 0xaf, 0xd8, 0xce, 0xac, 0x7d, 0xdf, 0x99, 0xff, 0xb1, 0x33, 0x70, 0xfc, 0x73, 0x46, 0x62, 0x35, 0x55, 0x6d, 0x0d, 0x98,- 0x63, 0xe9, 0xb9, 0x19, 0x8b, 0xd6, 0x90, 0x8d, 0xef, 0x83, 0x3d, 0xe9, 0x90, 0xff, 0x2f, 0xe7, 0x3f, 0x57, 0x23, 0x7b,- 0xc7, 0xb3, 0x50, 0xe4, 0x5f, 0xfe, 0xe5, 0xff, 0xad, 0xf9, 0x8f, 0xe2, 0xfe, 0x77, 0xbe, 0x5a, 0x47, 0xcd, 0x95, 0x55,- 0x6d, 0x4a, 0xe4, 0x5f, 0xfe, 0x7f, 0xef, 0x6d, 0xc7, 0xc5, 0x56, 0x6c, 0xa4, 0xc5, 0xdb, 0x59, 0xb3, 0x64, 0x5f, 0x15,- 0xad, 0xd1, 0x6f, 0x93, 0x28, 0x4c, 0xf0, 0x57, 0xf2, 0x9f, 0xaf, 0x7b, 0xbe, 0x67, 0xdc, 0x2b, 0xb3, 0xe5, 0x99, 0xda,- 0x57, 0xf5, 0xf9, 0x3f, 0x7b, 0x1e, 0x42, 0xe6, 0xfb, 0xe9, 0x5b, 0xf9, 0x1f, 0xfd, 0x6c, 0xf2, 0x7f, 0x6c, 0x7e, 0xb6,- 0xcc, 0xfd, 0x35, 0x16, 0x23, 0xd9, 0xd2, 0x57, 0x6d, 0x75, 0xa4, 0x46, 0xdb, 0xaa, 0x7e, 0x9e, 0xab, 0xd2, 0xf8, 0xde,- 0xfc, 0x47, 0xc1, 0x7d, 0xae, 0xb9, 0x56, 0x52, 0xfe, 0xe5, 0xff, 0x98, 0xac, 0xc0, 0xdb, 0x3d, 0xff, 0x2b, 0xae, 0xbf,- 0x2b, 0x9f, 0xe6, 0xfa, 0xcc, 0xf6, 0xff, 0x59, 0xf7, 0xff, 0xbe, 0x92, 0xff, 0xb3, 0x63, 0x79, 0x77, 0xfe, 0x3b, 0xd5,- 0x4c, 0xcd, 0x8c, 0x30, 0xce, 0xfc, 0x9b, 0x8e, 0xf9, 0xdf, 0x35, 0x9f, 0x47, 0xfe, 0x77, 0xe5, 0xff, 0xe7, 0xa7, 0x8d,- 0xcb, 0x7f, 0xaf, 0xfc, 0xaf, 0xeb, 0xff, 0x3f, 0x3b, 0xff, 0xeb, 0x7a, 0x5f, 0xab, 0xfb, 0x73, 0xb5, 0x5b, 0x9e, 0x99,- 0x01, 0xf7, 0xdb, 0xfc, 0xbb, 0x48, 0x57, 0x6d, 0xaf, 0x98, 0x87, 0x37, 0x33, 0x3b, 0x68, 0xf7, 0x95, 0x41, 0xf5, 0xbf,- 0xa9, 0x1f, 0xb3, 0xe8, 0x9b, 0x7f, 0x78, 0x46, 0xfe, 0xbf, 0xb0, 0xaf, 0x71, 0x3c, 0xee, 0x69, 0x59, 0x57, 0xfe, 0x3e,- 0xce, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xd3, 0x2a, 0xac, 0xaa, 0xba, 0x8d, 0x3b,- 0xab, 0x65, 0xe4, 0xd6, 0xf9, 0xc5, 0xe5, 0xba, 0x2e, 0x99, 0x55, 0xe4, 0x23, 0x6b, 0xf9, 0x6a, 0xd6, 0x34, 0xe6, 0xcf,- 0x81, 0x48, 0xad, 0x96, 0x3b, 0x3f, 0x53, 0x32, 0x35, 0xec, 0xd7, 0xcd, 0xb6, 0xff, 0xbd, 0x7e, 0x43, 0xbe, 0x92, 0xc8,- 0xaa, 0xf5, 0x05, 0x75, 0xf5, 0x9f, 0x8e, 0x82, 0xd5, 0x8a, 0xd9, 0x35, 0xf4, 0xf7, 0xe6, 0x7f, 0x74, 0xf5, 0xdb, 0xf5,- 0x9f, 0x55, 0xd4, 0x5b, 0x89, 0xc4, 0xca, 0xbc, 0xca, 0xfc, 0x57, 0x9c, 0xe3, 0x51, 0xf6, 0xbe, 0xb1, 0xb8, 0x4e, 0xc1,- 0x95, 0x56, 0xe2, 0xd9, 0x6b, 0xa2, 0xe2, 0xd5, 0xf9, 0xaf, 0xad, 0x96, 0x5b, 0xff, 0x9d, 0x90, 0xaf, 0x4f, 0x70, 0x5f,- 0xfe, 0xff, 0x6e, 0x57, 0x75, 0xfe, 0x33, 0xef, 0x5b, 0x53, 0xd9, 0x6a, 0x2e, 0xff, 0x3d, 0x56, 0xf6, 0xc5, 0xf2, 0x9e,- 0x47, 0x26, 0xff, 0x63, 0xfd, 0xb6, 0x15, 0xf9, 0xcf, 0x57, 0xe6, 0x39, 0x36, 0x65, 0xfd, 0x28, 0x4e, 0xf9, 0xfa, 0xfc,- 0xd7, 0x9f, 0x69, 0xf1, 0x9f, 0xff, 0xbb, 0xac, 0xb6, 0x7d, 0x4b, 0xfe, 0x73, 0xd5, 0x69, 0x66, 0xf3, 0x9f, 0xbd, 0xe2,- 0xbd, 0xbb, 0xfd, 0x5f, 0x73, 0x4d, 0xb0, 0x3e, 0xff, 0x91, 0xaa, 0x0c, 0xde, 0x27, 0xff, 0xb1, 0x20, 0xb9, 0xf2, 0x9f,- 0x6d, 0x03, 0xdf, 0x90, 0xff, 0xea, 0xe7, 0x7c, 0x74, 0xc8, 0x7f, 0x6e, 0xc4, 0x2b, 0x4a, 0x73, 0x1a, 0xed, 0xdb, 0xff,- 0x63, 0xdb, 0xf8, 0x5f, 0xff, 0xfc, 0x47, 0x49, 0xbf, 0xf0, 0xce, 0xfc, 0xd7, 0x57, 0xcb, 0xcd, 0x56, 0x0d, 0xbc, 0x3e,- 0xd6, 0xd7, 0xa7, 0xfd, 0xaf, 0xbf, 0x1e, 0x5e, 0xd1, 0xfe, 0x1f, 0x0b, 0xee, 0x52, 0xac, 0xbf, 0xaa, 0xee, 0x9f, 0xff,- 0xaa, 0xeb, 0xc2, 0xcc, 0x73, 0x93, 0x46, 0xef, 0xff, 0xc5, 0xe9, 0x59, 0x3c, 0x7a, 0xe7, 0x68, 0x3c, 0x4f, 0x31, 0xf8,- 0xf4, 0xa2, 0xfe, 0xd7, 0xff, 0x95, 0xed, 0xff, 0x9a, 0x51, 0xef, 0xae, 0xa3, 0xe9, 0xd7, 0x9e, 0x2f, 0xde, 0x63, 0x8b,- 0xf3, 0x4f, 0xdc, 0x8a, 0xed, 0x57, 0x56, 0x7d, 0x8e, 0xf1, 0xfc, 0x67, 0x5f, 0x93, 0xff, 0x8a, 0x8a, 0xd3, 0xf5, 0xed,- 0xe1, 0xf7, 0xe6, 0xbc, 0xcc, 0xdc, 0x75, 0xef, 0xb1, 0xb5, 0xd5, 0xe7, 0xc5, 0x3b, 0xf2, 0x5f, 0xf7, 0xd9, 0x63, 0xc9,- 0xb7, 0x4a, 0xa6, 0x96, 0x77, 0x2c, 0x9f, 0x0f, 0x23, 0xff, 0xcf, 0xcd, 0x7f, 0xdc, 0x70, 0xcf, 0xf0, 0x58, 0x3c, 0x1e,- 0xdd, 0x61, 0x0f, 0xef, 0xcd, 0x3f, 0xfd, 0xce, 0x88, 0xee, 0xf9, 0x5f, 0x3f, 0x2f, 0xf4, 0xcb, 0xed, 0x81, 0x2a, 0xf9,- 0x3c, 0xf1, 0x5a, 0x56, 0xfe, 0x73, 0xfd, 0x96, 0xd9, 0xf9, 0xff, 0x20, 0xff, 0xdf, 0xdd, 0xeb, 0xd0, 0x7f, 0x76, 0x03,- 0xf2, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfb, 0x67, 0xbb, 0x45, 0x6a, 0x7d, 0x5b, 0x0c, 0x56,- 0x32, 0x88, 0x74, 0xa5, 0xf8, 0x6c, 0x7d, 0x8c, 0x18, 0x5c, 0xf7, 0x35, 0x5f, 0x37, 0xf8, 0xfa, 0xf3, 0x15, 0x66, 0xd6,- 0x0f, 0xae, 0x3f, 0x8e, 0x75, 0x15, 0xd6, 0xeb, 0x8f, 0x52, 0xe6, 0xef, 0x47, 0x79, 0xed, 0xb5, 0xfe, 0x99, 0x99, 0xdf,- 0xcf, 0x99, 0x95, 0xbe, 0xb5, 0x67, 0xd4, 0xb5, 0x63, 0x5b, 0xb7, 0xba, 0x33, 0x26, 0x92, 0x3e, 0x3e, 0x4f, 0xfb, 0xf7,- 0xaa, 0x9f, 0x5d, 0x8f, 0x63, 0x2e, 0x4b, 0x51, 0xba, 0x06, 0x37, 0xf7, 0xd7, 0x9f, 0xb6, 0xaf, 0xaf, 0x57, 0x01, 0xd8,- 0xdd, 0x5f, 0xc8, 0x3f, 0x35, 0x28, 0x6e, 0x9f, 0x8b, 0xbf, 0xae, 0xa2, 0x4e, 0x5d, 0xad, 0xe2, 0xbb, 0x8f, 0xe3, 0x71,- 0xfa, 0x0c, 0x93, 0x68, 0xb8, 0xbe, 0xe5, 0xac, 0xff, 0x18, 0x2d, 0xf7, 0x75, 0x5c, 0xee, 0x23, 0xe6, 0xf3, 0x9f, 0x7f,- 0x3e, 0x53, 0x14, 0x57, 0xe6, 0xcd, 0x57, 0xc7, 0xac, 0xde, 0xfa, 0x7c, 0xfb, 0x9f, 0xb9, 0x52, 0x88, 0xe5, 0x9f, 0xaa,- 0xf6, 0x3b, 0x39, 0x4e, 0x6a, 0xb9, 0xae, 0x3e, 0x2b, 0x56, 0xbc, 0x12, 0x1b, 0xce, 0xad, 0xdc, 0xf5, 0xde, 0xb5, 0x33,- 0x64, 0x26, 0xff, 0x7d, 0x8f, 0xcd, 0xd1, 0xe6, 0x95, 0xdd, 0xf9, 0x7f, 0xee, 0x2b, 0xef, 0xc9, 0x7f, 0x9f, 0xb3, 0xef,- 0xb7, 0xcf, 0x33, 0xfb, 0xac, 0xc2, 0x0e, 0x47, 0xe0, 0xac, 0x4e, 0xec, 0x5b, 0xf3, 0x1f, 0x3f, 0x8e, 0x0c, 0xf6, 0xff,- 0x4e, 0xfe, 0xb9, 0x5f, 0xf0, 0xb4, 0xfc, 0x57, 0xb6, 0xcb, 0x15, 0x6d, 0xf9, 0xde, 0x6b, 0x66, 0xed, 0xbf, 0xf6, 0xff,- 0xdb, 0xf9, 0xbf, 0xff, 0x2a, 0x6c, 0x6f, 0x66, 0xfa, 0xed, 0xb3, 0x3e, 0xf9, 0x1f, 0x19, 0xf3, 0x92, 0xff, 0xb7, 0xe7,- 0xff, 0x09, 0xdf, 0x4d, 0xb3, 0xf7, 0xff, 0xde, 0x31, 0xfe, 0x57, 0xf5, 0x8a, 0xf6, 0x7f, 0x6e, 0x8c, 0xfd, 0xee, 0x6d,- 0xcb, 0x1f, 0xf3, 0xb7, 0x1c, 0x85, 0xd1, 0x3e, 0x80, 0xfe, 0xbf, 0xfc, 0xbf, 0x27, 0xff, 0x47, 0x7a, 0xf6, 0xc1, 0xb3,- 0xae, 0x33, 0x46, 0x8e, 0xc7, 0x73, 0xf2, 0x5f, 0x79, 0xc7, 0xee, 0x29, 0xe3, 0x7f, 0x4f, 0xfb, 0x66, 0x78, 0x63, 0xfe,- 0xef, 0xbd, 0xd7, 0xda, 0x63, 0xe6, 0xef, 0x33, 0xfb, 0x32, 0x4f, 0xce, 0xff, 0xb3, 0xfb, 0x64, 0xc7, 0x6d, 0x57, 0x85,- 0x51, 0xb8, 0xa7, 0x79, 0x46, 0xfe, 0x63, 0x53, 0xfe, 0x47, 0xc6, 0x06, 0xde, 0x9d, 0xff, 0xf1, 0xd6, 0x2a, 0x6e, 0x1f,- 0x63, 0x96, 0xff, 0xbb, 0xf3, 0xbf, 0x7f, 0xeb, 0x77, 0xf5, 0xc4, 0x62, 0x49, 0xd2, 0xc7, 0x8f, 0xc9, 0x13, 0xfb, 0xa4,- 0x3b, 0xb7, 0x4d, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xcc, 0x00, 0x1e, 0x7b, 0xb5,- 0x43, 0x05, 0xfd, 0x23, 0x5d, 0x6d, 0xbd, 0xee, 0xf3, 0x1e, 0x89, 0xaa, 0xee, 0x99, 0x6d, 0xe8, 0x5c, 0x41, 0xdf, 0xac,- 0xdb, 0xb7, 0x7e, 0x03, 0xf4, 0xae, 0xa0, 0x7f, 0x5e, 0xe5, 0x63, 0xfd, 0xe7, 0xad, 0x9c, 0x3f, 0xdf, 0xbb, 0x82, 0x7e,- 0xbf, 0xb5, 0xab, 0xf4, 0xfb, 0x26, 0xd9, 0x59, 0x41, 0x7f, 0xbc, 0xbf, 0x71, 0x6c, 0xdc, 0xae, 0x6c, 0x35, 0x83, 0xae,- 0x15, 0xf4, 0xbb, 0xaf, 0x05, 0xe3, 0xfe, 0xb5, 0x59, 0x63, 0xcf, 0xb4, 0xa8, 0xaa, 0xa0, 0xf1, 0xb4, 0x0a, 0xfa, 0x67,- 0x19, 0x7b, 0x52, 0x9d, 0x6c, 0xf9, 0xb7, 0xfe, 0xf7, 0xbe, 0xfc, 0xf7, 0xad, 0x93, 0x91, 0xad, 0x52, 0xd3, 0xbb, 0x82,- 0xa6, 0xfc, 0xcb, 0xbf, 0xfc, 0xaf, 0xaa, 0x91, 0x20, 0xff, 0x3c, 0x3d, 0xff, 0x3b, 0x2b, 0xe8, 0xa8, 0xa0, 0xb9, 0xbb,- 0x22, 0xd0, 0x21, 0xff, 0xae, 0xff, 0x1f, 0xf1, 0x04, 0x3d, 0xf9, 0x5f, 0xf3, 0x8a, 0xfc, 0x7f, 0xfd, 0xde, 0x9f, 0x0a,- 0xda, 0x2b, 0xf3, 0x1f, 0x4d, 0xc7, 0xff, 0xf6, 0xdf, 0xf1, 0xe1, 0x89, 0xf9, 0xd7, 0xff, 0xcf, 0xe7, 0xe2, 0xfe, 0x0a,- 0x9a, 0xf9, 0x34, 0xcb, 0xbf, 0xfe, 0x7f, 0xc5, 0xfc, 0x9f, 0x9a, 0xb6, 0x47, 0x05, 0xcd, 0xb9, 0x6d, 0x93, 0x7f, 0xd0,- 0x2b, 0xd4, 0xff, 0x07, 0xbd, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf9, 0xf3, 0x9f, 0xfd, 0x00, 0xf2, 0x0f, 0x7c, 0x2e, 0xff, 0xff, 0x00 };--// Font glyphs rectangles data (on atlas)-static const Rectangle terminalFontRecs[189] = {- { 4, 4, 4 , 16 },- { 16, 4, 1 , 11 },- { 25, 4, 3 , 3 },- { 36, 4, 6 , 11 },- { 50, 4, 5 , 11 },- { 63, 4, 5 , 11 },- { 76, 4, 5 , 11 },- { 89, 4, 1 , 2 },- { 98, 4, 2 , 13 },- { 108, 4, 2 , 13 },- { 118, 4, 3 , 3 },- { 129, 4, 5 , 5 },- { 142, 4, 1 , 3 },- { 151, 4, 5 , 1 },- { 164, 4, 1 , 1 },- { 173, 4, 6 , 12 },- { 187, 4, 5 , 11 },- { 200, 4, 2 , 11 },- { 210, 4, 5 , 11 },- { 223, 4, 5 , 11 },- { 236, 4, 5 , 11 },- { 249, 4, 5 , 11 },- { 262, 4, 5 , 11 },- { 275, 4, 5 , 11 },- { 288, 4, 5 , 11 },- { 301, 4, 5 , 11 },- { 314, 4, 1 , 8 },- { 323, 4, 1 , 10 },- { 332, 4, 4 , 5 },- { 344, 4, 5 , 3 },- { 357, 4, 4 , 5 },- { 369, 4, 5 , 11 },- { 382, 4, 11 , 11 },- { 401, 4, 5 , 11 },- { 414, 4, 5 , 11 },- { 427, 4, 5 , 11 },- { 440, 4, 5 , 11 },- { 453, 4, 5 , 11 },- { 466, 4, 5 , 11 },- { 479, 4, 5 , 11 },- { 492, 4, 5 , 11 },- { 4, 28, 1 , 11 },- { 13, 28, 5 , 11 },- { 26, 28, 5 , 11 },- { 39, 28, 5 , 11 },- { 52, 28, 7 , 11 },- { 67, 28, 5 , 11 },- { 80, 28, 5 , 11 },- { 93, 28, 5 , 11 },- { 106, 28, 5 , 13 },- { 119, 28, 5 , 11 },- { 132, 28, 5 , 11 },- { 145, 28, 5 , 11 },- { 158, 28, 5 , 11 },- { 171, 28, 5 , 11 },- { 184, 28, 7 , 11 },- { 199, 28, 5 , 11 },- { 212, 28, 5 , 11 },- { 225, 28, 5 , 11 },- { 238, 28, 2 , 13 },- { 248, 28, 6 , 12 },- { 262, 28, 2 , 13 },- { 272, 28, 5 , 4 },- { 285, 28, 5 , 1 },- { 298, 28, 2 , 2 },- { 308, 28, 5 , 8 },- { 321, 28, 5 , 11 },- { 334, 28, 5 , 8 },- { 347, 28, 5 , 11 },- { 360, 28, 5 , 8 },- { 373, 28, 4 , 11 },- { 385, 28, 5 , 10 },- { 398, 28, 5 , 11 },- { 411, 28, 1 , 11 },- { 420, 28, 1 , 13 },- { 429, 28, 5 , 11 },- { 442, 28, 1 , 11 },- { 451, 28, 7 , 8 },- { 466, 28, 5 , 8 },- { 479, 28, 5 , 8 },- { 492, 28, 5 , 10 },- { 4, 52, 5 , 10 },- { 17, 52, 4 , 8 },- { 29, 52, 5 , 8 },- { 42, 52, 3 , 11 },- { 53, 52, 5 , 8 },- { 66, 52, 5 , 8 },- { 79, 52, 7 , 8 },- { 94, 52, 5 , 8 },- { 107, 52, 5 , 10 },- { 120, 52, 5 , 8 },- { 133, 52, 3 , 13 },- { 144, 52, 1 , 15 },- { 153, 52, 3 , 13 },- { 164, 52, 5 , 3 },- { 177, 52, 1 , 11 },- { 186, 52, 5 , 11 },- { 199, 52, 5 , 10 },- { 212, 52, 5 , 10 },- { 225, 52, 5 , 10 },- { 238, 52, 0 , 0 },- { 246, 52, 0 , 0 },- { 254, 52, 0 , 0 },- { 262, 52, 7 , 8 },- { 277, 52, 0 , 0 },- { 285, 52, 0 , 0 },- { 293, 52, 5 , 3 },- { 306, 52, 7 , 8 },- { 321, 52, 5 , 1 },- { 334, 52, 3 , 3 },- { 345, 52, 5 , 7 },- { 358, 52, 0 , 0 },- { 366, 52, 0 , 0 },- { 374, 52, 0 , 0 },- { 382, 52, 5 , 10 },- { 395, 52, 7 , 11 },- { 410, 52, 1 , 1 },- { 419, 52, 0 , 0 },- { 427, 52, 0 , 0 },- { 435, 52, 0 , 0 },- { 443, 52, 0 , 0 },- { 451, 52, 0 , 0 },- { 459, 52, 0 , 0 },- { 467, 52, 5 , 13 },- { 480, 52, 5 , 11 },- { 493, 52, 5 , 14 },- { 4, 76, 5 , 14 },- { 17, 76, 5 , 14 },- { 30, 76, 5 , 14 },- { 43, 76, 5 , 13 },- { 56, 76, 5 , 13 },- { 69, 76, 9 , 11 },- { 86, 76, 5 , 13 },- { 99, 76, 5 , 14 },- { 112, 76, 5 , 14 },- { 125, 76, 5 , 14 },- { 138, 76, 5 , 13 },- { 151, 76, 2 , 14 },- { 161, 76, 2 , 14 },- { 171, 76, 3 , 14 },- { 182, 76, 3 , 13 },- { 193, 76, 5 , 11 },- { 206, 76, 5 , 14 },- { 219, 76, 5 , 14 },- { 232, 76, 5 , 14 },- { 245, 76, 5 , 14 },- { 258, 76, 5 , 14 },- { 271, 76, 5 , 13 },- { 284, 76, 5 , 5 },- { 297, 76, 5 , 13 },- { 310, 76, 5 , 14 },- { 323, 76, 5 , 14 },- { 336, 76, 5 , 14 },- { 349, 76, 5 , 13 },- { 362, 76, 5 , 14 },- { 375, 76, 5 , 11 },- { 388, 76, 5 , 11 },- { 401, 76, 5 , 11 },- { 414, 76, 5 , 11 },- { 427, 76, 5 , 11 },- { 440, 76, 5 , 11 },- { 453, 76, 5 , 10 },- { 466, 76, 5 , 10 },- { 479, 76, 9 , 8 },- { 496, 76, 5 , 10 },- { 4, 100, 5 , 11 },- { 17, 100, 5 , 11 },- { 30, 100, 5 , 11 },- { 43, 100, 5 , 10 },- { 56, 100, 2 , 11 },- { 66, 100, 2 , 11 },- { 76, 100, 3 , 11 },- { 87, 100, 3 , 10 },- { 98, 100, 5 , 11 },- { 111, 100, 5 , 11 },- { 124, 100, 5 , 11 },- { 137, 100, 5 , 11 },- { 150, 100, 5 , 11 },- { 163, 100, 5 , 11 },- { 176, 100, 5 , 10 },- { 189, 100, 5 , 5 },- { 202, 100, 5 , 10 },- { 215, 100, 5 , 11 },- { 228, 100, 5 , 11 },- { 241, 100, 5 , 11 },- { 254, 100, 5 , 10 },- { 267, 100, 5 , 13 },- { 280, 100, 4 , 8 },- { 292, 100, 5 , 12 },-};--// Font glyphs info data-// NOTE: No glyphs.image data provided-static const GlyphInfo terminalFontGlyphs[189] = {- { 32, 0, 14, 4, { 0 }},- { 33, 1, 3, 3, { 0 }},- { 34, 1, 3, 5, { 0 }},- { 35, 1, 3, 8, { 0 }},- { 36, 1, 3, 7, { 0 }},- { 37, 1, 3, 7, { 0 }},- { 38, 1, 3, 7, { 0 }},- { 39, 1, 3, 3, { 0 }},- { 40, 1, 2, 4, { 0 }},- { 41, 1, 2, 4, { 0 }},- { 42, 1, 3, 5, { 0 }},- { 43, 1, 7, 7, { 0 }},- { 44, 1, 13, 3, { 0 }},- { 45, 1, 9, 7, { 0 }},- { 46, 1, 13, 3, { 0 }},- { 47, 1, 2, 8, { 0 }},- { 48, 1, 3, 7, { 0 }},- { 49, 1, 3, 4, { 0 }},- { 50, 1, 3, 7, { 0 }},- { 51, 1, 3, 7, { 0 }},- { 52, 1, 3, 7, { 0 }},- { 53, 1, 3, 7, { 0 }},- { 54, 1, 3, 7, { 0 }},- { 55, 1, 3, 7, { 0 }},- { 56, 1, 3, 7, { 0 }},- { 57, 1, 3, 7, { 0 }},- { 58, 1, 6, 3, { 0 }},- { 59, 1, 6, 3, { 0 }},- { 60, 1, 7, 6, { 0 }},- { 61, 1, 8, 7, { 0 }},- { 62, 1, 7, 6, { 0 }},- { 63, 1, 3, 7, { 0 }},- { 64, 2, 3, 15, { 0 }},- { 65, 1, 3, 7, { 0 }},- { 66, 1, 3, 7, { 0 }},- { 67, 1, 3, 7, { 0 }},- { 68, 1, 3, 7, { 0 }},- { 69, 1, 3, 7, { 0 }},- { 70, 1, 3, 7, { 0 }},- { 71, 1, 3, 7, { 0 }},- { 72, 1, 3, 7, { 0 }},- { 73, 1, 3, 3, { 0 }},- { 74, 1, 3, 7, { 0 }},- { 75, 1, 3, 7, { 0 }},- { 76, 1, 3, 7, { 0 }},- { 77, 1, 3, 9, { 0 }},- { 78, 1, 3, 7, { 0 }},- { 79, 1, 3, 7, { 0 }},- { 80, 1, 3, 7, { 0 }},- { 81, 1, 3, 7, { 0 }},- { 82, 1, 3, 7, { 0 }},- { 83, 1, 3, 7, { 0 }},- { 84, 1, 3, 7, { 0 }},- { 85, 1, 3, 7, { 0 }},- { 86, 1, 3, 7, { 0 }},- { 87, 1, 3, 9, { 0 }},- { 88, 1, 3, 7, { 0 }},- { 89, 1, 3, 7, { 0 }},- { 90, 1, 3, 7, { 0 }},- { 91, 1, 2, 4, { 0 }},- { 92, 1, 2, 8, { 0 }},- { 93, 1, 2, 4, { 0 }},- { 94, 1, 3, 7, { 0 }},- { 95, 1, 15, 7, { 0 }},- { 96, 1, 0, 4, { 0 }},- { 97, 1, 6, 7, { 0 }},- { 98, 1, 3, 7, { 0 }},- { 99, 1, 6, 7, { 0 }},- { 100, 1, 3, 7, { 0 }},- { 101, 1, 6, 7, { 0 }},- { 102, 1, 3, 6, { 0 }},- { 103, 1, 6, 7, { 0 }},- { 104, 1, 3, 7, { 0 }},- { 105, 1, 3, 3, { 0 }},- { 106, 1, 3, 3, { 0 }},- { 107, 1, 3, 7, { 0 }},- { 108, 1, 3, 3, { 0 }},- { 109, 1, 6, 9, { 0 }},- { 110, 1, 6, 7, { 0 }},- { 111, 1, 6, 7, { 0 }},- { 112, 1, 6, 7, { 0 }},- { 113, 1, 6, 7, { 0 }},- { 114, 1, 6, 6, { 0 }},- { 115, 1, 6, 7, { 0 }},- { 116, 1, 3, 5, { 0 }},- { 117, 1, 6, 7, { 0 }},- { 118, 1, 6, 7, { 0 }},- { 119, 1, 6, 9, { 0 }},- { 120, 1, 6, 7, { 0 }},- { 121, 1, 6, 7, { 0 }},- { 122, 1, 6, 7, { 0 }},- { 123, 1, 2, 5, { 0 }},- { 124, 1, 1, 3, { 0 }},- { 125, 1, 2, 5, { 0 }},- { 126, 1, 8, 7, { 0 }},- { 161, 1, 3, 3, { 0 }},- { 162, 1, 3, 7, { 0 }},- { 163, 1, 3, 7, { 0 }},- { 8364, 1, 3, 7, { 0 }},- { 165, 1, 3, 7, { 0 }},- { 352, 0, 14, 4, { 0 }},- { 167, 0, 14, 4, { 0 }},- { 353, 0, 14, 4, { 0 }},- { 169, 1, 3, 9, { 0 }},- { 170, 0, 14, 4, { 0 }},- { 171, 0, 14, 4, { 0 }},- { 172, 1, 8, 7, { 0 }},- { 174, 1, 3, 9, { 0 }},- { 175, 1, 1, 7, { 0 }},- { 176, 1, 0, 5, { 0 }},- { 177, 1, 7, 7, { 0 }},- { 178, 0, 14, 4, { 0 }},- { 179, 0, 14, 4, { 0 }},- { 381, 0, 14, 4, { 0 }},- { 181, 1, 6, 7, { 0 }},- { 182, 1, 3, 9, { 0 }},- { 183, 1, 8, 3, { 0 }},- { 382, 0, 14, 4, { 0 }},- { 185, 0, 14, 4, { 0 }},- { 186, 0, 14, 4, { 0 }},- { 187, 0, 14, 4, { 0 }},- { 338, 0, 14, 4, { 0 }},- { 339, 0, 14, 4, { 0 }},- { 376, 1, 1, 7, { 0 }},- { 191, 1, 3, 7, { 0 }},- { 192, 1, 0, 7, { 0 }},- { 193, 1, 0, 7, { 0 }},- { 194, 1, 0, 7, { 0 }},- { 195, 1, 0, 7, { 0 }},- { 196, 1, 1, 7, { 0 }},- { 197, 1, 1, 7, { 0 }},- { 198, 1, 3, 11, { 0 }},- { 199, 1, 3, 7, { 0 }},- { 200, 1, 0, 7, { 0 }},- { 201, 1, 0, 7, { 0 }},- { 202, 1, 0, 7, { 0 }},- { 203, 1, 1, 7, { 0 }},- { 204, 0, 0, 3, { 0 }},- { 205, 1, 0, 3, { 0 }},- { 206, 0, 0, 3, { 0 }},- { 207, 0, 1, 3, { 0 }},- { 208, 1, 3, 7, { 0 }},- { 209, 1, 0, 7, { 0 }},- { 210, 1, 0, 7, { 0 }},- { 211, 1, 0, 7, { 0 }},- { 212, 1, 0, 7, { 0 }},- { 213, 1, 0, 7, { 0 }},- { 214, 1, 1, 7, { 0 }},- { 215, 1, 7, 7, { 0 }},- { 216, 1, 2, 7, { 0 }},- { 217, 1, 0, 7, { 0 }},- { 218, 1, 0, 7, { 0 }},- { 219, 1, 0, 7, { 0 }},- { 220, 1, 1, 7, { 0 }},- { 221, 1, 0, 7, { 0 }},- { 222, 1, 3, 7, { 0 }},- { 223, 1, 3, 7, { 0 }},- { 224, 1, 3, 7, { 0 }},- { 225, 1, 3, 7, { 0 }},- { 226, 1, 3, 7, { 0 }},- { 227, 1, 3, 7, { 0 }},- { 228, 1, 4, 7, { 0 }},- { 229, 1, 4, 7, { 0 }},- { 230, 1, 6, 11, { 0 }},- { 231, 1, 6, 7, { 0 }},- { 232, 1, 3, 7, { 0 }},- { 233, 1, 3, 7, { 0 }},- { 234, 1, 3, 7, { 0 }},- { 235, 1, 4, 7, { 0 }},- { 236, 0, 3, 3, { 0 }},- { 237, 1, 3, 3, { 0 }},- { 238, 0, 3, 3, { 0 }},- { 239, 0, 4, 3, { 0 }},- { 240, 1, 3, 7, { 0 }},- { 241, 1, 3, 7, { 0 }},- { 242, 1, 3, 7, { 0 }},- { 243, 1, 3, 7, { 0 }},- { 244, 1, 3, 7, { 0 }},- { 245, 1, 3, 7, { 0 }},- { 246, 1, 4, 7, { 0 }},- { 247, 1, 7, 7, { 0 }},- { 248, 1, 5, 7, { 0 }},- { 249, 1, 3, 7, { 0 }},- { 250, 1, 3, 7, { 0 }},- { 251, 1, 3, 7, { 0 }},- { 252, 1, 4, 7, { 0 }},- { 253, 1, 3, 7, { 0 }},- { 254, 1, 6, 6, { 0 }},- { 255, 1, 4, 7, { 0 }},-};--// Style loading function: Terminal-static void GuiLoadStyleTerminal(void)-{- // Load style properties provided- // NOTE: Default properties are propagated- for (int i = 0; i < TERMINAL_STYLE_PROPS_COUNT; i++)- {- GuiSetStyle(terminalStyleProps[i].controlId, terminalStyleProps[i].propertyId, terminalStyleProps[i].propertyValue);- }-- // Custom font loading- // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function- int terminalFontDataSize = 0;- unsigned char *data = DecompressData(terminalFontData, TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE, &terminalFontDataSize);- Image imFont = { data, 512, 256, 1, 2 };-- Font font = { 0 };- font.baseSize = 16;- font.glyphCount = 189;-- // Load texture from image- font.texture = LoadTextureFromImage(imFont);- UnloadImage(imFont); // Uncompressed image data can be unloaded from memory-- // Copy char recs data from global fontRecs- // NOTE: Required to avoid issues if trying to free font- font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));- memcpy(font.recs, terminalFontRecs, font.glyphCount*sizeof(Rectangle));-- // Copy font char info data from global fontChars- // NOTE: Required to avoid issues if trying to free font- font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));- memcpy(font.glyphs, terminalFontGlyphs, font.glyphCount*sizeof(GlyphInfo));-- GuiSetFont(font);-- // Setup a white rectangle on the font to be used on shapes drawing,- // it makes possible to draw shapes and text (full UI) in a single draw call- Rectangle fontWhiteRec = { 510, 254, 1, 1 };- SetShapesTexture(font.texture, fontWhiteRec);-- //------------------------------------------------------------------- // TODO: Custom user style setup: Set specific properties here (if required)- // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT-}
raygui/src/raygui.h view
@@ -616,7 +616,8 @@ // DropdownBox typedef enum { ARROW_PADDING = 16, // DropdownBox arrow separation from border and items- DROPDOWN_ITEMS_SPACING // DropdownBox items separation+ DROPDOWN_ITEMS_SPACING, // DropdownBox items separation+ DROPDOWN_ARROW_HIDDEN // DropdownBox arrow hidden } GuiDropdownBoxProperty; // TextBox/TextBoxMulti/ValueBox/Spinner@@ -636,6 +637,7 @@ LIST_ITEMS_SPACING, // ListView items separation SCROLLBAR_WIDTH, // ListView scrollbar size (usually width) SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)+ LIST_ITEMS_BORDER_WIDTH // ListView items border width } GuiListViewProperty; // ColorPicker@@ -722,6 +724,7 @@ RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers+RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control@@ -1292,11 +1295,11 @@ 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_223- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_224- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_225- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_226- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_227+ 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY+ 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO+ 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_228 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230@@ -1449,6 +1452,7 @@ static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings static int TextToInteger(const char *text); // Get integer value from text+static float TextToFloat(const char *text); // Get float value from text static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter)@@ -1743,6 +1747,9 @@ if (toggle) *active = i; } + // Close tab with middle mouse button pressed+ if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;+ GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding); GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); @@ -1864,7 +1871,7 @@ float wheelMove = GetMouseWheelMove(); // Set scrolling speed with mouse wheel based on ratio between bounds and content- Vector2 mouseWheelSpeed = { content.width / bounds.width, content.height / bounds.height };+ Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height }; if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED; if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED; @@ -2322,6 +2329,9 @@ int result = 0; GuiState state = guiState; + int temp = 0;+ if (active == NULL) active = &temp;+ int itemSelected = *active; int itemFocused = -1; @@ -2417,14 +2427,17 @@ } } - // Draw arrows (using icon if available)+ if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN))+ {+ // Draw arrows (using icon if available) #if defined(RAYGUI_NO_ICONS)- GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },- TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));+ GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); #else- GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },- TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL+ GuiDrawText("#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL #endif+ } //-------------------------------------------------------------------- *active = itemSelected;@@ -2451,7 +2464,10 @@ int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);- int textWidth = GetTextWidth(text) - GetTextWidth(text + textBoxCursorIndex);+ int textLength = (int)strlen(text); // Get current text length+ int thisCursorIndex = textBoxCursorIndex;+ if (thisCursorIndex > textLength) thisCursorIndex = textLength;+ int textWidth = GetTextWidth(text) - GetTextWidth(text + thisCursorIndex); int textIndexOffset = 0; // Text index offset to start drawing in the box // Cursor rectangle@@ -2500,6 +2516,8 @@ { state = STATE_PRESSED; + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;+ // If text does not fit in the textbox and current cursor position is out of bounds, // we add an index offset to text for drawing only what requires depending on cursor while (textWidth >= textBounds.width)@@ -2512,12 +2530,9 @@ textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex); } - int textLength = (int)strlen(text); // Get current text length int codepoint = GetCharPressed(); // Get Unicode codepoint if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; - if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;- // Encode codepoint as UTF-8 int codepointSize = 0; const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);@@ -2559,6 +2574,7 @@ for (int i = textBoxCursorIndex; i < textLength; i++) text[i] = text[i + nextCodepointSize]; textLength -= codepointSize;+ if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; // Make sure text last character is EOL text[textLength] = '\0';@@ -2578,6 +2594,8 @@ // Move backward text from cursor position for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + // TODO Check: >= cursor+codepointsize and <= length-codepointsize+ // Prevent cursor index from decrementing past 0 if (textBoxCursorIndex > 0) {@@ -2648,7 +2666,7 @@ if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) { mouseCursor.x = textBounds.x + textEndWidth;- mouseCursorIndex = (int)strlen(text);+ mouseCursorIndex = textLength; } // Place cursor at required index on mouse click@@ -2680,7 +2698,7 @@ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {- textBoxCursorIndex = (int)strlen(text); // GLOBAL: Place cursor index to the end of current text+ textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text result = 1; } }@@ -2931,6 +2949,117 @@ return result; } +// Floating point Value Box control, updates input val_str with numbers+// NOTE: Requires static variables: frameCounter+int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode)+{+ #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)+ #define RAYGUI_VALUEBOX_MAX_CHARS 32+ #endif++ int result = 0;+ GuiState state = guiState;++ //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";+ //sprintf(textValue, "%2.2f", *value);++ Rectangle textBounds = {0};+ if (text != NULL)+ {+ textBounds.width = (float)GetTextWidth(text) + 2;+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);+ }++ // Update control+ //--------------------------------------------------------------------+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)+ {+ Vector2 mousePoint = GetMousePosition();++ bool valueHasChanged = false;++ if (editMode)+ {+ state = STATE_PRESSED;++ int keyCount = (int)strlen(textValue);++ // Only allow keys in range [48..57]+ if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)+ {+ if (GetTextWidth(textValue) < bounds.width)+ {+ int key = GetCharPressed();+ if (((key >= 48) && (key <= 57)) ||+ (key == '.') ||+ ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position+ ((keyCount == 0) && (key == '-')))+ {+ textValue[keyCount] = (char)key;+ keyCount++;++ valueHasChanged = true;+ }+ }+ }++ // Pressed backspace+ if (IsKeyPressed(KEY_BACKSPACE))+ {+ if (keyCount > 0)+ {+ keyCount--;+ textValue[keyCount] = '\0';+ valueHasChanged = true;+ }+ }++ if (valueHasChanged) *value = TextToFloat(textValue);++ if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;+ }+ else+ {+ if (CheckCollisionPointRec(mousePoint, bounds))+ {+ state = STATE_FOCUSED;+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;+ }+ }+ }+ //--------------------------------------------------------------------++ // Draw control+ //--------------------------------------------------------------------+ Color baseColor = BLANK;+ if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));+ else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));++ GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);+ GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));++ // Draw cursor+ if (editMode)+ {+ // NOTE: ValueBox internal text is always centered+ Rectangle cursor = {bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 1,+ bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4,+ bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));+ }++ // Draw text label if provided+ GuiDrawText(text, textBounds,+ (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT,+ GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));+ //--------------------------------------------------------------------++ return result;+}+ // Slider control with pro parameters // NOTE: Other GuiSlider*() controls use this one int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth)@@ -2988,13 +3117,13 @@ if (*value > maxValue) *value = maxValue; else if (*value < minValue) *value = minValue; }- + // Control value change check- if(oldValue == *value) result = 0;+ if (oldValue == *value) result = 0; else result = 1; // Slider bar limits check- int sliderValue = (int)(((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - GuiGetStyle(SLIDER, BORDER_WIDTH)));+ float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); if (sliderWidth > 0) // Slider { slider.x += sliderValue;@@ -3005,7 +3134,7 @@ else if (sliderWidth == 0) // SliderBar { slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);- slider.width = (float)sliderValue;+ slider.width = sliderValue; if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH); } //--------------------------------------------------------------------@@ -3280,6 +3409,8 @@ // Draw visible items for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) {+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);+ if (state == STATE_DISABLED) { if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));@@ -3354,7 +3485,7 @@ GuiColorPanelHSV(bounds, text, &hsv); // Check if the hsv was changed, only then change the color.- // This is necessary, because the Color->HSV->Color conversion has precision errors.+ // This is required, because the Color->HSV->Color conversion has precision errors. // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value. // Otherwise GuiColorPanel would often modify it's color without user input. // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check.@@ -3896,14 +4027,14 @@ // Draw vertical grid lines for (int i = 0; i < linesV; i++) {- Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height };+ Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 }; GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); } // Draw horizontal grid lines for (int i = 0; i < linesH; i++) {- Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 };+ Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 }; GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); } }@@ -4571,7 +4702,7 @@ } } - if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE - ICON_TEXT_PADDING);+ if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); } return (int)textSize.x;@@ -4794,8 +4925,8 @@ { // NOTE: We consider icon height, probably different than text size GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);- textBoundsPosition.x += (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);- textBoundsWidthOffset = (RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);+ textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);+ textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); } #endif // Get size in bytes of text,@@ -4811,8 +4942,8 @@ float textOffsetX = 0.0f; float glyphWidth = 0; - float ellipsisWidth = GetTextWidth("...");- bool overflowReached = false;+ int ellipsisWidth = GetTextWidth("...");+ bool textOverflow = false; for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) { int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);@@ -4826,7 +4957,7 @@ if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; - // Wrap mode text measuring, to validate if + // Wrap mode text measuring, to validate if // it can be drawn or a new line is required if (wrapMode == TEXT_WRAP_CHAR) {@@ -4883,10 +5014,12 @@ { DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); }- else if (!overflowReached)+ else if (!textOverflow) {- overflowReached = true;- for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) {+ textOverflow = true;++ for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3)+ { DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); } }@@ -5450,6 +5583,37 @@ return value*sign; } +// Get float value from text+// NOTE: This function replaces atof() [stdlib.h]+// WARNING: Only '.' character is understood as decimal point+static float TextToFloat(const char *text)+{+ float value = 0.0f;+ float sign = 1.0f;++ if ((text[0] == '+') || (text[0] == '-'))+ {+ if (text[0] == '-') sign = -1.0f;+ text++;+ }++ int i = 0;+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');++ if (text[i++] != '.') value *= sign;+ else+ {+ float divisor = 10.0f;+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++)+ {+ value += ((float)(text[i] - '0'))/divisor;+ divisor = divisor*10.0f;+ }+ }++ return value;+}+ // Encode codepoint into UTF-8 text (char array size returned as parameter) static const char *CodepointToUTF8(int codepoint, int *byteSize) {@@ -5503,21 +5667,21 @@ if (0xf0 == (0xf8 & ptr[0])) { // 4 byte UTF-8 codepoint- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); *codepointSize = 4; } else if (0xe0 == (0xf0 & ptr[0])) { // 3 byte UTF-8 codepoint */- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); *codepointSize = 3; } else if (0xc0 == (0xe0 & ptr[0])) { // 2 byte UTF-8 codepoint- if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks+ if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); *codepointSize = 2; }
+ raygui/styles/amber/style_amber.h view
@@ -0,0 +1,609 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleAmber(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2023 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define AMBER_STYLE_PROPS_COUNT 17++// Custom style name: Amber+static const GuiStyleProp amberStyleProps[AMBER_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x898988ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x292929ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xd4d4d4ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xf1850dff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x292929ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xffffffff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xf1850dff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xf1850dff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0xffffffff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 18, 0xf1850dff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x333333ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING + { 10, 7, 0x202020ff }, // VALUEBOX_BASE_COLOR_PRESSED +};++// WARNING: This style uses a custom font: "Inter-Regular.ttf" (size: 16, spacing: 1)++#define AMBER_STYLE_FONT_ATLAS_COMP_SIZE 6417++// Font atlas image pixels data: DEFLATE compressed+static unsigned char amberFontData[AMBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0x9d, 0x07, 0x78, 0x15, 0xc5, 0xda, 0xc7, 0x4f, 0x1a, 0x3d, 0x20, 0x4d, 0x10, 0x41, 0x45, 0xa5, 0x89, 0x8a, 0x7a, 0x45,+ 0xb0, 0x60, 0x47, 0x51, 0xb0, 0xe3, 0xc5, 0x02, 0x36, 0x14, 0x95, 0x0b, 0x28, 0x88, 0x5c, 0xf1, 0x43, 0x6c, 0x20, 0xd2,+ 0x14, 0x15, 0xb1, 0x80, 0xc1, 0x02, 0xd8, 0x50, 0x14, 0x51, 0x41, 0x91, 0x2e, 0x1d, 0x2e, 0xc5, 0x84, 0x2e, 0xed, 0x86,+ 0x16, 0x02, 0x84, 0x10, 0x02, 0x21, 0xe4, 0xf7, 0x3d, 0x3b, 0x67, 0xcf, 0xc9, 0x81, 0xf3, 0xce, 0x9e, 0x9c, 0x18, 0x10,+ 0xb8, 0x2f, 0xbf, 0xe7, 0x21, 0xc9, 0xce, 0xd6, 0xf9, 0xcf, 0xce, 0xcc, 0xee, 0xfe, 0xdf, 0x19, 0x7c, 0x8a, 0xa2, 0x28,+ 0x8a, 0xa2, 0x28, 0x87, 0xf0, 0x1c, 0xf7, 0x84, 0x2d, 0x7b, 0x94, 0x07, 0x68, 0xca, 0x0b, 0xe2, 0xfa, 0x75, 0xe9, 0x62,+ 0x7e, 0xf6, 0xe3, 0x24, 0xeb, 0x3e, 0x63, 0x48, 0xb0, 0xa4, 0xc4, 0xd2, 0x93, 0x71, 0xb4, 0x72, 0xff, 0x2a, 0xc1, 0x3b,+ 0x54, 0xb0, 0xac, 0xd9, 0x84, 0x21, 0x0c, 0xe4, 0x74, 0x4b, 0xaa, 0x73, 0x86, 0xd2, 0xf2, 0x8b, 0x29, 0x19, 0xb6, 0xac,+ 0x02, 0xe7, 0x58, 0xcf, 0xf4, 0x64, 0xba, 0x5b, 0xd3, 0xea, 0xf0, 0x1f, 0x6b, 0x5a, 0x23, 0x2e, 0x0f, 0x5b, 0x56, 0x86,+ 0x11, 0x2e, 0xa7, 0x84, 0xa5, 0x75, 0xa0, 0x85, 0x65, 0x4f, 0xa5, 0x29, 0x21, 0x2e, 0xbf, 0x84, 0xf7, 0xf9, 0x8a, 0xb6,+ 0xd6, 0x7c, 0x7c, 0x8a, 0x24, 0xce, 0x2c, 0x02, 0xfd, 0x27, 0xd1, 0x2f, 0x6c, 0xd9, 0x07, 0x0c, 0xe2, 0x71, 0xa6, 0x89,+ 0xeb, 0xb7, 0x65, 0x08, 0x3e, 0x8a, 0x91, 0x41, 0xac, 0x75, 0x9f, 0xb5, 0xf8, 0xc4, 0x92, 0x72, 0x2f, 0x13, 0xb9, 0x90,+ 0x54, 0x4e, 0x35, 0x7f, 0x0d, 0x10, 0x8e, 0x1d, 0x28, 0x65, 0x99, 0x74, 0x64, 0x28, 0x6b, 0x88, 0x11, 0xd3, 0x9d, 0x33,+ 0x0c, 0x5f, 0x7a, 0x35, 0xa9, 0xc4, 0x87, 0x2d, 0x3d, 0x95, 0x3d, 0x54, 0x13, 0xd6, 0x2e, 0xce, 0xd3, 0xd4, 0xe4, 0x57,+ 0x6a, 0xd2, 0x5a, 0x3c, 0xc6, 0xb9, 0xa4, 0x59, 0xaf, 0x70, 0x22, 0x3d, 0xc3, 0x96, 0x95, 0xa0, 0xa3, 0x4b, 0xf9, 0xb0,+ 0xb4, 0x05, 0x0c, 0xb5, 0xec, 0x69, 0x2a, 0xb7, 0x8b, 0xe5, 0x2b, 0x8b, 0x89, 0xf4, 0x63, 0x3f, 0xbd, 0x85, 0xd4, 0xca,+ 0x8c, 0x67, 0x11, 0x79, 0x34, 0x2a, 0x02, 0xfd, 0x7f, 0xa5, 0x4f, 0xd8, 0xb2, 0x37, 0x79, 0x8d, 0x36, 0x8c, 0x17, 0xd7,+ 0x1f, 0x40, 0x07, 0x93, 0x37, 0x0b, 0xad, 0x7b, 0x6c, 0xca, 0xe7, 0x6c, 0xe0, 0x15, 0xf1, 0xde, 0x7d, 0xc9, 0xd4, 0x2a,+ 0x93, 0x69, 0x82, 0x8f, 0xab, 0x58, 0x44, 0x71, 0xcb, 0x3e, 0xfe, 0xcd, 0x38, 0x7c, 0x54, 0x23, 0xcf, 0x52, 0x3f, 0x38,+ 0x67, 0x18, 0xbe, 0xf4, 0x07, 0x5e, 0x16, 0xd7, 0xfe, 0x56, 0x5c, 0x3b, 0x91, 0xfe, 0x2c, 0x61, 0x33, 0x0b, 0x69, 0x19,+ 0x96, 0xd6, 0x90, 0x66, 0x3c, 0xce, 0x2e, 0x9a, 0xd1, 0x8c, 0xb3, 0x84, 0x6d, 0x37, 0xd2, 0x38, 0xaa, 0x5c, 0x8e, 0xb7,+ 0x94, 0xe3, 0x32, 0xec, 0xa5, 0x9c, 0xb0, 0x7c, 0x20, 0xef, 0x99, 0x2d, 0xae, 0xe2, 0xbf, 0x42, 0xea, 0xc3, 0x0c, 0xa1,+ 0x04, 0x07, 0x8b, 0x44, 0xff, 0xf1, 0xf4, 0x0a, 0x5b, 0xd6, 0x9b, 0x1e, 0xb4, 0xe4, 0xdb, 0xb0, 0xe5, 0x67, 0x90, 0x4d,+ 0x2e, 0xfb, 0xc9, 0x66, 0x3f, 0x07, 0xc9, 0x16, 0xca, 0xb9, 0x8f, 0x27, 0x49, 0x67, 0x18, 0xb3, 0xf9, 0x8e, 0x2d, 0x42,+ 0xfd, 0xd4, 0x9c, 0xf9, 0xb4, 0x62, 0x13, 0x15, 0x48, 0x64, 0x05, 0x17, 0x58, 0xcf, 0xea, 0x5a, 0x76, 0x70, 0x36, 0xdf,+ 0x58, 0xca, 0xa0, 0xff, 0x0c, 0x0f, 0x5f, 0x56, 0x8a, 0x7d, 0x34, 0x10, 0xd7, 0x6e, 0x4d, 0xb2, 0xb0, 0x34, 0x8e, 0xd6,+ 0x2c, 0x25, 0x93, 0xef, 0x39, 0x4f, 0xc8, 0xff, 0x49, 0xcc, 0x21, 0x87, 0x49, 0x4c, 0xa2, 0x8d, 0x50, 0x72, 0xd2, 0x89,+ 0x2b, 0x92, 0xd6, 0xb7, 0x39, 0x33, 0xc5, 0xe5, 0xf3, 0xb8, 0xcd, 0x3d, 0xc7, 0x3d, 0x9c, 0x2d, 0x5c, 0xa9, 0xf3, 0x7f,+ 0xd1, 0xe8, 0xff, 0x23, 0x2f, 0x85, 0x2d, 0x4b, 0x20, 0x81, 0x38, 0xe1, 0xde, 0x8c, 0x21, 0x9e, 0xf5, 0x54, 0x27, 0x9e,+ 0x57, 0xe8, 0x21, 0xd4, 0xb4, 0x0e, 0x2b, 0x78, 0xd4, 0xad, 0xff, 0xbf, 0xe0, 0x61, 0x51, 0x8b, 0x41, 0xa6, 0xed, 0x1c,+ 0xc6, 0xf3, 0x9e, 0xe7, 0xf5, 0x2d, 0x39, 0x4c, 0xa0, 0xac, 0x25, 0x35, 0x41, 0xe8, 0x61, 0xdc, 0x48, 0x9a, 0xa5, 0x4d,+ 0x3a, 0x95, 0x3c, 0xa1, 0x05, 0xa8, 0xc0, 0x50, 0x2e, 0xe0, 0x17, 0xae, 0xb5, 0xd4, 0x1a, 0xf6, 0xfa, 0xbf, 0x0c, 0x57,+ 0x16, 0x51, 0xef, 0x6b, 0x90, 0x78, 0xec, 0xb2, 0xe4, 0x52, 0xdd, 0xfd, 0x7d, 0x06, 0x8f, 0x58, 0xb6, 0x2d, 0x1a, 0xfd,+ 0xc7, 0x5a, 0xfa, 0x79, 0xb6, 0x2b, 0x4f, 0x37, 0x3f, 0xbf, 0xe2, 0x0e, 0x6b, 0x7b, 0xd6, 0xc3, 0xa3, 0xfd, 0x0f, 0x70,+ 0x0b, 0x33, 0x89, 0x23, 0x96, 0x3a, 0x96, 0x16, 0xe0, 0x16, 0x32, 0x58, 0xcb, 0x87, 0xf8, 0x38, 0x85, 0xf3, 0x0b, 0x78,+ 0x6e, 0x4f, 0xf3, 0x9b, 0x35, 0x6d, 0x1b, 0xd7, 0x59, 0x4a, 0xc6, 0x87, 0xd6, 0x6d, 0xbc, 0xda, 0xff, 0xa2, 0x22, 0xd9,+ 0xb4, 0x84, 0x87, 0x53, 0x93, 0x3c, 0x4a, 0x07, 0xf5, 0x79, 0xee, 0x88, 0xea, 0x3f, 0x9c, 0xa7, 0x0a, 0xbc, 0x6e, 0x7b,+ 0xbe, 0x65, 0x07, 0xc3, 0x19, 0xce, 0x36, 0xc6, 0x72, 0xb7, 0xb8, 0xce, 0x75, 0x6c, 0x65, 0x3e, 0x53, 0xac, 0x3d, 0x77,+ 0x87, 0x4a, 0xac, 0xa1, 0x16, 0x09, 0xcc, 0x60, 0x12, 0x6b, 0x85, 0x35, 0xab, 0xb0, 0x87, 0x7b, 0xa9, 0xce, 0x26, 0x3a,+ 0xf2, 0x1c, 0x1f, 0x17, 0xf0, 0xec, 0xfa, 0x32, 0xd2, 0x9a, 0xb6, 0xc4, 0xd2, 0xc7, 0xf3, 0xa2, 0x1c, 0x77, 0x1d, 0x61,+ 0xf5, 0x4f, 0x65, 0xb7, 0xe5, 0x49, 0xe9, 0xbf, 0xc1, 0xe7, 0x8b, 0x8d, 0x62, 0x09, 0x29, 0x3a, 0xfd, 0xa3, 0xe1, 0x5a,+ 0x86, 0x32, 0x9e, 0x7b, 0x68, 0x43, 0x36, 0xf7, 0x50, 0xd7, 0x5a, 0x47, 0xbc, 0xcc, 0x6e, 0x0e, 0xf0, 0x99, 0xb5, 0x77,+ 0x37, 0x9a, 0x7f, 0x99, 0x27, 0x9c, 0x39, 0xf8, 0x78, 0x83, 0xce, 0x61, 0xe9, 0xd7, 0xb3, 0xdb, 0xd4, 0xe4, 0x97, 0xb0,+ 0x9b, 0xf5, 0x3c, 0x5e, 0xc0, 0xb3, 0xeb, 0xc3, 0x28, 0x6b, 0xda, 0x52, 0xee, 0x3b, 0x06, 0x9f, 0xbd, 0x1f, 0x64, 0xac,+ 0x25, 0x65, 0x94, 0x7b, 0x57, 0x56, 0x25, 0xdb, 0x9a, 0x8b, 0x45, 0xa3, 0x7f, 0x7b, 0x9a, 0x47, 0xb1, 0xf6, 0xeb, 0x3c,+ 0x8d, 0x8f, 0x7a, 0x2c, 0xf1, 0x5c, 0xcb, 0xa9, 0xff, 0xcf, 0x24, 0x99, 0x17, 0x2d, 0xbd, 0xb1, 0x09, 0xa6, 0x6f, 0xdb,+ 0x90, 0xb9, 0xa6, 0x05, 0xec, 0x14, 0xb6, 0xc6, 0x49, 0xec, 0xa3, 0x1d, 0x09, 0x34, 0x66, 0x1e, 0x50, 0xbf, 0x80, 0xe7,+ 0xf6, 0x08, 0xf3, 0xac, 0x4f, 0xcb, 0x7b, 0xb9, 0xf8, 0x18, 0xd4, 0x7f, 0x84, 0x70, 0xed, 0x7e, 0xda, 0xb1, 0x95, 0xd6,+ 0x9c, 0xcb, 0x74, 0x8f, 0x36, 0xad, 0x68, 0xf4, 0xb7, 0x3f, 0x99, 0xca, 0xbd, 0x85, 0x1b, 0xf1, 0x71, 0x17, 0x5f, 0x58,+ 0xd2, 0xcb, 0xd3, 0x8b, 0x8a, 0x6e, 0xfb, 0x3f, 0x98, 0xaf, 0x84, 0x35, 0xaa, 0xf3, 0xa7, 0xdb, 0xb7, 0x49, 0x60, 0x0a,+ 0xb3, 0x59, 0xe3, 0xbe, 0x0b, 0x38, 0xbc, 0x06, 0x58, 0x45, 0x16, 0x39, 0x8c, 0xe4, 0x0d, 0x52, 0xc4, 0x27, 0x24, 0xe9,+ 0x8d, 0x91, 0xed, 0x9d, 0xc4, 0x99, 0x60, 0xed, 0x49, 0xfe, 0x7d, 0xc4, 0xb0, 0x99, 0x7a, 0x96, 0xb4, 0x38, 0x06, 0x91,+ 0x45, 0x2e, 0x33, 0x83, 0xfd, 0xc0, 0x23, 0xa5, 0xbf, 0xed, 0xc9, 0xb4, 0xb0, 0x4c, 0x67, 0x04, 0x4d, 0xf8, 0x8c, 0xe6,+ 0xec, 0xa2, 0x5d, 0xc4, 0xb5, 0x4f, 0xb7, 0x3c, 0x45, 0xf8, 0xcb, 0x52, 0xb1, 0xa8, 0x8e, 0x5c, 0x9c, 0xcd, 0xdc, 0x64,+ 0x79, 0xc7, 0x39, 0xe5, 0x18, 0xbc, 0xfb, 0xcf, 0x67, 0xa3, 0x67, 0x7a, 0xc2, 0x31, 0x58, 0x66, 0x23, 0x73, 0x1e, 0x5f,+ 0x90, 0x45, 0x1e, 0xdb, 0x78, 0xa9, 0x88, 0x4b, 0x56, 0x64, 0x7a, 0x0a, 0xef, 0x2c, 0x9c, 0xfb, 0x6c, 0x95, 0xf5, 0x69,+ 0xe5, 0xef, 0xa4, 0x0b, 0xc3, 0x4f, 0xd0, 0x6f, 0x0a, 0xe7, 0xf1, 0xb5, 0xc7, 0xdb, 0xe1, 0x23, 0xc7, 0xc9, 0xcc, 0x24,+ 0x51, 0x38, 0x9b, 0x5f, 0x8a, 0xe8, 0x6d, 0x4d, 0xd1, 0x72, 0x13, 0x17, 0x9e, 0xa0, 0xfa, 0x97, 0xe3, 0x1a, 0xfd, 0xb2,+ 0xa6, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0x72, 0x54, 0xb9, 0x8d, 0x8f,+ 0xf9, 0xd4, 0xc3, 0xd7, 0x72, 0x2b, 0x1f, 0xf1, 0x25, 0x8f, 0x79, 0x7e, 0xb9, 0xa9, 0x49, 0x92, 0xe8, 0x19, 0x68, 0x40,+ 0x92, 0x4b, 0x4f, 0xcb, 0x96, 0xb5, 0x79, 0x83, 0x31, 0x3c, 0x27, 0x3a, 0xde, 0x2f, 0x0b, 0x6e, 0x9d, 0x24, 0x38, 0x92,+ 0xfd, 0x9e, 0xb0, 0x24, 0x3e, 0xe7, 0x11, 0xeb, 0xb9, 0xb5, 0x34, 0xe7, 0xde, 0x52, 0x4c, 0xfb, 0x84, 0x6e, 0xc2, 0xd2,+ 0xee, 0x24, 0x79, 0x7e, 0x7f, 0x2b, 0x2d, 0x38, 0x6f, 0x7f, 0x08, 0xd2, 0x50, 0x78, 0xef, 0xed, 0x9d, 0xfb, 0x67, 0x31,+ 0x88, 0x31, 0x74, 0xb7, 0x3a, 0x3a, 0x02, 0xfe, 0x99, 0xcb, 0x38, 0x2d, 0xe2, 0x17, 0x96, 0x24, 0x2e, 0x8b, 0x5a, 0xfd,+ 0x27, 0xd8, 0xc2, 0x8b, 0xbc, 0xc0, 0x66, 0x3a, 0x8a, 0xe9, 0x9d, 0xd9, 0x4c, 0x67, 0x9e, 0xe1, 0x4f, 0xfa, 0x7b, 0x3a,+ 0x86, 0x0f, 0x8a, 0x51, 0x13, 0x8f, 0xb1, 0x8a, 0x67, 0x0d, 0x6d, 0x2c, 0x9e, 0xfe, 0x6d, 0xcc, 0xa6, 0x33, 0x0b, 0x99,+ 0x28, 0xa4, 0xd6, 0x77, 0xb7, 0x7d, 0x96, 0xc9, 0xc6, 0x17, 0x12, 0x9e, 0xf3, 0xdb, 0x79, 0xd9, 0x9c, 0x9b, 0x1c, 0x33,+ 0xd0, 0x8d, 0x74, 0x9e, 0xa7, 0x1b, 0x9b, 0x44, 0xbf, 0xdc, 0x30, 0x37, 0x6a, 0xe5, 0x50, 0x9e, 0xe5, 0x03, 0xeb, 0x57,+ 0xf1, 0x87, 0x58, 0x2d, 0x78, 0xbc, 0xff, 0xc1, 0x03, 0x41, 0xaa, 0x0b, 0xdf, 0x99, 0xa7, 0x72, 0xb5, 0xc7, 0xd7, 0xa9,+ 0x34, 0x3e, 0xe6, 0x21, 0xe6, 0x32, 0xda, 0xea, 0x08, 0x78, 0x81, 0x85, 0xac, 0xe7, 0x07, 0x16, 0xb1, 0x99, 0x6e, 0x1e,+ 0x5f, 0xad, 0xde, 0x61, 0x1d, 0x5f, 0x46, 0xad, 0xff, 0x62, 0xe3, 0xdd, 0x77, 0xdc, 0x25, 0x29, 0x16, 0xcf, 0xed, 0x0d,+ 0xe6, 0xe7, 0xdd, 0xa4, 0x5b, 0xef, 0xb2, 0xfb, 0x49, 0xe6, 0x67, 0x51, 0xff, 0x5e, 0x1e, 0xfe, 0x3b, 0xff, 0x3d, 0xf8,+ 0xbe, 0xd9, 0x6b, 0x55, 0x66, 0x0b, 0x9e, 0xe6, 0xfc, 0x28, 0x8a, 0x8d, 0xdc, 0x2f, 0xfa, 0x0a, 0x7a, 0xba, 0x77, 0xf9,+ 0x76, 0xe1, 0xdc, 0xe2, 0xc9, 0x74, 0xbf, 0xfd, 0x37, 0x62, 0x8f, 0xe8, 0x4b, 0x2f, 0x38, 0x71, 0x3c, 0xc0, 0x2a, 0xfe,+ 0xa0, 0xb5, 0x87, 0x37, 0x41, 0xe6, 0x24, 0xfe, 0x8f, 0x6d, 0x4c, 0xb6, 0xb8, 0x83, 0x9b, 0x31, 0xd1, 0xec, 0xb1, 0x11,+ 0x39, 0x42, 0x94, 0x92, 0xa3, 0xfe, 0x3b, 0x4c, 0x0d, 0x46, 0x1b, 0x54, 0x66, 0x8c, 0xd5, 0x1d, 0x96, 0x40, 0x1a, 0x77,+ 0xb0, 0xd7, 0x23, 0x02, 0xcb, 0xe6, 0x37, 0x2c, 0xe6, 0xe6, 0xe1, 0x4a, 0xcf, 0xf5, 0x9e, 0xb2, 0xfa, 0xbb, 0x2a, 0xb2,+ 0x85, 0x2b, 0xf8, 0x5e, 0xd4, 0xff, 0x53, 0xfa, 0x50, 0x9f, 0x8b, 0x2d, 0xa5, 0x36, 0x8e, 0x6c, 0x5a, 0x50, 0x81, 0xc6,+ 0x96, 0x78, 0xa7, 0x00, 0x1d, 0x59, 0x26, 0xee, 0xe1, 0x73, 0xde, 0x71, 0xe3, 0x0b, 0x16, 0x8b, 0x2d, 0x0b, 0xee, 0x97,+ 0xdf, 0x58, 0xb2, 0xb9, 0xe2, 0x2f, 0xa8, 0x7f, 0x0f, 0x2b, 0x98, 0xcd, 0x6d, 0x96, 0xf2, 0xdf, 0x83, 0xd4, 0x20, 0xd7,+ 0x8b, 0x6b, 0x94, 0xa2, 0x13, 0xeb, 0x99, 0xe8, 0xe1, 0x37, 0xbb, 0x97, 0xad, 0xe2, 0xde, 0xbb, 0x32, 0x8f, 0xb2, 0x24,+ 0xd0, 0x94, 0x27, 0x39, 0x9b, 0xdb, 0x88, 0x65, 0xb6, 0x78, 0x27, 0x38, 0xad, 0xf4, 0x3a, 0x62, 0x58, 0xc8, 0x63, 0x85,+ 0xba, 0xc2, 0x92, 0x2c, 0xe6, 0x19, 0x6b, 0xea, 0xa3, 0x8c, 0x64, 0x05, 0xd7, 0x5a, 0x52, 0x93, 0x78, 0x1f, 0x9f, 0x45,+ 0xff, 0x29, 0xa4, 0xb1, 0x92, 0x6d, 0x6c, 0x15, 0xe3, 0x3a, 0x9c, 0x58, 0x9e, 0xde, 0x64, 0xf0, 0x27, 0x59, 0xd6, 0x58,+ 0x38, 0xe7, 0xdc, 0x52, 0x2d, 0x4e, 0xcd, 0x3a, 0xcc, 0xe1, 0x5b, 0x86, 0xb3, 0x4c, 0xbc, 0xbb, 0xe2, 0xc9, 0x70, 0x23,+ 0x26, 0x6e, 0x04, 0x4b, 0xfb, 0x53, 0x30, 0x26, 0xb3, 0x89, 0x5b, 0xac, 0xb5, 0x5f, 0x55, 0xce, 0x0d, 0x92, 0x68, 0xbd,+ 0x86, 0xce, 0xe4, 0x08, 0x51, 0x15, 0x01, 0xf5, 0x77, 0xf3, 0x90, 0xe5, 0xc8, 0x4e, 0xa9, 0x1b, 0xc5, 0x34, 0xde, 0x67,+ 0x0d, 0xbb, 0xf0, 0xd1, 0x42, 0x6c, 0x29, 0x1d, 0xf7, 0xfd, 0x00, 0xd3, 0xda, 0x4c, 0x2f, 0xc4, 0xf5, 0xc5, 0x32, 0x9a,+ 0x09, 0x1e, 0x35, 0xdb, 0xab, 0xfc, 0xce, 0x2a, 0x8b, 0xb7, 0xfb, 0x1a, 0x52, 0x4d, 0x9d, 0x23, 0xeb, 0x5f, 0xcf, 0x38,+ 0x35, 0x63, 0x79, 0x83, 0x75, 0x62, 0xef, 0x10, 0x26, 0x98, 0x7b, 0xbf, 0x35, 0xd9, 0xd6, 0xa8, 0xcf, 0xa7, 0x48, 0xb1,+ 0xd4, 0x1f, 0xb7, 0xb0, 0x81, 0x29, 0x8c, 0x64, 0xbd, 0xdb, 0x86, 0x85, 0x6f, 0x99, 0x41, 0x7f, 0x06, 0x92, 0x4c, 0x6a,+ 0x30, 0xbe, 0x34, 0x52, 0xfc, 0xa5, 0x14, 0xc5, 0x19, 0xcb, 0x3f, 0xf9, 0x83, 0x25, 0xdc, 0x17, 0x75, 0xed, 0xef, 0xef,+ 0x01, 0x3e, 0xc7, 0x16, 0x7e, 0xe2, 0x12, 0x4b, 0xfa, 0xa5, 0xec, 0xa3, 0x99, 0xa5, 0xc7, 0xe1, 0x44, 0x29, 0x5e, 0xcc,+ 0x12, 0x73, 0xdc, 0x3b, 0x8c, 0xfe, 0xa7, 0xb2, 0x4d, 0x6c, 0x65, 0xb2, 0x4d, 0xed, 0x72, 0x1a, 0x07, 0xc5, 0xd8, 0x34,+ 0x6f, 0xde, 0x63, 0x71, 0x44, 0x5f, 0xd9, 0x55, 0xe4, 0x52, 0x55, 0x68, 0x99, 0x57, 0xd0, 0x86, 0x92, 0x94, 0xe4, 0x07,+ 0x7a, 0x7a, 0xf4, 0x61, 0xcb, 0x73, 0x90, 0x5a, 0x42, 0xef, 0x87, 0x60, 0xbd, 0xbc, 0xd6, 0xbd, 0x57, 0xc3, 0xef, 0x9c,+ 0xcd, 0x42, 0x34, 0xb2, 0xff, 0xd8, 0xbb, 0xdd, 0xda, 0xee, 0x5c, 0x72, 0x2d, 0xae, 0xc9, 0x1b, 0x79, 0xcb, 0xc4, 0x9e,+ 0xec, 0x13, 0xea, 0x7f, 0xd9, 0xe5, 0x3a, 0xd1, 0xf2, 0xa4, 0x12, 0xcb, 0x3d, 0xa4, 0xb0, 0x9a, 0x9a, 0x51, 0xe6, 0xed,+ 0xad, 0xec, 0x64, 0xbc, 0x67, 0x64, 0x60, 0x37, 0x7e, 0xb4, 0xa4, 0xd4, 0x33, 0x5a, 0x3f, 0xe2, 0x9e, 0x67, 0x35, 0x57,+ 0xff, 0x4c, 0xb1, 0x86, 0xce, 0x63, 0x1a, 0x53, 0x99, 0xca, 0x3e, 0x6b, 0x2d, 0x63, 0xa3, 0x17, 0x2b, 0x05, 0x65, 0x03,+ 0x51, 0x6d, 0x1d, 0xa9, 0xe8, 0xf6, 0x2f, 0x76, 0x09, 0xf7, 0xcb, 0xa5, 0x84, 0xfe, 0x9b, 0x25, 0x44, 0x06, 0x9f, 0xe5,+ 0x2a, 0x9d, 0x27, 0x7a, 0x7a, 0x77, 0xb9, 0xbd, 0xcb, 0x18, 0xd2, 0x2c, 0xd1, 0x38, 0x5d, 0xf8, 0xc3, 0xe2, 0x1b, 0xab,+ 0x05, 0xd4, 0x70, 0xef, 0x93, 0x74, 0xee, 0x0c, 0x4b, 0x2f, 0x46, 0x17, 0xaa, 0x04, 0x5d, 0xc0, 0x89, 0x05, 0x74, 0xb9,+ 0x7a, 0x45, 0x71, 0xc6, 0x71, 0x9f, 0x50, 0x8a, 0xbd, 0x69, 0x16, 0xf1, 0x99, 0xac, 0xac, 0xb5, 0x6f, 0x5a, 0x89, 0xfd,+ 0xc4, 0x73, 0x3d, 0x93, 0xdc, 0xb2, 0x9c, 0x61, 0x1c, 0xf2, 0x2b, 0xc4, 0x08, 0xab, 0xe1, 0xdc, 0x6e, 0x18, 0xc0, 0xea,+ 0xa8, 0x3c, 0x96, 0x4f, 0x93, 0xc6, 0x3f, 0xa8, 0x64, 0x88, 0x15, 0xfa, 0x9f, 0x6b, 0x18, 0x45, 0x0d, 0xaa, 0xd0, 0x87,+ 0x2c, 0xa1, 0x6f, 0x19, 0x47, 0x69, 0x97, 0x9f, 0x78, 0x51, 0xe8, 0xc1, 0x7e, 0xcd, 0x64, 0x6a, 0x52, 0x89, 0x51, 0xcc,+ 0x16, 0x8f, 0xfe, 0x32, 0x8b, 0xa9, 0x45, 0x39, 0x06, 0x92, 0xea, 0x46, 0x30, 0x1e, 0xde, 0x73, 0xda, 0xc2, 0x3f, 0xad,+ 0x4f, 0x46, 0xeb, 0xf9, 0x88, 0x1a, 0x54, 0xa4, 0x27, 0xfb, 0xa9, 0x24, 0x3e, 0x1f, 0x8c, 0xa6, 0x1a, 0x37, 0x93, 0xcc,+ 0xc0, 0x02, 0xe6, 0x46, 0xd1, 0x45, 0x71, 0x46, 0xf3, 0xfe, 0xc5, 0xee, 0x89, 0xde, 0x4e, 0x5d, 0x4a, 0xb3, 0x82, 0x97,+ 0x68, 0xc3, 0x34, 0x72, 0x68, 0xc1, 0x68, 0xde, 0x12, 0x62, 0x70, 0xf3, 0x82, 0xf5, 0x5f, 0x79, 0xb1, 0xae, 0xb3, 0xfb,+ 0xcd, 0xf3, 0x42, 0xee, 0xdf, 0xd3, 0xc5, 0xbb, 0x6c, 0x06, 0x39, 0x1c, 0x60, 0xb1, 0xb5, 0xfd, 0x0a, 0x44, 0x01, 0x74,+ 0x17, 0x9f, 0x0d, 0xc6, 0x99, 0xd8, 0xe0, 0x5f, 0xa8, 0x6c, 0xa9, 0xdd, 0xdf, 0x27, 0x87, 0xfd, 0xcc, 0xb1, 0xd4, 0xdf,+ 0x5d, 0x59, 0xea, 0x39, 0xa6, 0xc0, 0xef, 0xe4, 0x90, 0x43, 0xb2, 0xe5, 0x8a, 0x4f, 0x65, 0x1a, 0x07, 0xd8, 0xcb, 0x87,+ 0xd6, 0xb1, 0x27, 0x8e, 0x5c, 0x14, 0x67, 0xc1, 0xf9, 0xd4, 0x12, 0xef, 0xeb, 0x1f, 0xd3, 0xe0, 0x13, 0x73, 0x9d, 0x83,+ 0xf8, 0x92, 0xab, 0x78, 0x84, 0xa9, 0x0c, 0x11, 0x5a, 0xea, 0xff, 0x3b, 0x64, 0x54, 0x8a, 0x6f, 0x3d, 0xe2, 0x17, 0x0b,+ 0x47, 0x09, 0x6b, 0xbf, 0xb6, 0x60, 0x5b, 0x97, 0x8a, 0xe0, 0xd1, 0x4f, 0x3c, 0x82, 0xe7, 0x96, 0x18, 0x65, 0xc4, 0xc0,+ 0xdf, 0x11, 0xf3, 0x61, 0xaf, 0x71, 0x2a, 0xb0, 0x95, 0x67, 0x8e, 0x49, 0xa7, 0xb2, 0x72, 0x74, 0xa8, 0xc5, 0xaf, 0x2c,+ 0x65, 0x30, 0x4f, 0xf1, 0x2c, 0x5f, 0x58, 0x9e, 0xc1, 0x94, 0x13, 0x9b, 0x7f, 0xd0, 0x9a, 0x97, 0x79, 0x81, 0x3b, 0x8e,+ 0xcb, 0xe8, 0x1f, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0xe5, 0xe8,+ 0xd3, 0xdb, 0x78, 0xeb, 0x3f, 0xa0, 0xa3, 0xe8, 0xce, 0xf0, 0x7f, 0xa1, 0xbd, 0x8b, 0x0f, 0xf8, 0x9c, 0xa7, 0xc4, 0xaf,+ 0x78, 0xfe, 0xed, 0xdf, 0xa4, 0xa5, 0xeb, 0xb4, 0x90, 0xd3, 0xfd, 0xc4, 0x7b, 0xa4, 0x0e, 0xb5, 0xf8, 0x26, 0xef, 0x66,+ 0x28, 0x23, 0xe8, 0x20, 0x7a, 0x63, 0x9d, 0xed, 0xaf, 0x0c, 0xf1, 0xd0, 0x3d, 0xe9, 0x99, 0x2e, 0x6d, 0xdd, 0xc4, 0x63,+ 0x8b, 0x26, 0x24, 0x09, 0x8e, 0x64, 0xaf, 0x3d, 0xf6, 0x66, 0x68, 0x88, 0x03, 0xaa, 0x2c, 0x49, 0xc2, 0x78, 0xd4, 0xbd,+ 0x43, 0xdc, 0x39, 0xd7, 0x59, 0xc6, 0x42, 0x74, 0x72, 0xfc, 0x7d, 0x3e, 0xe6, 0x7e, 0x4b, 0xec, 0x80, 0x3f, 0xd7, 0x86,+ 0xd0, 0xd6, 0xea, 0xda, 0x89, 0xb4, 0x87, 0x7c, 0x52, 0x18, 0x4d, 0x37, 0x5e, 0xe4, 0x77, 0x36, 0x8a, 0x25, 0x20, 0x9e,+ 0x71, 0xac, 0xa6, 0x1f, 0xdd, 0x59, 0xc0, 0x22, 0x61, 0x0e, 0x03, 0xff, 0xf6, 0x43, 0xd8, 0x49, 0x96, 0xf8, 0x0d, 0xde,+ 0x9f, 0xee, 0x27, 0xce, 0x23, 0xb5, 0xab, 0xe8, 0x68, 0x1e, 0xcf, 0x2a, 0xfa, 0xd2, 0x97, 0xd5, 0x2c, 0x10, 0x8e, 0xed,+ 0x6c, 0x9f, 0x3f, 0x17, 0xc2, 0x9b, 0xc2, 0xc8, 0x82, 0x29, 0xd6, 0xb9, 0x12, 0xfc, 0xa9, 0x8f, 0x58, 0xb7, 0xb8, 0x90,+ 0x5d, 0x62, 0x74, 0x88, 0xd7, 0x1e, 0x53, 0xc8, 0x0d, 0x71, 0x19, 0xb6, 0xe3, 0x80, 0xe0, 0x79, 0x49, 0x21, 0x2f, 0xe8,+ 0x54, 0xea, 0xc8, 0x7c, 0x31, 0xc7, 0x7f, 0x60, 0x35, 0xfd, 0x79, 0x85, 0xa5, 0xcc, 0x11, 0xa2, 0x4d, 0x9c, 0x7d, 0x7c,+ 0xc5, 0xb3, 0xf4, 0x66, 0x19, 0x6b, 0xc5, 0x98, 0x90, 0xc8, 0x7b, 0x08, 0xbf, 0x9e, 0x18, 0x92, 0xcd, 0xf8, 0xab, 0x87,+ 0xd3, 0x9f, 0xe5, 0xae, 0x2f, 0x33, 0x81, 0x49, 0xc6, 0x61, 0x2a, 0x6f, 0x5f, 0x92, 0xae, 0xec, 0x14, 0xbc, 0x71, 0x91,+ 0x14, 0xf0, 0x4a, 0x1d, 0xc8, 0x32, 0xd7, 0x19, 0x55, 0x8a, 0x95, 0xbc, 0x7d, 0x14, 0xf5, 0xaf, 0xcd, 0x56, 0x4b, 0xbc,+ 0x91, 0xb7, 0xfe, 0x93, 0xf9, 0x35, 0xf8, 0xd7, 0x6c, 0x26, 0x8b, 0xfa, 0x7f, 0x49, 0xaa, 0x7b, 0x57, 0xca, 0xfa, 0xf7,+ 0x0d, 0xe6, 0x78, 0x09, 0x66, 0x8a, 0xa3, 0xd7, 0xe6, 0x9f, 0xc3, 0x42, 0x71, 0x26, 0x88, 0xc8, 0x7b, 0x08, 0xdf, 0x57,+ 0x3c, 0x6b, 0x79, 0x42, 0x48, 0x0f, 0x1d, 0x25, 0xaf, 0xae, 0xe0, 0xc3, 0xcc, 0x3f, 0x97, 0x04, 0x76, 0x08, 0x7b, 0xf8,+ 0x2b, 0xfa, 0xaf, 0x0e, 0x39, 0x76, 0x7d, 0xee, 0x3d, 0x6a, 0xfa, 0x57, 0x63, 0x9d, 0x1b, 0x95, 0x12, 0xad, 0xfe, 0x9d,+ 0xc8, 0x75, 0xef, 0x81, 0xfa, 0x64, 0xd1, 0x4d, 0xd4, 0xbf, 0x0d, 0xd3, 0x79, 0xcf, 0x43, 0xff, 0x95, 0x21, 0x57, 0x7d,+ 0x09, 0x99, 0x62, 0xad, 0x19, 0x38, 0x87, 0xb7, 0xf9, 0xa6, 0x50, 0x7b, 0x08, 0xdd, 0xd7, 0x27, 0x3c, 0xc6, 0xd3, 0x4c,+ 0x61, 0xb4, 0xd0, 0xbe, 0x57, 0x20, 0x2f, 0x42, 0xd4, 0x59, 0x68, 0x7e, 0x8c, 0xe0, 0x23, 0xcb, 0xfe, 0x1d, 0x9a, 0x89,+ 0x5b, 0xf7, 0xe5, 0x4a, 0x43, 0xcd, 0x42, 0x1c, 0xdb, 0xd9, 0xfe, 0xeb, 0x60, 0xeb, 0x32, 0xbd, 0x88, 0xf4, 0xef, 0xc8,+ 0x22, 0x0f, 0xcf, 0x99, 0xb7, 0xfe, 0x2d, 0x99, 0xc4, 0xab, 0x6e, 0xdd, 0x35, 0x8a, 0x0e, 0xa2, 0xfe, 0x8f, 0x72, 0xbe,+ 0xeb, 0xd0, 0x93, 0xf4, 0x3f, 0xf4, 0xaa, 0x8b, 0x93, 0x23, 0xcc, 0x43, 0x11, 0x38, 0x87, 0x04, 0x96, 0x09, 0x5e, 0xe5,+ 0x82, 0xec, 0x21, 0x74, 0x5f, 0x33, 0xf9, 0x94, 0x11, 0x2c, 0x65, 0x9a, 0x10, 0xbb, 0x76, 0x76, 0x30, 0x82, 0xa6, 0x20,+ 0xfa, 0xf7, 0x17, 0x46, 0xda, 0x4c, 0x61, 0x21, 0x63, 0x0c, 0x3d, 0xc4, 0xad, 0x37, 0xb1, 0xcc, 0xd0, 0xd5, 0xe3, 0xd8,+ 0xfd, 0x49, 0x36, 0x94, 0x10, 0xb6, 0x9f, 0x61, 0x46, 0x9e, 0x77, 0x48, 0x2e, 0x22, 0xfd, 0xd3, 0xf8, 0x89, 0xbd, 0xdc,+ 0x5a, 0x48, 0xfd, 0xef, 0x65, 0x23, 0x71, 0x14, 0x33, 0x73, 0x0b, 0xc8, 0xfa, 0x3b, 0x8e, 0xf5, 0xd7, 0x48, 0xa1, 0xb8,+ 0xa8, 0xff, 0xa1, 0x39, 0x1e, 0xc3, 0x4e, 0x21, 0x76, 0x30, 0x85, 0x5f, 0x78, 0x83, 0x24, 0xd2, 0x58, 0xec, 0x7a, 0xb3,+ 0xbd, 0x34, 0x4b, 0xb7, 0xc6, 0xed, 0x1c, 0xda, 0xfe, 0x8f, 0xe0, 0x6b, 0xc1, 0x99, 0xb6, 0x33, 0xa4, 0x8f, 0x1c, 0x2b,+ 0xf8, 0xfb, 0x43, 0xf3, 0x63, 0x85, 0x30, 0x7b, 0x47, 0xe1, 0xeb, 0xff, 0xfc, 0x63, 0xd7, 0xe1, 0x0a, 0x3a, 0x45, 0xa8,+ 0x09, 0x0b, 0x5e, 0xff, 0x57, 0x0d, 0xc6, 0x77, 0xc8, 0xfa, 0x8f, 0x23, 0x81, 0x0e, 0xa4, 0x89, 0xfd, 0xcd, 0xc8, 0xfa,+ 0x17, 0x67, 0x3b, 0x37, 0x71, 0x87, 0x99, 0xa3, 0xca, 0xae, 0x7f, 0x09, 0x56, 0xd2, 0x93, 0x0e, 0x82, 0xfe, 0x31, 0xec,+ 0x08, 0xc9, 0xf1, 0x9a, 0x1c, 0x14, 0x1c, 0x3f, 0xce, 0x39, 0x3a, 0x73, 0xdd, 0xdc, 0x44, 0x19, 0x31, 0xdf, 0xfc, 0x7b,+ 0x88, 0x31, 0x75, 0xd8, 0x29, 0x20, 0x3a, 0xa3, 0xc3, 0xaf, 0xe7, 0x21, 0x31, 0xfe, 0x73, 0x7c, 0xc8, 0x93, 0x59, 0x7f,+ 0x21, 0x4e, 0x21, 0x7f, 0xfb, 0x73, 0x41, 0x2c, 0xab, 0x85, 0x6f, 0xff, 0x27, 0x84, 0xb4, 0x27, 0xaf, 0x32, 0xa1, 0x88,+ 0xda, 0xff, 0xab, 0xc8, 0x30, 0x8e, 0xd0, 0x38, 0xd2, 0xcc, 0xb8, 0xe5, 0xd2, 0x16, 0x31, 0xfc, 0xe8, 0x8e, 0x47, 0x1f,+ 0xad, 0xfe, 0xce, 0xdc, 0x05, 0x9f, 0xf0, 0x85, 0xb9, 0x13, 0xec, 0xfa, 0x3b, 0x51, 0x53, 0x59, 0xf4, 0x12, 0xdb, 0xff,+ 0x9f, 0x19, 0x16, 0xfc, 0xfd, 0x25, 0x96, 0x46, 0x9d, 0x6b, 0x81, 0x3d, 0x54, 0x60, 0x1d, 0x2d, 0xe9, 0xc9, 0xb2, 0x08,+ 0xf5, 0xf7, 0xd3, 0x9c, 0x4c, 0x35, 0x6e, 0x67, 0x89, 0x18, 0xf7, 0x5c, 0x9b, 0x34, 0x06, 0x50, 0x8f, 0xaa, 0x74, 0x61,+ 0x8f, 0x30, 0x82, 0xab, 0x7f, 0xfb, 0x2b, 0x19, 0x4e, 0xa6, 0xd8, 0x17, 0xf5, 0xa7, 0xfb, 0x89, 0x8d, 0xf2, 0x4a, 0x9c,+ 0x63, 0xbf, 0xc9, 0xb9, 0x9c, 0x4a, 0x27, 0xf6, 0x8a, 0xb1, 0x5a, 0x85, 0xd1, 0x3f, 0x96, 0x75, 0x74, 0x35, 0x71, 0x2d,+ 0x9b, 0x84, 0x37, 0x12, 0x81, 0x2d, 0xaa, 0xb0, 0x55, 0x8c, 0x0e, 0xcf, 0xbf, 0x9e, 0x0a, 0x16, 0xfd, 0xeb, 0xb1, 0x9d,+ 0x1d, 0x66, 0x66, 0x21, 0x2f, 0xfd, 0x7d, 0x7c, 0xc4, 0x76, 0x51, 0xff, 0x5a, 0x6c, 0xe3, 0x0d, 0xce, 0xa1, 0x26, 0xdd,+ 0xc9, 0x14, 0x47, 0x73, 0x8f, 0xa4, 0x7f, 0x60, 0x0f, 0x2d, 0xc8, 0x20, 0x2b, 0xc2, 0x9c, 0x64, 0x29, 0xc6, 0xf7, 0x7f,+ 0x90, 0x15, 0xbc, 0x67, 0x79, 0xc7, 0xd2, 0x90, 0x1f, 0xd9, 0x43, 0x2e, 0x8b, 0xc5, 0x28, 0x76, 0xff, 0xf6, 0xdb, 0xf8,+ 0x4e, 0x7c, 0x7a, 0x08, 0xa4, 0xfb, 0xff, 0x55, 0x8e, 0xfa, 0x4a, 0x2e, 0x61, 0x9c, 0x99, 0x35, 0x64, 0x3e, 0xb7, 0x44,+ 0xac, 0x3f, 0x0a, 0xde, 0xff, 0x6f, 0x6e, 0xa2, 0x02, 0x7e, 0x17, 0xe3, 0xcd, 0xf2, 0xb7, 0x68, 0x4e, 0xb6, 0x10, 0xb3,+ 0x9a, 0x7f, 0x3d, 0xcb, 0x2c, 0xfa, 0xfb, 0x98, 0xe6, 0xc6, 0x68, 0x7b, 0xeb, 0x5f, 0x9e, 0x2d, 0xa2, 0xfe, 0xce, 0x7c,+ 0x95, 0xe3, 0xc8, 0x64, 0x1f, 0xbf, 0xb9, 0xb1, 0x51, 0xd1, 0xe6, 0x5a, 0x60, 0x0f, 0x07, 0x59, 0xc7, 0x8a, 0x08, 0xe3,+ 0x4a, 0x14, 0x8c, 0x62, 0x62, 0x4b, 0x73, 0x74, 0x48, 0x38, 0x22, 0xc7, 0x2e, 0x73, 0x8c, 0xbf, 0x97, 0x2d, 0x16, 0x21,+ 0x66, 0xa2, 0x20, 0x7b, 0x48, 0x24, 0x86, 0x2f, 0xa2, 0x9a, 0xc9, 0x4b, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14,+ 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x39, 0x31, 0xfc, 0xff, 0x43, 0x68, 0x67, 0xf5, 0xff, 0x3b,+ 0xf3, 0xae, 0xbf, 0xcb, 0xf7, 0xbc, 0x2a, 0xce, 0x3a, 0x1e, 0x3a, 0x42, 0xbf, 0x13, 0x07, 0xe0, 0xe5, 0x97, 0x6f, 0x25,+ 0x38, 0x8c, 0x5b, 0xf1, 0x6c, 0xc8, 0x5f, 0x6d, 0x85, 0x35, 0x5a, 0xd3, 0xde, 0xfd, 0xed, 0x1c, 0x92, 0x38, 0xdf, 0xfd,+ 0xfd, 0x71, 0x61, 0xbc, 0xdc, 0x33, 0x48, 0xe2, 0x4c, 0xf7, 0xf7, 0x93, 0xf9, 0x88, 0xba, 0xc2, 0x97, 0xdf, 0xb7, 0x83,+ 0xdf, 0xfc, 0x13, 0x18, 0x2c, 0xf8, 0x3f, 0xce, 0x3c, 0xe4, 0x7a, 0xc2, 0x67, 0x34, 0xa8, 0x41, 0x43, 0x1a, 0x0a, 0x4e,+ 0x86, 0x44, 0xeb, 0x77, 0xd6, 0xd2, 0x66, 0x8b, 0x8a, 0x62, 0xda, 0x85, 0x96, 0x31, 0x2f, 0x43, 0xff, 0x49, 0x23, 0x63,+ 0x97, 0xb3, 0x8e, 0x43, 0x5b, 0x8d, 0xa6, 0xe2, 0x48, 0xcb, 0xf6, 0xef, 0xff, 0x8e, 0x97, 0xbc, 0x17, 0x0b, 0x49, 0xb5,+ 0x8c, 0xbf, 0xde, 0x8e, 0xed, 0xbc, 0x45, 0x7b, 0x7e, 0x60, 0x8b, 0xe0, 0xd2, 0xac, 0x6f, 0xbc, 0x97, 0x23, 0x8d, 0x5b,+ 0xbe, 0x9b, 0xa0, 0x5e, 0xe8, 0xb7, 0xea, 0x01, 0x82, 0x5b, 0xf5, 0x6a, 0xb2, 0x83, 0x31, 0x0a, 0xb1, 0xa4, 0xf2, 0xb0,+ 0xa0, 0x7f, 0x60, 0xe4, 0xe0, 0xe7, 0xc9, 0xe5, 0xe5, 0xa0, 0x2f, 0x59, 0xfa, 0x06, 0x3e, 0x92, 0xa9, 0xae, 0x36, 0xdf,+ 0xf3, 0x9d, 0x90, 0x7e, 0x92, 0x99, 0xcb, 0xc0, 0xff, 0xfb, 0xb3, 0x6c, 0x14, 0xbc, 0x8d, 0xa7, 0x04, 0xfd, 0xa4, 0xaf,+ 0x91, 0xc7, 0xcd, 0x61, 0xe9, 0xfd, 0xd8, 0xcc, 0x2c, 0x61, 0x44, 0xb9, 0x01, 0xa2, 0xfb, 0xc5, 0x67, 0xfc, 0x20, 0xb3,+ 0xc8, 0x10, 0x47, 0x9f, 0x2e, 0xce, 0x06, 0xd2, 0x85, 0x52, 0xea, 0x78, 0x77, 0xf2, 0x91, 0x5c, 0x48, 0x5f, 0xf2, 0xba,+ 0x78, 0xac, 0x1e, 0x64, 0x33, 0x9f, 0x5d, 0x8c, 0x2f, 0xf0, 0x98, 0x77, 0xf9, 0xfa, 0xcc, 0xa1, 0xaf, 0x65, 0x8d, 0x7f,+ 0xb9, 0xea, 0x8c, 0xb6, 0x8c, 0x51, 0xed, 0xe3, 0x9f, 0x6c, 0x28, 0x80, 0xc3, 0x4b, 0xd2, 0xdf, 0x71, 0xe3, 0x04, 0x5c,+ 0x78, 0x8e, 0x27, 0x2a, 0xdc, 0xed, 0x56, 0x85, 0x3c, 0x77, 0x0c, 0xd9, 0xdf, 0xf8, 0x91, 0x19, 0xe6, 0xb7, 0xd3, 0x82,+ 0x23, 0xbf, 0x1e, 0x4a, 0x79, 0x36, 0x1a, 0x7d, 0x1f, 0x61, 0x0b, 0x27, 0x8b, 0xe7, 0x73, 0x0f, 0xbb, 0x4d, 0x4d, 0x77,+ 0x1a, 0x7b, 0x22, 0xcc, 0xff, 0xfe, 0x1d, 0x9f, 0x09, 0x4b, 0xfb, 0x09, 0xa3, 0x6f, 0xfa, 0xcc, 0xd8, 0xac, 0x73, 0x3d,+ 0xf6, 0x35, 0x49, 0xd4, 0xff, 0x31, 0x7e, 0xa4, 0x3b, 0x1f, 0x17, 0xa2, 0xd6, 0x3e, 0x99, 0xc9, 0x42, 0xbd, 0x50, 0x8a,+ 0xe1, 0xe6, 0xde, 0x2f, 0x43, 0x86, 0xc7, 0x8c, 0x13, 0x36, 0x7d, 0xde, 0x15, 0xfc, 0x33, 0x3e, 0x33, 0xb2, 0x6c, 0xcf,+ 0x88, 0x7b, 0x29, 0xbc, 0xfe, 0xce, 0xe8, 0xc3, 0x81, 0xf1, 0xcc, 0x3f, 0xb0, 0xc4, 0x2a, 0x2c, 0x32, 0x9e, 0x99, 0x92,+ 0x64, 0x73, 0x2d, 0x39, 0xc6, 0xb9, 0xf1, 0xa0, 0x65, 0xae, 0x0a, 0x1f, 0x37, 0xb0, 0x87, 0x46, 0xec, 0xb2, 0xf8, 0x85,+ 0xfc, 0x8e, 0x46, 0xe7, 0x3a, 0xbf, 0xe1, 0x7b, 0xcf, 0x2b, 0x7a, 0x90, 0x54, 0x71, 0x3c, 0x72, 0x9b, 0xfe, 0xa5, 0xc8,+ 0xb2, 0x8e, 0x5f, 0x2e, 0xeb, 0x1f, 0xc7, 0x6a, 0xae, 0xa1, 0x3c, 0xe9, 0x9c, 0x51, 0x84, 0xed, 0x79, 0x49, 0x2e, 0xe0,+ 0x6e, 0xb6, 0x78, 0x8c, 0x28, 0x2b, 0xeb, 0x53, 0x97, 0x54, 0x3a, 0x89, 0x6b, 0x5c, 0xc7, 0x56, 0x7e, 0xa3, 0x83, 0x38,+ 0x36, 0x6c, 0x51, 0xe8, 0x5f, 0x9b, 0x5c, 0x73, 0x47, 0x26, 0xb0, 0x5d, 0xa8, 0x6f, 0xfd, 0x79, 0xee, 0x94, 0x8b, 0xa6,+ 0xac, 0x35, 0xf5, 0xfe, 0xcd, 0x66, 0xd6, 0x90, 0x41, 0xd6, 0x73, 0x19, 0xcc, 0x1e, 0xcf, 0xf1, 0x4f, 0xcf, 0x34, 0x91,+ 0x19, 0x99, 0x9e, 0xb1, 0x05, 0xd5, 0xd9, 0x69, 0x99, 0x8f, 0xc0, 0xa6, 0xbf, 0x53, 0x3b, 0xb5, 0x8c, 0x4a, 0xff, 0xc6,+ 0x7c, 0x6a, 0x7e, 0x76, 0x8d, 0xe8, 0xe6, 0x2a, 0xb8, 0xe3, 0x67, 0x18, 0xbb, 0x98, 0xcb, 0x27, 0xac, 0xe1, 0xf1, 0x02,+ 0xeb, 0xbf, 0x91, 0x25, 0xac, 0x03, 0x86, 0x5b, 0x1d, 0x47, 0x65, 0xe8, 0x62, 0x1c, 0x73, 0x9f, 0x59, 0xfb, 0x38, 0x7f,+ 0x45, 0x7f, 0x1f, 0xb3, 0xcc, 0xcc, 0x13, 0xcd, 0xd9, 0x62, 0xe9, 0xd5, 0x34, 0x65, 0x33, 0x31, 0xbc, 0x6e, 0x9c, 0xc8,+ 0x43, 0xcc, 0x48, 0xce, 0x1b, 0x2c, 0x25, 0xc5, 0xdf, 0x06, 0xe6, 0x0a, 0xfd, 0xd0, 0x50, 0xba, 0x83, 0xc7, 0x5c, 0x17,+ 0x8e, 0xfb, 0xf7, 0x67, 0x86, 0x5b, 0xd2, 0xec, 0xfa, 0x77, 0xb7, 0xce, 0x1b, 0x64, 0xab, 0xff, 0x8b, 0x9a, 0xdb, 0x82,+ 0xad, 0xde, 0xc2, 0x28, 0xf4, 0x1f, 0xc8, 0xf5, 0xdc, 0xcf, 0x41, 0x61, 0xe6, 0xaa, 0xc3, 0xef, 0x9b, 0x64, 0x4b, 0xbc,+ 0xaa, 0x97, 0xfe, 0x4b, 0x43, 0x7c, 0xa1, 0x83, 0x2c, 0x2d, 0xcc, 0x93, 0xcc, 0x33, 0xa3, 0x20, 0xdb, 0x54, 0x2b, 0xc1,+ 0x5e, 0xce, 0x61, 0xae, 0x19, 0x07, 0xfc, 0x0e, 0x16, 0x70, 0x36, 0xfb, 0xac, 0x51, 0x8d, 0x17, 0x93, 0xc5, 0x9d, 0x64,+ 0x0b, 0x4e, 0xe5, 0xd0, 0xe7, 0x04, 0x8c, 0x3f, 0xd7, 0x46, 0x5b, 0x36, 0x5a, 0x67, 0xd1, 0xb1, 0xeb, 0x7f, 0x31, 0x6b,+ 0xfe, 0x66, 0xfd, 0xaf, 0x67, 0x07, 0x55, 0x88, 0xe1, 0x76, 0x72, 0xa3, 0xd0, 0xdf, 0x7f, 0x7f, 0x8e, 0x62, 0xb2, 0x98,+ 0x7e, 0x12, 0xbd, 0x82, 0xfd, 0xf3, 0x81, 0xd6, 0xd9, 0xa5, 0xec, 0xfa, 0x7f, 0x1a, 0xe2, 0x66, 0x9f, 0x21, 0x8e, 0x10,+ 0xee, 0xf4, 0x76, 0xf7, 0x51, 0x8b, 0x5d, 0x5c, 0xe4, 0x11, 0x09, 0xd0, 0x85, 0xfd, 0xe6, 0x19, 0xaa, 0x1c, 0xfb, 0xe8,+ 0xe4, 0x8e, 0x87, 0x2f, 0xb5, 0xc2, 0xcb, 0x4c, 0x19, 0xed, 0xc1, 0x3a, 0x8f, 0x91, 0x52, 0xbd, 0xf5, 0x3f, 0x8d, 0x5d,+ 0xc2, 0x73, 0x61, 0x64, 0xfd, 0x63, 0xd9, 0x6e, 0x9d, 0x79, 0xe3, 0xe8, 0xe8, 0x9f, 0xc0, 0x08, 0x0e, 0x90, 0xce, 0x8f,+ 0x4c, 0x8f, 0x5a, 0xff, 0xb3, 0xd8, 0x2f, 0xce, 0xdf, 0xe7, 0xe4, 0xfd, 0x50, 0xca, 0x11, 0xc7, 0x35, 0x6c, 0xe6, 0xd1,+ 0xa8, 0xf5, 0xbf, 0x91, 0x7d, 0x74, 0xa4, 0x32, 0x35, 0xe8, 0xcb, 0x6e, 0xf1, 0x59, 0xc7, 0xe7, 0xf6, 0xc6, 0x92, 0x3d,+ 0xce, 0xf2, 0x19, 0x96, 0x9b, 0x3a, 0xc2, 0xe1, 0x77, 0x56, 0x8a, 0xb3, 0xb9, 0xf9, 0xdb, 0xfe, 0x39, 0xa6, 0x0d, 0x89,+ 0x67, 0xb6, 0xb5, 0x06, 0xf7, 0xd6, 0x3f, 0x86, 0x5f, 0x18, 0x46, 0x25, 0xd7, 0xe3, 0x5f, 0x3a, 0x0a, 0xfd, 0x9d, 0x19,+ 0x78, 0x9e, 0xf8, 0x5b, 0xf5, 0xf7, 0xdf, 0xaf, 0x55, 0xa2, 0x5a, 0x3f, 0xbf, 0x7d, 0x1e, 0xcc, 0x52, 0x31, 0x52, 0xb4,+ 0x1e, 0xa3, 0x48, 0x67, 0x1f, 0x69, 0xf4, 0xb0, 0xce, 0x2b, 0x61, 0xd7, 0xdf, 0xc7, 0xed, 0x24, 0x73, 0x90, 0x03, 0xcc,+ 0xf3, 0x98, 0xfd, 0xea, 0x36, 0xb0, 0x6a, 0xea, 0x70, 0x3e, 0xf0, 0x5a, 0x30, 0x26, 0x06, 0x4b, 0x4d, 0x71, 0x13, 0x7b,+ 0xa8, 0x13, 0xec, 0x55, 0xee, 0xb1, 0xcc, 0x27, 0xe3, 0xad, 0x7f, 0x9d, 0x43, 0xde, 0xbd, 0xf4, 0x89, 0x4a, 0xff, 0xc7,+ 0xac, 0x73, 0xf8, 0x1d, 0x3d, 0xfd, 0x8f, 0x0c, 0xf1, 0x9e, 0xed, 0x65, 0x41, 0x4a, 0x65, 0xe9, 0x13, 0xe4, 0x7d, 0xa9,+ 0x97, 0xfe, 0x35, 0xd9, 0x61, 0x89, 0xb5, 0x3e, 0xde, 0xf5, 0x57, 0x42, 0x9f, 0x45, 0x2f, 0xb0, 0xd6, 0x83, 0xab, 0x84,+ 0x39, 0x52, 0x4a, 0x71, 0x01, 0x73, 0x55, 0xff, 0x13, 0x84, 0xa7, 0x98, 0xcf, 0x7c, 0xeb, 0xdb, 0xd5, 0x16, 0xc1, 0xef,+ 0x13, 0xf9, 0x9c, 0x63, 0xb6, 0xb8, 0x59, 0xf3, 0x4e, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14, 0x45, 0x51, 0x14,+ 0x45, 0x51, 0x14, 0x45, 0x39, 0x8a, 0x0c, 0x15, 0x7d, 0xb4, 0x87, 0x7e, 0x11, 0x6f, 0x10, 0xfc, 0xaa, 0x6a, 0xc3, 0x19,+ 0xeb, 0xbe, 0x8c, 0x65, 0xeb, 0x0b, 0x69, 0x68, 0x75, 0xab, 0xfb, 0xdd, 0x3d, 0x31, 0x96, 0x6f, 0x8e, 0x97, 0x52, 0x8b,+ 0x58, 0x1a, 0x0b, 0x73, 0xb7, 0x7b, 0x9d, 0x75, 0x05, 0xfe, 0x10, 0x47, 0xa2, 0xaf, 0xc4, 0x1f, 0xc1, 0x91, 0x3f, 0x0b,+ 0x7a, 0xfd, 0x52, 0x6a, 0x23, 0x4a, 0x50, 0x8b, 0xcb, 0xcc, 0x59, 0x9f, 0xc1, 0x0d, 0xe2, 0x08, 0xfb, 0xce, 0x3a, 0x55,+ 0xb9, 0xc4, 0xfa, 0x9d, 0xc8, 0xc9, 0xd3, 0x73, 0x2c, 0x69, 0xce, 0xb6, 0xa7, 0xd3, 0xc4, 0x63, 0xdc, 0xb6, 0x04, 0x93,+ 0x33, 0x71, 0x34, 0x16, 0xf2, 0xd5, 0xd9, 0xba, 0x76, 0x84, 0x99, 0xfa, 0x43, 0xc9, 0xa1, 0x81, 0x67, 0x7a, 0x2d, 0x36,+ 0xb0, 0x96, 0xff, 0x92, 0x62, 0x9d, 0x6b, 0xc0, 0xef, 0x47, 0x96, 0x47, 0x19, 0xad, 0xc3, 0x46, 0x52, 0x48, 0x67, 0x89,+ 0x25, 0x97, 0xcb, 0x32, 0x9e, 0x83, 0xa2, 0xef, 0xfc, 0x22, 0xd2, 0x59, 0x4d, 0x06, 0xaf, 0x83, 0xe0, 0x68, 0xf0, 0x3a,+ 0xeb, 0x04, 0x7a, 0x8a, 0xb1, 0x2c, 0xce, 0xf2, 0x6a, 0x51, 0x5e, 0xbf, 0x94, 0x9a, 0x43, 0x3f, 0x96, 0xb1, 0x93, 0xe1,+ 0x74, 0x67, 0x2d, 0x1b, 0x59, 0x27, 0x1c, 0x2d, 0x87, 0x1e, 0x6c, 0x61, 0x2b, 0xab, 0xa9, 0x65, 0xcd, 0xd3, 0x54, 0x56,+ 0x88, 0xe7, 0x99, 0x43, 0x1f, 0xb2, 0x48, 0x61, 0x0f, 0xd7, 0x8b, 0xe7, 0xe4, 0xe4, 0xcc, 0x2a, 0x76, 0xd3, 0x5b, 0xcc,+ 0xf3, 0x1c, 0x86, 0x92, 0xe1, 0xe1, 0x8e, 0x95, 0xae, 0xd0, 0xab, 0xb4, 0x2d, 0xe7, 0x15, 0x62, 0x88, 0xe1, 0x5d, 0xfa,+ 0x79, 0x94, 0x45, 0x59, 0xff, 0x18, 0x96, 0x9b, 0xd8, 0x9d, 0x52, 0x7c, 0x23, 0x8c, 0x0c, 0xed, 0x70, 0xbf, 0x99, 0x75,+ 0xa2, 0xb8, 0xe0, 0xa5, 0xda, 0x60, 0xbc, 0x62, 0xe5, 0x19, 0x63, 0xd5, 0xbf, 0x9a, 0xf5, 0xfe, 0x6a, 0x64, 0x71, 0xb2,+ 0x4a, 0xcb, 0x03, 0x0a, 0xd7, 0xa1, 0x5e, 0x81, 0xf5, 0x7f, 0xd3, 0x9c, 0x59, 0x26, 0xa3, 0x89, 0x25, 0x96, 0xd5, 0x74,+ 0x10, 0xd6, 0x19, 0x49, 0x02, 0xc5, 0x98, 0x28, 0x7a, 0xe7, 0x03, 0x79, 0xfa, 0x0e, 0x33, 0xc5, 0x63, 0xce, 0x30, 0xe5,+ 0xf4, 0x61, 0x76, 0x08, 0xf1, 0x29, 0x81, 0x9c, 0xa9, 0xc8, 0x0f, 0x16, 0xfd, 0x47, 0x59, 0xc6, 0xf1, 0xb4, 0xe9, 0x3f,+ 0xc8, 0xa3, 0xb4, 0x9d, 0xc9, 0x01, 0x31, 0xfe, 0xe8, 0xf0, 0xb2, 0xf8, 0x86, 0x78, 0x2e, 0x8e, 0xd3, 0xba, 0x21, 0x17,+ 0x71, 0x11, 0xed, 0xd9, 0x21, 0x46, 0x3f, 0xbd, 0xc5, 0x4c, 0x1a, 0x0b, 0xe3, 0x82, 0xd6, 0x61, 0xbf, 0x5b, 0xeb, 0xdf,+ 0x6c, 0xd1, 0xbf, 0xaf, 0xc7, 0xfd, 0x65, 0xbb, 0xa7, 0x73, 0x45, 0x35, 0x9d, 0x65, 0xb7, 0x92, 0x26, 0xfa, 0x5f, 0x65,+ 0xfd, 0x1b, 0xbb, 0xf1, 0x32, 0x7e, 0xe7, 0xd4, 0x30, 0xc1, 0xb7, 0x9a, 0xe3, 0xc6, 0x75, 0xb5, 0x67, 0xba, 0x47, 0x9e,+ 0x56, 0x22, 0xcf, 0x9d, 0xdf, 0xe2, 0xd0, 0x6d, 0x03, 0x2e, 0xb2, 0xcd, 0xc2, 0x5c, 0x33, 0xb5, 0xc9, 0x71, 0xbf, 0x3e,+ 0xdf, 0x6e, 0xd1, 0xff, 0xf2, 0xa8, 0xda, 0x7f, 0xef, 0xd2, 0x76, 0x03, 0xa9, 0x1e, 0xdb, 0x46, 0x2a, 0x8b, 0x37, 0xb0,+ 0x9f, 0xd9, 0x41, 0xc2, 0x1d, 0x40, 0xa3, 0x59, 0xc7, 0x4e, 0x66, 0x0a, 0xbe, 0xc3, 0xa6, 0xa4, 0xb9, 0xf7, 0xf6, 0x59,+ 0x16, 0xfd, 0x47, 0x79, 0xdc, 0x5f, 0xd1, 0xea, 0xdf, 0x8c, 0x34, 0x2e, 0x8d, 0xa2, 0xfe, 0x6f, 0xe0, 0xea, 0xff, 0xa0,+ 0xf9, 0xf9, 0xa1, 0x50, 0xdb, 0x06, 0xd6, 0x79, 0x40, 0x88, 0x0a, 0x0a, 0xcd, 0xd3, 0x2c, 0xc1, 0x13, 0x97, 0x13, 0x1c,+ 0xff, 0x7b, 0xbe, 0x10, 0x6f, 0x75, 0x63, 0x70, 0xeb, 0xb3, 0x2d, 0xfa, 0x37, 0x88, 0x52, 0x7f, 0xaf, 0xd2, 0x56, 0x8d,+ 0x83, 0x6e, 0xff, 0x26, 0x51, 0xd0, 0x2f, 0x52, 0x59, 0xac, 0xce, 0x41, 0xcf, 0xa8, 0x11, 0xc7, 0xd7, 0xf9, 0x93, 0xb8,+ 0xbc, 0x0a, 0xb8, 0x51, 0x8c, 0x6d, 0x2d, 0xfa, 0x07, 0xee, 0xaf, 0x19, 0x7f, 0x59, 0xff, 0x2e, 0xec, 0xb4, 0xce, 0xe9,+ 0x74, 0x24, 0xf4, 0xcf, 0xcf, 0xd3, 0x1a, 0xe4, 0x0a, 0xb9, 0x9a, 0xe3, 0xce, 0x3b, 0x14, 0xcf, 0x2e, 0xa1, 0x1f, 0x77,+ 0x5a, 0x70, 0x44, 0xf8, 0x36, 0x45, 0xa4, 0xbf, 0x57, 0x69, 0xf3, 0x31, 0x9d, 0x8f, 0x29, 0x4b, 0x79, 0xbe, 0x13, 0xa2,+ 0x1b, 0x22, 0x95, 0x45, 0xc7, 0xab, 0xfb, 0xa9, 0x69, 0xdf, 0xdf, 0x76, 0x67, 0x3c, 0x29, 0xa8, 0xfe, 0x3e, 0xc6, 0xb2,+ 0x88, 0x56, 0x3c, 0xc1, 0x42, 0xcf, 0xfe, 0xdf, 0x03, 0xe2, 0x08, 0xca, 0xd1, 0xe9, 0xbf, 0xd9, 0x44, 0x0c, 0x1c, 0x3d,+ 0xfd, 0x03, 0x79, 0x5a, 0x81, 0x6f, 0xc5, 0x18, 0xb4, 0x1c, 0xf3, 0xfc, 0x52, 0x82, 0xbe, 0xfc, 0x29, 0xb6, 0xbd, 0x0b,+ 0xcc, 0xb3, 0xd6, 0x05, 0xcc, 0x2a, 0x22, 0xfd, 0xbd, 0x4a, 0x9b, 0xd3, 0x46, 0x4d, 0x24, 0x93, 0x0c, 0xc6, 0x08, 0xcf,+ 0x77, 0x91, 0xca, 0xa2, 0xb3, 0xf5, 0x2f, 0x64, 0x91, 0xc1, 0x74, 0x4b, 0xb4, 0x95, 0x5d, 0xff, 0x52, 0x0c, 0x64, 0x21,+ 0x13, 0xb8, 0xea, 0x88, 0xeb, 0x7f, 0x25, 0x0f, 0x90, 0x61, 0x71, 0xa6, 0x1f, 0x19, 0xfd, 0xfd, 0x79, 0x9a, 0xc9, 0x58,+ 0x71, 0x6e, 0x95, 0x1c, 0x9e, 0x66, 0x07, 0x7b, 0x59, 0xca, 0xb9, 0x96, 0xf8, 0x84, 0xb9, 0xec, 0x65, 0x0f, 0xed, 0x8b,+ 0x48, 0xff, 0xa5, 0x9e, 0xa5, 0xcd, 0x5f, 0xf7, 0xdb, 0x7a, 0x94, 0x81, 0xb2, 0x38, 0xd3, 0x63, 0x96, 0x89, 0x52, 0x1e,+ 0x33, 0xc8, 0xd8, 0xf5, 0x2f, 0xeb, 0xc6, 0x71, 0x37, 0x21, 0x5b, 0x38, 0xaf, 0xa2, 0xd4, 0xbf, 0x81, 0x89, 0x2a, 0x5b,+ 0x66, 0xd1, 0xa2, 0xc1, 0x11, 0x7a, 0xef, 0x92, 0x68, 0x8d, 0xb6, 0x73, 0x8e, 0x19, 0x6f, 0x89, 0x5e, 0x0e, 0x50, 0x91,+ 0x62, 0xd6, 0x67, 0x6e, 0x5f, 0x94, 0xfa, 0xb7, 0xf3, 0x2c, 0x6d, 0xde, 0x04, 0xca, 0xe2, 0x43, 0x85, 0x3c, 0x17, 0xbb,+ 0xfe, 0x3f, 0x33, 0x82, 0x2b, 0xb8, 0x93, 0xd9, 0x8c, 0xf1, 0xd0, 0xa5, 0xa8, 0xf4, 0x2f, 0xc6, 0x2c, 0xbe, 0x11, 0x9e,+ 0x26, 0x8f, 0x9c, 0xfe, 0x85, 0x7f, 0x23, 0x13, 0xe9, 0x9d, 0x4b, 0x61, 0xdc, 0xfd, 0x27, 0xff, 0x85, 0xad, 0x2b, 0x16,+ 0x78, 0xac, 0x81, 0x68, 0xf4, 0xaf, 0x44, 0x6f, 0xa6, 0x30, 0x95, 0x5e, 0x9e, 0xcf, 0x9f, 0xd1, 0x50, 0x9c, 0x83, 0xe2,+ 0xd3, 0xe2, 0xb1, 0xc6, 0x18, 0x61, 0x94, 0x0d, 0x9f, 0x38, 0x06, 0xc8, 0x58, 0x8f, 0x18, 0x37, 0xe5, 0xf0, 0x08, 0x94,+ 0x0f, 0x58, 0xa5, 0xf9, 0xf0, 0x3f, 0xcb, 0x69, 0xf4, 0x13, 0xdf, 0xf0, 0x29, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,+ 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0xca, 0x89, 0x4a, 0x15, 0xae, 0x16, 0x7c, 0x88, 0x7e, 0x26, 0x72, 0x9f,+ 0xa7, 0x97, 0xb6, 0x32, 0xe7, 0x09, 0x0e, 0xc7, 0x5a, 0xc1, 0xaf, 0xdc, 0x8d, 0x85, 0xb1, 0xf2, 0x6b, 0xb8, 0x6e, 0x8b,+ 0xc4, 0xa0, 0x83, 0xfd, 0x22, 0x61, 0x7c, 0xfc, 0x4a, 0x34, 0x72, 0xbf, 0xc8, 0xd6, 0x0d, 0x8e, 0xea, 0x2f, 0x1d, 0xa3,+ 0x8c, 0x78, 0x0c, 0xc7, 0x1d, 0x1f, 0xa0, 0x92, 0x47, 0xac, 0xc0, 0xe1, 0x4b, 0x2e, 0xe5, 0x95, 0xb0, 0x65, 0x25, 0x3d,+ 0x1c, 0xb5, 0x31, 0xc7, 0xbd, 0xfa, 0x9d, 0xc9, 0x60, 0x0a, 0x69, 0xc2, 0x75, 0x3b, 0x0e, 0xdd, 0x3f, 0x78, 0x55, 0x9c,+ 0x4f, 0xc0, 0xeb, 0x0b, 0xfc, 0x43, 0xac, 0x75, 0xf3, 0xa5, 0x0b, 0x0b, 0x85, 0x6d, 0x5b, 0xba, 0xa3, 0x05, 0x3e, 0x0a,+ 0xc6, 0x7d, 0x56, 0x91, 0x5c, 0x21, 0xc2, 0xa4, 0x1c, 0xeb, 0xcd, 0xc8, 0xf0, 0x75, 0xc8, 0x14, 0x9c, 0x49, 0xf9, 0xc7,+ 0xe8, 0x2c, 0x1e, 0x23, 0x91, 0x55, 0x86, 0xf5, 0xc0, 0x5d, 0x56, 0xef, 0xc2, 0xd4, 0xb0, 0xa5, 0xb7, 0x31, 0x2e, 0x6c,+ 0xd9, 0x39, 0x6c, 0x63, 0xb0, 0xb8, 0x8f, 0x16, 0xa4, 0xb1, 0xc9, 0xdc, 0x21, 0x6d, 0xe9, 0x7a, 0x5c, 0xaa, 0x9f, 0x40,+ 0x26, 0xd7, 0x9a, 0x3a, 0x60, 0xb0, 0xe0, 0xc3, 0x1f, 0x4d, 0x26, 0xab, 0xc4, 0x51, 0x7b, 0xbd, 0xf4, 0x2f, 0xc3, 0x6e,+ 0xd7, 0x55, 0xb8, 0x80, 0x8e, 0xa2, 0x36, 0xfb, 0x4c, 0xf4, 0xcb, 0x57, 0x2c, 0x30, 0xa5, 0xae, 0x15, 0xcb, 0xc5, 0x73,+ 0xbb, 0x9e, 0xed, 0x54, 0x66, 0xb2, 0x38, 0xb3, 0x42, 0x19, 0x32, 0x3d, 0x8f, 0x11, 0x60, 0x30, 0xbf, 0x59, 0xc6, 0xe4,+ 0xeb, 0xc0, 0x48, 0xe1, 0xee, 0x95, 0xf4, 0x77, 0xdc, 0x48, 0x19, 0xe2, 0xe8, 0xee, 0xb3, 0x79, 0x82, 0xcb, 0x59, 0xc3,+ 0x64, 0x76, 0x58, 0x47, 0x9b, 0x3c, 0xd6, 0xf9, 0x0f, 0x5f, 0x70, 0xb1, 0x25, 0x8f, 0x9c, 0x2b, 0x7c, 0xc8, 0xd3, 0xa5,+ 0x22, 0x3b, 0x70, 0x86, 0xf1, 0xbe, 0xb9, 0x6f, 0xf6, 0x59, 0xe6, 0x3d, 0x99, 0x40, 0x67, 0xe2, 0x48, 0xe3, 0x0e, 0x66,+ 0xe1, 0x23, 0x89, 0xfe, 0x96, 0xa3, 0xbf, 0xcb, 0x42, 0x96, 0x58, 0xfc, 0x25, 0x49, 0xe6, 0x18, 0xf5, 0xd9, 0xe7, 0x31,+ 0xee, 0x7e, 0x6b, 0x52, 0xad, 0xe3, 0xa1, 0x8e, 0x14, 0xe2, 0x36, 0x6c, 0xfa, 0x3b, 0x6e, 0x3f, 0x69, 0x4c, 0xe0, 0xda,+ 0xe6, 0x9e, 0x49, 0xa4, 0x95, 0xc5, 0x3f, 0x7e, 0x3c, 0x50, 0x83, 0x21, 0x6c, 0x25, 0x35, 0x38, 0xcb, 0x4e, 0x51, 0xe8,+ 0x7f, 0x39, 0xe9, 0x14, 0xe3, 0x35, 0xeb, 0x78, 0xd1, 0xff, 0xe2, 0x27, 0x2e, 0x61, 0x1e, 0xc5, 0xd8, 0x49, 0x59, 0x36,+ 0x5a, 0xfd, 0xd7, 0x57, 0x82, 0xb5, 0x5e, 0x6d, 0x62, 0x8e, 0xd1, 0xc7, 0x7a, 0x0c, 0x1f, 0xe7, 0xb1, 0x2b, 0xe8, 0x6e,+ 0x0e, 0x47, 0x1e, 0xad, 0xd7, 0xa6, 0xff, 0xef, 0x96, 0xf9, 0x00, 0x4e, 0x0c, 0x62, 0xf8, 0x37, 0x79, 0xa2, 0x3b, 0xca,+ 0xa6, 0xff, 0x56, 0x9a, 0x9a, 0x9f, 0xaf, 0x8a, 0xfa, 0x3b, 0x91, 0x5f, 0x2d, 0x58, 0x43, 0x33, 0xab, 0x1b, 0x63, 0x37,+ 0xcf, 0xf3, 0xaa, 0x99, 0x65, 0xa5, 0x13, 0xdb, 0x2d, 0xb5, 0x4f, 0x09, 0x92, 0x79, 0x99, 0x34, 0x4b, 0x0c, 0x41, 0x0c,+ 0x2b, 0x69, 0xc1, 0x9f, 0xd6, 0xb1, 0xba, 0xcb, 0xb1, 0xf2, 0x90, 0xb9, 0xa5, 0x0e, 0x6f, 0xf7, 0x96, 0x8b, 0xae, 0x6f,+ 0x9b, 0xfe, 0x63, 0x82, 0x33, 0x0f, 0x9d, 0x58, 0x54, 0x66, 0xbd, 0x89, 0x41, 0xb9, 0x8c, 0x03, 0xd4, 0x8e, 0x42, 0xff,+ 0x0f, 0x19, 0xcb, 0x29, 0x5c, 0x4a, 0xb2, 0xa8, 0xbf, 0x8f, 0x7f, 0x33, 0x9d, 0x8d, 0xd6, 0x56, 0xc5, 0x99, 0xd3, 0xe5,+ 0x4f, 0x2e, 0x33, 0xf3, 0x78, 0xad, 0x75, 0xe7, 0xc1, 0x08, 0x67, 0x20, 0x93, 0x89, 0xa1, 0x0f, 0x93, 0x85, 0xfe, 0xbd,+ 0xcf, 0xcc, 0x07, 0x35, 0x83, 0x0d, 0x96, 0x63, 0xc4, 0xf0, 0x1d, 0x93, 0xa8, 0x4c, 0x25, 0x2a, 0x09, 0x4e, 0xdb, 0xb2,+ 0x6c, 0x65, 0x80, 0xd8, 0xab, 0xb7, 0xe9, 0x5f, 0x97, 0xb9, 0x1e, 0x23, 0x8a, 0x1f, 0xcf, 0xb4, 0x27, 0x95, 0x1d, 0xec,+ 0xb6, 0xcc, 0x88, 0xf1, 0xb5, 0xb9, 0x4b, 0xc3, 0xa9, 0xcf, 0x78, 0x72, 0x98, 0xcf, 0x93, 0x16, 0xfd, 0x4f, 0xe1, 0x00,+ 0xbd, 0x3c, 0x8e, 0xfa, 0x0a, 0xe9, 0x46, 0x39, 0x67, 0x26, 0xa7, 0xbb, 0xc5, 0x35, 0xae, 0x62, 0xb7, 0x19, 0x4f, 0xbf,+ 0x04, 0xcb, 0x2d, 0xe7, 0x56, 0x9d, 0x5c, 0xeb, 0x31, 0xce, 0x0f, 0x19, 0xc5, 0xfb, 0x05, 0xc1, 0x0b, 0xfa, 0x3a, 0x2b,+ 0x44, 0x9f, 0xa5, 0x4d, 0xff, 0x76, 0x2c, 0xa5, 0xd5, 0x09, 0x5b, 0xff, 0x9f, 0x62, 0xb9, 0xc3, 0x9c, 0x56, 0x76, 0x25,+ 0xdb, 0x2c, 0xa9, 0xc5, 0xff, 0xe6, 0xb3, 0xae, 0xca, 0x7e, 0xeb, 0x8c, 0x0b, 0x91, 0x99, 0x14, 0x9c, 0x77, 0xac, 0x20,+ 0xfa, 0x4f, 0x16, 0xd7, 0xfe, 0xdf, 0x20, 0xf1, 0x98, 0x3c, 0xab, 0x3b, 0xf9, 0xa5, 0x50, 0x73, 0xa7, 0x05, 0xf8, 0x32,+ 0xca, 0xfe, 0x5f, 0x73, 0x7d, 0x53, 0x78, 0x0c, 0x11, 0xcf, 0xd8, 0x90, 0x99, 0x69, 0x0a, 0xc3, 0x10, 0x9e, 0x8f, 0x42,+ 0xff, 0x65, 0x34, 0xd2, 0x5c, 0x3f, 0xa1, 0xb8, 0x95, 0xa5, 0xc2, 0x2c, 0x51, 0x92, 0xfe, 0xa5, 0x78, 0x82, 0x34, 0x8f,+ 0xbe, 0xac, 0x72, 0x3c, 0x52, 0x9c, 0xb6, 0x42, 0xe4, 0xa6, 0xa4, 0x7f, 0x5d, 0xde, 0x15, 0x47, 0x14, 0x52, 0x4e, 0x3c,+ 0x6c, 0xf5, 0xbf, 0xa2, 0xfa, 0x2b, 0xaa, 0xbf, 0x72, 0x62, 0x53, 0xc2, 0xe3, 0x6b, 0x92, 0xa2, 0x28, 0x8a, 0xa2, 0x28,+ 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,+ 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,+ 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28,+ 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,+ 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,+ 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28,+ 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2,+ 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a, 0xa2, 0x28, 0x8a,+ 0xa2, 0x28, 0x8a, 0xe2, 0xe0, 0xff, 0xa7, 0xf9, 0xa0, 0xfa, 0x2b, 0xff, 0xb3, 0xfa, 0xff, 0x3f };++// Font glyphs rectangles data (on atlas)+static const Rectangle amberFontRecs[95] = {+ { 4, 4, 3 , 16 },+ { 15, 4, 2 , 11 },+ { 25, 4, 4 , 5 },+ { 37, 4, 9 , 10 },+ { 54, 4, 8 , 14 },+ { 70, 4, 11 , 11 },+ { 89, 4, 9 , 11 },+ { 106, 4, 2 , 5 },+ { 116, 4, 4 , 13 },+ { 128, 4, 4 , 13 },+ { 140, 4, 6 , 6 },+ { 154, 4, 7 , 7 },+ { 169, 4, 3 , 5 },+ { 180, 4, 6 , 2 },+ { 194, 4, 2 , 3 },+ { 204, 4, 5 , 13 },+ { 217, 4, 8 , 11 },+ { 233, 4, 5 , 10 },+ { 4, 28, 8 , 10 },+ { 20, 28, 8 , 11 },+ { 36, 28, 8 , 10 },+ { 52, 28, 7 , 11 },+ { 67, 28, 8 , 11 },+ { 83, 28, 7 , 10 },+ { 98, 28, 8 , 11 },+ { 114, 28, 8 , 11 },+ { 130, 28, 2 , 8 },+ { 140, 28, 3 , 10 },+ { 151, 28, 7 , 8 },+ { 166, 28, 7 , 5 },+ { 181, 28, 7 , 8 },+ { 196, 28, 7 , 11 },+ { 211, 28, 12 , 13 },+ { 231, 28, 9 , 10 },+ { 4, 52, 7 , 10 },+ { 19, 52, 9 , 11 },+ { 36, 52, 8 , 10 },+ { 52, 52, 7 , 10 },+ { 67, 52, 6 , 10 },+ { 81, 52, 10 , 11 },+ { 99, 52, 8 , 10 },+ { 115, 52, 2 , 10 },+ { 125, 52, 7 , 11 },+ { 140, 52, 8 , 10 },+ { 156, 52, 6 , 10 },+ { 170, 52, 10 , 10 },+ { 188, 52, 8 , 10 },+ { 204, 52, 10 , 11 },+ { 222, 52, 7 , 10 },+ { 237, 52, 10 , 11 },+ { 4, 76, 8 , 10 },+ { 20, 76, 8 , 11 },+ { 36, 76, 8 , 10 },+ { 52, 76, 8 , 11 },+ { 68, 76, 9 , 10 },+ { 85, 76, 13 , 10 },+ { 106, 76, 9 , 10 },+ { 123, 76, 9 , 10 },+ { 140, 76, 8 , 10 },+ { 156, 76, 4 , 13 },+ { 168, 76, 5 , 13 },+ { 181, 76, 4 , 13 },+ { 193, 76, 6 , 5 },+ { 207, 76, 7 , 2 },+ { 222, 76, 4 , 3 },+ { 234, 76, 7 , 9 },+ { 4, 100, 7 , 11 },+ { 19, 100, 7 , 9 },+ { 34, 100, 8 , 11 },+ { 50, 100, 8 , 9 },+ { 66, 100, 5 , 11 },+ { 79, 100, 8 , 11 },+ { 95, 100, 6 , 10 },+ { 109, 100, 3 , 10 },+ { 120, 100, 4 , 13 },+ { 132, 100, 7 , 10 },+ { 147, 100, 2 , 10 },+ { 157, 100, 10 , 8 },+ { 175, 100, 6 , 8 },+ { 189, 100, 8 , 9 },+ { 205, 100, 7 , 11 },+ { 220, 100, 8 , 11 },+ { 236, 100, 4 , 8 },+ { 4, 124, 7 , 9 },+ { 19, 124, 5 , 10 },+ { 32, 124, 6 , 9 },+ { 46, 124, 8 , 8 },+ { 62, 124, 11 , 8 },+ { 81, 124, 7 , 8 },+ { 96, 124, 8 , 11 },+ { 112, 124, 7 , 8 },+ { 127, 124, 5 , 13 },+ { 140, 124, 2 , 17 },+ { 150, 124, 5 , 13 },+ { 163, 124, 7 , 4 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo amberFontGlyphs[95] = {+ { 32, 0, 12, 3, { 0 }},+ { 33, 1, 2, 3, { 0 }},+ { 34, 1, 2, 6, { 0 }},+ { 35, 0, 2, 8, { 0 }},+ { 36, 0, 0, 8, { 0 }},+ { 37, 1, 2, 12, { 0 }},+ { 38, 0, 2, 8, { 0 }},+ { 39, 1, 2, 3, { 0 }},+ { 40, 1, 1, 4, { 0 }},+ { 41, 0, 1, 4, { 0 }},+ { 42, 0, 2, 6, { 0 }},+ { 43, 1, 5, 8, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 7, 6, { 0 }},+ { 46, 1, 10, 3, { 0 }},+ { 47, 0, 1, 4, { 0 }},+ { 48, 0, 2, 8, { 0 }},+ { 49, 0, 2, 5, { 0 }},+ { 50, 0, 2, 8, { 0 }},+ { 51, 0, 2, 8, { 0 }},+ { 52, 0, 2, 8, { 0 }},+ { 53, 1, 2, 8, { 0 }},+ { 54, 0, 2, 8, { 0 }},+ { 55, 0, 2, 7, { 0 }},+ { 56, 0, 2, 8, { 0 }},+ { 57, 0, 2, 8, { 0 }},+ { 58, 1, 5, 3, { 0 }},+ { 59, 0, 5, 3, { 0 }},+ { 60, 1, 4, 8, { 0 }},+ { 61, 1, 6, 8, { 0 }},+ { 62, 1, 4, 8, { 0 }},+ { 63, 0, 2, 6, { 0 }},+ { 64, 0, 2, 12, { 0 }},+ { 65, 0, 2, 9, { 0 }},+ { 66, 1, 2, 8, { 0 }},+ { 67, 0, 2, 9, { 0 }},+ { 68, 1, 2, 9, { 0 }},+ { 69, 1, 2, 7, { 0 }},+ { 70, 1, 2, 7, { 0 }},+ { 71, 0, 2, 9, { 0 }},+ { 72, 1, 2, 9, { 0 }},+ { 73, 1, 2, 3, { 0 }},+ { 74, 0, 2, 7, { 0 }},+ { 75, 1, 2, 8, { 0 }},+ { 76, 1, 2, 7, { 0 }},+ { 77, 1, 2, 11, { 0 }},+ { 78, 1, 2, 9, { 0 }},+ { 79, 0, 2, 10, { 0 }},+ { 80, 1, 2, 8, { 0 }},+ { 81, 0, 2, 10, { 0 }},+ { 82, 1, 2, 8, { 0 }},+ { 83, 0, 2, 8, { 0 }},+ { 84, 0, 2, 8, { 0 }},+ { 85, 1, 2, 9, { 0 }},+ { 86, 0, 2, 9, { 0 }},+ { 87, 0, 2, 13, { 0 }},+ { 88, 0, 2, 9, { 0 }},+ { 89, 0, 2, 8, { 0 }},+ { 90, 0, 2, 8, { 0 }},+ { 91, 1, 1, 4, { 0 }},+ { 92, 0, 1, 4, { 0 }},+ { 93, 0, 1, 4, { 0 }},+ { 94, 0, 2, 6, { 0 }},+ { 95, 0, 12, 6, { 0 }},+ { 96, 0, 1, 4, { 0 }},+ { 97, 0, 4, 7, { 0 }},+ { 98, 1, 2, 8, { 0 }},+ { 99, 0, 4, 7, { 0 }},+ { 100, 0, 2, 8, { 0 }},+ { 101, 0, 4, 7, { 0 }},+ { 102, 0, 1, 4, { 0 }},+ { 103, 0, 4, 8, { 0 }},+ { 104, 1, 2, 7, { 0 }},+ { 105, 0, 2, 3, { 0 }},+ { 106, -1, 2, 3, { 0 }},+ { 107, 1, 2, 7, { 0 }},+ { 108, 1, 2, 3, { 0 }},+ { 109, 1, 4, 11, { 0 }},+ { 110, 1, 4, 7, { 0 }},+ { 111, 0, 4, 7, { 0 }},+ { 112, 1, 4, 8, { 0 }},+ { 113, 0, 4, 8, { 0 }},+ { 114, 1, 4, 4, { 0 }},+ { 115, 0, 4, 6, { 0 }},+ { 116, 0, 3, 4, { 0 }},+ { 117, 1, 4, 7, { 0 }},+ { 118, 0, 4, 7, { 0 }},+ { 119, 0, 4, 10, { 0 }},+ { 120, 0, 4, 7, { 0 }},+ { 121, 0, 4, 7, { 0 }},+ { 122, 0, 4, 7, { 0 }},+ { 123, 0, 1, 5, { 0 }},+ { 124, 1, -1, 4, { 0 }},+ { 125, 0, 1, 5, { 0 }},+ { 126, 1, 6, 8, { 0 }},+};++// Style loading function: Amber+static void GuiLoadStyleAmber(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < AMBER_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(amberStyleProps[i].controlId, amberStyleProps[i].propertyId, amberStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int amberFontDataSize = 0;+ unsigned char *data = DecompressData(amberFontData, AMBER_STYLE_FONT_ATLAS_COMP_SIZE, &amberFontDataSize);+ Image imFont = { data, 256, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 95;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, amberFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, amberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 254, 126, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/ashes/style_ashes.h view
@@ -0,0 +1,578 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleAshes(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define ASHES_STYLE_PROPS_COUNT 16++// Custom style name: Ashes+static const GuiStyleProp ashesStyleProps[ASHES_STYLE_PROPS_COUNT] = {+ { 0, 0, 0xf0f0f0ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x868686ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xe6e6e6ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0x929999ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xeaeaeaff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x98a1a8ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x3f3f3fff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xf6f6f6ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x414141ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x8b8b8bff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x777777ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x959595ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 18, 0x9dadb1ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x6b6b6bff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "v5loxical.ttf" (size: 16, spacing: 1)++#define ASHES_STYLE_FONT_ATLAS_COMP_SIZE 2042++// Font atlas image pixels data: DEFLATE compressed+static unsigned char ashesFontData[ASHES_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0xd1, 0xb2, 0xab, 0x36, 0x0c, 0x05, 0x50, 0xff, 0xff, 0x4f, 0xab, 0x0f, 0x9d, 0x4e, 0xdb, 0x69, 0x13, 0x90, 0x2c,+ 0x83, 0x21, 0xeb, 0xae, 0xb7, 0x9c, 0xdc, 0x40, 0x0c, 0x1b, 0x63, 0x88, 0x45, 0x0c, 0x00, 0x00, 0x00, 0xe0, 0xe7, 0xc5,+ 0xff, 0xbe, 0x12, 0x1f, 0xdf, 0x19, 0xa7, 0x3f, 0xe7, 0xdf, 0xaf, 0xc7, 0x87, 0xbf, 0xe6, 0x3e, 0x2f, 0x4e, 0x2f, 0xb7,+ 0xf2, 0x97, 0xf8, 0xdf, 0xf5, 0x8b, 0xe9, 0xa5, 0xc6, 0xe9, 0x6f, 0xf3, 0xed, 0xbd, 0xdf, 0x96, 0xf9, 0xe9, 0x93, 0x22,+ 0xb1, 0x8c, 0xec, 0xfb, 0x3f, 0x7f, 0xce, 0xd5, 0x2d, 0x1e, 0x5f, 0xfe, 0xf2, 0xfd, 0xaf, 0xd9, 0xd7, 0xe3, 0xe4, 0xab,+ 0xdf, 0xfe, 0x12, 0x07, 0x7f, 0x39, 0x9b, 0xbb, 0x78, 0x40, 0xfe, 0xe3, 0xcb, 0xe7, 0x7d, 0xff, 0xc4, 0x98, 0x38, 0x26,+ 0x9c, 0x5b, 0xee, 0x95, 0xed, 0xf9, 0x69, 0x4f, 0xcf, 0x6d, 0xeb, 0xef, 0x6d, 0x9c, 0xcb, 0x5c, 0x34, 0xac, 0xff, 0x6c,+ 0xab, 0x45, 0xc3, 0xbb, 0xe3, 0xc4, 0xde, 0x92, 0xd9, 0x9b, 0xb3, 0x69, 0xab, 0xbd, 0x7f, 0x34, 0x6c, 0xaf, 0x6b, 0xf3,+ 0xff, 0xcf, 0x7f, 0x23, 0x75, 0x14, 0x1c, 0x4d, 0xf9, 0xcf, 0xf7, 0xb9, 0xdf, 0x8e, 0xbe, 0x71, 0xd1, 0xd9, 0xd4, 0xb9,+ 0x3d, 0xb4, 0xfe, 0x7a, 0xdf, 0xa7, 0x5f, 0x9d, 0xff, 0x68, 0xfc, 0x1f, 0x47, 0x6b, 0x17, 0xf2, 0x3f, 0xbd, 0x15, 0xa2,+ 0xd8, 0xdb, 0x56, 0x7b, 0xa2, 0xd9, 0xad, 0x1f, 0x8b, 0x7b, 0xfa, 0x55, 0x09, 0xad, 0x1d, 0xcd, 0x22, 0xf9, 0x7f, 0x72,+ 0x7d, 0x6c, 0x4c, 0x6f, 0xbd, 0xf3, 0xfb, 0x44, 0x7e, 0xfd, 0x8e, 0xf7, 0x00, 0xf9, 0xbf, 0x22, 0xff, 0x95, 0xe4, 0xc6,+ 0x92, 0xa3, 0x7f, 0xf5, 0xca, 0xc0, 0x8a, 0xb6, 0xcc, 0xe5, 0x3f, 0x1a, 0x5b, 0x20, 0xdb, 0x6f, 0xe7, 0xd7, 0xff, 0xec,+ 0x48, 0x3d, 0x6e, 0xec, 0xff, 0xbf, 0x1d, 0x1d, 0x33, 0x47, 0xcd, 0x6c, 0x3a, 0x73, 0xcb, 0xfd, 0x7b, 0x5d, 0xe7, 0xaf,+ 0x88, 0xac, 0xc8, 0x7f, 0xf5, 0xfc, 0xbf, 0x72, 0x86, 0x3a, 0x36, 0xc9, 0xf3, 0xf5, 0xf9, 0x8f, 0xf6, 0x16, 0x58, 0x99,+ 0xff, 0xb3, 0x6d, 0x1f, 0x0b, 0xc7, 0xff, 0xb9, 0xab, 0xab, 0xfb, 0xf7, 0xff, 0xf7, 0x5f, 0xff, 0x1b, 0xe5, 0xeb, 0x46,+ 0xd9, 0x6b, 0x80, 0x71, 0xea, 0xec, 0xe1, 0x29, 0xf9, 0xef, 0x38, 0xfe, 0x55, 0x47, 0x4a, 0x1d, 0x57, 0xb8, 0xb2, 0xf9,+ 0x8f, 0x86, 0xb6, 0x8f, 0xa5, 0x47, 0xff, 0x4a, 0xaf, 0x24, 0xff, 0xbd, 0xe3, 0xff, 0x38, 0x71, 0x06, 0x18, 0xaf, 0xe8,+ 0xff, 0xf3, 0xa3, 0x9c, 0x68, 0xb8, 0x07, 0x57, 0xb9, 0xbb, 0x9a, 0xed, 0x31, 0x2b, 0xf7, 0x24, 0x77, 0x68, 0x77, 0xfd,+ 0xff, 0x75, 0xdb, 0xa0, 0xb6, 0x2f, 0xfc, 0xf5, 0xff, 0x9e, 0xdf, 0xff, 0xef, 0xb4, 0x35, 0x90, 0xff, 0xab, 0xf7, 0xdb,+ 0xb8, 0xb5, 0x7f, 0x95, 0x7f, 0xbf, 0x60, 0xeb, 0xca, 0xff, 0xda, 0xdf, 0xff, 0xc4, 0x41, 0x6f, 0x38, 0x1e, 0xd9, 0xff,+ 0x5f, 0xb3, 0x36, 0x21, 0x79, 0xe0, 0x58, 0x2f, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0xfc, 0xd0, 0xec, 0x99, 0xcc, 0xec, 0xe5, 0x6a, 0x15, 0xe0, 0x8e, 0xf7, 0x57, 0x97, 0x10, 0x6d, 0xf5, 0x1f, 0xfb,+ 0xaa, 0x49, 0x7e, 0x9e, 0x4d, 0x9a, 0x99, 0xf7, 0x9c, 0xab, 0x6f, 0x9e, 0xab, 0x24, 0x17, 0xc9, 0x9a, 0x6d, 0x91, 0xac,+ 0x5b, 0x9c, 0xdd, 0x8e, 0xf3, 0xb3, 0xec, 0xe7, 0xfe, 0xff, 0xdf, 0xb5, 0x2a, 0xfa, 0xf6, 0xe5, 0xd1, 0xd4, 0x32, 0xd7,+ 0xe5, 0x7f, 0xb4, 0xd7, 0x54, 0xcd, 0x57, 0xa8, 0xca, 0xd7, 0xc7, 0x1f, 0x9b, 0xe5, 0x3f, 0xb3, 0x3f, 0x66, 0xeb, 0xfe,+ 0x44, 0x61, 0x56, 0x64, 0x4c, 0xcf, 0xb7, 0x8c, 0x85, 0xfb, 0x5d, 0x57, 0x05, 0xc9, 0x31, 0x99, 0xff, 0x3b, 0xf7, 0xfd,+ 0x4a, 0x6d, 0x46, 0xf9, 0x7f, 0x43, 0xfe, 0x2b, 0xd5, 0x3d, 0x3b, 0xe6, 0x45, 0x77, 0xd5, 0xc7, 0x8d, 0xf4, 0x79, 0x51,+ 0x66, 0x7f, 0x88, 0xa9, 0xca, 0xea, 0x91, 0x3e, 0x0e, 0xef, 0x98, 0x7f, 0xfd, 0x7f, 0xa5, 0x36, 0xde, 0xdd, 0xf9, 0x9f,+ 0x7b, 0x22, 0xc0, 0xea, 0xea, 0x07, 0x6b, 0xfb, 0xa7, 0xde, 0xfe, 0x3f, 0x26, 0xf2, 0x9f, 0x7d, 0x86, 0xd9, 0x5e, 0xf9,+ 0x9f, 0x3f, 0xff, 0xaf, 0x57, 0x3b, 0xef, 0x1a, 0x05, 0x8f, 0x86, 0xe3, 0x7d, 0xf5, 0x49, 0x82, 0x5d, 0xf9, 0x1f, 0x85,+ 0xa7, 0xc0, 0xcd, 0x9e, 0x8f, 0x3e, 0x3b, 0xff, 0xb9, 0x2b, 0x11, 0xeb, 0xf2, 0xff, 0xec, 0xfe, 0x7f, 0xbc, 0xe0, 0xfc,+ 0xbf, 0x63, 0x7b, 0x8f, 0x4d, 0xcf, 0xff, 0xbb, 0x46, 0xd1, 0xef, 0xcb, 0x7f, 0xf6, 0x7b, 0x76, 0x7c, 0xfe, 0x5b, 0xcf,+ 0xff, 0xe5, 0xff, 0xed, 0xf9, 0xbf, 0xeb, 0x49, 0x66, 0x7b, 0xe4, 0x3f, 0x9a, 0xaa, 0xef, 0xca, 0xff, 0x5b, 0xf3, 0xbf,+ 0xeb, 0xf5, 0xbf, 0xe7, 0xe6, 0x7f, 0x94, 0xc6, 0x66, 0x73, 0xef, 0x7e, 0x42, 0xff, 0x3f, 0x0a, 0xd7, 0xac, 0xf2, 0x23,+ 0xd9, 0xeb, 0xc6, 0xff, 0xf2, 0x7f, 0xee, 0xee, 0xd9, 0xdd, 0xf9, 0x5f, 0x73, 0xff, 0xab, 0xef, 0xbc, 0xa0, 0xe3, 0xdd,+ 0x7b, 0x8f, 0xff, 0x57, 0xff, 0x16, 0x67, 0xed, 0xf2, 0x7b, 0xae, 0xb4, 0x45, 0xf9, 0xba, 0x7d, 0xcf, 0x6f, 0x49, 0xf2,+ 0xd7, 0xdf, 0xb2, 0x47, 0xce, 0x38, 0x78, 0x7f, 0x34, 0xf5, 0x73, 0x95, 0xea, 0xf0, 0x3b, 0xe4, 0x3f, 0xfb, 0xd4, 0x9f,+ 0xec, 0xbb, 0xf7, 0xc8, 0xff, 0xfa, 0x96, 0xbd, 0x3a, 0xff, 0x4f, 0xfc, 0xb5, 0xe2, 0xef, 0xb5, 0x42, 0x2c, 0x7e, 0xff,+ 0x6f, 0xef, 0x0b, 0x7b, 0x3d, 0x31, 0xcb, 0x76, 0xe5, 0xca, 0xbe, 0x15, 0xad, 0x05, 0x8e, 0xac, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9b, 0xfb, 0x70, 0x34, 0x7f, 0x32, 0x9a, 0xaa, 0x20, 0x64, 0xeb, 0xc0,+ 0x8d, 0xd3, 0xb5, 0xf0, 0xa3, 0x54, 0x79, 0x76, 0xbe, 0xba, 0xc2, 0xf7, 0x19, 0xcd, 0x9f, 0xbf, 0x69, 0x14, 0x66, 0x09,+ 0x67, 0x9f, 0x6d, 0x50, 0xa9, 0xad, 0x50, 0x5f, 0x56, 0x14, 0xab, 0x48, 0xce, 0xb7, 0x41, 0x14, 0x9e, 0xef, 0x70, 0xf4,+ 0x5d, 0xf2, 0x5b, 0x21, 0xf3, 0x5a, 0x65, 0x6e, 0xf9, 0x38, 0xf1, 0xdc, 0x81, 0x38, 0x9c, 0xdf, 0xd0, 0x9b, 0xff, 0xd5,+ 0x75, 0xb0, 0x2b, 0xb5, 0x3c, 0xfe, 0xfb, 0xda, 0x7d, 0x75, 0x27, 0xbe, 0x1d, 0x77, 0x2a, 0x55, 0x28, 0xb2, 0xc7, 0xe1,+ 0xfc, 0x5e, 0x38, 0xb7, 0xac, 0x91, 0xda, 0x02, 0x95, 0x7a, 0xe6, 0x9d, 0x6d, 0x1a, 0x85, 0x9a, 0x17, 0xe7, 0x7b, 0x9f,+ 0x28, 0xb6, 0xfd, 0x4c, 0xcd, 0x9d, 0x33, 0x33, 0x8a, 0xa3, 0xb0, 0xe7, 0x75, 0xd5, 0xc1, 0x8d, 0x96, 0x4c, 0x77, 0x54,+ 0xc1, 0xca, 0xd5, 0xee, 0xcd, 0xce, 0x24, 0x8d, 0xc9, 0xfd, 0x38, 0xbf, 0x7f, 0x47, 0x4b, 0x35, 0xae, 0xe3, 0x65, 0xc5,+ 0x97, 0x65, 0x65, 0xf2, 0x5f, 0xef, 0x4b, 0xd7, 0xe7, 0x3f, 0xbf, 0x06, 0x99, 0x0a, 0x52, 0x73, 0xbd, 0xe3, 0x7c, 0xfe,+ 0x77, 0xed, 0xff, 0xef, 0xce, 0x7f, 0xbe, 0x06, 0xcc, 0xd1, 0x79, 0x77, 0x65, 0x2f, 0x8a, 0x52, 0x26, 0xb3, 0xfb, 0x60,+ 0xbd, 0xff, 0x8f, 0xd2, 0x39, 0x55, 0xe7, 0xb6, 0xbd, 0x22, 0xff, 0x63, 0x61, 0xfe, 0xef, 0xee, 0xff, 0xf7, 0xcc, 0x7f,+ 0x5f, 0x2d, 0xdf, 0xb9, 0xfc, 0xe7, 0x53, 0x3e, 0x8a, 0x6b, 0xde, 0x77, 0xfe, 0x1f, 0xe9, 0xf1, 0xd3, 0xcc, 0xb2, 0xa2,+ 0xe5, 0x5c, 0x6b, 0x1c, 0x3c, 0x9f, 0xf0, 0xf9, 0xf9, 0x1f, 0xc5, 0x33, 0xe0, 0xa3, 0xa7, 0x61, 0xe4, 0xdb, 0x67, 0x76,+ 0x84, 0xbb, 0xbe, 0x0a, 0xf2, 0xf5, 0xcf, 0xc1, 0x88, 0x86, 0xb3, 0xfc, 0xa3, 0xca, 0x85, 0xb1, 0x41, 0xfe, 0xeb, 0xd7,+ 0x87, 0xbb, 0xfa, 0xff, 0xee, 0xeb, 0xd6, 0x3d, 0xf9, 0x1f, 0xa5, 0x71, 0x4c, 0x5f, 0x3b, 0x8f, 0xa9, 0xfe, 0x7f, 0xbc,+ 0x2c, 0xff, 0xd7, 0x3f, 0x07, 0x23, 0x5a, 0x46, 0xf9, 0x51, 0x7c, 0xde, 0x50, 0xef, 0xf9, 0xff, 0xb7, 0xe7, 0xe2, 0x46,+ 0xf9, 0xd9, 0x70, 0x6b, 0xf3, 0x7f, 0xee, 0x6a, 0xf5, 0xca, 0xfc, 0x0f, 0xf9, 0x3f, 0x79, 0x87, 0xeb, 0xe8, 0x5e, 0xc5,+ 0x48, 0xdf, 0x75, 0x99, 0xbd, 0x77, 0x74, 0xe5, 0xf9, 0xff, 0x75, 0xfd, 0xff, 0x58, 0x72, 0xfd, 0x7f, 0x45, 0x3f, 0xfb,+ 0xa4, 0xfe, 0xff, 0xfb, 0x9e, 0xfd, 0x9c, 0xfc, 0x9f, 0x49, 0xdc, 0x78, 0x44, 0x45, 0xd1, 0xae, 0x4a, 0xd0, 0xd7, 0x5e,+ 0xff, 0xeb, 0xbe, 0x9f, 0xd1, 0x73, 0xfe, 0x9f, 0xef, 0x49, 0xe7, 0x46, 0xb9, 0x9d, 0xcb, 0xba, 0xee, 0xfc, 0xff, 0x1d,+ 0xf9, 0xef, 0x59, 0xbb, 0xfb, 0x2b, 0x20, 0xee, 0x99, 0xff, 0x51, 0xfc, 0x7d, 0xcd, 0xbd, 0xe7, 0xff, 0x57, 0xe6, 0x6c,+ 0x8f, 0x7d, 0xe6, 0xbd, 0xf9, 0x3f, 0xfa, 0xfd, 0xcf, 0x13, 0xb7, 0xdb, 0xec, 0xd1, 0x27, 0x16, 0xbd, 0xf7, 0xae, 0xb3,+ 0xa3, 0x98, 0xba, 0x56, 0x21, 0xff, 0x9d, 0xf9, 0x7f, 0x53, 0xc2, 0x9e, 0x92, 0xff, 0x55, 0x47, 0x8c, 0xa7, 0x3c, 0x19,+ 0x42, 0xfe, 0xaf, 0xcd, 0xff, 0xaf, 0x24, 0xec, 0xbd, 0xf9, 0x7f, 0xdf, 0xd1, 0x2c, 0x3b, 0x86, 0x8e, 0x0b, 0xc7, 0xdd,+ 0x71, 0xe3, 0x18, 0xbf, 0xba, 0x5e, 0xd7, 0xac, 0xf3, 0xae, 0x2d, 0xf3, 0x84, 0xb5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x67, 0xb9, 0x44, 0xcb, 0x6c, 0xd9, 0x51, 0xaa, 0xc3, 0x9e, 0x9f, 0x0b, 0x99, 0xad,+ 0x35, 0x3f, 0x5a, 0xea, 0x14, 0x57, 0xaa, 0xc5, 0x1e, 0xcf, 0x37, 0x8d, 0x64, 0x5b, 0xde, 0xb5, 0xad, 0xa2, 0xbc, 0xf4,+ 0x95, 0xdb, 0xe4, 0xf3, 0xac, 0xa0, 0xfc, 0x93, 0x16, 0x2a, 0xd5, 0x33, 0xae, 0xcb, 0xc1, 0xea, 0xd9, 0xfc, 0xf9, 0xba,+ 0xfc, 0xf3, 0x55, 0x4f, 0xfb, 0x9e, 0x14, 0xd0, 0xfd, 0x2d, 0x32, 0x75, 0x5e, 0xcf, 0xb5, 0x42, 0x34, 0xb5, 0xe5, 0x5d,+ 0xdb, 0xea, 0x68, 0x8d, 0x62, 0xf9, 0xda, 0x76, 0xd5, 0xeb, 0x8e, 0x52, 0x3f, 0x78, 0x47, 0x0e, 0x2a, 0xfd, 0xd1, 0xfd,+ 0xb3, 0x5c, 0xe7, 0xe7, 0xf7, 0xd6, 0xf3, 0xff, 0xd4, 0xf3, 0xb1, 0x67, 0x7c, 0xa7, 0xef, 0xb5, 0xb4, 0x76, 0xfa, 0x0e,+ 0xd5, 0xfc, 0x77, 0x54, 0x97, 0xe9, 0x9c, 0xe7, 0x1e, 0x5f, 0x6a, 0x2e, 0x47, 0xeb, 0xf9, 0xff, 0x4e, 0xaf, 0x57, 0xf3,+ 0x9f, 0x1f, 0x2f, 0xcc, 0x8e, 0x2f, 0xe6, 0x9f, 0x50, 0x94, 0xaf, 0xde, 0x79, 0xdf, 0xeb, 0xdd, 0xcf, 0x48, 0x5a, 0xfd,+ 0x7a, 0x25, 0xff, 0xbb, 0xf6, 0x0d, 0x3d, 0xf9, 0x8f, 0x0d, 0xb7, 0x52, 0x7e, 0xf4, 0x36, 0x7f, 0x9e, 0x59, 0x3d, 0xbe,+ 0x74, 0xe7, 0x7f, 0xc7, 0xb6, 0xcf, 0x8f, 0xff, 0x9f, 0x97, 0xff, 0x28, 0xf4, 0xc3, 0xf7, 0xf5, 0x83, 0x99, 0xa7, 0x58,+ 0xd6, 0xc7, 0xf8, 0xfb, 0xef, 0x83, 0xf2, 0x7f, 0x77, 0xdb, 0x8f, 0x1f, 0xe8, 0xff, 0xf7, 0xd9, 0xef, 0xba, 0xc7, 0xc1,+ 0xf2, 0x2f, 0xff, 0xf2, 0x1f, 0x27, 0xc6, 0x63, 0x7b, 0xbc, 0x7e, 0x5d, 0xfe, 0x73, 0x95, 0xf9, 0xd7, 0xbf, 0x5e, 0xcb,+ 0xed, 0xda, 0x6d, 0x24, 0xff, 0xfb, 0xe5, 0x7f, 0xe6, 0x89, 0x61, 0x4f, 0x68, 0xf3, 0xde, 0xfb, 0x7f, 0xcf, 0x1a, 0x6b,+ 0xea, 0xff, 0xe5, 0xbf, 0x7e, 0xff, 0xff, 0x1d, 0xf9, 0xef, 0xbe, 0x97, 0xf7, 0x94, 0xeb, 0x7f, 0xe3, 0xe0, 0xb9, 0x40,+ 0x71, 0xcb, 0x73, 0xc4, 0xd6, 0xe4, 0xff, 0x19, 0xdb, 0xe4, 0x78, 0xaf, 0x7a, 0x52, 0xfe, 0x9f, 0xdf, 0xe6, 0x9d, 0xf7,+ 0x25, 0xdf, 0xf1, 0xbd, 0x9f, 0x99, 0xff, 0x37, 0x6c, 0x93, 0xa3, 0x11, 0xd3, 0x9e, 0xfd, 0xff, 0xf3, 0x73, 0x10, 0x8b,+ 0x7f, 0x83, 0xb2, 0x6f, 0xfe, 0xc7, 0x6b, 0xfa, 0xff, 0xe7, 0x6f, 0x93, 0xb8, 0xf1, 0x5b, 0xf4, 0xe6, 0x7f, 0xb7, 0xfb,+ 0x7f, 0x77, 0xff, 0x06, 0xed, 0x69, 0xe7, 0x3d, 0xcf, 0xfb, 0xfd, 0x4f, 0x6d, 0x4c, 0xfd, 0xa4, 0x7d, 0xf1, 0xae, 0x3b,+ 0xe7, 0x2a, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xd6, 0x55, 0xdf, 0x3c, 0x8a,+ 0x33, 0xab, 0xce, 0xbd, 0x56, 0xa9, 0xe6, 0x1e, 0xcb, 0xbe, 0x6b, 0xa5, 0x36, 0x4b, 0xb4, 0xcd, 0x5d, 0xea, 0xda, 0x32,+ 0x9f, 0x97, 0x1b, 0xc5, 0x2a, 0x2c, 0xbc, 0xeb, 0x08, 0xb0, 0xaa, 0x42, 0xfe, 0x68, 0xa8, 0x92, 0x5f, 0xab, 0xe6, 0x78,+ 0x4f, 0x2d, 0xf7, 0xb9, 0x99, 0xb2, 0xeb, 0xb6, 0x4c, 0x6f, 0x9d, 0x7c, 0xde, 0x75, 0x04, 0x58, 0xf9, 0x1c, 0x91, 0x68,+ 0xfc, 0xcc, 0xd8, 0xea, 0xbb, 0x8e, 0xaf, 0x33, 0xcf, 0x46, 0xa2, 0xf2, 0xc4, 0xfa, 0xb5, 0x8d, 0xd6, 0x96, 0x85, 0x3b,+ 0x8e, 0x59, 0xcf, 0xde, 0x4b, 0xf7, 0xeb, 0x51, 0xe5, 0xff, 0xd7, 0x92, 0xb4, 0x7a, 0x8e, 0xf8, 0x6c, 0x5d, 0x8e, 0xfc,+ 0x59, 0xea, 0x7e, 0x35, 0x1b, 0xa2, 0x30, 0xa7, 0x7f, 0x78, 0x4e, 0x06, 0x37, 0xf5, 0x3f, 0x9d, 0x75, 0x3b, 0xae, 0xcf,+ 0xff, 0x5e, 0xaf, 0xd7, 0xfa, 0x7f, 0xf9, 0x47, 0xfe, 0xe5, 0x5f, 0xfe, 0x91, 0xff, 0xf7, 0xe6, 0x3f, 0xe4, 0x9f, 0x5b,+ 0x47, 0xff, 0x2b, 0x9f, 0xdb, 0x21, 0xff, 0x73, 0x77, 0xff, 0xe4, 0x9f, 0x3b, 0xee, 0xfe, 0xf7, 0x55, 0xc8, 0x95, 0xff,+ 0xda, 0xaf, 0xaf, 0xe4, 0x1f, 0xf9, 0x7f, 0x7b, 0xff, 0x2f, 0xff, 0xb8, 0xff, 0x77, 0x4d, 0xfe, 0xd5, 0xc9, 0xce, 0xfd,+ 0x4a, 0x3a, 0xf7, 0x24, 0x44, 0xb8, 0xfe, 0xba, 0x85, 0xbd, 0xb1, 0xff, 0xb7, 0x99, 0x47, 0x2d, 0xab, 0xc5, 0xe1, 0x17,+ 0xe6, 0x7f, 0xc9, 0x3f, 0xfc, 0xda, 0xc8, 0xaf, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe3, 0xcf, 0x7f, 0xda, 0x01, 0xe4, 0x1f, 0xf8, 0xb9, 0xfc, 0xff,+ 0x01 };++// Font glyphs rectangles data (on atlas)+static const Rectangle ashesFontRecs[189] = {+ { 4, 4, 4 , 16 },+ { 16, 4, 1 , 10 },+ { 25, 4, 3 , 3 },+ { 36, 4, 6 , 8 },+ { 50, 4, 5 , 11 },+ { 63, 4, 7 , 8 },+ { 78, 4, 6 , 9 },+ { 92, 4, 1 , 3 },+ { 101, 4, 3 , 12 },+ { 112, 4, 3 , 12 },+ { 123, 4, 5 , 5 },+ { 136, 4, 5 , 5 },+ { 149, 4, 2 , 2 },+ { 159, 4, 4 , 1 },+ { 171, 4, 1 , 1 },+ { 180, 4, 5 , 10 },+ { 193, 4, 4 , 8 },+ { 205, 4, 2 , 8 },+ { 215, 4, 4 , 8 },+ { 227, 4, 4 , 8 },+ { 239, 4, 6 , 8 },+ { 253, 4, 4 , 8 },+ { 265, 4, 4 , 8 },+ { 277, 4, 4 , 8 },+ { 289, 4, 4 , 8 },+ { 301, 4, 4 , 8 },+ { 313, 4, 1 , 5 },+ { 322, 4, 2 , 6 },+ { 332, 4, 4 , 7 },+ { 344, 4, 4 , 4 },+ { 356, 4, 4 , 7 },+ { 368, 4, 4 , 10 },+ { 380, 4, 8 , 7 },+ { 396, 4, 4 , 10 },+ { 408, 4, 4 , 10 },+ { 420, 4, 4 , 10 },+ { 432, 4, 4 , 10 },+ { 444, 4, 4 , 10 },+ { 456, 4, 5 , 10 },+ { 469, 4, 4 , 10 },+ { 481, 4, 4 , 10 },+ { 493, 4, 1 , 10 },+ { 4, 28, 3 , 10 },+ { 15, 28, 4 , 10 },+ { 27, 28, 4 , 10 },+ { 39, 28, 7 , 10 },+ { 54, 28, 4 , 10 },+ { 66, 28, 4 , 10 },+ { 78, 28, 4 , 10 },+ { 90, 28, 5 , 11 },+ { 103, 28, 4 , 10 },+ { 115, 28, 4 , 10 },+ { 127, 28, 5 , 10 },+ { 140, 28, 4 , 10 },+ { 152, 28, 4 , 10 },+ { 164, 28, 7 , 10 },+ { 179, 28, 4 , 10 },+ { 191, 28, 4 , 10 },+ { 203, 28, 4 , 10 },+ { 215, 28, 2 , 12 },+ { 225, 28, 5 , 10 },+ { 238, 28, 2 , 12 },+ { 248, 28, 5 , 3 },+ { 261, 28, 5 , 1 },+ { 274, 28, 2 , 2 },+ { 284, 28, 4 , 8 },+ { 296, 28, 4 , 10 },+ { 308, 28, 3 , 8 },+ { 319, 28, 4 , 10 },+ { 331, 28, 4 , 8 },+ { 343, 28, 3 , 10 },+ { 354, 28, 5 , 11 },+ { 367, 28, 4 , 10 },+ { 379, 28, 1 , 10 },+ { 388, 28, 3 , 13 },+ { 399, 28, 4 , 10 },+ { 411, 28, 2 , 10 },+ { 421, 28, 7 , 8 },+ { 436, 28, 4 , 8 },+ { 448, 28, 4 , 8 },+ { 460, 28, 4 , 11 },+ { 472, 28, 4 , 11 },+ { 484, 28, 3 , 8 },+ { 495, 28, 4 , 8 },+ { 4, 52, 3 , 10 },+ { 15, 52, 4 , 8 },+ { 27, 52, 5 , 8 },+ { 40, 52, 7 , 8 },+ { 55, 52, 4 , 8 },+ { 67, 52, 4 , 11 },+ { 79, 52, 4 , 8 },+ { 91, 52, 4 , 12 },+ { 103, 52, 1 , 10 },+ { 112, 52, 4 , 12 },+ { 124, 52, 4 , 2 },+ { 136, 52, 1 , 10 },+ { 145, 52, 4 , 12 },+ { 157, 52, 5 , 10 },+ { 170, 52, 5 , 10 },+ { 183, 52, 5 , 10 },+ { 196, 52, 6 , 13 },+ { 210, 52, 4 , 10 },+ { 222, 52, 6 , 13 },+ { 236, 52, 7 , 9 },+ { 251, 52, 3 , 7 },+ { 262, 52, 6 , 5 },+ { 276, 52, 6 , 13 },+ { 290, 52, 7 , 9 },+ { 305, 52, 4 , 1 },+ { 317, 52, 3 , 5 },+ { 328, 52, 5 , 7 },+ { 341, 52, 3 , 5 },+ { 352, 52, 6 , 13 },+ { 366, 52, 6 , 13 },+ { 380, 52, 4 , 11 },+ { 392, 52, 6 , 10 },+ { 406, 52, 3 , 3 },+ { 417, 52, 6 , 13 },+ { 431, 52, 2 , 5 },+ { 441, 52, 3 , 5 },+ { 452, 52, 6 , 5 },+ { 466, 52, 7 , 10 },+ { 481, 52, 7 , 8 },+ { 496, 52, 6 , 13 },+ { 4, 76, 4 , 10 },+ { 16, 76, 4 , 13 },+ { 28, 76, 4 , 13 },+ { 40, 76, 4 , 13 },+ { 52, 76, 4 , 13 },+ { 64, 76, 4 , 13 },+ { 76, 76, 4 , 13 },+ { 88, 76, 7 , 10 },+ { 103, 76, 4 , 13 },+ { 115, 76, 4 , 13 },+ { 127, 76, 4 , 13 },+ { 139, 76, 4 , 13 },+ { 151, 76, 4 , 13 },+ { 163, 76, 2 , 13 },+ { 173, 76, 2 , 13 },+ { 183, 76, 3 , 13 },+ { 194, 76, 3 , 13 },+ { 205, 76, 5 , 10 },+ { 218, 76, 4 , 13 },+ { 230, 76, 4 , 13 },+ { 242, 76, 4 , 13 },+ { 254, 76, 4 , 13 },+ { 266, 76, 4 , 13 },+ { 278, 76, 4 , 13 },+ { 290, 76, 5 , 5 },+ { 303, 76, 6 , 12 },+ { 317, 76, 4 , 13 },+ { 329, 76, 4 , 13 },+ { 341, 76, 4 , 13 },+ { 353, 76, 4 , 13 },+ { 365, 76, 4 , 13 },+ { 377, 76, 6 , 13 },+ { 391, 76, 5 , 12 },+ { 404, 76, 4 , 12 },+ { 416, 76, 4 , 12 },+ { 428, 76, 4 , 12 },+ { 440, 76, 4 , 12 },+ { 452, 76, 4 , 12 },+ { 464, 76, 4 , 12 },+ { 476, 76, 7 , 8 },+ { 491, 76, 3 , 11 },+ { 4, 100, 4 , 12 },+ { 16, 100, 4 , 12 },+ { 28, 100, 4 , 12 },+ { 40, 100, 4 , 12 },+ { 52, 100, 3 , 12 },+ { 63, 100, 3 , 12 },+ { 74, 100, 3 , 12 },+ { 85, 100, 3 , 12 },+ { 96, 100, 6 , 13 },+ { 110, 100, 4 , 12 },+ { 122, 100, 4 , 12 },+ { 134, 100, 4 , 12 },+ { 146, 100, 4 , 12 },+ { 158, 100, 4 , 12 },+ { 170, 100, 4 , 12 },+ { 182, 100, 5 , 5 },+ { 195, 100, 6 , 10 },+ { 209, 100, 4 , 12 },+ { 221, 100, 4 , 12 },+ { 233, 100, 4 , 12 },+ { 245, 100, 4 , 12 },+ { 257, 100, 4 , 15 },+ { 269, 100, 6 , 13 },+ { 283, 100, 4 , 15 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo ashesFontGlyphs[189] = {+ { 32, 0, 13, 4, { 0 }},+ { 33, 0, 3, 4, { 0 }},+ { 34, 0, 1, 5, { 0 }},+ { 35, 0, 4, 8, { 0 }},+ { 36, 0, 2, 7, { 0 }},+ { 37, 0, 5, 9, { 0 }},+ { 38, 0, 4, 8, { 0 }},+ { 39, 0, 1, 3, { 0 }},+ { 40, 0, 2, 5, { 0 }},+ { 41, 0, 2, 5, { 0 }},+ { 42, 0, 3, 7, { 0 }},+ { 43, 0, 6, 7, { 0 }},+ { 44, 0, 12, 4, { 0 }},+ { 45, 0, 9, 5, { 0 }},+ { 46, 0, 12, 3, { 0 }},+ { 47, 0, 3, 7, { 0 }},+ { 48, 0, 5, 6, { 0 }},+ { 49, 0, 5, 4, { 0 }},+ { 50, 0, 5, 6, { 0 }},+ { 51, 0, 5, 6, { 0 }},+ { 52, 0, 5, 8, { 0 }},+ { 53, 0, 5, 6, { 0 }},+ { 54, 0, 5, 6, { 0 }},+ { 55, 0, 5, 6, { 0 }},+ { 56, 0, 5, 6, { 0 }},+ { 57, 0, 5, 6, { 0 }},+ { 58, 0, 8, 3, { 0 }},+ { 59, 0, 8, 4, { 0 }},+ { 60, 0, 5, 6, { 0 }},+ { 61, 0, 7, 7, { 0 }},+ { 62, 0, 5, 6, { 0 }},+ { 63, 1, 3, 7, { 0 }},+ { 64, 0, 5, 10, { 0 }},+ { 65, 0, 3, 6, { 0 }},+ { 66, 0, 3, 6, { 0 }},+ { 67, 0, 3, 6, { 0 }},+ { 68, 0, 3, 6, { 0 }},+ { 69, 0, 3, 6, { 0 }},+ { 70, 0, 3, 6, { 0 }},+ { 71, 0, 3, 6, { 0 }},+ { 72, 0, 3, 6, { 0 }},+ { 73, 0, 3, 3, { 0 }},+ { 74, 0, 3, 5, { 0 }},+ { 75, 0, 3, 6, { 0 }},+ { 76, 0, 3, 6, { 0 }},+ { 77, 0, 3, 9, { 0 }},+ { 78, 0, 3, 6, { 0 }},+ { 79, 0, 3, 6, { 0 }},+ { 80, 0, 3, 6, { 0 }},+ { 81, 0, 3, 7, { 0 }},+ { 82, 0, 3, 6, { 0 }},+ { 83, 0, 3, 6, { 0 }},+ { 84, 0, 3, 6, { 0 }},+ { 85, 0, 3, 6, { 0 }},+ { 86, 0, 3, 6, { 0 }},+ { 87, 0, 3, 9, { 0 }},+ { 88, 0, 3, 6, { 0 }},+ { 89, 0, 3, 6, { 0 }},+ { 90, 0, 3, 6, { 0 }},+ { 91, 0, 2, 4, { 0 }},+ { 92, 0, 3, 7, { 0 }},+ { 93, 0, 2, 4, { 0 }},+ { 94, 0, 3, 7, { 0 }},+ { 95, 0, 12, 7, { 0 }},+ { 96, 0, 1, 4, { 0 }},+ { 97, 0, 5, 6, { 0 }},+ { 98, 0, 3, 6, { 0 }},+ { 99, 0, 5, 5, { 0 }},+ { 100, 0, 3, 6, { 0 }},+ { 101, 0, 5, 6, { 0 }},+ { 102, 0, 3, 5, { 0 }},+ { 103, 0, 5, 6, { 0 }},+ { 104, 0, 3, 6, { 0 }},+ { 105, 0, 3, 3, { 0 }},+ { 106, 0, 3, 5, { 0 }},+ { 107, 0, 3, 6, { 0 }},+ { 108, 0, 3, 4, { 0 }},+ { 109, 0, 5, 9, { 0 }},+ { 110, 0, 5, 6, { 0 }},+ { 111, 0, 5, 6, { 0 }},+ { 112, 0, 5, 6, { 0 }},+ { 113, 0, 5, 6, { 0 }},+ { 114, 0, 5, 5, { 0 }},+ { 115, 0, 5, 6, { 0 }},+ { 116, 0, 3, 5, { 0 }},+ { 117, 0, 5, 6, { 0 }},+ { 118, 0, 5, 7, { 0 }},+ { 119, 0, 5, 9, { 0 }},+ { 120, 0, 5, 6, { 0 }},+ { 121, 0, 5, 6, { 0 }},+ { 122, 0, 5, 6, { 0 }},+ { 123, 0, 2, 6, { 0 }},+ { 124, 0, 3, 3, { 0 }},+ { 125, 0, 2, 6, { 0 }},+ { 126, 0, 1, 6, { 0 }},+ { 161, 0, 4, 4, { 0 }},+ { 162, 0, 3, 6, { 0 }},+ { 163, 0, 3, 7, { 0 }},+ { 8364, 0, 3, 7, { 0 }},+ { 165, 0, 3, 7, { 0 }},+ { 352, 1, 0, 8, { 0 }},+ { 167, 0, 3, 6, { 0 }},+ { 353, 1, 0, 8, { 0 }},+ { 169, 0, 1, 9, { 0 }},+ { 170, 0, 1, 5, { 0 }},+ { 171, 0, 6, 8, { 0 }},+ { 172, 1, 0, 8, { 0 }},+ { 174, 0, 1, 9, { 0 }},+ { 175, 0, 0, 6, { 0 }},+ { 176, 0, 1, 5, { 0 }},+ { 177, 0, 5, 7, { 0 }},+ { 178, 0, 1, 5, { 0 }},+ { 179, 1, 0, 8, { 0 }},+ { 381, 1, 0, 8, { 0 }},+ { 181, 0, 5, 6, { 0 }},+ { 182, 0, 3, 8, { 0 }},+ { 183, 0, 7, 5, { 0 }},+ { 382, 1, 0, 8, { 0 }},+ { 185, 0, 1, 4, { 0 }},+ { 186, 0, 1, 5, { 0 }},+ { 187, 0, 6, 8, { 0 }},+ { 338, 0, 3, 9, { 0 }},+ { 339, 0, 5, 9, { 0 }},+ { 376, 1, 0, 8, { 0 }},+ { 191, 0, 4, 6, { 0 }},+ { 192, 0, 0, 6, { 0 }},+ { 193, 0, 0, 6, { 0 }},+ { 194, 0, 0, 6, { 0 }},+ { 195, 0, 0, 6, { 0 }},+ { 196, 0, 0, 6, { 0 }},+ { 197, 0, 0, 6, { 0 }},+ { 198, 0, 3, 9, { 0 }},+ { 199, 0, 3, 6, { 0 }},+ { 200, 0, 0, 6, { 0 }},+ { 201, 0, 0, 6, { 0 }},+ { 202, 0, 0, 6, { 0 }},+ { 203, 0, 0, 6, { 0 }},+ { 204, 0, 0, 4, { 0 }},+ { 205, 0, 0, 4, { 0 }},+ { 206, 0, 0, 5, { 0 }},+ { 207, 0, 0, 5, { 0 }},+ { 208, 0, 3, 7, { 0 }},+ { 209, 0, 0, 6, { 0 }},+ { 210, 0, 0, 6, { 0 }},+ { 211, 0, 0, 6, { 0 }},+ { 212, 0, 0, 6, { 0 }},+ { 213, 0, 0, 6, { 0 }},+ { 214, 0, 0, 6, { 0 }},+ { 215, 0, 7, 7, { 0 }},+ { 216, 0, 2, 8, { 0 }},+ { 217, 0, 0, 6, { 0 }},+ { 218, 0, 0, 6, { 0 }},+ { 219, 0, 0, 6, { 0 }},+ { 220, 0, 0, 6, { 0 }},+ { 221, 0, 0, 6, { 0 }},+ { 222, 1, 0, 8, { 0 }},+ { 223, 0, 3, 7, { 0 }},+ { 224, 0, 1, 6, { 0 }},+ { 225, 0, 1, 6, { 0 }},+ { 226, 0, 1, 6, { 0 }},+ { 227, 0, 1, 6, { 0 }},+ { 228, 0, 1, 6, { 0 }},+ { 229, 0, 1, 6, { 0 }},+ { 230, 0, 5, 9, { 0 }},+ { 231, 0, 5, 5, { 0 }},+ { 232, 0, 1, 6, { 0 }},+ { 233, 0, 1, 6, { 0 }},+ { 234, 0, 1, 6, { 0 }},+ { 235, 0, 1, 6, { 0 }},+ { 236, 0, 1, 5, { 0 }},+ { 237, 0, 1, 5, { 0 }},+ { 238, 0, 1, 5, { 0 }},+ { 239, 0, 1, 5, { 0 }},+ { 240, 1, 0, 8, { 0 }},+ { 241, 0, 1, 6, { 0 }},+ { 242, 0, 1, 6, { 0 }},+ { 243, 0, 1, 6, { 0 }},+ { 244, 0, 1, 6, { 0 }},+ { 245, 0, 1, 6, { 0 }},+ { 246, 0, 1, 6, { 0 }},+ { 247, 0, 7, 7, { 0 }},+ { 248, 0, 4, 8, { 0 }},+ { 249, 0, 1, 6, { 0 }},+ { 250, 0, 1, 6, { 0 }},+ { 251, 0, 1, 6, { 0 }},+ { 252, 0, 1, 6, { 0 }},+ { 253, 0, 1, 6, { 0 }},+ { 254, 1, 0, 8, { 0 }},+ { 255, 0, 1, 6, { 0 }},+};++// Style loading function: Ashes+static void GuiLoadStyleAshes(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < ASHES_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(ashesStyleProps[i].controlId, ashesStyleProps[i].propertyId, ashesStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int ashesFontDataSize = 0;+ unsigned char *data = DecompressData(ashesFontData, ASHES_STYLE_FONT_ATLAS_COMP_SIZE, &ashesFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, ashesFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, ashesFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/bluish/style_bluish.h view
@@ -0,0 +1,619 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleBluish(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define BLUISH_STYLE_PROPS_COUNT 14++// Custom style name: Bluish+static const GuiStyleProp bluishStyleProps[BLUISH_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x5ca6a6ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0xb4e8f3ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0x447e77ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0x5f8792ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xcdeff7ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x4c6c74ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x3b5b5fff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xeaffffff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x275057ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x96aaacff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0xc8d7d9ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x8c9c9eff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0xe8eef1ff }, // DEFAULT_BACKGROUND_COLOR +};++// WARNING: This style uses a custom font: "homespun.ttf" (size: 10, spacing: 1)++#define BLUISH_STYLE_FONT_ATLAS_COMP_SIZE 2914++// Font atlas image pixels data: DEFLATE compressed+static unsigned char bluishFontData[BLUISH_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0x9d, 0xb1, 0x8e, 0x24, 0x49, 0x11, 0x86, 0x2b, 0xf3, 0x00, 0x09, 0x13, 0x01, 0x12, 0xe0, 0x20, 0x81, 0x90, 0xf0, 0x10,+ 0x12, 0x2e, 0x16, 0x3c, 0x02, 0x2f, 0x02, 0x0e, 0xef, 0x81, 0x07, 0x12, 0x06, 0x12, 0xce, 0x99, 0x38, 0x48, 0x20, 0xe1,+ 0x81, 0x83, 0xc0, 0xc3, 0xc5, 0xe5, 0x2c, 0x8c, 0xc3, 0x81, 0x93, 0x26, 0x33, 0xd0, 0x4e, 0xcf, 0x2e, 0xe2, 0xae, 0xfe,+ 0xc8, 0x8a, 0xac, 0xa8, 0xea, 0xea, 0x9b, 0x6f, 0x3f, 0xed, 0x1a, 0x95, 0x5d, 0xd5, 0x99, 0x19, 0x59, 0x35, 0xb3, 0x9d,+ 0x5f, 0x47, 0xd8, 0x02, 0x00, 0x00, 0x00, 0xf0, 0x09, 0xaa, 0x38, 0x56, 0xe5, 0xab, 0x6b, 0xe0, 0x4a, 0xb7, 0xe3, 0xd5,+ 0x69, 0x8f, 0x5d, 0xad, 0x06, 0xae, 0xe0, 0xb5, 0xf8, 0x6d, 0x1f, 0xa7, 0xbc, 0x90, 0x31, 0xb3, 0xf5, 0xdd, 0x7c, 0xac,+ 0xcf, 0x52, 0xe4, 0xf5, 0x35, 0x34, 0x8a, 0x75, 0x4c, 0x1c, 0xeb, 0xab, 0xe3, 0x35, 0x2b, 0xa2, 0xa5, 0x9a, 0x89, 0xfe,+ 0xd8, 0xf3, 0x59, 0xeb, 0x57, 0xf4, 0xce, 0x5a, 0x7b, 0x8f, 0xb6, 0x72, 0x8d, 0x26, 0x57, 0xc5, 0x9b, 0x77, 0x54, 0x33,+ 0xd4, 0x45, 0x3c, 0x6d, 0xf5, 0xb5, 0x37, 0xca, 0xa6, 0x57, 0x7b, 0xef, 0x60, 0xd6, 0xac, 0xbd, 0xcc, 0xc7, 0xc7, 0x47,+ 0x61, 0xa1, 0xd7, 0xeb, 0x96, 0xfd, 0xf1, 0xef, 0xcf, 0xfd, 0x29, 0x2b, 0xf7, 0xc1, 0x9b, 0x68, 0x75, 0x11, 0x2f, 0xd5,+ 0x9f, 0xdb, 0xcc, 0x95, 0xd5, 0x2b, 0x7a, 0x67, 0x2d, 0x9b, 0x67, 0x7b, 0xfd, 0xfc, 0x5b, 0x4f, 0xd7, 0xc7, 0x51, 0x9e,+ 0xdb, 0xd6, 0xe6, 0xae, 0x25, 0x3d, 0x57, 0xd5, 0x78, 0x17, 0xf7, 0xde, 0x5a, 0x9f, 0x85, 0x1e, 0x6a, 0xd9, 0x1f, 0x7f,+ 0xbd, 0xa2, 0xed, 0xe5, 0xaf, 0x1a, 0x59, 0x13, 0xfd, 0x29, 0xa2, 0xc5, 0x3f, 0x6b, 0x4f, 0xfc, 0xcb, 0x4b, 0x4f, 0xab,+ 0xb8, 0x9f, 0x4d, 0xdc, 0xd1, 0x47, 0x46, 0x3f, 0x1e, 0xff, 0xf2, 0xb2, 0x56, 0x8b, 0xf8, 0xa9, 0x74, 0x6e, 0xfc, 0xcb,+ 0xcb, 0xf3, 0xbf, 0x8a, 0xde, 0x17, 0x19, 0x7d, 0xfd, 0xb4, 0x8d, 0xfc, 0x5c, 0x8d, 0xdd, 0xff, 0xb7, 0x79, 0x56, 0x6b,+ 0xeb, 0xb8, 0xd8, 0xfb, 0xe3, 0x8d, 0xc5, 0xdf, 0xe4, 0x4f, 0x9e, 0xb7, 0xab, 0x78, 0xef, 0x28, 0x7a, 0xd2, 0xfd, 0xdf,+ 0x65, 0x7f, 0xca, 0xcb, 0xf3, 0x7f, 0x7d, 0xcc, 0x91, 0xbb, 0x30, 0x12, 0xff, 0x51, 0x8c, 0x8f, 0xbc, 0xf7, 0xf5, 0xb5,+ 0xe3, 0xf1, 0xbf, 0x5d, 0x71, 0xed, 0x5d, 0x8e, 0x5e, 0xc5, 0x4b, 0xe8, 0xf7, 0xbf, 0xe2, 0xfc, 0xce, 0xf3, 0x76, 0xed,+ 0x44, 0xc6, 0x97, 0x15, 0xe7, 0xf3, 0xb1, 0xe1, 0x08, 0x22, 0xf1, 0x2f, 0x72, 0x56, 0xcb, 0xe9, 0x3f, 0xff, 0xbd, 0xf8,+ 0x7b, 0x3d, 0xf5, 0xe2, 0x1f, 0x1b, 0x85, 0x05, 0x7f, 0x07, 0xbf, 0x5e, 0xfc, 0xed, 0xdd, 0xff, 0x87, 0xb6, 0x8d, 0x4d,+ 0xbd, 0xde, 0xbb, 0xd2, 0x7d, 0x46, 0x3d, 0xd3, 0x9f, 0xab, 0x8d, 0x02, 0xf6, 0xf0, 0x34, 0x11, 0xc7, 0x27, 0x62, 0x0f,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x66, 0xf9, 0x64, 0x19, 0x26, 0xd9, 0x2d, 0xfb, 0xac, 0x20, 0x6d, 0xe7,+ 0x78, 0x46, 0x92, 0xdf, 0xcb, 0xb3, 0xe6, 0x63, 0x39, 0xc9, 0xf9, 0xb1, 0x09, 0x23, 0xe5, 0xac, 0x96, 0xb6, 0xd9, 0xc2,+ 0x58, 0xdf, 0xcd, 0xd5, 0x76, 0x4e, 0x17, 0x73, 0x35, 0xea, 0xe5, 0x79, 0xf3, 0x51, 0x27, 0x7a, 0x37, 0xf3, 0x69, 0xb9,+ 0x0d, 0x76, 0xe7, 0x5a, 0xa8, 0xa5, 0x0f, 0xf7, 0xfa, 0x62, 0xe6, 0xcb, 0xbe, 0x7d, 0x55, 0xcf, 0xce, 0x53, 0xfe, 0x87,+ 0xd7, 0x4b, 0xe5, 0x55, 0xd8, 0xf4, 0xa8, 0x5b, 0xea, 0x39, 0x6d, 0x2a, 0xfe, 0x7a, 0x54, 0x7a, 0x6f, 0xde, 0xb7, 0x1e,+ 0xf5, 0xd5, 0x62, 0x2d, 0xdb, 0xed, 0x03, 0x15, 0x63, 0xed, 0x48, 0x44, 0xdd, 0x19, 0x73, 0xbc, 0x8a, 0xd1, 0xd8, 0x5a,+ 0x68, 0x6f, 0xd2, 0x06, 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x66, 0x67, 0x74, 0x67, 0xbc, 0xbe, 0x61, 0xd2, 0x43, 0xe7, 0xf4,+ 0x04, 0x5f, 0x25, 0xba, 0x7a, 0x3c, 0x0f, 0xa7, 0x3b, 0xf1, 0xaf, 0xc1, 0xb1, 0xdd, 0x5a, 0x6a, 0x68, 0x2f, 0xd8, 0x06,+ 0x73, 0xb8, 0xdf, 0x96, 0xd9, 0x36, 0x7f, 0x65, 0xfa, 0x89, 0x9d, 0x75, 0xce, 0x71, 0x2b, 0xc0, 0xc2, 0xd7, 0xb1, 0x77,+ 0x2b, 0x35, 0xf3, 0xf9, 0x5f, 0x26, 0x7e, 0x22, 0x97, 0xdd, 0xae, 0xc6, 0xf6, 0x27, 0xf6, 0x9c, 0x61, 0x92, 0x75, 0xce,+ 0xb5, 0xdc, 0x8d, 0x32, 0xf9, 0xc4, 0x3e, 0xa7, 0xe5, 0x88, 0xf8, 0xcf, 0x1a, 0x26, 0x3d, 0xed, 0x9c, 0xe5, 0x74, 0xa7,+ 0xc7, 0xe4, 0xfd, 0xef, 0xcd, 0x47, 0xe6, 0x1c, 0x7a, 0x1e, 0x90, 0xdf, 0x83, 0xd7, 0x40, 0xe3, 0x33, 0x1b, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xe3, 0xdb, 0x37, 0x31, 0x43, 0xc5, 0xb7, 0x76, 0xa2, 0x39, 0x7a,+ 0xea, 0xe9, 0xd6, 0x4d, 0x76, 0xcb, 0xcc, 0x5c, 0x8c, 0x5a, 0x62, 0x67, 0x8e, 0x3f, 0xef, 0xd6, 0x4e, 0x89, 0xfa, 0x54,+ 0xbb, 0x3d, 0x9f, 0x95, 0xb3, 0xfb, 0x67, 0xc3, 0x9e, 0xdd, 0xfe, 0xad, 0x17, 0xf4, 0x93, 0x3c, 0x73, 0xe9, 0x6d, 0xcf,+ 0x33, 0x77, 0x0b, 0x6f, 0x2d, 0x6d, 0x75, 0x2e, 0x66, 0xf7, 0xd0, 0x66, 0x3c, 0x14, 0x7f, 0x37, 0x2c, 0x2f, 0xfe, 0xb3,+ 0x63, 0x3e, 0xb7, 0x25, 0x9a, 0x47, 0xe4, 0x7a, 0xf1, 0xf7, 0x2c, 0x9f, 0xac, 0xf8, 0xef, 0xf3, 0x60, 0xf2, 0xe2, 0x3f,+ 0xe3, 0x70, 0xe9, 0xbe, 0x7b, 0x1e, 0xd4, 0x99, 0xf1, 0xd7, 0x79, 0xb4, 0xb6, 0xc4, 0x3f, 0x6e, 0xf9, 0xc4, 0xe3, 0xbf,+ 0xcf, 0x83, 0xc9, 0x8b, 0xff, 0x8c, 0xc3, 0xd1, 0x9d, 0x6c, 0x51, 0x3d, 0x9c, 0x7b, 0xc4, 0x06, 0x8e, 0x61, 0x9b, 0x88,+ 0x7f, 0x91, 0x7d, 0xdc, 0xeb, 0x7f, 0x46, 0xee, 0xff, 0x72, 0x98, 0x07, 0x93, 0xfb, 0xfc, 0xcf, 0x9a, 0x87, 0x32, 0xb0,+ 0x0f, 0xcb, 0x84, 0x2d, 0xd2, 0x93, 0xe7, 0x62, 0x9b, 0xef, 0x90, 0x13, 0xff, 0x99, 0x6b, 0x6d, 0x3b, 0x27, 0x1a, 0xff,+ 0x32, 0x11, 0xff, 0xcc, 0xbe, 0xfb, 0xf1, 0x2f, 0x8e, 0x2d, 0x32, 0x3e, 0x27, 0x3b, 0xfe, 0xb3, 0x56, 0x4b, 0x49, 0xbc,+ 0x96, 0x25, 0xc7, 0x3f, 0xee, 0xc9, 0xe4, 0xf6, 0xdd, 0x8f, 0xff, 0x7c, 0xef, 0x6e, 0x7f, 0xea, 0x01, 0x0e, 0x3d, 0x90,+ 0x71, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xb3, 0x38, 0x15, 0xa9, 0x7c, 0xcb, 0x68, 0xbb,+ 0x2d, 0xf4, 0xd6, 0xa0, 0x58, 0xf7, 0x27, 0x72, 0x32, 0xfd, 0x8c, 0x6b, 0x77, 0x45, 0xdf, 0x47, 0xcd, 0xd6, 0x4c, 0xdf,+ 0x8e, 0xae, 0x71, 0xb6, 0xcd, 0xf2, 0xf1, 0xbc, 0x97, 0xd8, 0x77, 0x50, 0x55, 0x6e, 0x9a, 0x2a, 0x32, 0xdd, 0x44, 0xbf,+ 0xbb, 0xef, 0xe5, 0xaa, 0xd0, 0xd7, 0xc9, 0xcc, 0x62, 0x61, 0x72, 0xbd, 0xda, 0x44, 0xdf, 0x9a, 0x38, 0xaa, 0xae, 0x51,+ 0xa7, 0xbf, 0x29, 0x3d, 0x9f, 0xcb, 0x61, 0x6b, 0x4e, 0x25, 0xbd, 0x63, 0x78, 0xdb, 0xeb, 0x8e, 0xae, 0x80, 0x2e, 0xef,+ 0xb1, 0xf5, 0xbe, 0x56, 0xe9, 0xb7, 0x2c, 0xb2, 0x9a, 0x59, 0x3c, 0x57, 0x8d, 0x89, 0xaa, 0x61, 0xfe, 0xfe, 0x91, 0xea,+ 0x9b, 0xaa, 0x96, 0xb4, 0x88, 0x6b, 0xb4, 0xe9, 0xef, 0x84, 0xdb, 0xa0, 0x8e, 0x54, 0xe4, 0xca, 0xde, 0x0a, 0xf0, 0x2a,+ 0xb9, 0xb5, 0x84, 0x5a, 0x25, 0xf1, 0x5c, 0x35, 0x9e, 0x79, 0xe0, 0x5f, 0x2d, 0x9a, 0x9b, 0x45, 0xaf, 0x99, 0xd8, 0x93,+ 0x21, 0x2b, 0xc3, 0xcc, 0xb6, 0x27, 0x67, 0x71, 0x46, 0xb4, 0x84, 0x57, 0xc0, 0xb1, 0x95, 0x3c, 0x8e, 0x33, 0x0f, 0xb6,+ 0x8e, 0x22, 0x7b, 0x67, 0x79, 0x7b, 0xfc, 0x97, 0x5d, 0x39, 0x41, 0xca, 0xb4, 0x2b, 0x13, 0x5b, 0x01, 0x47, 0xc7, 0xff,+ 0x28, 0xf3, 0x20, 0x2b, 0x03, 0x47, 0xbf, 0x68, 0xfc, 0x47, 0xd9, 0x66, 0xe2, 0xb1, 0x8c, 0x1b, 0xa3, 0xcb, 0x5d, 0x9e,+ 0x0c, 0xd9, 0xe7, 0x2c, 0xe1, 0xff, 0xc9, 0x5c, 0x23, 0xfe, 0x73, 0x19, 0x6a, 0x4a, 0x38, 0x97, 0xd0, 0xbd, 0xe2, 0x1f,+ 0xaf, 0x23, 0x35, 0x77, 0x4e, 0xbe, 0x7b, 0x79, 0x46, 0xfc, 0xe1, 0x71, 0x32, 0x1f, 0x35, 0xfc, 0x24, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x52, 0xfe, 0x8f, 0x88, 0xbd, 0x72, 0xff, 0x96, 0x3a, 0xd8, 0xd5, 0x2a, 0xd3, 0x2d,+ 0x25, 0xed, 0x9a, 0x9e, 0x63, 0xb4, 0xb7, 0xe6, 0xd9, 0xdb, 0x6b, 0x97, 0x69, 0xfb, 0xe7, 0x7f, 0x7b, 0xd0, 0xb7, 0x7f,+ 0x6b, 0xd2, 0xce, 0x7a, 0x7e, 0xcb, 0xf1, 0xdf, 0xe6, 0x3f, 0x22, 0xdf, 0x80, 0x97, 0x21, 0xa2, 0x6e, 0x76, 0x2b, 0x9a,+ 0xdc, 0x53, 0xed, 0x32, 0x67, 0x40, 0x9b, 0xd8, 0x83, 0xb8, 0x7f, 0x96, 0x9d, 0x16, 0xac, 0x43, 0x55, 0x4f, 0xcc, 0xb1,+ 0xd1, 0x07, 0x3e, 0x4c, 0xcc, 0xa1, 0xd1, 0x39, 0x14, 0x96, 0xd0, 0x6b, 0x55, 0x4d, 0xa2, 0xf2, 0x90, 0xf1, 0x5f, 0x82,+ 0x6e, 0x5f, 0xdf, 0x90, 0x2f, 0x23, 0x2b, 0xc7, 0x46, 0x99, 0x30, 0x7c, 0x8a, 0x53, 0x7f, 0x2c, 0x16, 0x7f, 0x55, 0xad,+ 0x2e, 0xfe, 0x6c, 0x3c, 0x23, 0xcb, 0x46, 0x7e, 0x05, 0x9b, 0xbc, 0x6c, 0x1e, 0xf9, 0x39, 0x36, 0xbc, 0x9d, 0x72, 0xed,+ 0x55, 0xc6, 0xe2, 0x1f, 0xcd, 0xed, 0x70, 0x46, 0xfc, 0x67, 0x6b, 0xdb, 0xe4, 0x66, 0xe6, 0x28, 0x17, 0xc9, 0xb1, 0x11,+ 0xcd, 0x10, 0xb2, 0xff, 0xf9, 0x9f, 0xed, 0x23, 0xe4, 0xed, 0x54, 0x9f, 0x93, 0x67, 0x63, 0xc6, 0xd3, 0x39, 0x6a, 0x67,+ 0x3e, 0xbe, 0x3b, 0x1f, 0x71, 0x2b, 0xfb, 0x43, 0xc5, 0xff, 0xca, 0x6e, 0xcf, 0x95, 0x38, 0xb2, 0xe6, 0x19, 0xf6, 0xcf,+ 0xa3, 0xae, 0x69, 0xe6, 0xe0, 0x75, 0x5b, 0x5e, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x93, 0x01,+ 0x68, 0x91, 0x39, 0x6d, 0x3e, 0x79, 0xfc, 0x8b, 0x56, 0xed, 0x5b, 0xf6, 0x35, 0xfb, 0x8e, 0x7d, 0xd7, 0xbe, 0xe2, 0x5c,+ 0xb1, 0xa6, 0xe5, 0x1b, 0x1a, 0x9d, 0x53, 0x83, 0x75, 0xca, 0x4a, 0xd8, 0xd7, 0xd9, 0x57, 0x8b, 0x2c, 0x36, 0xf3, 0xd1,+ 0x6b, 0x8d, 0xe2, 0xe1, 0xfb, 0x5f, 0x9e, 0x45, 0xb1, 0x9e, 0xb7, 0xe7, 0xe7, 0xf6, 0x64, 0x1f, 0xda, 0x3f, 0xed, 0x1f,+ 0xf6, 0x37, 0xfb, 0xd0, 0x3e, 0x2b, 0x3f, 0xc3, 0x5c, 0xf7, 0x52, 0xde, 0x8c, 0xe1, 0x29, 0x58, 0x4d, 0xcb, 0x3f, 0x47,+ 0x55, 0x08, 0x53, 0xd7, 0x2b, 0xcf, 0xd6, 0x44, 0x0b, 0xf9, 0x3a, 0xe3, 0x77, 0x52, 0xdf, 0xf1, 0x6e, 0xe1, 0x0a, 0x01,+ 0x7e, 0x55, 0xb1, 0x78, 0x3c, 0xe6, 0x32, 0xa7, 0xdc, 0xf6, 0xd7, 0xd6, 0xc6, 0xf4, 0x7b, 0xfb, 0x8f, 0xfd, 0xc0, 0xaa,+ 0xfd, 0xd0, 0xbe, 0x6a, 0x7f, 0xb5, 0xcf, 0xc9, 0xbc, 0x36, 0xeb, 0xe3, 0x6b, 0xd2, 0x87, 0xd1, 0xb9, 0x60, 0xbc, 0x73,+ 0xca, 0xcb, 0x2e, 0x60, 0x5d, 0xbd, 0x5f, 0xd6, 0xad, 0xac, 0xe2, 0xe6, 0xaa, 0xd1, 0xde, 0x50, 0x19, 0xe6, 0x39, 0x5a,+ 0x9b, 0x8b, 0x2e, 0x72, 0x0c, 0x75, 0x71, 0xe7, 0xa9, 0x7e, 0xab, 0xe3, 0xa3, 0x78, 0x8c, 0xf7, 0x1b, 0xd6, 0xb3, 0x20,+ 0x99, 0x18, 0xe9, 0xaf, 0xed, 0xcf, 0xf6, 0x0d, 0xfb, 0xb6, 0xfd, 0xcb, 0xfe, 0x6d, 0x1f, 0xd9, 0x67, 0x56, 0xef, 0x22,+ 0xe5, 0xe6, 0xe8, 0x27, 0xa5, 0x97, 0x0d, 0xa9, 0x38, 0x39, 0x9c, 0xba, 0x8c, 0xa7, 0xbe, 0xf7, 0xba, 0x5c, 0x9d, 0xde,+ 0x3c, 0xf5, 0xe1, 0xca, 0x51, 0x7b, 0xc3, 0x25, 0x34, 0x47, 0xaa, 0x72, 0xa0, 0xba, 0xff, 0x47, 0xf1, 0x18, 0xc7, 0xbf,+ 0x08, 0x43, 0x65, 0x7d, 0x8e, 0x7e, 0x61, 0x7f, 0xb7, 0xaf, 0xdb, 0x97, 0xec, 0x0b, 0xf6, 0x79, 0x7b, 0x5f, 0xc4, 0x4b,+ 0xad, 0xed, 0x51, 0x06, 0xa5, 0xb8, 0x01, 0x7a, 0x8b, 0xc7, 0x7a, 0xfc, 0x6b, 0x9a, 0x1d, 0x60, 0xef, 0x9e, 0x0b, 0x73,+ 0x75, 0xb6, 0x22, 0xcf, 0x7f, 0xf5, 0x13, 0x59, 0x3d, 0x53, 0x47, 0xf1, 0x98, 0x75, 0x28, 0x4c, 0xdc, 0x75, 0x7f, 0xb0,+ 0x9f, 0xd9, 0x4f, 0xed, 0x7b, 0xf6, 0x2b, 0xfb, 0xc8, 0x9a, 0x7d, 0x33, 0xb8, 0xb6, 0x4b, 0xb8, 0xde, 0xa0, 0x4d, 0xde,+ 0xff, 0x5d, 0xda, 0x77, 0xd7, 0x8e, 0xbf, 0xea, 0xb7, 0x3a, 0x3e, 0x8a, 0xc7, 0xac, 0x43, 0xa1, 0x5c, 0xc9, 0xf7, 0xed,+ 0xc7, 0xf6, 0x81, 0xfd, 0xd2, 0x7e, 0x64, 0xdf, 0xb7, 0xdf, 0xd8, 0x97, 0x27, 0xc6, 0x66, 0xa1, 0xdf, 0xbd, 0xbc, 0xdf,+ 0xca, 0xca, 0x20, 0xef, 0x54, 0x6e, 0x1e, 0xa1, 0x33, 0xde, 0x29, 0xce, 0x96, 0x78, 0xc4, 0x6d, 0x2c, 0xbd, 0x32, 0x7e,+ 0x62, 0xbf, 0xb5, 0x3f, 0xd9, 0x07, 0xf6, 0x3b, 0xfb, 0xa3, 0xfd, 0xc5, 0xde, 0x73, 0x4c, 0xba, 0x68, 0xcd, 0xbc, 0x59,+ 0xbf, 0xce, 0xe4, 0xef, 0x2a, 0xd9, 0xae, 0x51, 0xd6, 0x3b, 0x59, 0xa2, 0xbd, 0x34, 0x8a, 0xc7, 0xb5, 0xfc, 0x96, 0x99,+ 0xac, 0x7b, 0x8f, 0xed, 0x79, 0xc1, 0x96, 0x58, 0xce, 0x59, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,+ 0xc5, 0xfe, 0xf1, 0xdd, 0x9a, 0x65, 0x53, 0x76, 0x89, 0xb1, 0x15, 0x14, 0x71, 0x5a, 0x8a, 0xcc, 0x61, 0x51, 0x37, 0xd4,+ 0xda, 0x2a, 0xa1, 0x91, 0xce, 0x1c, 0x1f, 0xf9, 0x3b, 0xfa, 0x78, 0x9e, 0x15, 0x35, 0xe3, 0x23, 0x45, 0x3f, 0x75, 0x6d,+ 0x6e, 0xe5, 0x9e, 0x88, 0x85, 0xa2, 0x6b, 0x89, 0x99, 0x70, 0x34, 0x9a, 0xf0, 0x04, 0x9a, 0x3c, 0xcb, 0x5e, 0x76, 0x1e,+ 0x4d, 0x66, 0xc4, 0x79, 0x92, 0xce, 0x8d, 0x3a, 0xfe, 0x9e, 0x8c, 0xf2, 0x93, 0xcc, 0xeb, 0xb3, 0x7e, 0x96, 0x3d, 0x1f,+ 0xef, 0xa1, 0xbe, 0x99, 0x5b, 0x85, 0xcd, 0x9c, 0xb6, 0xb6, 0xe9, 0x13, 0xf3, 0x51, 0xfc, 0xb7, 0x7b, 0x12, 0x63, 0x0b,+ 0xc5, 0xe4, 0x0e, 0xfe, 0xba, 0xa3, 0xa5, 0xb3, 0xed, 0xf8, 0x6d, 0xca, 0x9e, 0xf1, 0x73, 0x69, 0x69, 0x83, 0x23, 0xba,+ 0x62, 0x54, 0x2c, 0x9b, 0x34, 0x99, 0x7c, 0x2b, 0xa6, 0x3a, 0xee, 0x83, 0x97, 0x91, 0xa8, 0x9d, 0x1a, 0xff, 0xb1, 0x85,+ 0x12, 0x89, 0x7f, 0x77, 0x33, 0x24, 0x68, 0xbb, 0x64, 0x94, 0x11, 0x47, 0xbb, 0x58, 0x65, 0xea, 0xe9, 0x9b, 0xd3, 0xe2,+ 0xdf, 0xe5, 0x4d, 0xee, 0x7d, 0x7b, 0xf3, 0x10, 0xcf, 0xff, 0xb2, 0x66, 0x71, 0x6c, 0x8f, 0xff, 0xd8, 0x42, 0x31, 0x51,+ 0x03, 0x6f, 0xce, 0xc4, 0x8a, 0x65, 0x77, 0xf2, 0x57, 0xba, 0xce, 0xec, 0x74, 0x56, 0x8e, 0xbb, 0x99, 0x8c, 0x59, 0x9e,+ 0x65, 0xb3, 0x6c, 0xcc, 0x01, 0x66, 0x03, 0x5b, 0x63, 0x7b, 0xfc, 0xc7, 0x16, 0x4a, 0xc4, 0x69, 0x19, 0x9b, 0x38, 0x25,+ 0xb8, 0xab, 0xee, 0xf9, 0x45, 0x3a, 0x8f, 0xd0, 0x4c, 0x25, 0xc8, 0xb3, 0x5a, 0xbc, 0x79, 0x28, 0x1b, 0x23, 0xe7, 0xe7,+ 0xd0, 0x89, 0xc4, 0x7f, 0x9f, 0x85, 0x12, 0x33, 0x08, 0xe2, 0xfe, 0xe6, 0xd8, 0x22, 0xea, 0x77, 0xcf, 0x71, 0x19, 0x7f,+ 0x66, 0x74, 0xb9, 0x36, 0xb6, 0x1a, 0x13, 0xfe, 0x2b, 0x23, 0xf3, 0x7c, 0x96, 0x85, 0x32, 0x6b, 0xce, 0x94, 0x09, 0xbf,+ 0xe4, 0xdc, 0xec, 0x87, 0xf1, 0x96, 0x3e, 0x88, 0x1d, 0xf9, 0x46, 0xb6, 0x3e, 0xe9, 0xe2, 0xbf, 0x1d, 0xdf, 0xbb, 0x65,+ 0x64, 0xf5, 0x61, 0xd2, 0xec, 0xb7, 0xc8, 0x1e, 0x37, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19,+ 0x2e, 0x4b, 0xb0, 0x86, 0x95, 0x6e, 0xd3, 0x47, 0x6b, 0x28, 0x6b, 0x8e, 0xe7, 0xdd, 0xdc, 0xdf, 0xef, 0x29, 0xee, 0x3e,+ 0x5d, 0x5e, 0x9f, 0xbd, 0x4f, 0x80, 0xf3, 0x0c, 0x17, 0xcf, 0x7d, 0xa8, 0xa1, 0x77, 0xa9, 0xce, 0x3b, 0x3c, 0x89, 0x3d,+ 0xaf, 0xb8, 0x77, 0x73, 0x7f, 0xbf, 0x47, 0x19, 0x1c, 0x55, 0x7a, 0x1f, 0x33, 0x7d, 0x1e, 0xad, 0x80, 0x2c, 0xc3, 0xc5,+ 0xf3, 0xce, 0x62, 0xef, 0xd2, 0x44, 0x8b, 0xbe, 0xbe, 0xfe, 0x7c, 0xbf, 0x39, 0x19, 0x84, 0xee, 0xed, 0xf7, 0xe8, 0x6a,+ 0x54, 0xca, 0xfb, 0xa8, 0x72, 0x05, 0xdc, 0x72, 0x5a, 0xd5, 0xe0, 0xd3, 0xff, 0x1c, 0x8f, 0x25, 0x9a, 0xd3, 0x4c, 0x1d,+ 0xbf, 0x39, 0x6f, 0x3a, 0x5b, 0x51, 0x2c, 0xe7, 0xd0, 0xfd, 0xfd, 0x9e, 0xee, 0xe6, 0x9b, 0x3a, 0x7e, 0xaf, 0x60, 0x94,+ 0x8f, 0xa7, 0x4f, 0x54, 0x64, 0x5c, 0xcf, 0x77, 0x64, 0xc2, 0xff, 0x88, 0x1d, 0x5f, 0x64, 0x46, 0x27, 0x73, 0x76, 0xc3,+ 0xaf, 0xb0, 0x57, 0x1f, 0x8b, 0xcc, 0xcd, 0x72, 0xb0, 0x13, 0xe2, 0x5f, 0x9c, 0x7a, 0x68, 0x79, 0x2d, 0xcb, 0xa0, 0xee,+ 0x5a, 0xd6, 0xf1, 0xeb, 0xee, 0xd5, 0x47, 0xe3, 0x6f, 0x27, 0xc5, 0xdf, 0x77, 0xdf, 0xb2, 0x5a, 0x88, 0x7f, 0x34, 0xfe,+ 0xfd, 0xa4, 0xe7, 0xbf, 0x76, 0xdf, 0x32, 0x5b, 0xce, 0x88, 0xbf, 0xb9, 0x35, 0xf5, 0x1e, 0x2d, 0xfe, 0xe5, 0x14, 0x57,+ 0x20, 0xbb, 0x8a, 0xa7, 0x9f, 0x4d, 0xee, 0xc8, 0xf8, 0xcf, 0x59, 0x1c, 0xe5, 0xce, 0x2d, 0x71, 0x5b, 0x25, 0xf3, 0x5d,+ 0xf2, 0xab, 0x78, 0xfa, 0x2d, 0xc7, 0x1d, 0xdf, 0xf3, 0x1d, 0x07, 0xbb, 0x63, 0x4b, 0xdc, 0xcb, 0xcb, 0x7c, 0x17, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2d, 0xfe, 0x4f, 0xd4, 0xe5, 0x99, 0x31, 0x53, 0xaa, 0xeb, 0xe7, 0x5c, 0x35,+ 0xc7, 0x8e, 0x97, 0x4f, 0x48, 0xb7, 0xdc, 0xdb, 0xa9, 0xaa, 0xa1, 0xe8, 0xc7, 0x5d, 0x1e, 0xed, 0x99, 0xd8, 0xc4, 0x0e,+ 0xb8, 0xef, 0x06, 0xb5, 0x09, 0x07, 0xa7, 0x3a, 0x0e, 0x4e, 0x0b, 0xe5, 0xd8, 0xe8, 0x4e, 0x3e, 0x21, 0x73, 0x72, 0x17,+ 0x64, 0x8e, 0x48, 0xf7, 0xbb, 0x89, 0x55, 0xd1, 0xc2, 0x9f, 0x33, 0x3e, 0x85, 0xf2, 0xe5, 0x68, 0xcf, 0x64, 0x76, 0x07,+ 0x7c, 0xce, 0xc1, 0x69, 0x21, 0x07, 0xc7, 0xab, 0x22, 0x55, 0x07, 0x55, 0xba, 0xf4, 0x6e, 0x4b, 0xae, 0x53, 0x15, 0xeb,+ 0xb7, 0x9e, 0x81, 0x8c, 0xfc, 0x6f, 0xd9, 0x3b, 0x60, 0x45, 0x98, 0x6e, 0x33, 0x4f, 0xd8, 0x99, 0x16, 0x9d, 0xff, 0xc1,+ 0xab, 0xde, 0x37, 0x53, 0xc9, 0x28, 0xb7, 0xdf, 0x5e, 0x85, 0xbe, 0x12, 0xca, 0x64, 0x75, 0xdf, 0x6f, 0x38, 0x77, 0x51,+ 0x39, 0x27, 0xb7, 0x22, 0x90, 0x6e, 0x29, 0x32, 0x27, 0x4a, 0x71, 0x6b, 0x52, 0xf5, 0x70, 0x7d, 0x9c, 0x6c, 0x77, 0xa8,+ 0x38, 0x96, 0x60, 0xd9, 0x91, 0xfb, 0x69, 0xdf, 0xbd, 0xdc, 0x27, 0x72, 0xec, 0xf4, 0x89, 0xb8, 0x64, 0xb5, 0xd8, 0x54,+ 0x7d, 0xa9, 0x71, 0x7e, 0x94, 0xe3, 0xb3, 0x06, 0x75, 0xc7, 0xb7, 0xb9, 0x47, 0xfc, 0xc7, 0xf3, 0x15, 0x7f, 0x32, 0x9c,+ 0x73, 0x1f, 0x45, 0x57, 0xe0, 0x5c, 0x8e, 0x8d, 0x6c, 0xa7, 0xb2, 0x0c, 0xec, 0x8d, 0xb3, 0xe3, 0x5f, 0x06, 0xe7, 0xe8,+ 0xac, 0x5d, 0x76, 0x57, 0x07, 0x23, 0xfe, 0xbc, 0xde, 0x93, 0x69, 0x26, 0xaf, 0xc5, 0xaf, 0xd0, 0xb7, 0x37, 0xfe, 0x67,+ 0xd8, 0x2c, 0x57, 0x30, 0x50, 0x72, 0x33, 0x03, 0x9d, 0x37, 0xa2, 0xe8, 0x4a, 0xb3, 0x8b, 0xf6, 0xf5, 0xd3, 0x95, 0x19,+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xd1, 0xf3, 0xff, 0xd4, 0x70, 0xcb, 0x95, 0xb3, 0xec, 0xe4, 0xe5,+ 0x1f, 0xca, 0x76, 0x78, 0xe6, 0x5c, 0xaa, 0xb9, 0x4c, 0x3f, 0xca, 0x47, 0xa9, 0x81, 0xfc, 0x2b, 0x37, 0xeb, 0x44, 0x55,+ 0xaa, 0xaa, 0x27, 0xf8, 0x30, 0x33, 0x86, 0x8f, 0x3a, 0xea, 0xed, 0xfc, 0x9c, 0xe3, 0xf0, 0xe8, 0xab, 0xd9, 0xc0, 0xd9,+ 0xc9, 0xc9, 0xef, 0xde, 0x9c, 0xb9, 0x99, 0x59, 0x31, 0xed, 0x92, 0x86, 0xcf, 0x8c, 0x5b, 0x91, 0xeb, 0xf0, 0xe8, 0x19,+ 0x6d, 0xd2, 0x2f, 0xf0, 0xab, 0x2f, 0x66, 0x7d, 0x5a, 0x1d, 0xdd, 0x91, 0x6a, 0x61, 0x8b, 0xa2, 0xdc, 0xdd, 0x94, 0xe9,+ 0xae, 0xc3, 0xd3, 0x43, 0x11, 0x9b, 0x69, 0x19, 0xed, 0xa5, 0x96, 0x44, 0x97, 0x2e, 0x6b, 0xb7, 0xd2, 0x82, 0x4f, 0xcc,+ 0x6b, 0x67, 0xd9, 0x29, 0x4e, 0xf6, 0x93, 0x47, 0xac, 0xfc, 0x72, 0xaf, 0xf8, 0x3f, 0xe6, 0x8c, 0xf9, 0x39, 0x29, 0x1e,+ 0x2d, 0xca, 0x36, 0xe9, 0xab, 0xe4, 0xc4, 0xff, 0xda, 0xf3, 0x92, 0x97, 0x65, 0xe3, 0x9c, 0x9e, 0xcd, 0x19, 0x61, 0x99,+ 0xfb, 0xd5, 0xd1, 0xf8, 0x97, 0xe4, 0xd1, 0x9f, 0x61, 0xf8, 0xcc, 0x64, 0xd9, 0x38, 0xcb, 0x3d, 0x9a, 0xb5, 0x2c, 0x8e,+ 0xbe, 0xff, 0x33, 0xef, 0x98, 0x7b, 0x1b, 0x3e, 0x57, 0x76, 0x78, 0xe2, 0x2e, 0x9d, 0xf6, 0xd5, 0xe1, 0xd1, 0xd0, 0xb1,+ 0x7c, 0x3d, 0x95, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0xe6, 0xb9, 0xfd, 0x61, 0x1e, 0x88, 0x3f, 0xbc, 0xda, 0xf8, 0xff, 0x17 };++// Font glyphs rectangles data (on atlas)+static const Rectangle bluishFontRecs[189] = {+ { 4, 4, 5 , 10 },+ { 17, 4, 2 , 8 },+ { 27, 4, 4 , 3 },+ { 39, 4, 6 , 8 },+ { 53, 4, 5 , 10 },+ { 66, 4, 6 , 8 },+ { 80, 4, 5 , 10 },+ { 93, 4, 2 , 3 },+ { 103, 4, 3 , 8 },+ { 114, 4, 3 , 8 },+ { 125, 4, 6 , 6 },+ { 139, 4, 6 , 6 },+ { 153, 4, 2 , 3 },+ { 163, 4, 5 , 2 },+ { 176, 4, 2 , 2 },+ { 186, 4, 6 , 8 },+ { 200, 4, 5 , 8 },+ { 213, 4, 3 , 8 },+ { 224, 4, 5 , 8 },+ { 237, 4, 5 , 8 },+ { 4, 22, 5 , 8 },+ { 17, 22, 5 , 8 },+ { 30, 22, 5 , 8 },+ { 43, 22, 5 , 8 },+ { 56, 22, 5 , 8 },+ { 69, 22, 5 , 8 },+ { 82, 22, 2 , 8 },+ { 92, 22, 2 , 9 },+ { 102, 22, 4 , 6 },+ { 114, 22, 5 , 4 },+ { 127, 22, 4 , 6 },+ { 139, 22, 5 , 8 },+ { 152, 22, 6 , 8 },+ { 166, 22, 5 , 8 },+ { 179, 22, 5 , 8 },+ { 192, 22, 5 , 8 },+ { 205, 22, 5 , 8 },+ { 218, 22, 5 , 8 },+ { 231, 22, 5 , 8 },+ { 4, 40, 5 , 8 },+ { 17, 40, 5 , 8 },+ { 30, 40, 4 , 8 },+ { 42, 40, 5 , 8 },+ { 55, 40, 5 , 8 },+ { 68, 40, 5 , 8 },+ { 81, 40, 8 , 8 },+ { 97, 40, 5 , 8 },+ { 110, 40, 5 , 8 },+ { 123, 40, 5 , 8 },+ { 136, 40, 5 , 9 },+ { 149, 40, 5 , 8 },+ { 162, 40, 5 , 8 },+ { 175, 40, 6 , 8 },+ { 189, 40, 5 , 8 },+ { 202, 40, 5 , 8 },+ { 215, 40, 8 , 8 },+ { 231, 40, 5 , 8 },+ { 4, 58, 5 , 8 },+ { 17, 58, 5 , 8 },+ { 30, 58, 3 , 8 },+ { 41, 58, 6 , 8 },+ { 55, 58, 3 , 8 },+ { 66, 58, 6 , 4 },+ { 80, 58, 5 , 1 },+ { 93, 58, 2 , 3 },+ { 103, 58, 5 , 6 },+ { 116, 58, 5 , 8 },+ { 129, 58, 5 , 6 },+ { 142, 58, 5 , 8 },+ { 155, 58, 5 , 6 },+ { 168, 58, 5 , 8 },+ { 181, 58, 5 , 7 },+ { 194, 58, 5 , 8 },+ { 207, 58, 2 , 8 },+ { 217, 58, 3 , 9 },+ { 228, 58, 5 , 8 },+ { 241, 58, 2 , 8 },+ { 4, 76, 8 , 6 },+ { 20, 76, 5 , 6 },+ { 33, 76, 5 , 6 },+ { 46, 76, 5 , 7 },+ { 59, 76, 5 , 7 },+ { 72, 76, 5 , 6 },+ { 85, 76, 5 , 6 },+ { 98, 76, 5 , 8 },+ { 111, 76, 5 , 6 },+ { 124, 76, 5 , 6 },+ { 137, 76, 8 , 6 },+ { 153, 76, 5 , 6 },+ { 166, 76, 5 , 7 },+ { 179, 76, 5 , 6 },+ { 192, 76, 4 , 8 },+ { 204, 76, 2 , 10 },+ { 214, 76, 4 , 8 },+ { 226, 76, 6 , 4 },+ { 240, 76, 2 , 8 },+ { 4, 94, 5 , 8 },+ { 17, 94, 5 , 8 },+ { 30, 94, 8 , 8 },+ { 46, 94, 6 , 8 },+ { 60, 94, 5 , 10 },+ { 73, 94, 5 , 10 },+ { 86, 94, 5 , 9 },+ { 99, 94, 7 , 8 },+ { 114, 94, 4 , 6 },+ { 126, 94, 5 , 4 },+ { 139, 94, 5 , 3 },+ { 152, 94, 7 , 8 },+ { 167, 94, 5 , 2 },+ { 180, 94, 4 , 4 },+ { 192, 94, 6 , 8 },+ { 206, 94, 4 , 6 },+ { 218, 94, 4 , 6 },+ { 230, 94, 8 , 8 },+ { 4, 112, 5 , 9 },+ { 17, 112, 6 , 8 },+ { 31, 112, 2 , 2 },+ { 41, 112, 8 , 8 },+ { 57, 112, 3 , 6 },+ { 68, 112, 4 , 6 },+ { 80, 112, 5 , 4 },+ { 93, 112, 6 , 8 },+ { 107, 112, 6 , 6 },+ { 121, 112, 5 , 10 },+ { 134, 112, 5 , 8 },+ { 147, 112, 5 , 10 },+ { 160, 112, 5 , 10 },+ { 173, 112, 5 , 10 },+ { 186, 112, 5 , 10 },+ { 199, 112, 5 , 10 },+ { 212, 112, 5 , 10 },+ { 225, 112, 6 , 8 },+ { 239, 112, 5 , 9 },+ { 4, 130, 5 , 10 },+ { 17, 130, 5 , 10 },+ { 30, 130, 5 , 10 },+ { 43, 130, 5 , 10 },+ { 56, 130, 4 , 10 },+ { 68, 130, 4 , 10 },+ { 80, 130, 4 , 10 },+ { 92, 130, 4 , 10 },+ { 104, 130, 6 , 8 },+ { 118, 130, 5 , 10 },+ { 131, 130, 5 , 10 },+ { 144, 130, 5 , 10 },+ { 157, 130, 5 , 10 },+ { 170, 130, 5 , 10 },+ { 183, 130, 5 , 10 },+ { 196, 130, 4 , 4 },+ { 208, 130, 5 , 10 },+ { 221, 130, 5 , 10 },+ { 234, 130, 5 , 10 },+ { 4, 148, 5 , 10 },+ { 17, 148, 5 , 10 },+ { 30, 148, 5 , 10 },+ { 43, 148, 5 , 8 },+ { 56, 148, 5 , 8 },+ { 69, 148, 5 , 9 },+ { 82, 148, 5 , 9 },+ { 95, 148, 5 , 9 },+ { 108, 148, 5 , 9 },+ { 121, 148, 5 , 8 },+ { 134, 148, 5 , 10 },+ { 147, 148, 6 , 6 },+ { 161, 148, 5 , 7 },+ { 174, 148, 5 , 9 },+ { 187, 148, 5 , 9 },+ { 200, 148, 5 , 9 },+ { 213, 148, 5 , 8 },+ { 226, 148, 3 , 9 },+ { 237, 148, 3 , 9 },+ { 4, 166, 4 , 9 },+ { 16, 166, 4 , 8 },+ { 28, 166, 5 , 9 },+ { 41, 166, 5 , 9 },+ { 54, 166, 5 , 9 },+ { 67, 166, 5 , 9 },+ { 80, 166, 5 , 9 },+ { 93, 166, 5 , 9 },+ { 106, 166, 5 , 8 },+ { 119, 166, 4 , 6 },+ { 131, 166, 5 , 8 },+ { 144, 166, 5 , 9 },+ { 157, 166, 5 , 9 },+ { 170, 166, 5 , 9 },+ { 183, 166, 5 , 8 },+ { 196, 166, 5 , 10 },+ { 209, 166, 5 , 10 },+ { 222, 166, 5 , 9 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo bluishFontGlyphs[189] = {+ { 32, 0, 9, 5, { 0 }},+ { 33, 0, 1, 2, { 0 }},+ { 34, 0, 1, 4, { 0 }},+ { 35, 0, 1, 6, { 0 }},+ { 36, 0, 0, 5, { 0 }},+ { 37, 0, 1, 6, { 0 }},+ { 38, 0, 0, 5, { 0 }},+ { 39, 0, 1, 2, { 0 }},+ { 40, 0, 1, 3, { 0 }},+ { 41, 0, 1, 3, { 0 }},+ { 42, 0, 1, 6, { 0 }},+ { 43, 0, 2, 6, { 0 }},+ { 44, 0, 7, 2, { 0 }},+ { 45, 0, 4, 5, { 0 }},+ { 46, 0, 7, 2, { 0 }},+ { 47, 0, 1, 6, { 0 }},+ { 48, 0, 1, 5, { 0 }},+ { 49, 0, 1, 3, { 0 }},+ { 50, 0, 1, 5, { 0 }},+ { 51, 0, 1, 5, { 0 }},+ { 52, 0, 1, 5, { 0 }},+ { 53, 0, 1, 5, { 0 }},+ { 54, 0, 1, 5, { 0 }},+ { 55, 0, 1, 5, { 0 }},+ { 56, 0, 1, 5, { 0 }},+ { 57, 0, 1, 5, { 0 }},+ { 58, 0, 1, 2, { 0 }},+ { 59, 0, 1, 2, { 0 }},+ { 60, 0, 2, 4, { 0 }},+ { 61, 0, 3, 5, { 0 }},+ { 62, 0, 2, 4, { 0 }},+ { 63, 0, 1, 5, { 0 }},+ { 64, 0, 1, 6, { 0 }},+ { 65, 0, 1, 5, { 0 }},+ { 66, 0, 1, 5, { 0 }},+ { 67, 0, 1, 5, { 0 }},+ { 68, 0, 1, 5, { 0 }},+ { 69, 0, 1, 5, { 0 }},+ { 70, 0, 1, 5, { 0 }},+ { 71, 0, 1, 5, { 0 }},+ { 72, 0, 1, 5, { 0 }},+ { 73, 0, 1, 4, { 0 }},+ { 74, 0, 1, 5, { 0 }},+ { 75, 0, 1, 5, { 0 }},+ { 76, 0, 1, 5, { 0 }},+ { 77, 0, 1, 8, { 0 }},+ { 78, 0, 1, 5, { 0 }},+ { 79, 0, 1, 5, { 0 }},+ { 80, 0, 1, 5, { 0 }},+ { 81, 0, 1, 5, { 0 }},+ { 82, 0, 1, 5, { 0 }},+ { 83, 0, 1, 5, { 0 }},+ { 84, 0, 1, 6, { 0 }},+ { 85, 0, 1, 5, { 0 }},+ { 86, 0, 1, 5, { 0 }},+ { 87, 0, 1, 8, { 0 }},+ { 88, 0, 1, 5, { 0 }},+ { 89, 0, 1, 5, { 0 }},+ { 90, 0, 1, 5, { 0 }},+ { 91, 0, 1, 3, { 0 }},+ { 92, 0, 1, 6, { 0 }},+ { 93, 0, 1, 3, { 0 }},+ { 94, 0, 1, 6, { 0 }},+ { 95, 0, 9, 5, { 0 }},+ { 96, 0, 1, 2, { 0 }},+ { 97, 0, 3, 5, { 0 }},+ { 98, 0, 1, 5, { 0 }},+ { 99, 0, 3, 5, { 0 }},+ { 100, 0, 1, 5, { 0 }},+ { 101, 0, 3, 5, { 0 }},+ { 102, 0, 1, 5, { 0 }},+ { 103, 0, 3, 5, { 0 }},+ { 104, 0, 1, 5, { 0 }},+ { 105, 0, 1, 2, { 0 }},+ { 106, 0, 1, 3, { 0 }},+ { 107, 0, 1, 5, { 0 }},+ { 108, 0, 1, 2, { 0 }},+ { 109, 0, 3, 8, { 0 }},+ { 110, 0, 3, 5, { 0 }},+ { 111, 0, 3, 5, { 0 }},+ { 112, 0, 3, 5, { 0 }},+ { 113, 0, 3, 5, { 0 }},+ { 114, 0, 3, 5, { 0 }},+ { 115, 0, 3, 5, { 0 }},+ { 116, 0, 1, 5, { 0 }},+ { 117, 0, 3, 5, { 0 }},+ { 118, 0, 3, 5, { 0 }},+ { 119, 0, 3, 8, { 0 }},+ { 120, 0, 3, 5, { 0 }},+ { 121, 0, 3, 5, { 0 }},+ { 122, 0, 3, 5, { 0 }},+ { 123, 0, 1, 4, { 0 }},+ { 124, 0, 0, 2, { 0 }},+ { 125, 0, 1, 4, { 0 }},+ { 126, 0, 3, 6, { 0 }},+ { 161, 0, 1, 2, { 0 }},+ { 162, 0, 2, 5, { 0 }},+ { 163, 0, 1, 5, { 0 }},+ { 8364, 0, 1, 7, { 0 }},+ { 165, 0, 1, 6, { 0 }},+ { 352, 0, -1, 5, { 0 }},+ { 167, 0, 0, 5, { 0 }},+ { 353, 0, 0, 5, { 0 }},+ { 169, 0, 1, 7, { 0 }},+ { 170, 0, -1, 4, { 0 }},+ { 171, 0, 3, 5, { 0 }},+ { 172, 0, 4, 5, { 0 }},+ { 174, 0, 1, 7, { 0 }},+ { 175, 0, -1, 5, { 0 }},+ { 176, 0, -1, 4, { 0 }},+ { 177, 0, 1, 6, { 0 }},+ { 178, 0, -1, 4, { 0 }},+ { 179, 0, -1, 4, { 0 }},+ { 381, 0, 1, 7, { 0 }},+ { 181, 0, 1, 5, { 0 }},+ { 182, 0, 1, 6, { 0 }},+ { 183, 0, 4, 2, { 0 }},+ { 382, 0, 1, 7, { 0 }},+ { 185, 0, -1, 3, { 0 }},+ { 186, 0, -1, 4, { 0 }},+ { 187, 0, 3, 5, { 0 }},+ { 338, 0, 1, 6, { 0 }},+ { 339, 0, 3, 6, { 0 }},+ { 376, 0, -1, 5, { 0 }},+ { 191, 0, 1, 5, { 0 }},+ { 192, 0, -1, 5, { 0 }},+ { 193, 0, -1, 5, { 0 }},+ { 194, 0, -1, 5, { 0 }},+ { 195, 0, -1, 5, { 0 }},+ { 196, 0, -1, 5, { 0 }},+ { 197, 0, -1, 5, { 0 }},+ { 198, 0, 1, 6, { 0 }},+ { 199, 0, 1, 5, { 0 }},+ { 200, 0, -1, 5, { 0 }},+ { 201, 0, -1, 5, { 0 }},+ { 202, 0, -1, 5, { 0 }},+ { 203, 0, -1, 5, { 0 }},+ { 204, 0, -1, 4, { 0 }},+ { 205, 0, -1, 4, { 0 }},+ { 206, 0, -1, 4, { 0 }},+ { 207, 0, -1, 4, { 0 }},+ { 208, 0, 1, 6, { 0 }},+ { 209, 0, -1, 5, { 0 }},+ { 210, 0, -1, 5, { 0 }},+ { 211, 0, -1, 5, { 0 }},+ { 212, 0, -1, 5, { 0 }},+ { 213, 0, -1, 5, { 0 }},+ { 214, 0, -1, 5, { 0 }},+ { 215, 0, 3, 4, { 0 }},+ { 216, 0, 0, 5, { 0 }},+ { 217, 0, -1, 5, { 0 }},+ { 218, 0, -1, 5, { 0 }},+ { 219, 0, -1, 5, { 0 }},+ { 220, 0, -1, 5, { 0 }},+ { 221, 0, -1, 5, { 0 }},+ { 222, 0, 1, 5, { 0 }},+ { 223, 0, 1, 5, { 0 }},+ { 224, 0, 0, 5, { 0 }},+ { 225, 0, 0, 5, { 0 }},+ { 226, 0, 0, 5, { 0 }},+ { 227, 0, 0, 5, { 0 }},+ { 228, 0, 1, 5, { 0 }},+ { 229, 0, -1, 5, { 0 }},+ { 230, 0, 3, 6, { 0 }},+ { 231, 0, 3, 5, { 0 }},+ { 232, 0, 0, 5, { 0 }},+ { 233, 0, 0, 5, { 0 }},+ { 234, 0, 0, 5, { 0 }},+ { 235, 0, 1, 5, { 0 }},+ { 236, 0, 0, 3, { 0 }},+ { 237, 0, 0, 2, { 0 }},+ { 238, 0, 0, 3, { 0 }},+ { 239, 0, 1, 3, { 0 }},+ { 240, 0, 0, 5, { 0 }},+ { 241, 0, 0, 5, { 0 }},+ { 242, 0, 0, 5, { 0 }},+ { 243, 0, 0, 5, { 0 }},+ { 244, 0, 0, 5, { 0 }},+ { 245, 0, 0, 5, { 0 }},+ { 246, 0, 1, 5, { 0 }},+ { 247, 0, 2, 4, { 0 }},+ { 248, 0, 2, 5, { 0 }},+ { 249, 0, 0, 5, { 0 }},+ { 250, 0, 0, 5, { 0 }},+ { 251, 0, 0, 5, { 0 }},+ { 252, 0, 1, 5, { 0 }},+ { 253, 0, 0, 5, { 0 }},+ { 254, 0, 0, 5, { 0 }},+ { 255, 0, 1, 5, { 0 }},+};++// Style loading function: Bluish+static void GuiLoadStyleBluish(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < BLUISH_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(bluishStyleProps[i].controlId, bluishStyleProps[i].propertyId, bluishStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int bluishFontDataSize = 0;+ unsigned char *data = DecompressData(bluishFontData, BLUISH_STYLE_FONT_ATLAS_COMP_SIZE, &bluishFontDataSize);+ Image imFont = { data, 256, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 10;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, bluishFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, bluishFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 254, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/candy/style_candy.h view
@@ -0,0 +1,589 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleCandy(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define CANDY_STYLE_PROPS_COUNT 17++// Custom style name: Candy+static const GuiStyleProp candyStyleProps[CANDY_STYLE_PROPS_COUNT] = {+ { 0, 0, 0xe58b68ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0xfeda96ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xe59b5fff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xee813fff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xfcd85bff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xfc6955ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xb34848ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xeb7272ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0xbd4a4aff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x94795dff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0xc2a37aff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x9c8369ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0xd77575ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0xfff5e1ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "v5easter.ttf" (size: 15, spacing: 0)++#define CANDY_STYLE_FONT_ATLAS_COMP_SIZE 2260++// Font atlas image pixels data: DEFLATE compressed+static unsigned char candyFontData[CANDY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x4d, 0x92, 0xd4, 0x38, 0x10, 0x06, 0x50, 0xdd, 0x80, 0xfb, 0xcc, 0x61, 0xe6, 0x4a, 0x73, 0x45, 0x8e, 0xc0, 0x86,+ 0x25, 0xa1, 0x89, 0x61, 0x88, 0x20, 0x80, 0x2e, 0x4b, 0x4a, 0xa5, 0x6c, 0xd9, 0xf5, 0x78, 0x1b, 0xa2, 0xdd, 0x5d, 0x55,+ 0xfe, 0xf9, 0x2c, 0xc9, 0x2e, 0xa5, 0x6b, 0x01, 0x00, 0x00, 0x00, 0xde, 0xdc, 0x7f, 0xff, 0xfe, 0xfc, 0x59, 0xf9, 0xe0,+ 0xa7, 0x3f, 0x7f, 0xb7, 0x7e, 0xb8, 0xf4, 0x68, 0x49, 0xfc, 0x2f, 0x8f, 0x3f, 0x49, 0xdf, 0x2b, 0x94, 0x83, 0x25, 0xed,+ 0xcf, 0xfc, 0xfb, 0xcf, 0x6a, 0xca, 0xbb, 0xbf, 0x7a, 0x9d, 0xd6, 0x27, 0x8a, 0x2c, 0x3b, 0x7a, 0xd5, 0x7a, 0xb0, 0x4e,+ 0xa5, 0x63, 0x49, 0x0d, 0xad, 0x5d, 0x9d, 0xde, 0xab, 0x63, 0x7b, 0xa7, 0xbd, 0xfe, 0x65, 0x78, 0x1d, 0xcb, 0x82, 0x65,+ 0x75, 0x72, 0x1f, 0xaf, 0xcc, 0xff, 0xef, 0xff, 0x32, 0xf3, 0x7f, 0xfc, 0x9a, 0x33, 0xc7, 0xc4, 0xcf, 0xb5, 0xa9, 0x09,+ 0xf9, 0x1f, 0x3f, 0x8b, 0x1c, 0xaf, 0xc1, 0xeb, 0xa3, 0xb8, 0x0c, 0xff, 0x4d, 0xfb, 0xfc, 0x9a, 0xf9, 0xaa, 0x2b, 0x97,+ 0xf5, 0xa5, 0x76, 0xfe, 0x38, 0x6f, 0x7d, 0x9a, 0xb9, 0x7d, 0x78, 0xe6, 0xb2, 0xdc, 0xfc, 0xb7, 0x7e, 0x37, 0x7a, 0x66,+ 0x8f, 0xf7, 0x0e, 0x7a, 0x5b, 0xf3, 0x3a, 0x74, 0xec, 0xb7, 0x5b, 0xb1, 0x9c, 0x2d, 0x3c, 0xba, 0xc6, 0xc7, 0xe7, 0x92,+ 0xd6, 0xd2, 0xf9, 0x36, 0x77, 0xe4, 0xd8, 0xb8, 0xe2, 0x28, 0x6e, 0xef, 0xcd, 0x8c, 0x76, 0xa9, 0xfe, 0xb2, 0xb5, 0xe5,+ 0xbf, 0xf7, 0xa8, 0xad, 0x8b, 0x5b, 0xda, 0x32, 0xdc, 0xd2, 0xc6, 0xfa, 0x2c, 0x79, 0x5b, 0x38, 0x2b, 0xff, 0x75, 0x22,+ 0xfd, 0x25, 0xd0, 0xe3, 0x3c, 0x3e, 0x6b, 0xb7, 0x3e, 0x7f, 0xf4, 0x28, 0xc9, 0x3d, 0x66, 0x67, 0xf3, 0x7f, 0xdc, 0x1f,+ 0x2e, 0x87, 0xe7, 0x9b, 0xf3, 0x7a, 0x5c, 0x3b, 0xe5, 0x3f, 0xda, 0x43, 0xee, 0x1f, 0xdd, 0xe4, 0xb5, 0xff, 0xeb, 0xf3,+ 0xdf, 0x4a, 0x64, 0x1d, 0x1c, 0xa9, 0xe6, 0xb6, 0xc6, 0x3d, 0xe3, 0xe9, 0xe8, 0x19, 0x7d, 0x7c, 0x8c, 0x7b, 0x7e, 0xff,+ 0xbf, 0x3d, 0x6e, 0xac, 0xcb, 0x46, 0x4e, 0xf9, 0x09, 0xdb, 0xb7, 0xff, 0xdf, 0xd7, 0x2f, 0x58, 0xd3, 0xff, 0x6f, 0x8d,+ 0xff, 0xcb, 0xe9, 0xad, 0x7f, 0x2b, 0x59, 0xf1, 0xbd, 0x5f, 0x43, 0x3d, 0xa0, 0xb9, 0xab, 0x0a, 0xb1, 0xfd, 0x39, 0x97,+ 0xff, 0x15, 0x7d, 0x80, 0xd1, 0xd1, 0xdf, 0x33, 0xfa, 0xff, 0x91, 0x2d, 0x18, 0xbd, 0xce, 0x9c, 0xb5, 0x66, 0xe3, 0xd7,+ 0xf9, 0xaf, 0xdb, 0x62, 0x79, 0xe7, 0xf9, 0xd9, 0x2d, 0x98, 0xff, 0xaa, 0xb1, 0x5e, 0xf5, 0xe8, 0x51, 0x5c, 0x2f, 0xbd,+ 0x37, 0x56, 0x6f, 0x71, 0xe5, 0xf4, 0x8c, 0xf6, 0xbf, 0x75, 0xfd, 0x7f, 0xe6, 0xea, 0xc0, 0xd8, 0x9d, 0x8d, 0xba, 0xe1,+ 0xb1, 0x22, 0xff, 0x77, 0x69, 0xc5, 0xb2, 0x7a, 0xd5, 0xae, 0xff, 0x45, 0xee, 0x69, 0x67, 0xf4, 0xe7, 0xee, 0x92, 0xff,+ 0xda, 0x71, 0x36, 0xed, 0x5f, 0x12, 0xbf, 0xe3, 0xbe, 0xea, 0x5b, 0x05, 0xad, 0xbb, 0x8d, 0xe7, 0xdd, 0xc5, 0xde, 0x31,+ 0xff, 0xf7, 0xb8, 0xff, 0xbf, 0xc7, 0xb6, 0x5c, 0x3b, 0x92, 0xdb, 0x31, 0xff, 0xf0, 0x1e, 0xdf, 0x26, 0x3c, 0xef, 0x5b,+ 0x8b, 0xf2, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdd, 0x67, 0xe7, 0xc4, 0x2b,+ 0x44, 0x8e, 0xcd, 0xb9, 0xa9, 0x4b, 0xea, 0x22, 0xc5, 0xe6, 0x46, 0x9f, 0x5b, 0xc3, 0x39, 0x5a, 0x35, 0x7b, 0x6e, 0x5e,+ 0xf8, 0xeb, 0x7a, 0x42, 0x33, 0xaf, 0x7b, 0x3c, 0x17, 0x79, 0x64, 0x5e, 0x76, 0xb4, 0xd6, 0xf9, 0x68, 0x4d, 0xa0, 0x48,+ 0xed, 0xa4, 0xd9, 0xda, 0xe9, 0xe3, 0x6b, 0x1c, 0x99, 0xc1, 0x3a, 0x3b, 0xe7, 0xed, 0xac, 0x8a, 0xcd, 0xd1, 0x9c, 0xf6,+ 0x55, 0xbd, 0xad, 0xc3, 0x95, 0xea, 0x76, 0xab, 0xd3, 0x90, 0x5d, 0x35, 0x63, 0x65, 0xfe, 0x4b, 0x57, 0x6d, 0xec, 0xbe,+ 0xf9, 0xce, 0x35, 0x71, 0x46, 0xfb, 0x79, 0x35, 0xf7, 0xca, 0xf4, 0x3e, 0x19, 0x6d, 0xa9, 0x9e, 0x9f, 0xff, 0xe8, 0xba,+ 0xb7, 0xb6, 0x6a, 0xdd, 0xb6, 0x8a, 0xfd, 0x95, 0xf9, 0x8f, 0xf6, 0xed, 0x8e, 0x5b, 0xbe, 0xf1, 0x8a, 0x07, 0xe7, 0x54,+ 0xb4, 0xa9, 0x1b, 0xe5, 0x7f, 0xfc, 0xdd, 0x56, 0xce, 0x61, 0x9f, 0x6b, 0x7b, 0x6b, 0x5a, 0xfe, 0xe3, 0x7d, 0x9f, 0xdd,+ 0xda, 0xf8, 0xdc, 0xaa, 0x39, 0xeb, 0xf2, 0x5f, 0xd2, 0xab, 0x32, 0xed, 0x99, 0xff, 0x9e, 0xf6, 0x21, 0x32, 0x36, 0x18,+ 0xff, 0xcb, 0xe8, 0x19, 0x77, 0xf4, 0xdd, 0x22, 0xed, 0xff, 0xf1, 0x5a, 0xde, 0xb9, 0xfd, 0xdf, 0x25, 0xff, 0x65, 0xab,+ 0xfe, 0xff, 0xec, 0xd1, 0x38, 0x96, 0xf3, 0xeb, 0x6a, 0xb3, 0xed, 0xfe, 0x24, 0xa3, 0x91, 0x2d, 0x3e, 0x5b, 0x1d, 0x39,+ 0x7a, 0xdd, 0x21, 0xf3, 0x89, 0x4d, 0xf7, 0xba, 0xc6, 0x55, 0xde, 0x72, 0xfc, 0x1f, 0xbf, 0xee, 0x2b, 0xff, 0xb3, 0xfd,+ 0xe9, 0x72, 0x41, 0xfe, 0x57, 0x6d, 0xbb, 0x3b, 0xe7, 0x7f, 0xa6, 0xe7, 0x77, 0x56, 0xfe, 0xcb, 0xcb, 0xa7, 0x50, 0xcd,+ 0xe6, 0x3f, 0xfe, 0x6c, 0x9c, 0xd1, 0x9c, 0xd7, 0x0b, 0xef, 0x6f, 0xad, 0x38, 0x07, 0xc6, 0xef, 0x37, 0x14, 0xf9, 0xbf,+ 0x55, 0xfe, 0xaf, 0x6f, 0xff, 0x7b, 0x9f, 0xad, 0xf8, 0xde, 0xf9, 0x2f, 0x53, 0xd7, 0xf8, 0x56, 0xfc, 0xdd, 0x6e, 0xfd,+ 0xff, 0xec, 0x73, 0xe7, 0xb9, 0xe7, 0xd3, 0x75, 0x7d, 0xdc, 0xd8, 0xf5, 0xa4, 0xd8, 0xd3, 0x0c, 0x62, 0x55, 0xb3, 0xd7,+ 0x1c, 0x53, 0x25, 0xfc, 0x0c, 0xaf, 0x32, 0x7c, 0x06, 0x90, 0xff, 0x5f, 0x97, 0xac, 0x7b, 0x3a, 0x32, 0xac, 0xce, 0xd3,+ 0xbd, 0xf2, 0x3f, 0xf7, 0x4d, 0x83, 0xfc, 0xa7, 0x0d, 0xd6, 0x0b, 0xda, 0x7f, 0x58, 0x7b, 0x97, 0x3d, 0xef, 0xf7, 0xc9,+ 0xe8, 0xd3, 0x03, 0xef, 0xdb, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x38, 0x57,+ 0xe0, 0xf5, 0x2c, 0xcf, 0xe3, 0x2a, 0x18, 0x25, 0x58, 0x05, 0xbb, 0x74, 0x54, 0x4e, 0xae, 0xc1, 0xf7, 0x1b, 0x99, 0xa5,+ 0xbc, 0x5b, 0x2d, 0x82, 0xd1, 0xfa, 0x88, 0x23, 0xb5, 0xb1, 0xcb, 0x70, 0x9d, 0xaf, 0x68, 0x15, 0x9b, 0x32, 0x59, 0x73,+ 0x34, 0x3e, 0xff, 0x2e, 0x3a, 0x83, 0xfa, 0x68, 0x7f, 0x7e, 0xaa, 0xdf, 0xea, 0x97, 0xef, 0xbe, 0xd6, 0x7f, 0x86, 0xdf,+ 0xb5, 0x76, 0xcd, 0xf7, 0x9b, 0xdd, 0x27, 0x3d, 0x5b, 0x28, 0x92, 0xff, 0x1d, 0xab, 0xee, 0x65, 0x55, 0xf9, 0xb8, 0x53,+ 0xbd, 0xed, 0x91, 0x3a, 0xbc, 0xed, 0x7a, 0x1e, 0xf3, 0xf9, 0xef, 0xad, 0x29, 0x50, 0x27, 0xab, 0x7e, 0x8e, 0x9e, 0x2b,+ 0x8e, 0xb7, 0xcb, 0xd1, 0xdc, 0xe4, 0xd7, 0xad, 0xdc, 0xa7, 0xfa, 0xf9, 0xc7, 0xff, 0xfe, 0xfe, 0x30, 0xff, 0x35, 0x3c,+ 0x1b, 0xa7, 0xfd, 0x89, 0x32, 0xe7, 0x57, 0xbf, 0x47, 0xfe, 0xc7, 0xcf, 0x99, 0x77, 0xa8, 0xb7, 0x5d, 0x12, 0x7e, 0x9a,+ 0x39, 0xf3, 0x3d, 0x5a, 0x53, 0x24, 0x9a, 0xff, 0x91, 0x34, 0xbd, 0x3e, 0xcb, 0x95, 0x8e, 0x0a, 0x6a, 0xa3, 0xf9, 0x6f,+ 0xbd, 0x6b, 0x24, 0xff, 0x75, 0xb8, 0xf6, 0x4a, 0xff, 0xb6, 0x1c, 0x6b, 0x5d, 0xf6, 0xcc, 0x7f, 0xa4, 0xc7, 0x59, 0x4f,+ 0xcc, 0xff, 0x5c, 0x8d, 0xaf, 0x72, 0x7a, 0xfe, 0x73, 0x9f, 0x53, 0xd1, 0x37, 0x92, 0xe9, 0x4d, 0x76, 0xff, 0xef, 0xd6,+ 0x46, 0x5b, 0xbc, 0x2e, 0xff, 0xf5, 0x83, 0xf7, 0x5f, 0xd5, 0xfe, 0xc7, 0xeb, 0xab, 0xd6, 0x83, 0x4f, 0xf8, 0x84, 0xfc,+ 0x97, 0x4d, 0xfa, 0xff, 0xf9, 0xcf, 0x52, 0xdb, 0x33, 0xff, 0xe3, 0x3d, 0xae, 0xf1, 0x76, 0x7d, 0xac, 0xaf, 0xd0, 0x1e,+ 0x01, 0xd4, 0xc0, 0x19, 0xa0, 0x27, 0xff, 0xb1, 0xf6, 0x3f, 0x3a, 0xfe, 0x8f, 0x27, 0xa3, 0x3e, 0xb6, 0xfd, 0xcf, 0x1d,+ 0xff, 0xaf, 0xaa, 0x45, 0x98, 0xfb, 0xbc, 0xad, 0xac, 0x5a, 0x9b, 0xb1, 0xbe, 0x56, 0xb4, 0xfd, 0x6f, 0xf5, 0x0e, 0x66,+ 0xf2, 0x5f, 0x26, 0x93, 0xf8, 0xf1, 0xf5, 0xbf, 0x55, 0xed, 0xff, 0xf9, 0xd7, 0xff, 0x6b, 0x20, 0x21, 0xab, 0xaa, 0x6e,+ 0xd6, 0xe1, 0x6b, 0x31, 0xb3, 0x55, 0xd5, 0xfa, 0xef, 0x34, 0xf4, 0x9c, 0x9b, 0x5f, 0xdf, 0xa5, 0xe8, 0xd9, 0x2a, 0x19,+ 0xa3, 0xbe, 0x5d, 0xfb, 0xff, 0xd7, 0xb4, 0xff, 0x3d, 0xad, 0x7f, 0xa4, 0x0e, 0xd9, 0xba, 0xeb, 0x7f, 0xd1, 0xf1, 0xd3,+ 0xdc, 0xfd, 0xbf, 0xeb, 0xeb, 0x08, 0x66, 0x5f, 0xf9, 0x39, 0xf3, 0xb5, 0xae, 0xfa, 0x44, 0x3b, 0xf6, 0xff, 0xe3, 0x63,+ 0xab, 0x91, 0x51, 0x7d, 0xde, 0xfd, 0xbf, 0x98, 0x56, 0xfe, 0xd7, 0xbc, 0xeb, 0xba, 0x63, 0x4e, 0xfe, 0xf7, 0xdc, 0x07,+ 0x7b, 0xe5, 0xbf, 0xf7, 0x29, 0xe6, 0x35, 0xfd, 0x4e, 0xfc, 0x6e, 0x7b, 0xb0, 0x9d, 0xff, 0x7b, 0x7d, 0xff, 0xe7, 0xfc,+ 0x27, 0x8f, 0x5e, 0x9d, 0xff, 0xdd, 0xce, 0x00, 0x59, 0x4f, 0xbc, 0x2e, 0x49, 0x7b, 0x32, 0x72, 0x17, 0x6f, 0xf7, 0xf3,+ 0xa5, 0xfc, 0xf3, 0xfc, 0xef, 0x6f, 0xd6, 0xc7, 0xf7, 0x9b, 0xae, 0xef, 0x5b, 0xcb, 0x3f, 0xbc, 0xaf, 0xf6, 0xf7, 0x7f,+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x9e, 0x0f, 0x58, 0x27, 0xe7, 0x0a, 0xc6, 0x2a,+ 0x0d, 0x95, 0xe6, 0x8c, 0xd3, 0x1a, 0xfe, 0x9d, 0x91, 0x75, 0x89, 0xd7, 0xb0, 0x88, 0xd4, 0xe0, 0x2e, 0x8d, 0xba, 0x35,+ 0x39, 0xdb, 0xe6, 0x9c, 0xf5, 0x6c, 0xd7, 0xda, 0x1b, 0x3b, 0x2e, 0x46, 0xb6, 0x54, 0xbb, 0x86, 0xca, 0x79, 0xdb, 0x21,+ 0xba, 0xbf, 0x6b, 0x63, 0x76, 0x77, 0x6d, 0x54, 0xae, 0xc9, 0xa9, 0x07, 0x50, 0x1b, 0x75, 0x54, 0xe2, 0xf3, 0xd5, 0x46,+ 0xcf, 0x00, 0xf5, 0x8f, 0xda, 0x4e, 0x35, 0xf4, 0x3b, 0xa3, 0x7b, 0x3d, 0xb6, 0xac, 0xa7, 0xaa, 0x63, 0x5e, 0xa5, 0xe8,+ 0xc8, 0xb6, 0x59, 0xbf, 0x9e, 0xe3, 0xc7, 0x45, 0x4d, 0x7a, 0x87, 0xde, 0xba, 0x24, 0xfb, 0xef, 0xef, 0x76, 0x05, 0xd9,+ 0xba, 0xac, 0xfd, 0xcf, 0xc8, 0xff, 0x58, 0x0d, 0xd6, 0x91, 0x3a, 0x63, 0x99, 0xf9, 0xdf, 0xab, 0x3f, 0x16, 0x7f, 0x1e,+ 0x44, 0x56, 0xc5, 0xfd, 0x7b, 0xcc, 0xda, 0x8d, 0x3f, 0x99, 0xe0, 0x3e, 0xfb, 0x7b, 0xf5, 0xfa, 0xf5, 0x9c, 0x29, 0xe7,+ 0xea, 0x42, 0x5c, 0x95, 0xff, 0xbc, 0xfe, 0x7f, 0xb4, 0x3f, 0x1d, 0x79, 0x26, 0xd2, 0x6c, 0x2d, 0xc5, 0x99, 0x27, 0x8b,+ 0x9c, 0xbd, 0x2e, 0x73, 0xa3, 0x82, 0x9e, 0x31, 0xeb, 0x0e, 0xdb, 0x61, 0x66, 0x1b, 0x95, 0xe0, 0x93, 0x17, 0xb2, 0xf2,+ 0x9f, 0x51, 0xcf, 0x74, 0x7c, 0xfc, 0xd7, 0xde, 0x56, 0xb9, 0xe7, 0xc5, 0xd8, 0xeb, 0xed, 0xba, 0xac, 0x4e, 0x8c, 0x63,+ 0xae, 0x7d, 0x92, 0x51, 0x4e, 0xfe, 0xfb, 0x7b, 0xb5, 0xbb, 0xef, 0xd3, 0xd2, 0x31, 0x4e, 0xde, 0x3f, 0xff, 0xa3, 0x9f,+ 0x25, 0xb3, 0x8f, 0x3b, 0x5b, 0x5d, 0xfa, 0x9a, 0x65, 0xf3, 0x4f, 0x2a, 0xd9, 0xfd, 0xd8, 0xbe, 0x3a, 0xff, 0x6b, 0x9e,+ 0x06, 0x93, 0xbd, 0x8d, 0x5a, 0xa3, 0x86, 0xac, 0xf6, 0xbf, 0x35, 0x02, 0xa9, 0x5b, 0x8c, 0x0b, 0xfb, 0xb2, 0x3d, 0x7e,+ 0xfd, 0x7f, 0xee, 0x58, 0x59, 0xb1, 0x6c, 0xfe, 0xb8, 0xdd, 0x37, 0xe3, 0xbb, 0xe4, 0xff, 0x0e, 0xe7, 0xc8, 0x78, 0xab,+ 0x9d, 0xd1, 0xf7, 0x3d, 0xbf, 0xfd, 0xcf, 0xc8, 0x7f, 0xfe, 0x15, 0xd0, 0x3b, 0x2e, 0x5b, 0x9f, 0xd5, 0xd9, 0x6b, 0x70,+ 0xf2, 0x2f, 0xff, 0xf1, 0xbe, 0x4a, 0x4d, 0xaf, 0x70, 0xb9, 0xe2, 0xe9, 0x60, 0x57, 0x8d, 0xff, 0x73, 0xaf, 0x43, 0xdd,+ 0xb5, 0xff, 0x7f, 0xf7, 0x7d, 0x3a, 0xd3, 0x6b, 0xa7, 0xbc, 0x55, 0xdf, 0x60, 0xf6, 0x6c, 0xff, 0xb4, 0xfc, 0x3f, 0x7b,+ 0x9f, 0x4a, 0xbd, 0xfc, 0xe7, 0x9e, 0x01, 0xd6, 0x65, 0x7c, 0x24, 0xbb, 0xef, 0x97, 0xff, 0xbb, 0x3c, 0x35, 0x48, 0xfe,+ 0x9f, 0x31, 0xe6, 0x3b, 0xf7, 0x7b, 0x0e, 0x39, 0xdf, 0xff, 0x2b, 0x27, 0x3e, 0x01, 0xef, 0xec, 0xfb, 0xff, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x33, 0x7e, 0x33, 0x2b, 0x3d, 0x1f, 0xfd, 0xe5, 0xa7, 0xfa,+ 0xad, 0x7e, 0xf9, 0xee, 0x6b, 0xfd, 0xe7, 0xb0, 0xce, 0xc9, 0x19, 0x6b, 0xa1, 0x2e, 0xf7, 0xda, 0xba, 0xdc, 0xc7, 0x7b,+ 0xfb, 0x2e, 0x55, 0xb9, 0x7b, 0x8f, 0xd9, 0x3a, 0xb8, 0x85, 0x57, 0xa6, 0x2f, 0xab, 0x9e, 0x43, 0x74, 0xee, 0xe1, 0xab,+ 0xd7, 0xfc, 0x54, 0x3f, 0xff, 0xf8, 0xdf, 0xdf, 0x1f, 0x6e, 0xcb, 0xbe, 0x7a, 0x60, 0x79, 0x6b, 0xa1, 0x2e, 0xf7, 0xca,+ 0xba, 0xdc, 0x7d, 0x7b, 0x7b, 0xf7, 0xaa, 0xdc, 0xfd, 0x6b, 0x51, 0x37, 0x49, 0xdf, 0xb5, 0xb3, 0xe4, 0xe2, 0xdb, 0x72,+ 0xaf, 0x1a, 0xce, 0x35, 0x5c, 0x5b, 0x73, 0xae, 0x2e, 0xef, 0xf9, 0xeb, 0xb2, 0xaa, 0x87, 0xd9, 0x4a, 0xce, 0x6e, 0x47,+ 0x74, 0x6c, 0x2d, 0xae, 0xd9, 0x9b, 0xfd, 0xef, 0xb8, 0xd3, 0xec, 0xe7, 0x99, 0xfc, 0xef, 0x54, 0xa7, 0xb9, 0xbd, 0xbd,+ 0xe3, 0xcf, 0x51, 0x7a, 0x4e, 0x5d, 0xee, 0xd6, 0xde, 0x2e, 0x27, 0xcf, 0xbc, 0x8d, 0x6d, 0xa1, 0xfe, 0x3e, 0xeb, 0x1e,+ 0x75, 0x96, 0xee, 0x9e, 0xff, 0x9d, 0xb6, 0x63, 0x0d, 0xd6, 0xe5, 0xdf, 0xab, 0xf6, 0xf6, 0xae, 0xf9, 0xbf, 0x47, 0xa5,+ 0x95, 0x9e, 0xfc, 0xef, 0x76, 0xdc, 0x3e, 0xb1, 0xfd, 0x2f, 0x1d, 0xd5, 0xee, 0x33, 0x97, 0xe5, 0xd4, 0x8c, 0x7f, 0xe7,+ 0xba, 0xbc, 0xef, 0x93, 0xff, 0x22, 0xff, 0xa7, 0xf4, 0xff, 0xcf, 0x5b, 0x36, 0xdf, 0x37, 0x58, 0x71, 0xfd, 0xff, 0x5e,+ 0x75, 0x79, 0xdf, 0xa9, 0xfd, 0xdf, 0xa7, 0xce, 0xe2, 0x33, 0xf3, 0xbf, 0x63, 0x7b, 0xaa, 0x2e, 0xa7, 0xfc, 0xd7, 0xcd,+ 0xd2, 0xb7, 0xcb, 0x11, 0x15, 0x3f, 0x22, 0x76, 0xaa, 0x57, 0x9d, 0x7d, 0x6d, 0xb0, 0xff, 0x0e, 0xfb, 0x13, 0xea, 0x72,+ 0xde, 0x27, 0xff, 0x33, 0xd7, 0xff, 0xcf, 0x4f, 0x5f, 0x19, 0x7a, 0x0e, 0xf8, 0x15, 0x67, 0xa0, 0xd8, 0xfd, 0xff, 0xb3,+ 0xaf, 0x8b, 0x67, 0x3d, 0x97, 0x28, 0xf7, 0x3b, 0x59, 0xcf, 0xa9, 0xcb, 0x79, 0x9f, 0xbb, 0x3d, 0x33, 0xf7, 0xff, 0xfb,+ 0xee, 0x2c, 0x96, 0xe1, 0x1c, 0x67, 0x3c, 0xeb, 0xbf, 0x5c, 0x54, 0xc5, 0x38, 0xfa, 0xfd, 0x9f, 0x3b, 0x7d, 0xa3, 0x52,+ 0x7d, 0xd7, 0xd5, 0xc9, 0xb1, 0x16, 0xeb, 0x8f, 0xd6, 0x35, 0x55, 0x8c, 0x5f, 0xe7, 0xbf, 0xf5, 0x5d, 0x4a, 0x9e, 0x94,+ 0xff, 0x27, 0xec, 0x6d, 0xc7, 0x2c, 0xac, 0xf4, 0x97, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0xd0, 0x3d, 0x43, 0xf3, 0xf8, 0xbb, 0xcd, 0x3b, 0xd7, 0x20, 0x05, 0x66, 0xe7, 0xe3, 0x3c, 0x63, 0x3e, 0x1e, 0x90, 0x3d,+ 0xb7, 0x71, 0xaf, 0x7a, 0xdc, 0x40, 0xee, 0xfc, 0x7f, 0xf9, 0x07, 0xf9, 0x97, 0x7f, 0x90, 0x7f, 0xf9, 0x07, 0xf9, 0xff,+ 0xf9, 0x97, 0x55, 0xfe, 0xe1, 0xe6, 0xf9, 0xaf, 0x4b, 0x6a, 0x9b, 0x03, 0x77, 0x39, 0x03, 0x44, 0xf2, 0x5f, 0xf4, 0xff,+ 0xe1, 0xb1, 0xdf, 0x01, 0x30, 0xfe, 0x07, 0xe3, 0x7f, 0xf9, 0x87, 0x77, 0xcc, 0x7f, 0xeb, 0xfb, 0xbf, 0x46, 0xff, 0xf0,+ 0x8c, 0xf1, 0xbf, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xf2, 0xff, 0x3f, 0xdb, 0x01, 0xe4, 0x1f, 0x78, 0xbb, 0xfc, 0xff, 0x0b };++// Font glyphs rectangles data (on atlas)+static const Rectangle candyFontRecs[189] = {+ { 4, 4, 3 , 15 },+ { 15, 4, 2 , 9 },+ { 25, 4, 3 , 2 },+ { 36, 4, 8 , 9 },+ { 52, 4, 6 , 11 },+ { 66, 4, 7 , 9 },+ { 81, 4, 7 , 9 },+ { 96, 4, 1 , 2 },+ { 105, 4, 3 , 11 },+ { 116, 4, 3 , 11 },+ { 127, 4, 7 , 7 },+ { 142, 4, 6 , 5 },+ { 156, 4, 2 , 3 },+ { 166, 4, 5 , 1 },+ { 179, 4, 2 , 2 },+ { 189, 4, 5 , 10 },+ { 202, 4, 6 , 9 },+ { 216, 4, 4 , 9 },+ { 228, 4, 6 , 9 },+ { 242, 4, 6 , 9 },+ { 256, 4, 7 , 9 },+ { 271, 4, 6 , 9 },+ { 285, 4, 6 , 9 },+ { 299, 4, 6 , 9 },+ { 313, 4, 6 , 9 },+ { 327, 4, 6 , 9 },+ { 341, 4, 2 , 6 },+ { 351, 4, 2 , 7 },+ { 361, 4, 4 , 6 },+ { 373, 4, 5 , 3 },+ { 386, 4, 4 , 6 },+ { 398, 4, 6 , 9 },+ { 412, 4, 8 , 7 },+ { 428, 4, 6 , 9 },+ { 442, 4, 6 , 9 },+ { 456, 4, 6 , 9 },+ { 470, 4, 6 , 9 },+ { 484, 4, 6 , 9 },+ { 4, 27, 6 , 9 },+ { 18, 27, 6 , 9 },+ { 32, 27, 6 , 9 },+ { 46, 27, 2 , 9 },+ { 56, 27, 6 , 9 },+ { 70, 27, 6 , 9 },+ { 84, 27, 6 , 9 },+ { 98, 27, 8 , 9 },+ { 114, 27, 6 , 9 },+ { 128, 27, 6 , 9 },+ { 142, 27, 6 , 9 },+ { 156, 27, 6 , 9 },+ { 170, 27, 6 , 9 },+ { 184, 27, 6 , 9 },+ { 198, 27, 6 , 9 },+ { 212, 27, 6 , 9 },+ { 226, 27, 6 , 9 },+ { 240, 27, 8 , 9 },+ { 256, 27, 6 , 9 },+ { 270, 27, 6 , 9 },+ { 284, 27, 6 , 9 },+ { 298, 27, 3 , 11 },+ { 309, 27, 5 , 10 },+ { 322, 27, 3 , 11 },+ { 333, 27, 6 , 4 },+ { 347, 27, 6 , 1 },+ { 361, 27, 3 , 2 },+ { 372, 27, 6 , 7 },+ { 386, 27, 6 , 10 },+ { 400, 27, 6 , 7 },+ { 414, 27, 6 , 10 },+ { 428, 27, 6 , 7 },+ { 442, 27, 5 , 10 },+ { 455, 27, 7 , 10 },+ { 470, 27, 6 , 10 },+ { 484, 27, 2 , 10 },+ { 494, 27, 2 , 12 },+ { 4, 50, 6 , 10 },+ { 18, 50, 3 , 10 },+ { 29, 50, 8 , 7 },+ { 45, 50, 6 , 7 },+ { 59, 50, 6 , 7 },+ { 73, 50, 6 , 10 },+ { 87, 50, 6 , 10 },+ { 101, 50, 6 , 7 },+ { 115, 50, 6 , 7 },+ { 129, 50, 3 , 10 },+ { 140, 50, 6 , 7 },+ { 154, 50, 6 , 7 },+ { 168, 50, 8 , 7 },+ { 184, 50, 6 , 7 },+ { 198, 50, 6 , 10 },+ { 212, 50, 6 , 7 },+ { 226, 50, 4 , 11 },+ { 238, 50, 1 , 11 },+ { 247, 50, 4 , 11 },+ { 259, 50, 6 , 2 },+ { 273, 50, 2 , 10 },+ { 283, 50, 6 , 11 },+ { 297, 50, 8 , 9 },+ { 313, 50, 7 , 9 },+ { 328, 50, 6 , 9 },+ { 342, 50, 0 , 0 },+ { 350, 50, 6 , 11 },+ { 364, 50, 0 , 0 },+ { 372, 50, 8 , 8 },+ { 388, 50, 5 , 7 },+ { 401, 50, 7 , 6 },+ { 416, 50, 7 , 12 },+ { 431, 50, 8 , 8 },+ { 447, 50, 6 , 1 },+ { 461, 50, 4 , 5 },+ { 473, 50, 6 , 7 },+ { 487, 50, 3 , 5 },+ { 498, 50, 3 , 5 },+ { 4, 73, 0 , 0 },+ { 12, 73, 6 , 9 },+ { 26, 73, 6 , 9 },+ { 40, 73, 4 , 4 },+ { 52, 73, 0 , 0 },+ { 60, 73, 2 , 5 },+ { 70, 73, 4 , 7 },+ { 82, 73, 7 , 6 },+ { 97, 73, 10 , 9 },+ { 115, 73, 10 , 7 },+ { 133, 73, 0 , 0 },+ { 141, 73, 6 , 9 },+ { 155, 73, 6 , 12 },+ { 169, 73, 6 , 12 },+ { 183, 73, 6 , 12 },+ { 197, 73, 6 , 12 },+ { 211, 73, 6 , 11 },+ { 225, 73, 6 , 12 },+ { 239, 73, 10 , 9 },+ { 257, 73, 6 , 12 },+ { 271, 73, 6 , 12 },+ { 285, 73, 6 , 12 },+ { 299, 73, 6 , 12 },+ { 313, 73, 6 , 11 },+ { 327, 73, 3 , 12 },+ { 338, 73, 3 , 12 },+ { 349, 73, 4 , 12 },+ { 361, 73, 4 , 11 },+ { 373, 73, 8 , 9 },+ { 389, 73, 6 , 12 },+ { 403, 73, 6 , 12 },+ { 417, 73, 6 , 12 },+ { 431, 73, 6 , 12 },+ { 445, 73, 6 , 12 },+ { 459, 73, 6 , 11 },+ { 473, 73, 5 , 5 },+ { 486, 73, 9 , 10 },+ { 4, 96, 6 , 12 },+ { 18, 96, 6 , 12 },+ { 32, 96, 6 , 12 },+ { 46, 96, 6 , 11 },+ { 60, 96, 6 , 12 },+ { 74, 96, 7 , 12 },+ { 89, 96, 6 , 10 },+ { 103, 96, 6 , 10 },+ { 117, 96, 6 , 10 },+ { 131, 96, 6 , 10 },+ { 145, 96, 6 , 10 },+ { 159, 96, 6 , 9 },+ { 173, 96, 6 , 11 },+ { 187, 96, 10 , 7 },+ { 205, 96, 6 , 10 },+ { 219, 96, 6 , 10 },+ { 233, 96, 6 , 10 },+ { 247, 96, 6 , 10 },+ { 261, 96, 6 , 9 },+ { 275, 96, 3 , 10 },+ { 286, 96, 3 , 10 },+ { 297, 96, 4 , 10 },+ { 309, 96, 4 , 9 },+ { 321, 96, 7 , 12 },+ { 336, 96, 6 , 13 },+ { 350, 96, 6 , 10 },+ { 364, 96, 6 , 10 },+ { 378, 96, 6 , 10 },+ { 392, 96, 6 , 10 },+ { 406, 96, 6 , 9 },+ { 420, 96, 7 , 12 },+ { 435, 96, 8 , 8 },+ { 451, 96, 6 , 10 },+ { 465, 96, 6 , 10 },+ { 479, 96, 6 , 10 },+ { 493, 96, 6 , 9 },+ { 4, 119, 6 , 13 },+ { 18, 119, 7 , 12 },+ { 33, 119, 6 , 12 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo candyFontGlyphs[189] = {+ { 32, 0, 12, 3, { 0 }},+ { 33, 0, 3, 3, { 0 }},+ { 34, 0, 2, 4, { 0 }},+ { 35, 0, 3, 9, { 0 }},+ { 36, 0, 2, 7, { 0 }},+ { 37, 0, 3, 8, { 0 }},+ { 38, 0, 3, 8, { 0 }},+ { 39, 0, 2, 2, { 0 }},+ { 40, 1, 2, 5, { 0 }},+ { 41, 1, 2, 5, { 0 }},+ { 42, 0, 4, 8, { 0 }},+ { 43, 0, 6, 7, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 7, 6, { 0 }},+ { 46, 0, 10, 3, { 0 }},+ { 47, 1, 3, 7, { 0 }},+ { 48, 0, 3, 7, { 0 }},+ { 49, 0, 3, 5, { 0 }},+ { 50, 0, 3, 7, { 0 }},+ { 51, 0, 3, 7, { 0 }},+ { 52, 0, 3, 8, { 0 }},+ { 53, 0, 3, 7, { 0 }},+ { 54, 0, 3, 7, { 0 }},+ { 55, 0, 3, 7, { 0 }},+ { 56, 0, 3, 7, { 0 }},+ { 57, 0, 3, 7, { 0 }},+ { 58, 0, 6, 3, { 0 }},+ { 59, 0, 6, 3, { 0 }},+ { 60, 1, 5, 6, { 0 }},+ { 61, 1, 7, 7, { 0 }},+ { 62, 1, 5, 6, { 0 }},+ { 63, 0, 3, 7, { 0 }},+ { 64, 0, 4, 9, { 0 }},+ { 65, 0, 3, 7, { 0 }},+ { 66, 0, 3, 7, { 0 }},+ { 67, 0, 3, 7, { 0 }},+ { 68, 0, 3, 7, { 0 }},+ { 69, 0, 3, 7, { 0 }},+ { 70, 0, 3, 7, { 0 }},+ { 71, 0, 3, 7, { 0 }},+ { 72, 0, 3, 7, { 0 }},+ { 73, 0, 3, 3, { 0 }},+ { 74, 0, 3, 7, { 0 }},+ { 75, 0, 3, 7, { 0 }},+ { 76, 0, 3, 7, { 0 }},+ { 77, 0, 3, 9, { 0 }},+ { 78, 0, 3, 7, { 0 }},+ { 79, 0, 3, 7, { 0 }},+ { 80, 0, 3, 7, { 0 }},+ { 81, 0, 3, 7, { 0 }},+ { 82, 0, 3, 7, { 0 }},+ { 83, 0, 3, 7, { 0 }},+ { 84, 0, 3, 7, { 0 }},+ { 85, 0, 3, 7, { 0 }},+ { 86, 0, 3, 7, { 0 }},+ { 87, 0, 3, 9, { 0 }},+ { 88, 0, 3, 7, { 0 }},+ { 89, 0, 3, 7, { 0 }},+ { 90, 0, 3, 7, { 0 }},+ { 91, 1, 2, 5, { 0 }},+ { 92, 1, 3, 7, { 0 }},+ { 93, 1, 2, 5, { 0 }},+ { 94, 0, 3, 7, { 0 }},+ { 95, 0, 11, 7, { 0 }},+ { 96, 0, 0, 4, { 0 }},+ { 97, 0, 5, 7, { 0 }},+ { 98, 0, 2, 7, { 0 }},+ { 99, 0, 5, 7, { 0 }},+ { 100, 0, 2, 7, { 0 }},+ { 101, 0, 5, 7, { 0 }},+ { 102, 0, 2, 6, { 0 }},+ { 103, 0, 5, 7, { 0 }},+ { 104, 0, 2, 7, { 0 }},+ { 105, 0, 2, 3, { 0 }},+ { 106, 0, 2, 3, { 0 }},+ { 107, 0, 2, 7, { 0 }},+ { 108, 0, 2, 4, { 0 }},+ { 109, 0, 5, 9, { 0 }},+ { 110, 0, 5, 7, { 0 }},+ { 111, 0, 5, 7, { 0 }},+ { 112, 0, 5, 7, { 0 }},+ { 113, 0, 5, 7, { 0 }},+ { 114, 0, 5, 7, { 0 }},+ { 115, 0, 5, 7, { 0 }},+ { 116, 0, 2, 4, { 0 }},+ { 117, 0, 5, 7, { 0 }},+ { 118, 0, 5, 7, { 0 }},+ { 119, 0, 5, 9, { 0 }},+ { 120, 0, 5, 7, { 0 }},+ { 121, 0, 5, 7, { 0 }},+ { 122, 0, 5, 7, { 0 }},+ { 123, 1, 2, 6, { 0 }},+ { 124, 1, 2, 3, { 0 }},+ { 125, 1, 2, 6, { 0 }},+ { 126, 0, 0, 7, { 0 }},+ { 161, 0, 3, 3, { 0 }},+ { 162, 0, 2, 7, { 0 }},+ { 163, 0, 3, 9, { 0 }},+ { 8364, 0, 3, 8, { 0 }},+ { 165, 0, 3, 7, { 0 }},+ { 352, 0, 12, 1, { 0 }},+ { 167, 0, 2, 7, { 0 }},+ { 353, 0, 12, 1, { 0 }},+ { 169, 0, 0, 9, { 0 }},+ { 170, 0, 0, 6, { 0 }},+ { 171, 1, 5, 9, { 0 }},+ { 172, 0, 0, 7, { 0 }},+ { 174, 0, 0, 9, { 0 }},+ { 175, 0, 0, 7, { 0 }},+ { 176, 0, 0, 5, { 0 }},+ { 177, 0, 4, 7, { 0 }},+ { 178, 0, 0, 4, { 0 }},+ { 179, 0, 0, 4, { 0 }},+ { 381, 0, 12, 1, { 0 }},+ { 181, 0, 5, 7, { 0 }},+ { 182, 0, 3, 7, { 0 }},+ { 183, 0, 6, 5, { 0 }},+ { 382, 0, 12, 1, { 0 }},+ { 185, 0, 0, 3, { 0 }},+ { 186, 0, 0, 5, { 0 }},+ { 187, 1, 5, 9, { 0 }},+ { 338, 0, 3, 11, { 0 }},+ { 339, 0, 5, 11, { 0 }},+ { 376, 0, 12, 1, { 0 }},+ { 191, 0, 4, 7, { 0 }},+ { 192, 0, 0, 7, { 0 }},+ { 193, 0, 0, 7, { 0 }},+ { 194, 0, 0, 7, { 0 }},+ { 195, 0, 0, 7, { 0 }},+ { 196, 0, 1, 7, { 0 }},+ { 197, 0, 0, 7, { 0 }},+ { 198, 0, 3, 11, { 0 }},+ { 199, 0, 3, 7, { 0 }},+ { 200, 0, 0, 7, { 0 }},+ { 201, 0, 0, 7, { 0 }},+ { 202, 0, 0, 7, { 0 }},+ { 203, 0, 1, 7, { 0 }},+ { 204, -1, 0, 3, { 0 }},+ { 205, 0, 0, 3, { 0 }},+ { 206, -1, 0, 3, { 0 }},+ { 207, -1, 1, 3, { 0 }},+ { 208, 0, 3, 9, { 0 }},+ { 209, 0, 0, 7, { 0 }},+ { 210, 0, 0, 7, { 0 }},+ { 211, 0, 0, 7, { 0 }},+ { 212, 0, 0, 7, { 0 }},+ { 213, 0, 0, 7, { 0 }},+ { 214, 0, 1, 7, { 0 }},+ { 215, 0, 7, 6, { 0 }},+ { 216, 0, 3, 10, { 0 }},+ { 217, 0, 0, 7, { 0 }},+ { 218, 0, 0, 7, { 0 }},+ { 219, 0, 0, 7, { 0 }},+ { 220, 0, 1, 7, { 0 }},+ { 221, 0, 0, 7, { 0 }},+ { 222, 0, 0, 7, { 0 }},+ { 223, 0, 3, 7, { 0 }},+ { 224, 0, 2, 7, { 0 }},+ { 225, 0, 2, 7, { 0 }},+ { 226, 0, 2, 7, { 0 }},+ { 227, 0, 2, 7, { 0 }},+ { 228, 0, 3, 7, { 0 }},+ { 229, 0, 1, 7, { 0 }},+ { 230, 0, 5, 11, { 0 }},+ { 231, 0, 5, 7, { 0 }},+ { 232, 0, 2, 7, { 0 }},+ { 233, 0, 2, 7, { 0 }},+ { 234, 0, 2, 7, { 0 }},+ { 235, 0, 3, 7, { 0 }},+ { 236, 0, 2, 4, { 0 }},+ { 237, 0, 2, 4, { 0 }},+ { 238, 0, 2, 4, { 0 }},+ { 239, 0, 3, 4, { 0 }},+ { 240, 0, 0, 7, { 0 }},+ { 241, 0, 2, 7, { 0 }},+ { 242, 0, 2, 7, { 0 }},+ { 243, 0, 2, 7, { 0 }},+ { 244, 0, 2, 7, { 0 }},+ { 245, 0, 2, 7, { 0 }},+ { 246, 0, 3, 7, { 0 }},+ { 247, 0, 0, 7, { 0 }},+ { 248, 0, 5, 9, { 0 }},+ { 249, 0, 2, 7, { 0 }},+ { 250, 0, 2, 7, { 0 }},+ { 251, 0, 2, 7, { 0 }},+ { 252, 0, 3, 7, { 0 }},+ { 253, 0, 2, 7, { 0 }},+ { 254, 0, 0, 7, { 0 }},+ { 255, 0, 3, 7, { 0 }},+};++// Style loading function: Candy+static void GuiLoadStyleCandy(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < CANDY_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(candyStyleProps[i].controlId, candyStyleProps[i].propertyId, candyStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int candyFontDataSize = 0;+ unsigned char *data = DecompressData(candyFontData, CANDY_STYLE_FONT_ATLAS_COMP_SIZE, &candyFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 15;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, candyFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, candyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/cherry/style_cherry.h view
@@ -0,0 +1,617 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleCherry(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define CHERRY_STYLE_PROPS_COUNT 17++// Custom style name: Cherry+static const GuiStyleProp cherryStyleProps[CHERRY_STYLE_PROPS_COUNT] = {+ { 0, 0, 0xda5757ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x753233ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xe17373ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xfaaa97ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xe06262ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xfdb4aaff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xe03c46ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0x5b1e20ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0xc2474fff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0xa19292ff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x706060ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x9e8585ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x0000000f }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0xfb8170ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x3a1720ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000016 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "Westington.ttf" (size: 15, spacing: 0)++#define CHERRY_STYLE_FONT_ATLAS_COMP_SIZE 2821++// Font atlas image pixels data: DEFLATE compressed+static unsigned char cherryFontData[CHERRY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x59, 0x92, 0xdc, 0xba, 0x11, 0x05, 0x50, 0xee, 0x7f, 0xd3, 0xd7, 0xe1, 0x70, 0x84, 0xed, 0x27, 0xa9, 0x09, 0x20,+ 0x91, 0x20, 0xab, 0x5b, 0x47, 0xe7, 0xaf, 0xa1, 0x1a, 0x38, 0x24, 0x26, 0x16, 0x12, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xf2,+ 0xef, 0x7f, 0x5f, 0xfd, 0xf5, 0xcf, 0x65, 0xff, 0xff, 0xaa, 0xdc, 0xbe, 0x73, 0xfd, 0xb3, 0xb3, 0xf8, 0xae, 0x59, 0xf8,+ 0x7f, 0xf9, 0xf2, 0xbb, 0x64, 0xfa, 0x33, 0xd7, 0x8f, 0x7b, 0xfd, 0x58, 0xef, 0xce, 0xfd, 0xfa, 0x31, 0x5c, 0x37, 0x9f,+ 0xbf, 0xf6, 0xdd, 0x2a, 0xaf, 0xb9, 0x2f, 0x59, 0xbf, 0x7b, 0x3a, 0xae, 0xc8, 0xdc, 0x35, 0xb8, 0x3f, 0xa7, 0xd7, 0xf0,+ 0x95, 0xeb, 0xef, 0x9c, 0xe1, 0x59, 0x1c, 0x7f, 0xab, 0xb5, 0x1a, 0xe0, 0xeb, 0xbf, 0x8e, 0xee, 0xa6, 0x14, 0xee, 0xab,+ 0xff, 0xbd, 0x22, 0x8b, 0x65, 0xa3, 0xd7, 0xec, 0xdd, 0x57, 0x59, 0xa8, 0xa5, 0x2a, 0x57, 0x21, 0x8b, 0xe7, 0x61, 0xf5,+ 0xdc, 0xa5, 0x54, 0xff, 0x8c, 0xbe, 0x6d, 0x5a, 0x8e, 0xe7, 0xae, 0x24, 0xd3, 0x7f, 0x1d, 0xbf, 0xa2, 0xf2, 0x6e, 0x33,+ 0xf7, 0xd5, 0xdd, 0xab, 0xfb, 0xdf, 0x39, 0x53, 0xf7, 0xef, 0xd9, 0xf8, 0x1f, 0xd5, 0x97, 0xf7, 0xe7, 0xfb, 0xee, 0x28,+ 0xf2, 0xdf, 0xde, 0x45, 0xed, 0xbe, 0xdb, 0x89, 0xf4, 0xdc, 0xdc, 0x9d, 0x29, 0x9e, 0x8d, 0xfa, 0xff, 0xbb, 0x8f, 0x97,+ 0x14, 0x7b, 0x5e, 0x59, 0xb8, 0x4f, 0xb3, 0x54, 0xeb, 0xcd, 0xf4, 0x26, 0x2a, 0x35, 0xdd, 0x6e, 0x2f, 0x6a, 0xbf, 0xa7,+ 0xfb, 0xf5, 0x35, 0xb8, 0x3b, 0xdf, 0x99, 0x3c, 0x82, 0x94, 0xe2, 0xff, 0x5a, 0xac, 0xb1, 0x9f, 0x8a, 0xff, 0x71, 0xac,+ 0x8c, 0xe2, 0x29, 0xc3, 0x2b, 0x9c, 0x96, 0xef, 0x9f, 0x52, 0x8d, 0x76, 0x6a, 0x9c, 0x55, 0xbf, 0x7f, 0x66, 0xcf, 0x5e,+ 0x06, 0xa3, 0xb9, 0xee, 0x5e, 0xe8, 0x7c, 0xaf, 0x2f, 0xc5, 0xda, 0x75, 0xa5, 0x8f, 0x9f, 0xad, 0xde, 0xfa, 0x28, 0x7e,+ 0xb3, 0x5c, 0x17, 0x67, 0xa2, 0x3f, 0x74, 0xa2, 0x4f, 0xf2, 0x09, 0xf1, 0x9f, 0xc2, 0x08, 0xae, 0x5a, 0xc7, 0xa7, 0xa9,+ 0x6d, 0xce, 0xa1, 0xfa, 0xb5, 0x3b, 0xfe, 0xd7, 0xcb, 0xc6, 0x91, 0x91, 0xd6, 0x71, 0x58, 0x4a, 0x23, 0xe9, 0x7a, 0x1b,+ 0xbe, 0xfb, 0xda, 0xbb, 0xb9, 0xa2, 0x4c, 0xd4, 0x9e, 0x59, 0x9e, 0x01, 0xd8, 0x89, 0xff, 0xfe, 0xf1, 0x7f, 0x4a, 0xaf,+ 0x98, 0xab, 0x8d, 0x6b, 0x35, 0x71, 0x16, 0xbe, 0x59, 0x9a, 0x6a, 0xb6, 0x1c, 0x9d, 0x65, 0xbd, 0x1a, 0xe3, 0xbf, 0x36,+ 0x72, 0x4a, 0xdb, 0xdc, 0x44, 0x7d, 0xec, 0x96, 0xa6, 0xfb, 0x35, 0xad, 0xaf, 0xb8, 0x8f, 0xff, 0xbb, 0xf6, 0x7f, 0xbf,+ 0xff, 0xff, 0x7e, 0xfb, 0xdf, 0x3d, 0xfa, 0x9f, 0x9f, 0xc5, 0x18, 0x9f, 0xd3, 0xe7, 0xe2, 0xff, 0x64, 0xdf, 0xbf, 0x36,+ 0x96, 0x4f, 0x71, 0x9e, 0x32, 0x4d, 0x23, 0xf6, 0x94, 0x47, 0xe7, 0x69, 0x99, 0xd5, 0xe9, 0xab, 0xab, 0x53, 0xfe, 0x8c,+ 0xfa, 0x3c, 0xf6, 0x4f, 0x1d, 0xff, 0x67, 0xe9, 0xd9, 0xc0, 0xb8, 0x6f, 0x75, 0x77, 0x66, 0xd2, 0x3e, 0xff, 0xf7, 0xde,+ 0x53, 0xd6, 0xb5, 0x5a, 0x27, 0x85, 0x31, 0x76, 0x65, 0xd6, 0xbc, 0xfa, 0x34, 0xb1, 0xf3, 0xd9, 0xe4, 0xfb, 0xd7, 0xa9,+ 0x3a, 0xd7, 0x98, 0x72, 0xed, 0x9e, 0x89, 0x67, 0x3f, 0xeb, 0xb3, 0x0a, 0x4f, 0xf5, 0xa6, 0x66, 0xe6, 0x62, 0xae, 0xe2,+ 0xbc, 0x69, 0x0a, 0x3d, 0x9c, 0x4f, 0x8f, 0xff, 0x4f, 0xaa, 0x89, 0x3e, 0xf1, 0xf7, 0x27, 0x69, 0x1e, 0xe9, 0x77, 0x45,+ 0x40, 0x26, 0x46, 0xe2, 0x57, 0xa1, 0x9e, 0xfe, 0x0e, 0xcf, 0xff, 0xc7, 0xf1, 0x5f, 0x1d, 0xff, 0x67, 0xea, 0xf7, 0x18,+ 0x6b, 0xcf, 0x01, 0xf2, 0xe1, 0xad, 0xbf, 0x1a, 0xa0, 0x67, 0x4e, 0xfe, 0xe9, 0xfa, 0x39, 0x87, 0xc7, 0x85, 0x7f, 0xe3,+ 0x75, 0x05, 0xf7, 0x0f, 0x20, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x5e, 0x37,+ 0xb8, 0xbe, 0x16, 0xb1, 0x3b, 0x4b, 0x6b, 0xe5, 0xfd, 0x7e, 0x2f, 0x1d, 0xbd, 0x47, 0xf5, 0x68, 0x2b, 0xb9, 0xa0, 0x33,+ 0xf5, 0xdd, 0xb3, 0xbc, 0xa2, 0x73, 0x74, 0x34, 0xf9, 0xc7, 0x1a, 0xd5, 0x99, 0x73, 0xba, 0x73, 0x5d, 0xc6, 0x99, 0x77,+ 0x57, 0xf2, 0xfb, 0xae, 0xad, 0x06, 0x5e, 0x5d, 0x21, 0xd0, 0x99, 0xed, 0x60, 0xf6, 0xfa, 0x56, 0xee, 0xa8, 0x95, 0x4f,+ 0xdb, 0x59, 0x8b, 0x78, 0x9f, 0x81, 0xf9, 0x1a, 0x66, 0x88, 0xee, 0xca, 0x51, 0x97, 0x8d, 0x35, 0xfb, 0xbf, 0xdf, 0xc9,+ 0x95, 0x55, 0xdb, 0xe3, 0x7b, 0xaa, 0x92, 0x77, 0xa9, 0x9a, 0xb3, 0x39, 0x2d, 0x9f, 0x3b, 0xf3, 0xcd, 0xe6, 0x32, 0xfa,+ 0xd4, 0x33, 0xb6, 0x5f, 0x8b, 0xfb, 0x30, 0xac, 0xad, 0xe5, 0xce, 0xf2, 0x5a, 0xf8, 0xb4, 0xe5, 0x8b, 0x48, 0xf1, 0x3d,+ 0x6b, 0xf7, 0xda, 0x99, 0xec, 0x3f, 0xd5, 0x2c, 0x59, 0x67, 0xe2, 0x3f, 0xe5, 0xef, 0x92, 0xdb, 0x7b, 0xe2, 0x1a, 0x66,+ 0x28, 0xaa, 0x66, 0x5e, 0xca, 0x46, 0xbd, 0x96, 0x8d, 0xb5, 0xee, 0x5d, 0xf1, 0xbf, 0x13, 0xe1, 0xb3, 0xf9, 0x7b, 0xd3,+ 0xb2, 0xba, 0x7f, 0x25, 0x1b, 0x7a, 0xb5, 0x1f, 0xdc, 0x19, 0x21, 0x77, 0xc7, 0x9e, 0x8d, 0x33, 0x73, 0x26, 0xfe, 0xf3,+ 0x01, 0xf1, 0xbf, 0x53, 0x17, 0x7d, 0xcf, 0xf8, 0x4f, 0x43, 0xed, 0x9c, 0xd2, 0x15, 0xfa, 0x3d, 0x76, 0x2b, 0x7b, 0x59,+ 0x5c, 0xe5, 0x8c, 0xce, 0x69, 0x6e, 0x8f, 0x3a, 0xd6, 0x14, 0x3f, 0x19, 0xff, 0xeb, 0xf5, 0xcd, 0xa9, 0xf8, 0xbf, 0xdb,+ 0xad, 0x23, 0xa5, 0xdd, 0x9e, 0xfa, 0xf6, 0xc1, 0x5a, 0xa9, 0x8b, 0x32, 0x9d, 0x5b, 0xb4, 0x12, 0xff, 0x19, 0xee, 0xa0,+ 0x51, 0xd9, 0xb7, 0xa0, 0x9a, 0x0d, 0xb9, 0x23, 0xfe, 0xe7, 0xf3, 0x9b, 0x67, 0xb2, 0xee, 0xed, 0x88, 0xf3, 0x77, 0xe2,+ 0x7f, 0x74, 0x05, 0x53, 0xcc, 0xd6, 0xb7, 0x9e, 0xe5, 0x7b, 0xfc, 0x69, 0xbd, 0x59, 0xd4, 0x67, 0xf6, 0x9a, 0xc9, 0x37,+ 0x68, 0xff, 0xcf, 0xc7, 0x7f, 0xe5, 0x5d, 0x67, 0xe7, 0x66, 0xf2, 0x5a, 0xfc, 0x67, 0xbb, 0x85, 0x4f, 0xf3, 0xe8, 0xf2,+ 0x8d, 0xbc, 0x5f, 0x33, 0xf3, 0x05, 0xb5, 0x18, 0x4f, 0xeb, 0x78, 0xa3, 0xf6, 0x69, 0x27, 0x7a, 0x98, 0xeb, 0xf1, 0x9f,+ 0xa3, 0xe3, 0xff, 0x95, 0x4f, 0xa8, 0xf7, 0xff, 0xef, 0x3e, 0xbb, 0x77, 0xfe, 0xaf, 0x6b, 0xee, 0x69, 0xa6, 0xed, 0x4e,+ 0x43, 0x2f, 0xe2, 0x7c, 0xcd, 0x90, 0xd7, 0x9e, 0x91, 0x55, 0x3e, 0xff, 0x44, 0x44, 0x56, 0x63, 0xab, 0x1a, 0xff, 0xbd,+ 0xf3, 0xff, 0x1d, 0xf3, 0xcc, 0x73, 0x47, 0x9f, 0x42, 0xa4, 0xa6, 0x38, 0xbe, 0xca, 0xd6, 0x0c, 0x79, 0x36, 0xe2, 0x3f,+ 0x0d, 0xf1, 0x7f, 0xf7, 0xfc, 0x6e, 0x37, 0xfe, 0x33, 0x78, 0xbe, 0x91, 0x6f, 0x13, 0xff, 0x29, 0xc5, 0x7f, 0x9a, 0x23,+ 0x32, 0xe5, 0xd8, 0xba, 0x96, 0x9f, 0x4f, 0x9e, 0x79, 0xfe, 0x3f, 0x7e, 0xca, 0xba, 0xf3, 0x24, 0x79, 0xf6, 0x3b, 0xd5,+ 0x7f, 0xed, 0x30, 0x3a, 0x4b, 0x59, 0x8e, 0xb0, 0x94, 0x72, 0xf3, 0xcf, 0x8f, 0xf9, 0xb2, 0xd9, 0x4a, 0x8d, 0x6b, 0x88,+ 0x6a, 0x4e, 0xea, 0xd5, 0x7d, 0xd5, 0xf3, 0xfa, 0xbe, 0x36, 0xcf, 0xbc, 0x72, 0x67, 0xaf, 0x06, 0x39, 0x89, 0xf9, 0x19,+ 0xbf, 0x49, 0x73, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0x60,+ 0xa6, 0x94, 0xd5, 0x6b, 0xf6, 0x7f, 0x55, 0x73, 0x90, 0xe5, 0x36, 0xcb, 0xf4, 0xda, 0x5a, 0xdf, 0x0c, 0x8f, 0xb1, 0x63,+ 0xa5, 0xf4, 0xd9, 0x2c, 0xdc, 0xf3, 0xe7, 0xb6, 0x76, 0xf5, 0xb3, 0x98, 0xcf, 0x32, 0xed, 0x2b, 0xd3, 0xc7, 0xeb, 0xad,+ 0xef, 0xd7, 0xd0, 0xd7, 0x5f, 0x77, 0x15, 0x56, 0x38, 0xaf, 0x5e, 0xad, 0x99, 0x5c, 0xf1, 0x6f, 0xd4, 0x15, 0xd7, 0x44,+ 0x86, 0xbb, 0x9d, 0x1c, 0xfa, 0x77, 0xe7, 0xfe, 0xeb, 0xfb, 0xf5, 0xee, 0x7b, 0xf5, 0xe5, 0x2d, 0xbc, 0xb6, 0x33, 0xe8,+ 0x5e, 0x8f, 0x64, 0xe1, 0xce, 0xe2, 0x7d, 0x38, 0xfb, 0x3f, 0x47, 0x59, 0x04, 0x53, 0xc8, 0xf4, 0x71, 0xee, 0x78, 0x67,+ 0xf2, 0x3f, 0x8d, 0xf2, 0x3c, 0xfe, 0xf9, 0xef, 0x2b, 0xf7, 0x53, 0x2d, 0x67, 0x72, 0x06, 0xb9, 0x24, 0x7b, 0xd7, 0x5a,+ 0xe7, 0xf6, 0x5e, 0x5d, 0xef, 0x47, 0x9c, 0xb9, 0xa2, 0xf5, 0xf8, 0x5f, 0x6f, 0x77, 0x4e, 0xc5, 0xff, 0x7e, 0x16, 0xde,+ 0x9d, 0x1c, 0x3d, 0xfb, 0x7f, 0xbf, 0x6f, 0xfd, 0xaf, 0xe5, 0xde, 0xd9, 0xb5, 0x95, 0xeb, 0x76, 0x9c, 0x09, 0x67, 0x9c,+ 0x61, 0x6a, 0xf5, 0x38, 0xae, 0xc5, 0xfc, 0xce, 0x9f, 0x13, 0xff, 0x57, 0x29, 0xfe, 0xaf, 0x0f, 0x8a, 0xff, 0xbb, 0x76,+ 0xe7, 0x2a, 0xee, 0x27, 0x72, 0xd7, 0x33, 0xbb, 0x1a, 0xdb, 0x9c, 0xdf, 0x6b, 0xd5, 0x94, 0xfa, 0xc3, 0x29, 0x67, 0x4f,+ 0x7c, 0x2b, 0x07, 0xd7, 0x78, 0x77, 0x93, 0x71, 0xdf, 0xbf, 0x56, 0x53, 0xd6, 0x32, 0x31, 0xdd, 0x8f, 0x28, 0xb2, 0xb4,+ 0x3b, 0x41, 0x3d, 0x2f, 0x58, 0x0e, 0x64, 0x47, 0x59, 0xad, 0xe9, 0x53, 0xe8, 0xff, 0x5f, 0x5b, 0xfb, 0x48, 0x54, 0xf3,+ 0x1e, 0xd7, 0x72, 0xac, 0xa7, 0xd0, 0xee, 0xcc, 0xc4, 0xdf, 0x5e, 0x16, 0xde, 0x4c, 0x8e, 0xb2, 0xae, 0xc5, 0x3a, 0xf2,+ 0x6a, 0xab, 0x31, 0xd6, 0x7a, 0x98, 0xd9, 0x1a, 0x6d, 0xcd, 0xd4, 0x0d, 0x59, 0xdc, 0xab, 0xa1, 0xde, 0x5e, 0x54, 0xf2,+ 0xc9, 0xd5, 0x6b, 0x80, 0xbc, 0x36, 0xff, 0x77, 0x15, 0x32, 0xd5, 0xaf, 0xe5, 0xe6, 0xab, 0xcc, 0xbd, 0x55, 0x8e, 0xaf,+ 0x96, 0x73, 0x6f, 0x26, 0x6b, 0x7b, 0x4f, 0xfe, 0xe2, 0xd5, 0xf3, 0x73, 0x4d, 0xcd, 0x6a, 0xe5, 0xa5, 0xf6, 0x7f, 0x3d,+ 0x02, 0xe6, 0x76, 0xa5, 0xdc, 0xe9, 0xd5, 0x54, 0x33, 0x76, 0xf7, 0xf7, 0x7e, 0xde, 0x9f, 0xff, 0x5f, 0xcb, 0xe0, 0xfd,+ 0x59, 0xd9, 0x59, 0xd3, 0xf0, 0x3f, 0xfa, 0x3e, 0xeb, 0xed, 0x67, 0x38, 0x39, 0x5a, 0xfb, 0xf7, 0xc6, 0x7f, 0x8a, 0xe3,+ 0xc9, 0xd9, 0x7a, 0x38, 0x4b, 0x39, 0x87, 0xc7, 0xf3, 0x5b, 0xe7, 0xc6, 0x3f, 0x9f, 0x78, 0x3f, 0xed, 0xe4, 0xb2, 0x7f,+ 0xf6, 0x7b, 0xe6, 0xb1, 0x1e, 0xd3, 0x89, 0xd9, 0x97, 0xe7, 0xce, 0xc4, 0xda, 0x31, 0xa5, 0xf1, 0x8e, 0xad, 0xcd, 0xff,+ 0x65, 0x63, 0x8e, 0x6f, 0x77, 0xbf, 0xde, 0x14, 0x66, 0x15, 0xff, 0x86, 0x5f, 0x0a, 0x7c, 0x3d, 0x03, 0x91, 0xbf, 0x22,+ 0xf7, 0xf0, 0x4f, 0x3c, 0xc6, 0x8e, 0xe7, 0xff, 0xd5, 0x7e, 0x53, 0x6d, 0xe7, 0x80, 0xb9, 0x79, 0x9f, 0xca, 0xfc, 0x6e,+ 0x75, 0xcc, 0x08, 0x54, 0x9e, 0x31, 0x57, 0x76, 0x0e, 0xe8, 0x18, 0xc1, 0x65, 0xf9, 0xf9, 0x3f, 0xf0, 0x53, 0x6a, 0xa2,+ 0xda, 0xbc, 0x22, 0xf0, 0xfd, 0x47, 0x3b, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,+ 0x9e, 0xbf, 0x88, 0x5e, 0x5f, 0xeb, 0xba, 0x9e, 0xeb, 0xb0, 0x9e, 0x71, 0x65, 0x76, 0x7d, 0xea, 0x55, 0xca, 0x1a, 0xb9,+ 0x97, 0x9b, 0x66, 0x2e, 0x5b, 0x73, 0x3d, 0x5b, 0x5d, 0x35, 0x43, 0xd6, 0x5e, 0xe9, 0xf8, 0x95, 0xf5, 0x57, 0x5f, 0xd3,+ 0xe7, 0x2d, 0xaf, 0x1c, 0x77, 0x16, 0x73, 0x18, 0xac, 0xdc, 0x53, 0xfd, 0xc7, 0xba, 0x77, 0x2e, 0xae, 0x62, 0x46, 0x9f,+ 0x4a, 0xb6, 0xe3, 0x4a, 0xbc, 0xde, 0xe5, 0x3b, 0xcd, 0xe2, 0x67, 0x65, 0x39, 0xa7, 0xf3, 0xa8, 0x16, 0xc9, 0x60, 0xc5,+ 0x68, 0x26, 0xd6, 0x9c, 0xee, 0xe5, 0x1b, 0xa8, 0x96, 0x8d, 0xaf, 0x7a, 0x3d, 0xcf, 0x49, 0x16, 0xeb, 0x8f, 0xb5, 0x1c,+ 0x7d, 0x27, 0x8f, 0x7b, 0x7d, 0x0d, 0x73, 0x96, 0x73, 0x64, 0x5d, 0x8b, 0xad, 0x4d, 0x26, 0xda, 0x87, 0xea, 0xb9, 0x98,+ 0x6d, 0x01, 0x57, 0xdb, 0xcd, 0xd5, 0x9a, 0xa4, 0x1a, 0xff, 0xd5, 0xcf, 0x3a, 0x13, 0xff, 0x77, 0xc7, 0x96, 0xdb, 0x9c,+ 0x13, 0xd9, 0xcc, 0x6f, 0xf8, 0x6c, 0xaf, 0xb0, 0xa7, 0xfd, 0x4d, 0x71, 0x8d, 0xfe, 0xf9, 0x75, 0x81, 0xa7, 0x56, 0x07,+ 0xd6, 0x73, 0x47, 0xbf, 0x71, 0x0f, 0xa4, 0x2d, 0x6b, 0xe4, 0x5c, 0x3e, 0xd6, 0xf5, 0xf8, 0x5f, 0x1d, 0x2f, 0xac, 0xe6,+ 0x33, 0xcc, 0x44, 0xeb, 0x34, 0xdb, 0xfe, 0x67, 0xeb, 0xea, 0x3f, 0xdf, 0xff, 0xbf, 0x36, 0xda, 0xd0, 0xb9, 0xd1, 0xc1,+ 0x6c, 0x1e, 0x8e, 0xd5, 0xbb, 0xa9, 0x5e, 0x3a, 0xce, 0x0d, 0xbc, 0xf7, 0xd7, 0xf1, 0xfd, 0x77, 0xf7, 0x4e, 0x95, 0x91,+ 0x52, 0xb6, 0x33, 0x36, 0x65, 0xf9, 0x6c, 0xdc, 0x1f, 0xf5, 0x7a, 0xce, 0xe5, 0xd5, 0xf8, 0x1f, 0xd5, 0x26, 0x6b, 0x23,+ 0xb8, 0x71, 0xfb, 0x3f, 0x93, 0x6b, 0x72, 0x6f, 0xb7, 0x8a, 0x1c, 0x89, 0xc3, 0x7a, 0xe9, 0xce, 0x4e, 0x27, 0x7f, 0xaa,+ 0x13, 0x53, 0xae, 0x99, 0x72, 0xac, 0xf4, 0xc4, 0xf8, 0x7f, 0x9c, 0x71, 0x24, 0x85, 0x7c, 0x25, 0x3b, 0xa3, 0xa8, 0xdd,+ 0xf6, 0xa5, 0xe3, 0xdd, 0xb2, 0xb5, 0x97, 0xc3, 0xb9, 0x6f, 0xdd, 0x31, 0xfe, 0x3f, 0x3b, 0xff, 0xb7, 0xbf, 0xe3, 0x58,+ 0xcf, 0x6e, 0x45, 0xab, 0xb5, 0xd9, 0xaf, 0xe7, 0x22, 0x1f, 0xd2, 0xab, 0xa9, 0xd5, 0x0e, 0xfb, 0x7f, 0x1d, 0xcf, 0x59,+ 0xe7, 0xa5, 0xf8, 0xef, 0x1d, 0x09, 0xe5, 0xc0, 0xfc, 0xe4, 0xf3, 0xd1, 0xbf, 0x32, 0xfe, 0xef, 0x98, 0x31, 0xab, 0xee,+ 0x38, 0x72, 0xb6, 0xb4, 0xb2, 0xe3, 0xea, 0xfc, 0x3d, 0xf9, 0x44, 0x0b, 0xdf, 0xb5, 0x4f, 0xc2, 0x4f, 0x8d, 0xff, 0x37,+ 0xf7, 0x18, 0xd9, 0x89, 0xff, 0xf3, 0x59, 0x9a, 0xf3, 0x87, 0x79, 0xbd, 0xdd, 0x4f, 0x1c, 0xed, 0x11, 0x9b, 0xf6, 0x38,+ 0xdc, 0x8f, 0xe1, 0x9d, 0xd2, 0xb9, 0x7d, 0x78, 0x6a, 0x51, 0xba, 0x53, 0xfa, 0x56, 0xfb, 0x3f, 0x33, 0x0b, 0xf5, 0x74,+ 0xfc, 0x77, 0xce, 0x86, 0xe6, 0x50, 0xeb, 0xb8, 0x3e, 0x9a, 0xe8, 0x9f, 0x1b, 0xed, 0xf8, 0xc4, 0x6a, 0xcb, 0xf0, 0x4e,+ 0xff, 0xbf, 0xfe, 0xfb, 0x8b, 0x7f, 0xce, 0x66, 0xa5, 0x38, 0xab, 0xf5, 0x93, 0xc6, 0xff, 0xd7, 0xd4, 0xae, 0x51, 0x79,+ 0x69, 0xfc, 0xff, 0x19, 0xaf, 0xff, 0x7b, 0x7f, 0x81, 0x75, 0x1d, 0x6e, 0x87, 0x9f, 0x2e, 0x3d, 0xdf, 0x63, 0xdc, 0x2b,+ 0xcd, 0x2b, 0xed, 0xff, 0xdc, 0x48, 0xf4, 0xbd, 0xf8, 0xef, 0xea, 0x2f, 0xab, 0x09, 0x3a, 0xe7, 0x59, 0xde, 0x6d, 0xc3,+ 0x6b, 0xbb, 0x38, 0xee, 0xfd, 0xda, 0x66, 0x76, 0x74, 0x50, 0x2b, 0xcd, 0xe1, 0xf1, 0xff, 0xee, 0x55, 0xae, 0x1c, 0xcf,+ 0xa7, 0xc4, 0xbf, 0xbc, 0xea, 0xa7, 0xea, 0x8c, 0x4a, 0x1c, 0x3e, 0x15, 0xc3, 0xcf, 0xdf, 0x4d, 0x7b, 0xcf, 0xff, 0xd7,+ 0xeb, 0xe8, 0xb5, 0xe7, 0xff, 0x3b, 0x2d, 0xc3, 0xd3, 0xcf, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x80, 0xef, 0xb7, 0xfe, 0x6c, 0x9c, 0x99, 0xa6, 0x9e, 0xd5, 0x7b, 0x37, 0x2b, 0xc0, 0xde, 0x11, 0xa5, 0xb4, 0xf6,+ 0x6c, 0x36, 0xb7, 0x75, 0xf7, 0xfa, 0xb4, 0x7a, 0x7e, 0xf0, 0x6c, 0xac, 0x3a, 0xac, 0xff, 0xba, 0xfc, 0xd4, 0x71, 0x9e,+ 0xca, 0xc2, 0x55, 0xb9, 0x1f, 0x9e, 0xbb, 0x96, 0x69, 0xbf, 0xc2, 0xb3, 0xef, 0x51, 0xcd, 0x05, 0x9d, 0xa5, 0x1c, 0x10,+ 0xab, 0x71, 0x96, 0xcd, 0x0c, 0xf5, 0xf5, 0xb5, 0x67, 0xb3, 0xb5, 0x4e, 0x6f, 0xe6, 0xea, 0x6c, 0xe4, 0x87, 0xae, 0x9f,+ 0xa3, 0x9d, 0xd5, 0xa5, 0xdd, 0xc7, 0xb9, 0x7e, 0xc5, 0x3a, 0x72, 0x73, 0x67, 0xe3, 0xcc, 0x67, 0xf9, 0xcc, 0x64, 0x50,+ 0x3b, 0xe5, 0x91, 0x75, 0xa5, 0xbd, 0x99, 0x0b, 0x56, 0x57, 0x34, 0x3e, 0xb7, 0xd6, 0xb6, 0xbe, 0x0a, 0x6c, 0x37, 0xbf,+ 0xd5, 0x73, 0xfd, 0xb7, 0x6a, 0x5f, 0xe4, 0xd7, 0xa3, 0xcc, 0x07, 0xe4, 0x74, 0x38, 0xbb, 0x9a, 0xed, 0xcc, 0x5e, 0x23,+ 0xe7, 0xbf, 0xe1, 0xde, 0xde, 0x21, 0x3b, 0x6b, 0x08, 0x53, 0xec, 0x51, 0x8d, 0x32, 0x1a, 0xdc, 0xc7, 0xe7, 0x6e, 0xf9,+ 0x5c, 0x0e, 0xb8, 0x6b, 0x22, 0x33, 0x6d, 0x0a, 0xd9, 0x2f, 0x32, 0x58, 0xd7, 0xde, 0x5d, 0x56, 0xbb, 0x47, 0x67, 0xf2,+ 0x96, 0xe7, 0xc0, 0x1d, 0x75, 0xbd, 0x98, 0x9b, 0xeb, 0x5a, 0x6e, 0x93, 0x53, 0x6c, 0x7b, 0x3b, 0x4b, 0x3a, 0xea, 0xe7,+ 0x6a, 0x2f, 0x6f, 0xa6, 0x6c, 0x3d, 0xa3, 0xe1, 0x4c, 0xcf, 0xf2, 0x99, 0xf2, 0xf5, 0x5c, 0xe6, 0xb3, 0xd9, 0x6f, 0xf2,+ 0x58, 0x59, 0xca, 0x77, 0xdb, 0x35, 0x91, 0x87, 0xff, 0xd4, 0x5d, 0xf3, 0x7c, 0x36, 0x8b, 0x4a, 0x0d, 0x5a, 0xcb, 0x91,+ 0xf8, 0x5c, 0xc9, 0x6c, 0xae, 0x83, 0x13, 0x57, 0xeb, 0x2a, 0xde, 0x39, 0x9f, 0x11, 0xff, 0xb9, 0xbd, 0xe6, 0xd7, 0x56,+ 0xdd, 0xd6, 0xdd, 0x2e, 0xce, 0xb4, 0x99, 0xf5, 0x7a, 0xa3, 0xfa, 0xb9, 0xb5, 0xac, 0x34, 0x73, 0xd9, 0x79, 0xae, 0xe9,+ 0x91, 0x7e, 0x65, 0x8f, 0xca, 0x95, 0x4f, 0xad, 0xb4, 0x03, 0x4f, 0x95, 0x54, 0x46, 0x30, 0x4f, 0xc5, 0xff, 0x67, 0xb4,+ 0xef, 0xb5, 0xdd, 0x0d, 0xc7, 0xe3, 0xff, 0x94, 0x7b, 0x45, 0xfd, 0x65, 0x29, 0xcf, 0xde, 0x74, 0xcc, 0x0b, 0xa5, 0xb5,+ 0xec, 0x6a, 0x9a, 0x9f, 0xaf, 0xec, 0x66, 0xf7, 0xb9, 0xf1, 0x5f, 0xdd, 0x3b, 0xe6, 0xad, 0xf8, 0xcf, 0xc7, 0xb7, 0xff,+ 0xeb, 0xbb, 0x9b, 0xfe, 0xf9, 0x19, 0x55, 0x4a, 0x3d, 0x8b, 0xce, 0xb2, 0xab, 0xb8, 0xef, 0xda, 0x6e, 0xaf, 0xf9, 0xc4,+ 0xf8, 0x66, 0x36, 0x27, 0xf0, 0x93, 0xf1, 0x5f, 0xb9, 0x2a, 0xbd, 0x25, 0xbb, 0x33, 0x43, 0x6f, 0xb4, 0xff, 0xf3, 0xcf,+ 0x0d, 0xde, 0x8a, 0xff, 0xea, 0xf3, 0xff, 0x99, 0xbd, 0x3c, 0x4f, 0xb4, 0x8c, 0x95, 0x96, 0xfc, 0xec, 0x3e, 0x09, 0x27,+ 0xc6, 0x39, 0xa7, 0xdb, 0xff, 0xca, 0x78, 0xe4, 0x1a, 0xee, 0xfc, 0x7e, 0xba, 0xe4, 0xda, 0x9e, 0xf9, 0xfd, 0xb4, 0x19,+ 0x99, 0xa7, 0xc6, 0xf7, 0x9f, 0xb5, 0xdf, 0xea, 0xf5, 0xda, 0xf3, 0xb4, 0x9f, 0x70, 0xac, 0x1d, 0x33, 0x00, 0xcf, 0x3f,+ 0x73, 0xfc, 0xb4, 0x73, 0x57, 0xdd, 0x89, 0xe5, 0xb9, 0xef, 0xd3, 0x51, 0x3e, 0xf3, 0xbd, 0xe5, 0x4c, 0xe5, 0x6f, 0xfa,+ 0xf5, 0xef, 0x67, 0xe5, 0x10, 0x1e, 0xff, 0x86, 0x76, 0xaf, 0xfc, 0xb9, 0xdf, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa9, 0xdf, 0xde, 0xd7, 0xd7, 0xbd, 0x57, 0xd7, 0x7c, 0xf7, 0x67, 0xe2, 0x8e, 0x35,+ 0x3c, 0xd0, 0xb6, 0x16, 0x34, 0x93, 0xb9, 0xe0, 0xba, 0x63, 0x31, 0x5b, 0x99, 0x4d, 0x80, 0xf9, 0x36, 0xff, 0x8d, 0x75,+ 0x7e, 0xd5, 0xcf, 0xcd, 0x30, 0xf3, 0x82, 0x55, 0x7c, 0x30, 0x1f, 0xff, 0x19, 0xe6, 0x32, 0xea, 0x2e, 0xbd, 0x26, 0xb2,+ 0x0b, 0x5c, 0x85, 0xfc, 0x55, 0xd1, 0x47, 0x80, 0xa5, 0xf8, 0x9f, 0xc9, 0xc8, 0xfd, 0x49, 0xa5, 0x29, 0xef, 0x3e, 0x06,+ 0xfc, 0x79, 0x94, 0xfd, 0xbd, 0xe2, 0x7f, 0x27, 0x7f, 0x3d, 0xf0, 0x7e, 0xfc, 0xa7, 0x58, 0x5a, 0xcf, 0x15, 0x0b, 0xfc,+ 0xda, 0xfb, 0x9f, 0x99, 0xfd, 0x4f, 0x7b, 0xe9, 0xd5, 0xb0, 0xc7, 0x44, 0xf5, 0xa9, 0x24, 0xd0, 0xf1, 0x7c, 0x70, 0xa7,+ 0xb4, 0xfe, 0x9b, 0x84, 0x99, 0xe7, 0x19, 0xae, 0x1c, 0x7c, 0xff, 0xe7, 0x92, 0xb5, 0xfa, 0xca, 0x19, 0x84, 0xef, 0xdf,+ 0xef, 0x70, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x79, 0xff, 0xf9, 0xe7, 0x3c, 0x80, 0xf8, 0x07, 0xfe, 0xba, 0xf8, 0xff, 0x17 };++// Font glyphs rectangles data (on atlas)+static const Rectangle cherryFontRecs[189] = {+ { 4, 4, 5 , 15 },+ { 17, 4, 3 , 10 },+ { 28, 4, 5 , 2 },+ { 41, 4, 10 , 10 },+ { 59, 4, 7 , 11 },+ { 74, 4, 7 , 10 },+ { 89, 4, 8 , 10 },+ { 105, 4, 1 , 2 },+ { 114, 4, 3 , 10 },+ { 125, 4, 3 , 10 },+ { 136, 4, 3 , 3 },+ { 147, 4, 7 , 7 },+ { 162, 4, 2 , 2 },+ { 172, 4, 6 , 3 },+ { 186, 4, 1 , 1 },+ { 195, 4, 4 , 10 },+ { 207, 4, 5 , 8 },+ { 220, 4, 5 , 8 },+ { 233, 4, 5 , 8 },+ { 246, 4, 5 , 8 },+ { 259, 4, 5 , 8 },+ { 272, 4, 5 , 8 },+ { 285, 4, 5 , 8 },+ { 298, 4, 5 , 8 },+ { 311, 4, 5 , 8 },+ { 324, 4, 5 , 8 },+ { 337, 4, 3 , 10 },+ { 348, 4, 3 , 12 },+ { 359, 4, 6 , 7 },+ { 373, 4, 6 , 4 },+ { 387, 4, 6 , 7 },+ { 401, 4, 5 , 10 },+ { 414, 4, 8 , 10 },+ { 430, 4, 7 , 9 },+ { 445, 4, 7 , 9 },+ { 460, 4, 6 , 9 },+ { 474, 4, 6 , 9 },+ { 488, 4, 7 , 9 },+ { 4, 27, 6 , 9 },+ { 18, 27, 6 , 9 },+ { 32, 27, 7 , 9 },+ { 47, 27, 3 , 9 },+ { 58, 27, 6 , 9 },+ { 72, 27, 7 , 9 },+ { 87, 27, 7 , 9 },+ { 102, 27, 11 , 9 },+ { 121, 27, 8 , 9 },+ { 137, 27, 6 , 9 },+ { 151, 27, 6 , 9 },+ { 165, 27, 7 , 9 },+ { 180, 27, 7 , 9 },+ { 195, 27, 6 , 9 },+ { 209, 27, 7 , 9 },+ { 224, 27, 8 , 9 },+ { 240, 27, 9 , 9 },+ { 257, 27, 11 , 9 },+ { 276, 27, 7 , 9 },+ { 291, 27, 7 , 9 },+ { 306, 27, 7 , 9 },+ { 321, 27, 3 , 9 },+ { 332, 27, 4 , 10 },+ { 344, 27, 3 , 9 },+ { 355, 27, 3 , 3 },+ { 366, 27, 7 , 2 },+ { 381, 27, 2 , 2 },+ { 391, 27, 6 , 6 },+ { 405, 27, 6 , 9 },+ { 419, 27, 6 , 6 },+ { 433, 27, 6 , 9 },+ { 447, 27, 6 , 6 },+ { 461, 27, 5 , 9 },+ { 474, 27, 5 , 9 },+ { 487, 27, 7 , 9 },+ { 4, 50, 3 , 7 },+ { 15, 50, 3 , 8 },+ { 26, 50, 6 , 9 },+ { 40, 50, 4 , 9 },+ { 52, 50, 11 , 6 },+ { 71, 50, 7 , 6 },+ { 86, 50, 5 , 6 },+ { 99, 50, 6 , 8 },+ { 113, 50, 6 , 8 },+ { 127, 50, 5 , 6 },+ { 140, 50, 5 , 6 },+ { 153, 50, 5 , 9 },+ { 166, 50, 7 , 6 },+ { 181, 50, 7 , 6 },+ { 196, 50, 11 , 6 },+ { 215, 50, 7 , 6 },+ { 230, 50, 7 , 8 },+ { 245, 50, 6 , 6 },+ { 259, 50, 5 , 9 },+ { 272, 50, 1 , 9 },+ { 281, 50, 5 , 9 },+ { 294, 50, 7 , 3 },+ { 309, 50, 3 , 10 },+ { 320, 50, 7 , 10 },+ { 335, 50, 7 , 10 },+ { 350, 50, 6 , 9 },+ { 364, 50, 7 , 9 },+ { 379, 50, 6 , 12 },+ { 393, 50, 7 , 11 },+ { 408, 50, 5 , 9 },+ { 421, 50, 5 , 5 },+ { 434, 50, 4 , 5 },+ { 446, 50, 6 , 7 },+ { 460, 50, 6 , 3 },+ { 474, 50, 5 , 5 },+ { 487, 50, 6 , 1 },+ { 4, 73, 3 , 3 },+ { 15, 73, 7 , 10 },+ { 30, 73, 3 , 5 },+ { 41, 73, 3 , 5 },+ { 52, 73, 7 , 12 },+ { 67, 73, 6 , 8 },+ { 81, 73, 7 , 9 },+ { 96, 73, 2 , 3 },+ { 106, 73, 6 , 9 },+ { 120, 73, 3 , 5 },+ { 131, 73, 3 , 5 },+ { 142, 73, 6 , 7 },+ { 156, 73, 13 , 9 },+ { 177, 73, 10 , 6 },+ { 195, 73, 7 , 11 },+ { 210, 73, 5 , 10 },+ { 223, 73, 7 , 12 },+ { 238, 73, 7 , 12 },+ { 253, 73, 7 , 12 },+ { 268, 73, 7 , 12 },+ { 283, 73, 7 , 11 },+ { 298, 73, 7 , 11 },+ { 313, 73, 12 , 9 },+ { 333, 73, 6 , 11 },+ { 347, 73, 7 , 12 },+ { 362, 73, 7 , 12 },+ { 377, 73, 7 , 12 },+ { 392, 73, 7 , 11 },+ { 407, 73, 3 , 12 },+ { 418, 73, 3 , 12 },+ { 429, 73, 3 , 12 },+ { 440, 73, 3 , 11 },+ { 451, 73, 7 , 9 },+ { 466, 73, 8 , 12 },+ { 482, 73, 6 , 12 },+ { 496, 73, 6 , 12 },+ { 4, 96, 6 , 12 },+ { 18, 96, 6 , 12 },+ { 32, 96, 6 , 11 },+ { 46, 96, 5 , 5 },+ { 59, 96, 8 , 9 },+ { 75, 96, 8 , 12 },+ { 91, 96, 8 , 12 },+ { 107, 96, 8 , 12 },+ { 123, 96, 8 , 11 },+ { 139, 96, 7 , 12 },+ { 154, 96, 7 , 9 },+ { 169, 96, 8 , 9 },+ { 185, 96, 6 , 9 },+ { 199, 96, 6 , 9 },+ { 213, 96, 6 , 9 },+ { 227, 96, 6 , 9 },+ { 241, 96, 6 , 8 },+ { 255, 96, 6 , 10 },+ { 269, 96, 10 , 6 },+ { 287, 96, 6 , 8 },+ { 301, 96, 6 , 9 },+ { 315, 96, 6 , 9 },+ { 329, 96, 6 , 9 },+ { 343, 96, 6 , 8 },+ { 357, 96, 3 , 10 },+ { 368, 96, 3 , 10 },+ { 379, 96, 3 , 10 },+ { 390, 96, 3 , 9 },+ { 401, 96, 6 , 10 },+ { 415, 96, 7 , 9 },+ { 430, 96, 5 , 9 },+ { 443, 96, 5 , 9 },+ { 456, 96, 5 , 9 },+ { 469, 96, 5 , 9 },+ { 482, 96, 5 , 8 },+ { 495, 96, 7 , 9 },+ { 4, 119, 8 , 8 },+ { 20, 119, 7 , 9 },+ { 35, 119, 7 , 9 },+ { 50, 119, 7 , 9 },+ { 65, 119, 7 , 8 },+ { 80, 119, 7 , 11 },+ { 95, 119, 5 , 8 },+ { 108, 119, 7 , 10 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo cherryFontGlyphs[189] = {+ { 32, 0, 12, 5, { 0 }},+ { 33, 0, 2, 4, { 0 }},+ { 34, 0, 2, 6, { 0 }},+ { 35, 0, 2, 11, { 0 }},+ { 36, 0, 2, 8, { 0 }},+ { 37, 0, 2, 8, { 0 }},+ { 38, 0, 2, 9, { 0 }},+ { 39, 0, 2, 2, { 0 }},+ { 40, 0, 2, 4, { 0 }},+ { 41, 0, 2, 4, { 0 }},+ { 42, 0, 2, 4, { 0 }},+ { 43, 0, 4, 8, { 0 }},+ { 44, 0, 11, 3, { 0 }},+ { 45, 0, 6, 7, { 0 }},+ { 46, 0, 11, 2, { 0 }},+ { 47, 0, 2, 5, { 0 }},+ { 48, 0, 4, 6, { 0 }},+ { 49, 0, 4, 6, { 0 }},+ { 50, 0, 4, 6, { 0 }},+ { 51, 0, 4, 6, { 0 }},+ { 52, 0, 4, 6, { 0 }},+ { 53, 0, 4, 6, { 0 }},+ { 54, 0, 4, 6, { 0 }},+ { 55, 0, 4, 6, { 0 }},+ { 56, 0, 4, 6, { 0 }},+ { 57, 0, 4, 6, { 0 }},+ { 58, 0, 2, 4, { 0 }},+ { 59, 0, 2, 4, { 0 }},+ { 60, 0, 4, 7, { 0 }},+ { 61, 0, 5, 7, { 0 }},+ { 62, 0, 4, 7, { 0 }},+ { 63, 0, 2, 6, { 0 }},+ { 64, 0, 2, 9, { 0 }},+ { 65, 0, 3, 8, { 0 }},+ { 66, 0, 3, 8, { 0 }},+ { 67, 0, 3, 7, { 0 }},+ { 68, 0, 3, 7, { 0 }},+ { 69, 0, 3, 8, { 0 }},+ { 70, 0, 3, 7, { 0 }},+ { 71, 0, 3, 7, { 0 }},+ { 72, 0, 3, 8, { 0 }},+ { 73, 0, 3, 4, { 0 }},+ { 74, 0, 3, 7, { 0 }},+ { 75, 0, 3, 8, { 0 }},+ { 76, 0, 3, 8, { 0 }},+ { 77, 0, 3, 12, { 0 }},+ { 78, 0, 3, 9, { 0 }},+ { 79, 0, 3, 7, { 0 }},+ { 80, 0, 3, 7, { 0 }},+ { 81, 0, 3, 8, { 0 }},+ { 82, 0, 3, 8, { 0 }},+ { 83, 0, 3, 7, { 0 }},+ { 84, 0, 3, 8, { 0 }},+ { 85, 0, 3, 9, { 0 }},+ { 86, 0, 3, 10, { 0 }},+ { 87, 0, 3, 12, { 0 }},+ { 88, 0, 3, 8, { 0 }},+ { 89, 0, 3, 8, { 0 }},+ { 90, 0, 3, 8, { 0 }},+ { 91, 0, 3, 4, { 0 }},+ { 92, 0, 2, 5, { 0 }},+ { 93, 0, 3, 4, { 0 }},+ { 94, 0, 3, 4, { 0 }},+ { 95, 0, 10, 8, { 0 }},+ { 96, 0, 2, 3, { 0 }},+ { 97, 0, 6, 7, { 0 }},+ { 98, 0, 3, 7, { 0 }},+ { 99, 0, 6, 7, { 0 }},+ { 100, 0, 3, 7, { 0 }},+ { 101, 0, 6, 7, { 0 }},+ { 102, 0, 3, 6, { 0 }},+ { 103, 0, 5, 6, { 0 }},+ { 104, 0, 3, 8, { 0 }},+ { 105, 0, 5, 4, { 0 }},+ { 106, 0, 5, 4, { 0 }},+ { 107, 0, 3, 7, { 0 }},+ { 108, 0, 3, 5, { 0 }},+ { 109, 0, 6, 12, { 0 }},+ { 110, 0, 6, 8, { 0 }},+ { 111, 0, 6, 6, { 0 }},+ { 112, 0, 6, 7, { 0 }},+ { 113, 0, 6, 7, { 0 }},+ { 114, 0, 6, 6, { 0 }},+ { 115, 0, 6, 6, { 0 }},+ { 116, 0, 3, 6, { 0 }},+ { 117, 0, 6, 8, { 0 }},+ { 118, 0, 6, 8, { 0 }},+ { 119, 0, 6, 12, { 0 }},+ { 120, 0, 6, 8, { 0 }},+ { 121, 0, 6, 8, { 0 }},+ { 122, 0, 6, 7, { 0 }},+ { 123, 0, 3, 6, { 0 }},+ { 124, 0, 3, 2, { 0 }},+ { 125, 0, 3, 6, { 0 }},+ { 126, 0, 6, 8, { 0 }},+ { 161, 0, 4, 4, { 0 }},+ { 162, 0, 4, 8, { 0 }},+ { 163, 0, 2, 8, { 0 }},+ { 8364, 0, 3, 7, { 0 }},+ { 165, 0, 3, 8, { 0 }},+ { 352, 0, 0, 7, { 0 }},+ { 167, 0, 2, 8, { 0 }},+ { 353, 0, 3, 6, { 0 }},+ { 169, 0, 1, 6, { 0 }},+ { 170, 0, 2, 5, { 0 }},+ { 171, 0, 5, 7, { 0 }},+ { 172, 0, 6, 7, { 0 }},+ { 174, 0, 1, 6, { 0 }},+ { 175, 0, 2, 7, { 0 }},+ { 176, 0, 2, 4, { 0 }},+ { 177, 0, 3, 8, { 0 }},+ { 178, 0, 2, 4, { 0 }},+ { 179, 0, 2, 4, { 0 }},+ { 381, 0, 0, 8, { 0 }},+ { 181, 0, 6, 7, { 0 }},+ { 182, 0, 3, 8, { 0 }},+ { 183, 0, 6, 3, { 0 }},+ { 382, 0, 3, 7, { 0 }},+ { 185, 0, 2, 4, { 0 }},+ { 186, 0, 2, 4, { 0 }},+ { 187, 0, 5, 7, { 0 }},+ { 338, 0, 3, 14, { 0 }},+ { 339, 0, 6, 11, { 0 }},+ { 376, 0, 1, 8, { 0 }},+ { 191, 0, 4, 6, { 0 }},+ { 192, 0, 0, 8, { 0 }},+ { 193, 0, 0, 8, { 0 }},+ { 194, 0, 0, 8, { 0 }},+ { 195, 0, 0, 8, { 0 }},+ { 196, 0, 1, 8, { 0 }},+ { 197, 0, 1, 8, { 0 }},+ { 198, 0, 3, 13, { 0 }},+ { 199, 0, 3, 7, { 0 }},+ { 200, 0, 0, 8, { 0 }},+ { 201, 0, 0, 8, { 0 }},+ { 202, 0, 0, 8, { 0 }},+ { 203, 0, 1, 8, { 0 }},+ { 204, 0, 0, 4, { 0 }},+ { 205, 0, 0, 4, { 0 }},+ { 206, 0, 0, 4, { 0 }},+ { 207, 0, 1, 4, { 0 }},+ { 208, 0, 3, 8, { 0 }},+ { 209, 0, 0, 9, { 0 }},+ { 210, 0, 0, 7, { 0 }},+ { 211, 0, 0, 7, { 0 }},+ { 212, 0, 0, 7, { 0 }},+ { 213, 0, 0, 7, { 0 }},+ { 214, 0, 1, 7, { 0 }},+ { 215, 1, 5, 7, { 0 }},+ { 216, 0, 3, 9, { 0 }},+ { 217, 0, 0, 9, { 0 }},+ { 218, 0, 0, 9, { 0 }},+ { 219, 0, 0, 9, { 0 }},+ { 220, 0, 1, 9, { 0 }},+ { 221, 0, 0, 8, { 0 }},+ { 222, 0, 2, 8, { 0 }},+ { 223, 0, 3, 9, { 0 }},+ { 224, 0, 3, 7, { 0 }},+ { 225, 0, 3, 7, { 0 }},+ { 226, 0, 3, 7, { 0 }},+ { 227, 0, 3, 7, { 0 }},+ { 228, 0, 4, 7, { 0 }},+ { 229, 0, 2, 7, { 0 }},+ { 230, 0, 6, 11, { 0 }},+ { 231, 0, 6, 7, { 0 }},+ { 232, 0, 3, 7, { 0 }},+ { 233, 0, 3, 7, { 0 }},+ { 234, 0, 3, 7, { 0 }},+ { 235, 0, 4, 7, { 0 }},+ { 236, 0, 2, 4, { 0 }},+ { 237, 0, 2, 4, { 0 }},+ { 238, 0, 2, 4, { 0 }},+ { 239, 0, 3, 4, { 0 }},+ { 240, 0, 2, 7, { 0 }},+ { 241, 0, 3, 8, { 0 }},+ { 242, 0, 3, 6, { 0 }},+ { 243, 0, 3, 6, { 0 }},+ { 244, 0, 3, 6, { 0 }},+ { 245, 0, 3, 6, { 0 }},+ { 246, 0, 4, 6, { 0 }},+ { 247, 0, 3, 8, { 0 }},+ { 248, 0, 4, 9, { 0 }},+ { 249, 0, 3, 8, { 0 }},+ { 250, 0, 3, 8, { 0 }},+ { 251, 0, 3, 8, { 0 }},+ { 252, 0, 4, 8, { 0 }},+ { 253, 0, 3, 8, { 0 }},+ { 254, 0, 4, 6, { 0 }},+ { 255, 0, 4, 8, { 0 }},+};++// Style loading function: Cherry+static void GuiLoadStyleCherry(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < CHERRY_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(cherryStyleProps[i].controlId, cherryStyleProps[i].propertyId, cherryStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int cherryFontDataSize = 0;+ unsigned char *data = DecompressData(cherryFontData, CHERRY_STYLE_FONT_ATLAS_COMP_SIZE, &cherryFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 15;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, cherryFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, cherryFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/cyber/style_cyber.h view
@@ -0,0 +1,591 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleCyber(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define CYBER_STYLE_PROPS_COUNT 17++// Custom style name: Cyber+static const GuiStyleProp cyberStyleProps[CYBER_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x2f7486ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x024658ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0x51bfd3ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0x82cde0ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x3299b4ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xb6e1eaff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xeb7630ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xffbc51ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0xd86f36ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x134b5aff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x02313dff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x17505fff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x0000000e }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x81c0d0ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x00222bff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000015 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "Kyrou 7 Wide.ttf" (size: 14, spacing: 0)++#define CYBER_STYLE_FONT_ATLAS_COMP_SIZE 2286++// Font atlas image pixels data: DEFLATE compressed+static unsigned char cyberFontData[CYBER_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x81, 0x6e, 0xdb, 0x36, 0x10, 0x06, 0x60, 0x21, 0xef, 0xff, 0xc6, 0x99, 0xf6, 0x0f, 0xe8, 0xd0, 0x2d, 0x45, 0x6b,+ 0x89, 0x3c, 0x92, 0xb2, 0xec, 0x7c, 0xfd, 0x80, 0x61, 0x88, 0x62, 0x5b, 0xa2, 0x78, 0xe4, 0x49, 0x0a, 0xcf, 0xd9, 0x00,+ 0x00, 0x00, 0x00, 0x26, 0xcb, 0xc5, 0x9f, 0x96, 0xe6, 0x9f, 0xce, 0x3b, 0xa2, 0x9f, 0xff, 0x9e, 0x7b, 0xec, 0xfa, 0x57,+ 0x7f, 0xbb, 0xe7, 0xe1, 0xb9, 0xd3, 0x9e, 0x5f, 0x7f, 0x92, 0xc3, 0xdf, 0x4d, 0xa9, 0x75, 0x73, 0x7a, 0xc6, 0x8e, 0xcf,+ 0x4c, 0x5f, 0xbc, 0x3d, 0xde, 0x87, 0x74, 0xbf, 0x62, 0xe5, 0xc8, 0xf8, 0xf3, 0xdf, 0xde, 0xd5, 0xdf, 0x8f, 0x7b, 0x71,+ 0x5b, 0x2f, 0xcf, 0xc9, 0x1e, 0xa5, 0xe1, 0x37, 0xce, 0x5e, 0xbf, 0x0d, 0xec, 0xfd, 0x7e, 0xe9, 0x5c, 0x94, 0xd3, 0x31,+ 0x63, 0x5b, 0x70, 0x34, 0x19, 0x3c, 0x97, 0x19, 0x1e, 0xd1, 0xda, 0xe3, 0xff, 0xac, 0x5f, 0xe4, 0xb7, 0xff, 0x6e, 0xa5,+ 0x48, 0xcb, 0xc2, 0xf8, 0xdf, 0xba, 0xc6, 0x97, 0xf5, 0x79, 0x51, 0x1a, 0x22, 0xbd, 0xff, 0x35, 0xad, 0x47, 0x5b, 0x1b,+ 0xf1, 0xd2, 0xfc, 0xbb, 0x29, 0x1d, 0xf1, 0xac, 0x33, 0xd2, 0x3b, 0x72, 0x9e, 0xb5, 0xc6, 0x8a, 0xa3, 0xf9, 0xfa, 0xb3,+ 0xcf, 0xc1, 0xd7, 0xef, 0xcb, 0xc7, 0xc8, 0xbd, 0xa1, 0xa5, 0xf6, 0xf2, 0x27, 0xa6, 0x90, 0xcd, 0xcd, 0x3a, 0xfb, 0xab,+ 0xf3, 0xc2, 0x94, 0x63, 0x29, 0x43, 0x67, 0xef, 0xf8, 0x73, 0xab, 0xf3, 0xf7, 0xda, 0x11, 0xaf, 0x3f, 0xd7, 0xcf, 0xa4,+ 0xd1, 0xbc, 0x36, 0x9a, 0xfd, 0x6c, 0xa9, 0x2c, 0x88, 0xdf, 0x79, 0x63, 0xf1, 0xcc, 0x1c, 0x69, 0x24, 0xef, 0x3c, 0xda,+ 0xf6, 0xf9, 0x43, 0xfb, 0x5e, 0xbd, 0xca, 0xfc, 0x9f, 0x81, 0xf3, 0x97, 0x52, 0x3b, 0x9f, 0xe5, 0x94, 0xad, 0x47, 0x7c,+ 0xfc, 0xe9, 0x7b, 0xe1, 0x98, 0x3f, 0xb2, 0xff, 0x67, 0x9b, 0x92, 0xd3, 0x66, 0xe2, 0xb9, 0x4c, 0xf7, 0xb5, 0xd2, 0xbf,+ 0x71, 0x5b, 0xcf, 0x99, 0x93, 0xbf, 0x7f, 0xd8, 0x17, 0xe7, 0x62, 0x57, 0xc4, 0xff, 0xff, 0xa3, 0x58, 0x06, 0x22, 0x36,+ 0x83, 0x33, 0xcc, 0xdc, 0xeb, 0xff, 0x71, 0xfb, 0xd0, 0xf9, 0xcb, 0xf4, 0xab, 0xda, 0xff, 0xa3, 0x37, 0xa5, 0xfc, 0x21,+ 0xd3, 0x46, 0xd9, 0x7d, 0xe1, 0xbd, 0xe4, 0x2c, 0xca, 0xd2, 0x1e, 0xcd, 0xff, 0xd7, 0x65, 0x3b, 0x6b, 0xae, 0x96, 0x7a,+ 0xee, 0x9d, 0x56, 0xaf, 0xff, 0xd3, 0x38, 0xba, 0xac, 0x8b, 0xff, 0xeb, 0xfd, 0x35, 0x78, 0xfe, 0x72, 0xf1, 0xf5, 0xf9,+ 0x9c, 0x2b, 0xf4, 0x7a, 0xc6, 0xb3, 0xf6, 0xfa, 0xff, 0xaa, 0x11, 0x63, 0x45, 0xfe, 0x9f, 0x17, 0xcf, 0xff, 0x7b, 0xee,+ 0xff, 0xe7, 0x4d, 0xe2, 0x3f, 0xc3, 0x4f, 0xa4, 0x32, 0xfd, 0xfe, 0x7c, 0x5b, 0xb6, 0x3b, 0xf6, 0x7c, 0x21, 0x43, 0x47,+ 0x3c, 0xeb, 0x5e, 0x4c, 0x26, 0xfd, 0x6e, 0x1a, 0x67, 0xc5, 0xda, 0xfd, 0xdd, 0xe7, 0xde, 0xff, 0xf7, 0xfc, 0x1f, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9e, 0xd5, 0x9d, 0xb9, 0xe0, 0x75, 0x95,+ 0x55, 0xb4, 0x23, 0xab, 0x6e, 0x47, 0xd6, 0xec, 0x56, 0x5f, 0x79, 0x5e, 0x87, 0xa8, 0xbe, 0xce, 0xb8, 0x7d, 0x95, 0x73,+ 0xdf, 0xba, 0xe1, 0xb1, 0xea, 0x28, 0x39, 0x5d, 0x47, 0xdf, 0x56, 0x8f, 0xe0, 0xbc, 0x76, 0xeb, 0x59, 0x25, 0xab, 0xf5,+ 0xb5, 0x5f, 0x57, 0xd6, 0xa6, 0x4c, 0xb9, 0x05, 0x7b, 0x56, 0xbf, 0xa7, 0xab, 0x3e, 0x41, 0x75, 0x1d, 0xfa, 0x75, 0x55,+ 0x01, 0xc7, 0x57, 0xc8, 0x1f, 0xbf, 0xf3, 0xbe, 0xfc, 0x28, 0xda, 0xf7, 0x38, 0x13, 0xce, 0xd9, 0x8a, 0xf8, 0xcf, 0x61,+ 0x45, 0x80, 0x5c, 0x58, 0xdb, 0x75, 0x5d, 0x25, 0xdc, 0x75, 0x95, 0x76, 0xce, 0xe3, 0xbf, 0xbd, 0x66, 0x73, 0x26, 0x47,+ 0x6b, 0xca, 0xd1, 0x33, 0x6b, 0x04, 0xa8, 0x8c, 0x5b, 0x33, 0xe2, 0xbf, 0x9a, 0x3b, 0xbc, 0x76, 0xfc, 0x57, 0xeb, 0x89,+ 0xe5, 0xe0, 0xbc, 0xa7, 0xb1, 0x6f, 0xdf, 0x61, 0xfb, 0x76, 0xd3, 0xf8, 0x3f, 0x8f, 0xa9, 0x0c, 0x57, 0x29, 0x9e, 0xd7,+ 0x9f, 0xe6, 0xd9, 0x9b, 0xa2, 0xb4, 0x56, 0xd3, 0x73, 0x2f, 0x8f, 0x2c, 0xab, 0xf2, 0xff, 0x9c, 0x5c, 0x79, 0xa4, 0x29,+ 0x97, 0x9d, 0x3b, 0xc6, 0xb6, 0x8e, 0x5a, 0x8f, 0x2b, 0x8a, 0x9d, 0xd5, 0x2b, 0x7c, 0xfe, 0xfc, 0x3e, 0x56, 0x4f, 0xf9,+ 0x9a, 0xf8, 0x1f, 0x8f, 0xc4, 0x3c, 0x65, 0xce, 0x9a, 0x73, 0x6f, 0x22, 0xc5, 0x79, 0x6b, 0xcd, 0x6b, 0xaf, 0x98, 0xff,+ 0xf3, 0x52, 0xf3, 0x7f, 0xcb, 0xf5, 0x7f, 0x26, 0x5c, 0xbd, 0xd6, 0x5a, 0x6d, 0x6f, 0x3e, 0x97, 0x2b, 0xf2, 0xff, 0x96,+ 0x99, 0x7d, 0x7c, 0xfe, 0x1f, 0xd9, 0x9a, 0xe6, 0x59, 0xf8, 0xfa, 0xf8, 0x6f, 0x3b, 0xa6, 0x5c, 0xfa, 0xda, 0xd7, 0x8b,+ 0xff, 0xdc, 0xe2, 0xfe, 0x5f, 0x16, 0xd6, 0x66, 0xce, 0x94, 0xd1, 0x6d, 0x4d, 0xfc, 0xb7, 0xd5, 0x43, 0x1f, 0xb9, 0xfe,+ 0x1f, 0x8b, 0xf0, 0xf3, 0x08, 0xf8, 0x4b, 0xfc, 0x4f, 0xca, 0xff, 0x67, 0xbd, 0xba, 0xff, 0x5e, 0xc9, 0xc8, 0x0c, 0xda,+ 0x7e, 0x4c, 0x99, 0x9e, 0x7f, 0x8f, 0xd6, 0xf6, 0x5d, 0x9d, 0xff, 0xcf, 0x7a, 0xfd, 0x56, 0x3e, 0xef, 0xe7, 0x5b, 0xc6,+ 0x7a, 0xe5, 0xf6, 0x84, 0x6f, 0x73, 0x58, 0xfd, 0x7c, 0xcf, 0x77, 0x94, 0xbe, 0xdf, 0x53, 0x6c, 0x6d, 0x70, 0xef, 0xe7,+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x5e, 0x65, 0x75, 0xbf, 0x15,+ 0x53, 0x69, 0x58, 0x1f, 0xda, 0x52, 0x3f, 0xf3, 0xb8, 0xfa, 0xe6, 0xa3, 0x1a, 0x12, 0x7b, 0x53, 0xed, 0xcd, 0x59, 0xad,+ 0xd9, 0x5a, 0x07, 0x61, 0xb4, 0x4e, 0x67, 0xe5, 0xdd, 0x5b, 0x5a, 0xf9, 0x7c, 0xcd, 0x63, 0x4e, 0xd6, 0x01, 0x6f, 0x13,+ 0x7b, 0xe0, 0xf9, 0x9a, 0xe7, 0x0c, 0xd4, 0x5c, 0x18, 0xa9, 0x22, 0x98, 0x85, 0x2b, 0x4c, 0x53, 0x6a, 0x95, 0xf6, 0x0a,+ 0x1c, 0xad, 0x5b, 0x33, 0xa9, 0xca, 0xc3, 0xea, 0x7e, 0x3d, 0x63, 0x6b, 0x7f, 0x1d, 0x85, 0x67, 0xc4, 0xff, 0x71, 0x0f,+ 0xc9, 0xe4, 0xb3, 0xdd, 0xf7, 0xd3, 0xb3, 0xd8, 0x7f, 0x5c, 0x5b, 0xf9, 0xa3, 0xb1, 0xdf, 0xf4, 0x6c, 0xcf, 0xf0, 0x59,+ 0xce, 0x60, 0x25, 0x84, 0xbd, 0x73, 0xbe, 0x69, 0x8f, 0xfe, 0xb1, 0x9e, 0xb7, 0x6e, 0x05, 0xfc, 0x3b, 0xc5, 0xff, 0x56,+ 0xac, 0x58, 0xb8, 0x3a, 0xfe, 0xb7, 0xa6, 0x7d, 0xca, 0xb4, 0x23, 0x9a, 0x57, 0x7d, 0xfb, 0xa3, 0x3b, 0xc7, 0x9a, 0x53,+ 0xcb, 0x2a, 0x17, 0xd6, 0x7a, 0x48, 0x47, 0xef, 0xaa, 0x8e, 0x00, 0x29, 0xce, 0xff, 0xfd, 0x2d, 0x3d, 0x2b, 0xc7, 0x78,+ 0xcd, 0xf8, 0xaf, 0xb5, 0x66, 0x06, 0xce, 0xf0, 0xda, 0xf9, 0x7f, 0x66, 0xe5, 0xee, 0x4a, 0x74, 0xec, 0x0f, 0xde, 0x65,+ 0x2f, 0xcf, 0xce, 0xf5, 0xab, 0x83, 0xad, 0xe9, 0x3b, 0x19, 0xf6, 0xee, 0xd7, 0xe5, 0x97, 0xf8, 0xcc, 0x92, 0x6b, 0xf4,+ 0x1c, 0xb4, 0x70, 0xb5, 0x1a, 0x69, 0x6f, 0xfc, 0xe7, 0xd2, 0xf9, 0x7f, 0x6b, 0xfc, 0xf6, 0x8c, 0xad, 0x74, 0xbe, 0xb6,+ 0xe2, 0xbb, 0xd6, 0x5f, 0x99, 0xd3, 0x1e, 0xbb, 0xa6, 0x1e, 0xed, 0xcc, 0x6f, 0xe8, 0xc8, 0x84, 0x7e, 0x9b, 0x93, 0x4f,+ 0x48, 0x31, 0x07, 0xef, 0xcd, 0xfc, 0x7b, 0xc6, 0xd9, 0x74, 0xdc, 0x19, 0xc8, 0xc1, 0x18, 0x98, 0x45, 0x39, 0xf8, 0xcc,+ 0x79, 0x30, 0x53, 0xf3, 0xb5, 0x75, 0x77, 0x17, 0x57, 0x66, 0x74, 0xd7, 0xbc, 0xdb, 0xb3, 0xda, 0xe4, 0xca, 0xf9, 0x3f,+ 0xdd, 0xd9, 0xee, 0xc8, 0xfc, 0x9f, 0xe1, 0x3a, 0x99, 0x67, 0xb9, 0xdf, 0x76, 0xbb, 0xf9, 0xbf, 0x2d, 0x36, 0x73, 0x79,+ 0xfe, 0x2f, 0xfe, 0xaf, 0x7e, 0xd2, 0xb2, 0xbd, 0x44, 0xfc, 0xaf, 0xbd, 0xfe, 0x9f, 0x33, 0x82, 0x54, 0x67, 0xd9, 0x6d,+ 0xf1, 0x33, 0x82, 0xfa, 0xab, 0xd6, 0xc5, 0xff, 0xf6, 0xad, 0xaa, 0x35, 0xbe, 0x5b, 0x6d, 0xca, 0x67, 0xc4, 0x7f, 0x4b,+ 0xfe, 0x9f, 0xe2, 0xfd, 0xff, 0xf6, 0x6f, 0xd8, 0x4a, 0x57, 0xce, 0xd2, 0x9e, 0x77, 0xbc, 0x67, 0x8f, 0xe0, 0x9d, 0x47,+ 0xb4, 0xb1, 0xe7, 0xff, 0x77, 0x1b, 0x83, 0xc7, 0xbe, 0x53, 0xe5, 0x3b, 0xf7, 0x7f, 0x75, 0x97, 0xf1, 0xd7, 0x72, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x5e, 0xb7, 0x90, 0x4b, 0xd7, 0xcb, 0x57, 0xeb,+ 0xd6, 0xf5, 0xaf, 0x58, 0xcd, 0xa4, 0x96, 0xc9, 0xa4, 0xb3, 0xb5, 0x37, 0xac, 0xce, 0xcf, 0x60, 0xbb, 0x67, 0xf8, 0x77,+ 0xd2, 0xb0, 0x22, 0x2c, 0xa5, 0x33, 0x7c, 0xbf, 0x75, 0xab, 0x23, 0xab, 0x06, 0x33, 0xb5, 0x75, 0x67, 0x9e, 0xef, 0x9c,+ 0x56, 0xc3, 0xfe, 0x6a, 0x2f, 0x56, 0x5f, 0x49, 0x69, 0xc5, 0x64, 0xca, 0xb5, 0x09, 0x7a, 0xc7, 0xbb, 0x74, 0xb6, 0x59,+ 0xef, 0xb9, 0xfe, 0xda, 0xc6, 0xad, 0x55, 0x66, 0xbe, 0x6e, 0xdf, 0xcb, 0x3d, 0xfb, 0x73, 0xa8, 0xdf, 0xa7, 0x3c, 0x42,+ 0x6f, 0x53, 0xea, 0x7a, 0xb7, 0x54, 0xe3, 0xd8, 0x1b, 0xd6, 0xd0, 0x67, 0xb8, 0x36, 0x58, 0xca, 0xed, 0x30, 0xb3, 0xe7,+ 0x8d, 0x7d, 0xda, 0xd9, 0x5a, 0xed, 0x0c, 0xcc, 0xa0, 0x29, 0xd6, 0xbf, 0xcb, 0x60, 0x65, 0x88, 0x1c, 0xac, 0xf1, 0xce,+ 0xb2, 0xf5, 0xed, 0xe9, 0x8c, 0xfe, 0xf6, 0xe3, 0x4d, 0x73, 0x9b, 0xb6, 0xd5, 0xab, 0xfe, 0xb8, 0x7d, 0x56, 0xba, 0x97,+ 0x66, 0x9b, 0x5a, 0x9b, 0x5e, 0x9d, 0x6f, 0xdc, 0xbd, 0xb6, 0xc7, 0x79, 0xf5, 0xb1, 0xf5, 0xd7, 0x06, 0x95, 0x5a, 0x2c,+ 0xf3, 0xe2, 0x3f, 0xdd, 0x15, 0xa5, 0xf6, 0xa1, 0xab, 0x8e, 0xbe, 0xf8, 0x6f, 0x7b, 0xdf, 0x94, 0xe6, 0xff, 0xb3, 0xf8,+ 0x5b, 0xbb, 0x7d, 0xb4, 0xda, 0x7e, 0x35, 0xfe, 0xfb, 0xfb, 0x40, 0x16, 0xd4, 0x48, 0x3d, 0xcb, 0x4a, 0x2a, 0x5b, 0xc6,+ 0xaf, 0xb1, 0xd7, 0xc5, 0xff, 0x51, 0xeb, 0x8d, 0xe6, 0x1b, 0xb3, 0xe6, 0xff, 0x0c, 0xe7, 0xff, 0xad, 0x7d, 0x35, 0xcd,+ 0xdf, 0x2f, 0xd4, 0x92, 0x53, 0x1d, 0x55, 0x77, 0xde, 0x4f, 0xbf, 0x29, 0x63, 0x2b, 0x7e, 0x1b, 0xc6, 0xea, 0xed, 0x3d,+ 0xe3, 0xf6, 0x9c, 0xca, 0x9d, 0xd7, 0x6f, 0x9d, 0x31, 0xf6, 0xdd, 0x23, 0xfe, 0xb3, 0x28, 0xd3, 0xc9, 0x50, 0xbb, 0xa6,+ 0x6b, 0xdf, 0xaf, 0xb9, 0xbb, 0x94, 0xcb, 0xaa, 0x8a, 0xce, 0xf9, 0x2e, 0x8c, 0x75, 0xdb, 0x5b, 0xc7, 0xc1, 0xfd, 0x82,+ 0xf9, 0x7f, 0xe5, 0x1d, 0xd0, 0x7a, 0x55, 0xf8, 0x6b, 0xe2, 0xff, 0x59, 0xd7, 0x46, 0xeb, 0xfa, 0x76, 0x4f, 0xfc, 0xe7,+ 0xe2, 0xe3, 0xb8, 0x3e, 0xfe, 0x3f, 0xfe, 0x18, 0x41, 0xe9, 0xc8, 0x6b, 0xd7, 0x6c, 0x9f, 0x39, 0xbe, 0x8c, 0x8e, 0x75,+ 0xcf, 0xc9, 0xff, 0x9f, 0x1f, 0xff, 0x77, 0xbe, 0x43, 0x91, 0x37, 0xba, 0x43, 0x93, 0x5f, 0xee, 0xb2, 0x5c, 0xf7, 0x3c,+ 0xb6, 0x7e, 0xfd, 0xfd, 0x5a, 0xdb, 0xc7, 0xee, 0xff, 0x7f, 0xdf, 0xfc, 0xff, 0xce, 0x7f, 0xb3, 0xe0, 0xef, 0x36, 0x56,+ 0xb6, 0xd3, 0xfd, 0xe3, 0x7b, 0xfe, 0xc8, 0xfc, 0xe8, 0x6e, 0xc8, 0xf7, 0xcd, 0xff, 0xef, 0xff, 0x17, 0x4b, 0xaa, 0xad,+ 0x5e, 0x71, 0x4d, 0x72, 0xc7, 0xfb, 0x7b, 0xb3, 0xfb, 0xfb, 0xd1, 0xbd, 0xd0, 0x55, 0xf9, 0xff, 0x76, 0xf3, 0xfb, 0xff,+ 0xf0, 0x9a, 0xe3, 0x13, 0x20, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0xaf, 0x29,+ 0x53, 0x5e, 0x37, 0x91, 0x1f, 0x6b, 0xc8, 0x3f, 0x06, 0x56, 0x23, 0xad, 0xab, 0x22, 0x7b, 0x5c, 0x03, 0xeb, 0x73, 0xe0,+ 0xef, 0x47, 0xd7, 0x1e, 0x57, 0x26, 0xad, 0x1f, 0x7d, 0xc6, 0x91, 0xa5, 0x78, 0xae, 0xc6, 0xd7, 0x32, 0xe7, 0xb7, 0xff,+ 0x9f, 0xbb, 0xd6, 0xf7, 0x71, 0xbd, 0x84, 0xb1, 0x33, 0xd2, 0xb3, 0xf2, 0xf0, 0x5e, 0x15, 0x0a, 0xf7, 0x1f, 0xed, 0x91,+ 0xc3, 0x3a, 0x92, 0x77, 0xae, 0x22, 0xbb, 0x97, 0xaa, 0xcb, 0xac, 0x3f, 0xae, 0xb1, 0x78, 0xc8, 0x49, 0x5d, 0xcf, 0xe7,+ 0x54, 0xbb, 0x3d, 0x3b, 0x57, 0xc7, 0xb5, 0xb0, 0xf7, 0xc6, 0xf5, 0xf2, 0xc7, 0x55, 0x91, 0x33, 0x38, 0xfa, 0x9d, 0x47,+ 0x7f, 0x4a, 0x47, 0xf7, 0xa7, 0x33, 0x96, 0xe6, 0x4f, 0xc8, 0xa4, 0xea, 0x5c, 0xc7, 0xad, 0xb1, 0xbf, 0xf0, 0x4a, 0xe1,+ 0xbd, 0x2b, 0xfe, 0xf3, 0x25, 0x43, 0xc8, 0x0b, 0xae, 0x6e, 0x69, 0x1d, 0x8f, 0x5f, 0x6b, 0xe5, 0x4c, 0x9a, 0x57, 0x84,+ 0x8f, 0x54, 0xdc, 0xb1, 0x9e, 0xaa, 0xbd, 0x27, 0x9e, 0xf7, 0xd3, 0x7b, 0x57, 0x91, 0xfd, 0x3c, 0x39, 0xae, 0xbc, 0x6c,+ 0xf5, 0x9b, 0xb6, 0x56, 0x49, 0x21, 0x3b, 0x78, 0xd6, 0xd6, 0xe3, 0x2c, 0xee, 0x4f, 0xf3, 0x7f, 0x2d, 0xb3, 0x79, 0xd6,+ 0xb1, 0xb7, 0xee, 0x6b, 0x96, 0x5c, 0x09, 0xb6, 0xf4, 0x84, 0x1c, 0x66, 0x5b, 0xaf, 0x18, 0x27, 0x2d, 0x99, 0xe8, 0x3d,+ 0xf7, 0x3b, 0x8d, 0xbd, 0x21, 0x07, 0x79, 0xf8, 0x5d, 0xeb, 0xde, 0x8e, 0x8c, 0x4a, 0x69, 0xb8, 0xc2, 0x6f, 0xc9, 0x0e,+ 0xf6, 0x4b, 0xb7, 0xde, 0x35, 0xfe, 0x5b, 0xe6, 0xff, 0xbc, 0x69, 0xfc, 0xef, 0x37, 0xdf, 0xef, 0xfa, 0xf7, 0x9f, 0xb5,+ 0xce, 0xff, 0xf7, 0xda, 0x3a, 0x33, 0x83, 0x7f, 0x7c, 0xbf, 0x6d, 0x5d, 0xa5, 0xcf, 0xfe, 0xfb, 0x8e, 0xaf, 0x11, 0xff,+ 0x77, 0x9e, 0x27, 0xeb, 0xf1, 0xff, 0xf9, 0x02, 0xfb, 0x9d, 0xd2, 0x1d, 0x9d, 0xb3, 0xf8, 0xdf, 0x6f, 0xb9, 0x75, 0x66,+ 0x65, 0xab, 0xea, 0xb3, 0xaa, 0x95, 0x95, 0x3e, 0xef, 0x1b, 0xff, 0x2d, 0xf9, 0xd2, 0xab, 0x5e, 0x27, 0x6f, 0xc3, 0x11,+ 0x74, 0xd7, 0xf8, 0x3f, 0x7f, 0xf2, 0x50, 0x7f, 0x42, 0xf6, 0x8c, 0xad, 0xfb, 0x45, 0x77, 0xf0, 0x9e, 0x77, 0xec, 0xcf,+ 0x8b, 0xff, 0x91, 0x0a, 0x85, 0xc7, 0xf7, 0x5d, 0xee, 0x70, 0x9d, 0xbc, 0xa2, 0x1e, 0xe2, 0x3d, 0xf6, 0x3b, 0x8b, 0xe6,+ 0xa2, 0x7b, 0x3f, 0xc9, 0x71, 0x07, 0xff, 0x9e, 0x4f, 0x0d, 0x6a, 0xfd, 0x78, 0xf5, 0xf6, 0x67, 0xf5, 0xc6, 0x2b, 0xf6,+ 0x5b, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xa7, 0x95, 0x3c, 0x39, 0x59,+ 0x05, 0xbc, 0x75, 0xd5, 0x2e, 0xfa, 0x55, 0xb5, 0x66, 0x6a, 0x26, 0x54, 0xc9, 0x7c, 0xb4, 0xf6, 0x66, 0xbf, 0xfc, 0x68,+ 0xb6, 0xc1, 0x77, 0x86, 0xab, 0x56, 0xf3, 0xfd, 0x69, 0xbd, 0x78, 0xb5, 0xcf, 0x57, 0x6b, 0xa6, 0x8e, 0xd5, 0x8b, 0x3d,+ 0x5b, 0x29, 0xfd, 0x59, 0x1c, 0xcf, 0x56, 0x55, 0x80, 0x3d, 0x7a, 0xe7, 0xf3, 0x7a, 0xbe, 0xd6, 0x03, 0x32, 0x1e, 0xfd,+ 0xdf, 0xa1, 0x07, 0x65, 0x59, 0x5e, 0xb1, 0x72, 0x9f, 0x3f, 0xf4, 0x50, 0x9e, 0x94, 0x03, 0xb4, 0xad, 0x65, 0xdf, 0x6f,+ 0xb5, 0xf5, 0xf1, 0x3e, 0xa7, 0xb1, 0xb2, 0xdf, 0xbd, 0xb6, 0x8e, 0xd4, 0xf3, 0x85, 0x96, 0x2b, 0xe2, 0xf3, 0xaa, 0xa8,+ 0xaf, 0xb3, 0xb5, 0xe5, 0x68, 0xb7, 0x37, 0x39, 0x56, 0xf1, 0xcf, 0xac, 0x39, 0xff, 0x9d, 0x7a, 0x7d, 0x86, 0xda, 0x42,+ 0xfc, 0x23, 0xfe, 0xbf, 0x5b, 0xaf, 0x17, 0xff, 0x7c, 0xdf, 0xfc, 0x7f, 0x1f, 0xaa, 0x17, 0xbf, 0xdd, 0x6a, 0xeb, 0xf8,+ 0xb5, 0xd0, 0x7d, 0xb6, 0xde, 0xb5, 0x0a, 0x22, 0x70, 0xc5, 0x1d, 0xd8, 0xb1, 0x27, 0xb8, 0xc0, 0x6b, 0xe4, 0x60, 0x95,+ 0xb8, 0x36, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xe2, 0xdf, 0x7f, 0xda, 0x01, 0xc4, 0x3f,+ 0xf0, 0xed, 0xe2, 0xff, 0x1f };++// Font glyphs rectangles data (on atlas)+static const Rectangle cyberFontRecs[189] = {+ { 4, 4, 4 , 14 },+ { 16, 4, 1 , 8 },+ { 25, 4, 4 , 3 },+ { 37, 4, 8 , 8 },+ { 53, 4, 8 , 9 },+ { 69, 4, 8 , 8 },+ { 85, 4, 8 , 8 },+ { 101, 4, 1 , 3 },+ { 110, 4, 4 , 9 },+ { 122, 4, 4 , 9 },+ { 134, 4, 5 , 6 },+ { 147, 4, 5 , 6 },+ { 160, 4, 2 , 2 },+ { 170, 4, 4 , 1 },+ { 182, 4, 1 , 1 },+ { 191, 4, 8 , 8 },+ { 207, 4, 8 , 8 },+ { 223, 4, 2 , 8 },+ { 233, 4, 8 , 8 },+ { 249, 4, 8 , 8 },+ { 265, 4, 8 , 8 },+ { 281, 4, 8 , 8 },+ { 297, 4, 8 , 8 },+ { 313, 4, 7 , 8 },+ { 328, 4, 8 , 8 },+ { 344, 4, 8 , 8 },+ { 360, 4, 1 , 4 },+ { 369, 4, 2 , 5 },+ { 379, 4, 4 , 8 },+ { 391, 4, 5 , 3 },+ { 404, 4, 4 , 8 },+ { 416, 4, 7 , 8 },+ { 431, 4, 8 , 8 },+ { 447, 4, 8 , 8 },+ { 463, 4, 8 , 8 },+ { 479, 4, 8 , 8 },+ { 495, 4, 8 , 8 },+ { 4, 26, 7 , 8 },+ { 19, 26, 7 , 8 },+ { 34, 26, 8 , 8 },+ { 50, 26, 8 , 8 },+ { 66, 26, 5 , 8 },+ { 79, 26, 7 , 8 },+ { 94, 26, 8 , 8 },+ { 110, 26, 7 , 8 },+ { 125, 26, 8 , 8 },+ { 141, 26, 8 , 8 },+ { 157, 26, 8 , 8 },+ { 173, 26, 8 , 8 },+ { 189, 26, 8 , 9 },+ { 205, 26, 8 , 8 },+ { 221, 26, 8 , 8 },+ { 237, 26, 8 , 8 },+ { 253, 26, 8 , 8 },+ { 269, 26, 8 , 8 },+ { 285, 26, 9 , 8 },+ { 302, 26, 8 , 8 },+ { 318, 26, 8 , 8 },+ { 334, 26, 8 , 8 },+ { 350, 26, 4 , 9 },+ { 362, 26, 8 , 8 },+ { 378, 26, 4 , 9 },+ { 390, 26, 4 , 3 },+ { 402, 26, 7 , 1 },+ { 417, 26, 2 , 3 },+ { 427, 26, 7 , 5 },+ { 442, 26, 7 , 8 },+ { 457, 26, 7 , 5 },+ { 472, 26, 7 , 8 },+ { 487, 26, 7 , 5 },+ { 4, 48, 4 , 8 },+ { 16, 48, 7 , 7 },+ { 31, 48, 7 , 8 },+ { 46, 48, 1 , 8 },+ { 55, 48, 3 , 10 },+ { 66, 48, 7 , 8 },+ { 81, 48, 4 , 8 },+ { 93, 48, 9 , 5 },+ { 110, 48, 7 , 5 },+ { 125, 48, 7 , 5 },+ { 140, 48, 7 , 7 },+ { 155, 48, 7 , 7 },+ { 170, 48, 5 , 5 },+ { 183, 48, 7 , 5 },+ { 198, 48, 5 , 8 },+ { 211, 48, 7 , 5 },+ { 226, 48, 7 , 5 },+ { 241, 48, 9 , 5 },+ { 258, 48, 7 , 5 },+ { 273, 48, 7 , 7 },+ { 288, 48, 7 , 5 },+ { 303, 48, 4 , 9 },+ { 315, 48, 1 , 9 },+ { 324, 48, 4 , 9 },+ { 336, 48, 8 , 2 },+ { 352, 48, 1 , 8 },+ { 361, 48, 7 , 8 },+ { 376, 48, 7 , 8 },+ { 391, 48, 8 , 9 },+ { 407, 48, 8 , 9 },+ { 423, 48, 8 , 10 },+ { 439, 48, 4 , 9 },+ { 451, 48, 7 , 8 },+ { 466, 48, 8 , 8 },+ { 482, 48, 7 , 6 },+ { 497, 48, 5 , 3 },+ { 4, 70, 5 , 3 },+ { 17, 70, 8 , 8 },+ { 33, 70, 0 , 0 },+ { 41, 70, 4 , 3 },+ { 53, 70, 8 , 6 },+ { 69, 70, 4 , 5 },+ { 81, 70, 4 , 5 },+ { 93, 70, 8 , 10 },+ { 109, 70, 7 , 7 },+ { 124, 70, 5 , 7 },+ { 137, 70, 1 , 1 },+ { 146, 70, 7 , 8 },+ { 161, 70, 2 , 5 },+ { 171, 70, 4 , 5 },+ { 183, 70, 5 , 3 },+ { 196, 70, 14 , 8 },+ { 218, 70, 13 , 5 },+ { 239, 70, 8 , 9 },+ { 255, 70, 7 , 8 },+ { 270, 70, 8 , 10 },+ { 286, 70, 8 , 10 },+ { 302, 70, 8 , 10 },+ { 318, 70, 8 , 10 },+ { 334, 70, 8 , 9 },+ { 350, 70, 8 , 12 },+ { 366, 70, 14 , 8 },+ { 388, 70, 8 , 10 },+ { 404, 70, 7 , 10 },+ { 419, 70, 7 , 10 },+ { 434, 70, 7 , 10 },+ { 449, 70, 7 , 9 },+ { 464, 70, 5 , 10 },+ { 477, 70, 5 , 10 },+ { 490, 70, 5 , 10 },+ { 4, 92, 5 , 9 },+ { 17, 92, 8 , 8 },+ { 33, 92, 8 , 10 },+ { 49, 92, 8 , 10 },+ { 65, 92, 8 , 10 },+ { 81, 92, 8 , 10 },+ { 97, 92, 8 , 10 },+ { 113, 92, 8 , 9 },+ { 129, 92, 4 , 4 },+ { 141, 92, 8 , 8 },+ { 157, 92, 8 , 10 },+ { 173, 92, 8 , 10 },+ { 189, 92, 8 , 10 },+ { 205, 92, 8 , 9 },+ { 221, 92, 8 , 10 },+ { 237, 92, 7 , 9 },+ { 252, 92, 7 , 9 },+ { 267, 92, 7 , 8 },+ { 282, 92, 7 , 8 },+ { 297, 92, 7 , 8 },+ { 312, 92, 7 , 8 },+ { 327, 92, 7 , 8 },+ { 342, 92, 7 , 9 },+ { 357, 92, 13 , 5 },+ { 378, 92, 7 , 7 },+ { 393, 92, 7 , 8 },+ { 408, 92, 7 , 8 },+ { 423, 92, 7 , 8 },+ { 438, 92, 7 , 8 },+ { 453, 92, 3 , 8 },+ { 464, 92, 2 , 8 },+ { 474, 92, 3 , 8 },+ { 485, 92, 3 , 8 },+ { 4, 114, 8 , 8 },+ { 20, 114, 7 , 8 },+ { 35, 114, 7 , 8 },+ { 50, 114, 7 , 8 },+ { 65, 114, 7 , 8 },+ { 80, 114, 7 , 8 },+ { 95, 114, 7 , 8 },+ { 110, 114, 5 , 6 },+ { 123, 114, 7 , 5 },+ { 138, 114, 7 , 8 },+ { 153, 114, 7 , 8 },+ { 168, 114, 7 , 8 },+ { 183, 114, 7 , 8 },+ { 198, 114, 7 , 10 },+ { 213, 114, 7 , 10 },+ { 228, 114, 7 , 10 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo cyberFontGlyphs[189] = {+ { 32, 0, 11, 4, { 0 }},+ { 33, 0, 3, 2, { 0 }},+ { 34, 0, 3, 4, { 0 }},+ { 35, 0, 3, 8, { 0 }},+ { 36, 0, 3, 8, { 0 }},+ { 37, 0, 3, 8, { 0 }},+ { 38, 0, 3, 8, { 0 }},+ { 39, 0, 3, 2, { 0 }},+ { 40, 0, 3, 4, { 0 }},+ { 41, 0, 3, 4, { 0 }},+ { 42, 0, 4, 6, { 0 }},+ { 43, 0, 4, 6, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 7, 5, { 0 }},+ { 46, 0, 10, 2, { 0 }},+ { 47, 0, 3, 8, { 0 }},+ { 48, 0, 3, 8, { 0 }},+ { 49, 0, 3, 3, { 0 }},+ { 50, 0, 3, 8, { 0 }},+ { 51, 0, 3, 8, { 0 }},+ { 52, 0, 3, 8, { 0 }},+ { 53, 0, 3, 8, { 0 }},+ { 54, 0, 3, 8, { 0 }},+ { 55, 0, 3, 7, { 0 }},+ { 56, 0, 3, 8, { 0 }},+ { 57, 0, 3, 8, { 0 }},+ { 58, 0, 6, 2, { 0 }},+ { 59, 0, 6, 3, { 0 }},+ { 60, 0, 3, 5, { 0 }},+ { 61, 0, 6, 6, { 0 }},+ { 62, 0, 3, 5, { 0 }},+ { 63, 0, 3, 7, { 0 }},+ { 64, 0, 3, 8, { 0 }},+ { 65, 0, 3, 8, { 0 }},+ { 66, 0, 3, 8, { 0 }},+ { 67, 0, 3, 8, { 0 }},+ { 68, 0, 3, 8, { 0 }},+ { 69, 0, 3, 7, { 0 }},+ { 70, 0, 3, 7, { 0 }},+ { 71, 0, 3, 8, { 0 }},+ { 72, 0, 3, 8, { 0 }},+ { 73, 0, 3, 6, { 0 }},+ { 74, 0, 3, 7, { 0 }},+ { 75, 0, 3, 8, { 0 }},+ { 76, 0, 3, 7, { 0 }},+ { 77, 0, 3, 9, { 0 }},+ { 78, 0, 3, 8, { 0 }},+ { 79, 0, 3, 8, { 0 }},+ { 80, 0, 3, 8, { 0 }},+ { 81, 0, 3, 8, { 0 }},+ { 82, 0, 3, 8, { 0 }},+ { 83, 0, 3, 8, { 0 }},+ { 84, 0, 3, 8, { 0 }},+ { 85, 0, 3, 8, { 0 }},+ { 86, 0, 3, 8, { 0 }},+ { 87, 0, 3, 10, { 0 }},+ { 88, 0, 3, 8, { 0 }},+ { 89, 0, 3, 8, { 0 }},+ { 90, 0, 3, 8, { 0 }},+ { 91, 0, 3, 4, { 0 }},+ { 92, 0, 3, 8, { 0 }},+ { 93, 0, 3, 4, { 0 }},+ { 94, 0, 3, 4, { 0 }},+ { 95, 0, 11, 7, { 0 }},+ { 96, 0, 3, 3, { 0 }},+ { 97, 0, 6, 7, { 0 }},+ { 98, 0, 3, 7, { 0 }},+ { 99, 0, 6, 7, { 0 }},+ { 100, 0, 3, 7, { 0 }},+ { 101, 0, 6, 7, { 0 }},+ { 102, 0, 3, 5, { 0 }},+ { 103, 0, 6, 7, { 0 }},+ { 104, 0, 3, 7, { 0 }},+ { 105, 0, 3, 2, { 0 }},+ { 106, -2, 3, 2, { 0 }},+ { 107, 0, 3, 7, { 0 }},+ { 108, 0, 3, 4, { 0 }},+ { 109, 0, 6, 10, { 0 }},+ { 110, 0, 6, 7, { 0 }},+ { 111, 0, 6, 7, { 0 }},+ { 112, 0, 6, 7, { 0 }},+ { 113, 0, 6, 7, { 0 }},+ { 114, 0, 6, 6, { 0 }},+ { 115, 0, 6, 7, { 0 }},+ { 116, 0, 3, 6, { 0 }},+ { 117, 0, 6, 7, { 0 }},+ { 118, 0, 6, 7, { 0 }},+ { 119, 0, 6, 10, { 0 }},+ { 120, 0, 6, 7, { 0 }},+ { 121, 0, 6, 7, { 0 }},+ { 122, 0, 6, 7, { 0 }},+ { 123, 0, 3, 5, { 0 }},+ { 124, 0, 3, 2, { 0 }},+ { 125, 0, 3, 5, { 0 }},+ { 126, 0, 6, 8, { 0 }},+ { 161, 0, 3, 2, { 0 }},+ { 162, 0, 4, 7, { 0 }},+ { 163, 0, 3, 7, { 0 }},+ { 8364, 0, 3, 9, { 0 }},+ { 165, 0, 3, 8, { 0 }},+ { 352, 0, 1, 8, { 0 }},+ { 167, 0, 4, 5, { 0 }},+ { 353, 0, 3, 7, { 0 }},+ { 169, 0, 3, 9, { 0 }},+ { 170, 0, 3, 7, { 0 }},+ { 171, 0, 6, 6, { 0 }},+ { 172, 0, 7, 6, { 0 }},+ { 174, 0, 3, 9, { 0 }},+ { 175, 0, 11, 3, { 0 }},+ { 176, 0, 3, 4, { 0 }},+ { 177, 0, 6, 8, { 0 }},+ { 178, 0, 3, 4, { 0 }},+ { 179, 0, 3, 4, { 0 }},+ { 381, 0, 1, 8, { 0 }},+ { 181, 0, 6, 7, { 0 }},+ { 182, 0, 4, 6, { 0 }},+ { 183, 0, 7, 2, { 0 }},+ { 382, 0, 3, 7, { 0 }},+ { 185, 0, 3, 4, { 0 }},+ { 186, 0, 3, 5, { 0 }},+ { 187, 0, 6, 6, { 0 }},+ { 338, 0, 3, 14, { 0 }},+ { 339, 0, 6, 13, { 0 }},+ { 376, 0, 2, 8, { 0 }},+ { 191, 0, 3, 7, { 0 }},+ { 192, 0, 1, 8, { 0 }},+ { 193, 0, 1, 8, { 0 }},+ { 194, 0, 1, 8, { 0 }},+ { 195, 0, 1, 8, { 0 }},+ { 196, 0, 2, 8, { 0 }},+ { 197, 0, -1, 8, { 0 }},+ { 198, 0, 3, 14, { 0 }},+ { 199, 0, 3, 8, { 0 }},+ { 200, 0, 1, 7, { 0 }},+ { 201, 0, 1, 7, { 0 }},+ { 202, 0, 1, 7, { 0 }},+ { 203, 0, 2, 7, { 0 }},+ { 204, 0, 1, 6, { 0 }},+ { 205, 0, 1, 6, { 0 }},+ { 206, 0, 1, 6, { 0 }},+ { 207, 0, 2, 6, { 0 }},+ { 208, 0, 3, 9, { 0 }},+ { 209, 0, 1, 8, { 0 }},+ { 210, 0, 1, 8, { 0 }},+ { 211, 0, 1, 8, { 0 }},+ { 212, 0, 1, 8, { 0 }},+ { 213, 0, 1, 8, { 0 }},+ { 214, 0, 2, 8, { 0 }},+ { 215, 1, 6, 6, { 0 }},+ { 216, 0, 3, 8, { 0 }},+ { 217, 0, 1, 8, { 0 }},+ { 218, 0, 1, 8, { 0 }},+ { 219, 0, 1, 8, { 0 }},+ { 220, 0, 2, 8, { 0 }},+ { 221, 0, 1, 8, { 0 }},+ { 222, 0, 3, 7, { 0 }},+ { 223, 0, 3, 7, { 0 }},+ { 224, 0, 3, 7, { 0 }},+ { 225, 0, 3, 7, { 0 }},+ { 226, 0, 3, 7, { 0 }},+ { 227, 0, 3, 7, { 0 }},+ { 228, 0, 3, 7, { 0 }},+ { 229, 0, 2, 7, { 0 }},+ { 230, 0, 6, 13, { 0 }},+ { 231, 0, 6, 7, { 0 }},+ { 232, 0, 3, 7, { 0 }},+ { 233, 0, 3, 7, { 0 }},+ { 234, 0, 3, 7, { 0 }},+ { 235, 0, 3, 7, { 0 }},+ { 236, -1, 3, 2, { 0 }},+ { 237, 0, 3, 2, { 0 }},+ { 238, -1, 3, 2, { 0 }},+ { 239, -1, 3, 2, { 0 }},+ { 240, 0, 3, 8, { 0 }},+ { 241, 0, 3, 7, { 0 }},+ { 242, 0, 3, 7, { 0 }},+ { 243, 0, 3, 7, { 0 }},+ { 244, 0, 3, 7, { 0 }},+ { 245, 0, 3, 7, { 0 }},+ { 246, 0, 3, 7, { 0 }},+ { 247, 0, 4, 6, { 0 }},+ { 248, 0, 6, 7, { 0 }},+ { 249, 0, 3, 7, { 0 }},+ { 250, 0, 3, 7, { 0 }},+ { 251, 0, 3, 7, { 0 }},+ { 252, 0, 3, 7, { 0 }},+ { 253, 0, 3, 7, { 0 }},+ { 254, 0, 3, 7, { 0 }},+ { 255, 0, 3, 7, { 0 }},+};++// Style loading function: Cyber+static void GuiLoadStyleCyber(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < CYBER_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(cyberStyleProps[i].controlId, cyberStyleProps[i].propertyId, cyberStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int cyberFontDataSize = 0;+ unsigned char *data = DecompressData(cyberFontData, CYBER_STYLE_FONT_ATLAS_COMP_SIZE, &cyberFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 14;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, cyberFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, cyberFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/dark/style_dark.h view
@@ -0,0 +1,589 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleDark(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define DARK_STYLE_PROPS_COUNT 23++// Custom style name: Dark+static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING + { 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED + { 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED + { 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED + { 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED + { 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED + { 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED +};++// WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0)++#define DARK_STYLE_FONT_ATLAS_COMP_SIZE 2126++// Font atlas image pixels data: DEFLATE compressed+static unsigned char darkFontData[DARK_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0xdb, 0x72, 0xa4, 0x3a, 0x12, 0x05, 0x50, 0xfd, 0xff, 0x4f, 0xe7, 0x3c, 0x4c, 0x4c, 0x4c, 0x74, 0x9c, 0xd3, 0x20,+ 0xa5, 0x52, 0x17, 0xec, 0xd5, 0xeb, 0xcd, 0xe5, 0x76, 0x51, 0xa0, 0x94, 0x84, 0x28, 0x36, 0xd1, 0x00, 0x00, 0x00, 0x80,+ 0x5f, 0x2f, 0xfe, 0xf5, 0x27, 0xf1, 0xd7, 0xdf, 0x8c, 0xee, 0xbf, 0xf3, 0xfc, 0xf3, 0xff, 0xbd, 0x1a, 0x0f, 0xef, 0xd5,+ 0xb7, 0xad, 0xa3, 0xef, 0x1b, 0x03, 0x7b, 0xe2, 0xdf, 0xb7, 0x2f, 0xba, 0xff, 0xee, 0xdf, 0x3e, 0xdf, 0xf8, 0xef, 0x3f,+ 0xfd, 0xa5, 0xe7, 0xad, 0x8f, 0xa1, 0xfd, 0x3e, 0xfe, 0x7f, 0xc6, 0x8e, 0x62, 0x2c, 0xd9, 0xf7, 0xef, 0x5b, 0x37, 0xbe,+ 0xed, 0x95, 0xff, 0x27, 0x1e, 0x3e, 0x4f, 0xe6, 0x28, 0xf5, 0xd4, 0xd6, 0x0d, 0xf5, 0x1f, 0x5d, 0x95, 0x18, 0xa5, 0x2d,+ 0xe7, 0xff, 0xef, 0x1a, 0x85, 0x3d, 0x55, 0x76, 0x4f, 0x3e, 0x55, 0xfa, 0xf8, 0xfe, 0x78, 0x6a, 0xfd, 0xe3, 0x3d, 0x60,+ 0x94, 0x7c, 0x96, 0xf9, 0xd6, 0x18, 0xd3, 0xbf, 0xdd, 0xd7, 0x92, 0x6a, 0x3e, 0xd5, 0xcc, 0x2b, 0xad, 0xe4, 0x28, 0x9d,+ 0xa8, 0xff, 0x48, 0xf7, 0x54, 0x31, 0x58, 0xd1, 0x15, 0x7b, 0x30, 0xd3, 0x0f, 0xb7, 0x8d, 0xf5, 0x1f, 0xa5, 0x73, 0x97,+ 0x28, 0x6b, 0x73, 0x27, 0xea, 0xff, 0x79, 0xd4, 0x6e, 0x25, 0xed, 0x26, 0x5e, 0xf6, 0x51, 0x6d, 0x2d, 0xaf, 0x9d, 0xa7,+ 0xae, 0xae, 0xff, 0xe7, 0xdf, 0x1c, 0x1d, 0x6f, 0x63, 0x70, 0xec, 0xae, 0xd8, 0x4f, 0xb9, 0xf1, 0xbf, 0x7e, 0x3f, 0xc6,+ 0x5f, 0xc7, 0xe6, 0xec, 0x3c, 0x64, 0x64, 0x0f, 0xc7, 0xe0, 0xd9, 0xd5, 0xec, 0x08, 0x7b, 0x72, 0xfc, 0xef, 0x9b, 0x0b,+ 0xaa, 0xff, 0xb5, 0xf5, 0x9f, 0xf9, 0x24, 0xd1, 0xb9, 0x05, 0x99, 0x31, 0xb1, 0x5d, 0x50, 0xff, 0xa3, 0xfd, 0xd0, 0xf3,+ 0xbe, 0xaa, 0x9a, 0xcb, 0x8f, 0xae, 0x4b, 0xf4, 0x9d, 0x61, 0xef, 0x6b, 0x85, 0xe3, 0x73, 0xa3, 0xf1, 0xfa, 0x1f, 0xef,+ 0x3d, 0xdf, 0xfe, 0xda, 0xe8, 0x5e, 0xfd, 0xfb, 0x99, 0xdd, 0xfc, 0x1e, 0xdf, 0x57, 0xff, 0x91, 0x18, 0x53, 0xce, 0xd7,+ 0x73, 0x4d, 0xfd, 0x47, 0x62, 0xe5, 0xa2, 0x95, 0xad, 0xf2, 0xe5, 0xd6, 0x25, 0xea, 0xd6, 0x0c, 0xce, 0x1f, 0x81, 0xf7,+ 0xfa, 0x7f, 0x3b, 0x1f, 0x3c, 0x3f, 0xfe, 0xc7, 0x15, 0xe3, 0x7f, 0xa4, 0xd7, 0x86, 0x5b, 0xa2, 0xf7, 0xfd, 0x5a, 0xfd,+ 0x47, 0xa2, 0x66, 0xa2, 0xe4, 0xbc, 0xbc, 0x2d, 0x59, 0xcb, 0xab, 0x5d, 0x33, 0xdc, 0x73, 0xb4, 0xde, 0x46, 0xd1, 0xaa,+ 0xb3, 0x9a, 0x9f, 0x55, 0xff, 0xad, 0x60, 0xfc, 0xef, 0x9b, 0x03, 0xcc, 0x7e, 0x8e, 0xf8, 0xd8, 0xe8, 0x5f, 0x59, 0xff,+ 0xbb, 0x56, 0xec, 0xd7, 0xb7, 0xc6, 0xb8, 0xe2, 0xc8, 0x58, 0xff, 0xaf, 0x9c, 0xff, 0xe7, 0xd7, 0x00, 0xc6, 0xce, 0x63,+ 0xe2, 0xd2, 0xea, 0xcf, 0x9c, 0x33, 0x57, 0x5d, 0xb1, 0xaf, 0xfd, 0x36, 0x41, 0x24, 0xbe, 0xab, 0x51, 0xb3, 0x8a, 0xb3,+ 0xfa, 0x18, 0x8c, 0x8f, 0xff, 0xbb, 0xae, 0xff, 0xbf, 0xcf, 0xb9, 0xef, 0x18, 0xff, 0xdb, 0xeb, 0xe8, 0x7e, 0xcb, 0xf6,+ 0x00, 0x7b, 0x7b, 0x80, 0x50, 0xfd, 0xe0, 0x7b, 0xc4, 0x80, 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x0a, 0xbf, 0x9f, 0x5f, 0x9f, 0x63, 0x30, 0x9e, 0x84, 0xbd, 0x3e, 0x81, 0x7d, 0x26, 0x13, 0x38, 0xbb,+ 0x87, 0xaa, 0xfe, 0xe2, 0x73, 0x76, 0xfc, 0x48, 0xd2, 0x42, 0x7f, 0xcb, 0x88, 0xe1, 0xa7, 0x1f, 0x54, 0x26, 0x0a, 0x64,+ 0x32, 0x0d, 0xda, 0x60, 0x9b, 0xa8, 0xcd, 0x52, 0x1a, 0xdb, 0xfa, 0x3d, 0x2d, 0xfe, 0x0b, 0xf5, 0x7f, 0xfe, 0x95, 0x96,+ 0xc8, 0xef, 0xd9, 0x59, 0xff, 0xa3, 0x6d, 0x2f, 0x97, 0x8f, 0x3b, 0x37, 0x96, 0xec, 0x4e, 0x14, 0x8b, 0xc2, 0x63, 0xb8,+ 0x6f, 0x5c, 0xfd, 0x33, 0x43, 0x67, 0x47, 0xbb, 0x9e, 0xa9, 0xff, 0xd1, 0xec, 0xd3, 0x78, 0xe8, 0x85, 0xef, 0xa9, 0xff,+ 0xb6, 0xa5, 0xfe, 0xe3, 0x23, 0xf5, 0x5f, 0x9d, 0x24, 0x53, 0x95, 0x42, 0x9e, 0x49, 0xbe, 0x19, 0x3f, 0x86, 0xf9, 0x84,+ 0xdf, 0x6c, 0x8b, 0xfb, 0x4e, 0xfd, 0x67, 0xda, 0xd6, 0x73, 0xce, 0xaa, 0xfa, 0x7f, 0xdf, 0xb7, 0x99, 0xd1, 0x64, 0xfe,+ 0xe7, 0x35, 0x95, 0xbf, 0x27, 0x47, 0xf7, 0xed, 0x39, 0x5a, 0x6b, 0xdb, 0xca, 0xec, 0x58, 0xf9, 0x95, 0xfa, 0x8f, 0xe4,+ 0x5f, 0x89, 0x97, 0x1e, 0xa5, 0x36, 0x81, 0xbd, 0x26, 0xb5, 0x6d, 0x6f, 0xfd, 0x57, 0x3f, 0xf7, 0xe7, 0x8e, 0xfa, 0x3f,+ 0x9f, 0xa3, 0xbb, 0xea, 0x1c, 0xae, 0x76, 0xac, 0xfc, 0xd9, 0xe3, 0xff, 0x7b, 0x2f, 0xb9, 0xa3, 0x7d, 0xcc, 0x8c, 0xf4,+ 0x27, 0xc7, 0xff, 0x73, 0x3f, 0x3f, 0x5b, 0xff, 0x55, 0xad, 0x3d, 0x36, 0xce, 0x4c, 0xb2, 0x63, 0xe5, 0xce, 0x55, 0xb2,+ 0xdd, 0xe7, 0xff, 0xab, 0x3e, 0x59, 0x1b, 0x9e, 0x4d, 0xc4, 0xb5, 0xf5, 0x3f, 0xb3, 0x0a, 0xb9, 0x6e, 0xbe, 0x70, 0x66,+ 0xfe, 0x9f, 0x7b, 0xbe, 0x6d, 0xe6, 0xa9, 0x80, 0xb7, 0x8d, 0xff, 0xbb, 0xae, 0x92, 0xb5, 0xcd, 0x35, 0xb9, 0xf7, 0xbd,+ 0x2a, 0x9f, 0x52, 0x37, 0x9e, 0xdf, 0x1f, 0xc5, 0x33, 0xbc, 0xaf, 0xd7, 0x7f, 0x7e, 0x95, 0xbf, 0x15, 0xad, 0x4a, 0x9e,+ 0x9b, 0xff, 0xef, 0x7e, 0xd2, 0x49, 0xe6, 0x5d, 0x6a, 0xfa, 0xdf, 0xbe, 0xab, 0xc2, 0xb5, 0xa3, 0xc0, 0xdf, 0xaf, 0x36,+ 0x44, 0xd1, 0xc8, 0x51, 0x95, 0xdf, 0xff, 0xe7, 0xb6, 0x8d, 0x3f, 0xf1, 0x6c, 0xfc, 0x4a, 0x7c, 0x0c, 0x3e, 0x4f, 0xff,+ 0x44, 0xfd, 0x67, 0xde, 0x39, 0xf3, 0xbf, 0x46, 0x8f, 0x61, 0x65, 0xfd, 0x9f, 0xeb, 0x01, 0xe4, 0x6e, 0xc2, 0x8d, 0xb3,+ 0x18, 0xe0, 0xe7, 0xf4, 0x00, 0x9e, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0xec, 0xbe, 0x13, 0xfb, 0xef, 0xd9, 0x5c, 0x99, 0xd4, 0xf8, 0xf1, 0xfb, 0xa4, 0x77, 0x26, 0xe6, 0xb7, 0x97, 0x14, 0xb2,+ 0xe7, 0xdf, 0xfa, 0xf3, 0x95, 0x8a, 0x3c, 0xde, 0x28, 0xbc, 0x6b, 0xfd, 0x29, 0x93, 0xe4, 0x39, 0x4b, 0x71, 0x34, 0x77,+ 0xe0, 0x7d, 0x0f, 0x8f, 0x1f, 0x97, 0x99, 0xd7, 0x5a, 0x61, 0x9a, 0x42, 0x24, 0xd2, 0x5e, 0xde, 0xf6, 0x7a, 0x7f, 0x36,+ 0x70, 0x94, 0x6d, 0xf1, 0x58, 0x1d, 0x55, 0x65, 0x27, 0xdf, 0x9e, 0x98, 0x3f, 0x9f, 0xbc, 0x13, 0x2f, 0xad, 0xae, 0xbf,+ 0xfe, 0x7b, 0x92, 0x23, 0xd6, 0xe7, 0x18, 0xf5, 0xfc, 0x34, 0x93, 0x7a, 0x31, 0x96, 0xc1, 0x36, 0xd7, 0x06, 0x56, 0x8f,+ 0x50, 0x6d, 0xb2, 0x42, 0x62, 0xaa, 0xa5, 0xcc, 0x67, 0xff, 0xbd, 0x6f, 0x69, 0x1b, 0x1c, 0xb9, 0x6e, 0x48, 0xcc, 0x8c,+ 0xce, 0xfa, 0xaa, 0xfe, 0x69, 0x1b, 0xec, 0x6f, 0x32, 0x79, 0x75, 0x51, 0x9a, 0x44, 0x91, 0xff, 0x3f, 0x91, 0x48, 0x6d,+ 0x6e, 0xc9, 0x2c, 0xbe, 0x7c, 0x46, 0x7c, 0x26, 0xa7, 0x2a, 0x16, 0xef, 0xd9, 0x4c, 0xfd, 0xb7, 0x43, 0xf5, 0x9f, 0x49,+ 0x3d, 0x38, 0x9f, 0x98, 0x1d, 0xa9, 0xda, 0xdd, 0x5b, 0xff, 0xd1, 0xd1, 0x7f, 0x65, 0x66, 0xd7, 0x51, 0x78, 0xce, 0xf0,+ 0x3e, 0xe3, 0xad, 0x1e, 0xff, 0xdb, 0xe3, 0x7e, 0x1a, 0x4f, 0x75, 0x5b, 0x3f, 0x42, 0x65, 0x7a, 0x93, 0xb1, 0xfa, 0x5f,+ 0xdd, 0x63, 0xcd, 0x3c, 0x07, 0x29, 0x3e, 0x37, 0xfe, 0x9f, 0x49, 0xcc, 0x8e, 0xc4, 0xd9, 0x75, 0xe6, 0x7d, 0xeb, 0xd7,+ 0x5e, 0xa2, 0xb0, 0xfe, 0x33, 0x3d, 0x40, 0xbe, 0xfe, 0x77, 0xce, 0xa6, 0xb3, 0x79, 0x93, 0x31, 0xdd, 0x86, 0xce, 0xd4,+ 0x7f, 0xe5, 0xd3, 0x96, 0x56, 0x24, 0xe6, 0x8e, 0x3f, 0xd9, 0xf1, 0xd4, 0xf8, 0xdf, 0x52, 0xe3, 0x7f, 0x6e, 0x9c, 0xa8,+ 0x3b, 0xf6, 0xb5, 0x73, 0xe5, 0xf7, 0xfa, 0x8f, 0x0d, 0xef, 0xb6, 0xaf, 0xfe, 0x33, 0x3d, 0x61, 0x2c, 0x9b, 0xff, 0x67,+ 0xab, 0x25, 0x86, 0xe7, 0xd7, 0x3b, 0x13, 0x73, 0x33, 0xeb, 0xcc, 0xf7, 0xd7, 0x7f, 0xe5, 0x33, 0x4c, 0xda, 0x54, 0xfa,+ 0x72, 0x94, 0x8e, 0xc8, 0xfb, 0xc6, 0xff, 0x15, 0xb3, 0xe9, 0x4c, 0xfa, 0xfe, 0x3d, 0xeb, 0x7f, 0xad, 0xf8, 0x88, 0xb5,+ 0xe3, 0x79, 0x88, 0x2b, 0x66, 0x85, 0x27, 0xce, 0xff, 0xab, 0x12, 0xd8, 0x73, 0xe7, 0xff, 0xd5, 0x2b, 0xf2, 0x73, 0xc7,+ 0xf2, 0xde, 0xf1, 0x3f, 0xd7, 0x42, 0x62, 0x68, 0x7c, 0x6e, 0x9f, 0xaa, 0xff, 0x5b, 0xbe, 0xd1, 0x50, 0xd1, 0x6f, 0x45,+ 0x49, 0xef, 0x96, 0x79, 0x6e, 0x4b, 0xe5, 0x3c, 0xaa, 0x72, 0xfd, 0x6a, 0xe6, 0xfa, 0xff, 0xcc, 0xb7, 0x53, 0x56, 0xbf,+ 0x5b, 0xfe, 0xfa, 0xff, 0xda, 0xfa, 0x8f, 0xe2, 0x2d, 0xe6, 0x9e, 0x5e, 0xea, 0xe6, 0xf7, 0xd3, 0x7e, 0xee, 0x38, 0x82,+ 0x6a, 0x59, 0xeb, 0x39, 0x71, 0x3e, 0xc4, 0xef, 0x9a, 0x33, 0xf3, 0xd3, 0xbf, 0xe1, 0x6d, 0x3f, 0x18, 0x9b, 0x01, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xde, 0xc3, 0x14, 0xaf, 0x77, 0x38, 0xbc, 0x65, 0x4b,+ 0x64, 0x72, 0x29, 0x5b, 0x69, 0xce, 0x5d, 0x4b, 0x24, 0xf3, 0x67, 0xb7, 0xae, 0x77, 0xaf, 0xac, 0xff, 0x64, 0xb3, 0x69,+ 0xe6, 0x99, 0xc4, 0xf9, 0xcc, 0x3e, 0x3e, 0x7b, 0x34, 0xdf, 0x32, 0x3c, 0x22, 0x91, 0xc6, 0x5a, 0x79, 0xbc, 0x5a, 0x6a,+ 0xdf, 0x65, 0x5b, 0x59, 0x6f, 0x0f, 0xd0, 0x9f, 0x0f, 0x53, 0x7f, 0x8f, 0x69, 0xa4, 0xf6, 0x79, 0x4d, 0x32, 0xff, 0x4c,+ 0x5b, 0x6a, 0xe9, 0x04, 0xe2, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0x31, 0xfd, 0x97, 0xdf, 0xb3, 0x5a, 0xe3, 0x73, 0x47, 0x33,+ 0x9b, 0x17, 0x5f, 0x7d, 0xbc, 0x6a, 0xd3, 0xdb, 0x6a, 0x7a, 0x80, 0x8a, 0xfa, 0xaf, 0xdb, 0xca, 0xfd, 0xf7, 0xc6, 0x46,+ 0xf2, 0x7e, 0xfa, 0xf8, 0xfc, 0xfd, 0xa7, 0xf1, 0xd1, 0x24, 0x81, 0x5c, 0xca, 0xe4, 0xae, 0x4f, 0x95, 0xcb, 0xe5, 0xca,+ 0xa7, 0xb7, 0xed, 0x1c, 0xff, 0x33, 0x49, 0x52, 0x99, 0xb4, 0xd0, 0xea, 0x57, 0xb2, 0xbd, 0x65, 0xae, 0xfe, 0x33, 0x99,+ 0x4d, 0x51, 0x94, 0x67, 0x5c, 0xf7, 0xdc, 0x93, 0x48, 0xce, 0xaf, 0x4f, 0x1e, 0xcd, 0x78, 0x4d, 0x25, 0xaf, 0xca, 0xd8,+ 0xdd, 0xfb, 0x4a, 0x4c, 0x26, 0x3e, 0x44, 0xd7, 0xf1, 0x8e, 0xe9, 0xb1, 0x70, 0xd7, 0xd3, 0x02, 0x33, 0xcf, 0xa4, 0x68,+ 0xc9, 0xd4, 0xcc, 0x28, 0x9b, 0xe1, 0x57, 0xbf, 0xb2, 0xa2, 0xfe, 0xe3, 0xe1, 0x3c, 0xb9, 0xfa, 0x99, 0x65, 0xd5, 0x47,+ 0xb3, 0xa7, 0x67, 0xf8, 0x62, 0xfd, 0xaf, 0x9d, 0xa7, 0xd5, 0x9c, 0xff, 0x47, 0xfa, 0x59, 0x3c, 0x77, 0xb6, 0x98, 0xe8,+ 0x4c, 0x77, 0xfe, 0x69, 0xf5, 0xbf, 0x77, 0x1f, 0x57, 0xf7, 0xe6, 0xcf, 0x33, 0xec, 0xf6, 0xd1, 0xfa, 0x9f, 0x49, 0x8b,+ 0xaf, 0x39, 0x5f, 0x79, 0x5f, 0xff, 0xaf, 0x5c, 0xd9, 0xb8, 0xa3, 0xfe, 0x6f, 0xa9, 0xf2, 0xb1, 0x7d, 0xbe, 0xb6, 0xfe,+ 0xcf, 0xd7, 0xd0, 0x6c, 0xf2, 0xfb, 0xf9, 0x6d, 0x8f, 0xb2, 0xf3, 0xff, 0x9a, 0x75, 0xa1, 0xea, 0x79, 0xc4, 0x6d, 0x3d,+ 0xe8, 0xaa, 0xa7, 0xab, 0xbd, 0xcd, 0x1d, 0xaa, 0xcf, 0x77, 0xef, 0x18, 0xff, 0x43, 0xfd, 0x2f, 0x58, 0x0b, 0xaf, 0x1d,+ 0x25, 0xf3, 0x2b, 0xcc, 0x33, 0xfd, 0xc9, 0xf8, 0xb3, 0xec, 0x6b, 0x57, 0xc9, 0x32, 0x7d, 0x68, 0xcf, 0x2b, 0xf9, 0x27,+ 0x6e, 0x7c, 0x75, 0xfe, 0xdf, 0xf3, 0x54, 0xa0, 0x6f, 0xd5, 0x7f, 0x24, 0xd7, 0xb7, 0xee, 0xa8, 0xff, 0xb5, 0x57, 0x06,+ 0xd6, 0x5f, 0xcb, 0xbf, 0x79, 0xfe, 0xbf, 0xa2, 0xcf, 0xfb, 0x76, 0xfd, 0x7f, 0x61, 0x0e, 0xbd, 0xe6, 0x5b, 0x28, 0xe7,+ 0xea, 0x7f, 0x6e, 0xdc, 0x56, 0xff, 0x2b, 0x56, 0x8c, 0xf3, 0x9f, 0x7a, 0xc5, 0xf9, 0x7f, 0xef, 0x4c, 0xe3, 0xe7, 0xd7,+ 0x7f, 0x7d, 0xd2, 0xf9, 0x9a, 0xf3, 0xcd, 0x76, 0xe9, 0x77, 0x61, 0xee, 0xfa, 0x4e, 0xf2, 0x9e, 0x16, 0xb3, 0x66, 0xed,+ 0x23, 0xf3, 0x94, 0xde, 0xda, 0xa7, 0x39, 0xc5, 0xa2, 0x4a, 0xcf, 0x5d, 0xe5, 0xdd, 0x73, 0xfd, 0x7f, 0xef, 0x37, 0x8a,+ 0xaa, 0xb7, 0x50, 0xfd, 0x7f, 0xa3, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdb,+ 0xee, 0xd0, 0xdb, 0x9b, 0xa8, 0x5f, 0x9f, 0x82, 0x71, 0x7b, 0xa2, 0xfe, 0xdb, 0x5d, 0x33, 0xed, 0xda, 0x44, 0xfd, 0xd6,+ 0x95, 0x4c, 0xf4, 0xbd, 0x44, 0xfd, 0xdf, 0x78, 0xc7, 0xc7, 0x6d, 0x89, 0xfa, 0x75, 0x77, 0x4e, 0xdf, 0x9e, 0xa8, 0xdf,+ 0x5e, 0xf2, 0x87, 0x6e, 0x4e, 0xd4, 0xcf, 0xdf, 0x3b, 0x75, 0x6b, 0xa2, 0x3e, 0x6b, 0xef, 0x98, 0xec, 0xed, 0xfb, 0xe3,+ 0xe0, 0x31, 0x5b, 0x75, 0x77, 0x69, 0x7c, 0xf4, 0xce, 0xcf, 0xf1, 0x8c, 0xa6, 0x15, 0x3d, 0x4a, 0xe5, 0x5d, 0x9a, 0xeb,+ 0x13, 0xf5, 0x7f, 0x4a, 0xbd, 0xee, 0x4a, 0xd4, 0x7f, 0xcf, 0x19, 0x8b, 0x4d, 0xdb, 0x1f, 0x43, 0xf3, 0xc6, 0xb5, 0x89,+ 0x5a, 0xcf, 0xfd, 0xe8, 0xbd, 0xcf, 0x47, 0xf8, 0x76, 0xa2, 0xf6, 0x6f, 0xab, 0xff, 0x55, 0xfb, 0x29, 0x8a, 0xaa, 0xae,+ 0xf7, 0x95, 0x7d, 0x59, 0x41, 0x75, 0xf5, 0x1f, 0xe5, 0xaf, 0xed, 0x4d, 0xd4, 0xca, 0xae, 0x27, 0xa8, 0xff, 0xef, 0xac,+ 0x01, 0xe4, 0xd6, 0xad, 0xe6, 0x12, 0x75, 0x4f, 0xb6, 0x80, 0x9d, 0x89, 0x5a, 0x5f, 0xaf, 0xff, 0xcc, 0xac, 0x5c, 0xfd,+ 0xdf, 0x39, 0xff, 0x8f, 0xb2, 0x57, 0x32, 0xbd, 0x46, 0x7e, 0xfd, 0xff, 0xcb, 0x4f, 0xd4, 0xfa, 0x99, 0xf5, 0x7f, 0x47,+ 0xa2, 0xae, 0xfa, 0x3f, 0x33, 0xff, 0x5f, 0xf7, 0x54, 0x82, 0x9d, 0x89, 0xba, 0xc6, 0xff, 0x55, 0x15, 0x71, 0x77, 0x95,+ 0xdf, 0x95, 0x9b, 0xfb, 0xcd, 0xf3, 0xff, 0xdc, 0x93, 0x40, 0xb3, 0x3d, 0xc0, 0xbe, 0x84, 0xd6, 0x13, 0x89, 0xfa, 0x12,+ 0x75, 0x67, 0x8e, 0xd7, 0xf3, 0xec, 0xef, 0x9b, 0xd7, 0x63, 0x6e, 0x9f, 0xff, 0xd7, 0x5e, 0xab, 0xf9, 0xe7, 0x9a, 0xd2,+ 0xea, 0x15, 0xef, 0x55, 0xf3, 0xff, 0xda, 0x2b, 0x5b, 0x12, 0x75, 0xab, 0x8f, 0xda, 0x6f, 0x5f, 0xff, 0x3b, 0xdb, 0xd3,+ 0xc0, 0xee, 0x79, 0xed, 0xf9, 0x9e, 0x10, 0xf8, 0xda, 0x37, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf9, 0xef, 0x3f, 0xfb, 0x01, 0xd4, 0x3f,+ 0xf0, 0xeb, 0xea, 0xff, 0x3f };++// Font glyphs rectangles data (on atlas)+static const Rectangle darkFontRecs[189] = {+ { 4, 4, 4 , 16 },+ { 16, 4, 1 , 9 },+ { 25, 4, 3 , 3 },+ { 36, 4, 6 , 9 },+ { 50, 4, 5 , 13 },+ { 63, 4, 7 , 9 },+ { 78, 4, 5 , 9 },+ { 91, 4, 1 , 3 },+ { 100, 4, 3 , 9 },+ { 111, 4, 3 , 9 },+ { 122, 4, 5 , 5 },+ { 135, 4, 5 , 5 },+ { 148, 4, 2 , 3 },+ { 158, 4, 4 , 1 },+ { 170, 4, 1 , 1 },+ { 179, 4, 3 , 9 },+ { 190, 4, 5 , 9 },+ { 203, 4, 3 , 9 },+ { 214, 4, 5 , 9 },+ { 227, 4, 5 , 9 },+ { 240, 4, 5 , 9 },+ { 253, 4, 5 , 9 },+ { 266, 4, 5 , 9 },+ { 279, 4, 5 , 9 },+ { 292, 4, 5 , 9 },+ { 305, 4, 5 , 9 },+ { 318, 4, 1 , 7 },+ { 327, 4, 2 , 9 },+ { 337, 4, 3 , 5 },+ { 348, 4, 4 , 3 },+ { 360, 4, 3 , 5 },+ { 371, 4, 5 , 9 },+ { 384, 4, 7 , 9 },+ { 399, 4, 5 , 9 },+ { 412, 4, 5 , 9 },+ { 425, 4, 5 , 9 },+ { 438, 4, 5 , 9 },+ { 451, 4, 5 , 9 },+ { 464, 4, 5 , 9 },+ { 477, 4, 5 , 9 },+ { 490, 4, 5 , 9 },+ { 4, 28, 1 , 9 },+ { 13, 28, 5 , 9 },+ { 26, 28, 5 , 9 },+ { 39, 28, 5 , 9 },+ { 52, 28, 7 , 9 },+ { 67, 28, 5 , 9 },+ { 80, 28, 5 , 9 },+ { 93, 28, 5 , 9 },+ { 106, 28, 5 , 9 },+ { 119, 28, 5 , 9 },+ { 132, 28, 5 , 9 },+ { 145, 28, 5 , 9 },+ { 158, 28, 5 , 9 },+ { 171, 28, 5 , 9 },+ { 184, 28, 7 , 9 },+ { 199, 28, 5 , 9 },+ { 212, 28, 5 , 9 },+ { 225, 28, 5 , 9 },+ { 238, 28, 3 , 9 },+ { 249, 28, 3 , 9 },+ { 260, 28, 3 , 9 },+ { 271, 28, 5 , 3 },+ { 284, 28, 5 , 1 },+ { 297, 28, 2 , 2 },+ { 307, 28, 5 , 7 },+ { 320, 28, 5 , 9 },+ { 333, 28, 5 , 7 },+ { 346, 28, 5 , 9 },+ { 359, 28, 5 , 7 },+ { 372, 28, 4 , 9 },+ { 384, 28, 5 , 9 },+ { 397, 28, 5 , 9 },+ { 410, 28, 1 , 9 },+ { 419, 28, 5 , 11 },+ { 432, 28, 5 , 9 },+ { 445, 28, 2 , 9 },+ { 455, 28, 7 , 7 },+ { 470, 28, 5 , 7 },+ { 483, 28, 5 , 7 },+ { 496, 28, 5 , 9 },+ { 4, 52, 5 , 9 },+ { 17, 52, 5 , 7 },+ { 30, 52, 5 , 7 },+ { 43, 52, 4 , 8 },+ { 55, 52, 5 , 7 },+ { 68, 52, 5 , 7 },+ { 81, 52, 7 , 7 },+ { 96, 52, 5 , 7 },+ { 109, 52, 5 , 9 },+ { 122, 52, 5 , 7 },+ { 135, 52, 4 , 9 },+ { 147, 52, 1 , 9 },+ { 156, 52, 4 , 9 },+ { 168, 52, 6 , 2 },+ { 182, 52, 1 , 9 },+ { 191, 52, 5 , 11 },+ { 204, 52, 6 , 9 },+ { 218, 52, 6 , 9 },+ { 232, 52, 5 , 9 },+ { 245, 52, 5 , 12 },+ { 258, 52, 5 , 9 },+ { 271, 52, 5 , 10 },+ { 284, 52, 7 , 9 },+ { 299, 52, 5 , 9 },+ { 312, 52, 6 , 5 },+ { 326, 52, 5 , 3 },+ { 339, 52, 7 , 9 },+ { 354, 52, 5 , 9 },+ { 367, 52, 4 , 4 },+ { 379, 52, 5 , 7 },+ { 392, 52, 5 , 9 },+ { 405, 52, 5 , 9 },+ { 418, 52, 5 , 12 },+ { 431, 52, 5 , 9 },+ { 444, 52, 7 , 9 },+ { 459, 52, 1 , 1 },+ { 468, 52, 5 , 10 },+ { 481, 52, 5 , 9 },+ { 494, 52, 5 , 9 },+ { 4, 76, 6 , 5 },+ { 18, 76, 9 , 9 },+ { 35, 76, 9 , 7 },+ { 52, 76, 5 , 11 },+ { 65, 76, 5 , 9 },+ { 78, 76, 5 , 12 },+ { 91, 76, 5 , 12 },+ { 104, 76, 5 , 12 },+ { 117, 76, 6 , 12 },+ { 131, 76, 5 , 11 },+ { 144, 76, 5 , 13 },+ { 157, 76, 9 , 9 },+ { 174, 76, 5 , 12 },+ { 187, 76, 5 , 12 },+ { 200, 76, 5 , 12 },+ { 213, 76, 5 , 12 },+ { 226, 76, 5 , 11 },+ { 239, 76, 2 , 12 },+ { 249, 76, 2 , 12 },+ { 259, 76, 3 , 12 },+ { 270, 76, 3 , 11 },+ { 281, 76, 6 , 9 },+ { 295, 76, 6 , 12 },+ { 309, 76, 5 , 12 },+ { 322, 76, 5 , 12 },+ { 335, 76, 5 , 12 },+ { 348, 76, 6 , 12 },+ { 362, 76, 5 , 11 },+ { 375, 76, 5 , 5 },+ { 388, 76, 7 , 9 },+ { 403, 76, 5 , 12 },+ { 416, 76, 5 , 12 },+ { 429, 76, 5 , 12 },+ { 442, 76, 5 , 11 },+ { 455, 76, 5 , 12 },+ { 468, 76, 5 , 9 },+ { 481, 76, 5 , 9 },+ { 494, 76, 5 , 10 },+ { 4, 100, 5 , 10 },+ { 17, 100, 5 , 10 },+ { 30, 100, 6 , 10 },+ { 44, 100, 5 , 9 },+ { 57, 100, 5 , 11 },+ { 70, 100, 9 , 7 },+ { 87, 100, 5 , 10 },+ { 100, 100, 5 , 10 },+ { 113, 100, 5 , 10 },+ { 126, 100, 5 , 10 },+ { 139, 100, 5 , 9 },+ { 152, 100, 2 , 10 },+ { 162, 100, 2 , 10 },+ { 172, 100, 3 , 10 },+ { 183, 100, 3 , 9 },+ { 194, 100, 6 , 9 },+ { 208, 100, 6 , 10 },+ { 222, 100, 5 , 10 },+ { 235, 100, 5 , 10 },+ { 248, 100, 5 , 10 },+ { 261, 100, 6 , 10 },+ { 275, 100, 5 , 9 },+ { 288, 100, 5 , 5 },+ { 301, 100, 7 , 7 },+ { 316, 100, 5 , 10 },+ { 329, 100, 5 , 10 },+ { 342, 100, 5 , 10 },+ { 355, 100, 5 , 9 },+ { 368, 100, 5 , 12 },+ { 381, 100, 5 , 11 },+ { 394, 100, 5 , 11 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo darkFontGlyphs[189] = {+ { 32, 0, 13, 4, { 0 }},+ { 33, 2, 4, 5, { 0 }},+ { 34, 2, 4, 7, { 0 }},+ { 35, 1, 4, 8, { 0 }},+ { 36, 1, 2, 7, { 0 }},+ { 37, 1, 4, 9, { 0 }},+ { 38, 1, 4, 7, { 0 }},+ { 39, 2, 4, 5, { 0 }},+ { 40, 3, 4, 7, { 0 }},+ { 41, 1, 4, 7, { 0 }},+ { 42, 1, 4, 7, { 0 }},+ { 43, 1, 6, 7, { 0 }},+ { 44, 1, 12, 5, { 0 }},+ { 45, 1, 8, 6, { 0 }},+ { 46, 2, 12, 5, { 0 }},+ { 47, 1, 4, 5, { 0 }},+ { 48, 1, 4, 7, { 0 }},+ { 49, 2, 4, 7, { 0 }},+ { 50, 1, 4, 7, { 0 }},+ { 51, 1, 4, 7, { 0 }},+ { 52, 1, 4, 7, { 0 }},+ { 53, 1, 4, 7, { 0 }},+ { 54, 1, 4, 7, { 0 }},+ { 55, 1, 4, 7, { 0 }},+ { 56, 1, 4, 7, { 0 }},+ { 57, 1, 4, 7, { 0 }},+ { 58, 2, 6, 5, { 0 }},+ { 59, 1, 6, 5, { 0 }},+ { 60, 1, 6, 5, { 0 }},+ { 61, 1, 7, 6, { 0 }},+ { 62, 1, 6, 5, { 0 }},+ { 63, 1, 4, 7, { 0 }},+ { 64, 1, 4, 9, { 0 }},+ { 65, 1, 4, 7, { 0 }},+ { 66, 1, 4, 7, { 0 }},+ { 67, 1, 4, 7, { 0 }},+ { 68, 1, 4, 7, { 0 }},+ { 69, 1, 4, 7, { 0 }},+ { 70, 1, 4, 7, { 0 }},+ { 71, 1, 4, 7, { 0 }},+ { 72, 1, 4, 7, { 0 }},+ { 73, 2, 4, 5, { 0 }},+ { 74, 1, 4, 7, { 0 }},+ { 75, 1, 4, 7, { 0 }},+ { 76, 1, 4, 7, { 0 }},+ { 77, 1, 4, 9, { 0 }},+ { 78, 1, 4, 7, { 0 }},+ { 79, 1, 4, 7, { 0 }},+ { 80, 1, 4, 7, { 0 }},+ { 81, 1, 4, 7, { 0 }},+ { 82, 1, 4, 7, { 0 }},+ { 83, 1, 4, 7, { 0 }},+ { 84, 1, 4, 7, { 0 }},+ { 85, 1, 4, 7, { 0 }},+ { 86, 1, 4, 7, { 0 }},+ { 87, 1, 4, 9, { 0 }},+ { 88, 1, 4, 7, { 0 }},+ { 89, 1, 4, 7, { 0 }},+ { 90, 1, 4, 7, { 0 }},+ { 91, 3, 4, 7, { 0 }},+ { 92, 1, 4, 5, { 0 }},+ { 93, 1, 4, 7, { 0 }},+ { 94, 1, 4, 7, { 0 }},+ { 95, 0, 14, 5, { 0 }},+ { 96, 1, 4, 5, { 0 }},+ { 97, 1, 6, 7, { 0 }},+ { 98, 1, 4, 7, { 0 }},+ { 99, 1, 6, 7, { 0 }},+ { 100, 1, 4, 7, { 0 }},+ { 101, 1, 6, 7, { 0 }},+ { 102, 1, 4, 6, { 0 }},+ { 103, 1, 6, 7, { 0 }},+ { 104, 1, 4, 7, { 0 }},+ { 105, 2, 4, 5, { 0 }},+ { 106, 1, 4, 7, { 0 }},+ { 107, 1, 4, 7, { 0 }},+ { 108, 2, 4, 5, { 0 }},+ { 109, 1, 6, 9, { 0 }},+ { 110, 1, 6, 7, { 0 }},+ { 111, 1, 6, 7, { 0 }},+ { 112, 1, 6, 7, { 0 }},+ { 113, 1, 6, 7, { 0 }},+ { 114, 1, 6, 7, { 0 }},+ { 115, 1, 6, 7, { 0 }},+ { 116, 1, 5, 6, { 0 }},+ { 117, 1, 6, 7, { 0 }},+ { 118, 1, 6, 7, { 0 }},+ { 119, 1, 6, 9, { 0 }},+ { 120, 1, 6, 7, { 0 }},+ { 121, 1, 6, 7, { 0 }},+ { 122, 1, 6, 7, { 0 }},+ { 123, 2, 4, 7, { 0 }},+ { 124, 2, 4, 5, { 0 }},+ { 125, 1, 4, 7, { 0 }},+ { 126, 1, 4, 8, { 0 }},+ { 161, 2, 6, 5, { 0 }},+ { 162, 1, 4, 7, { 0 }},+ { 163, 1, 4, 8, { 0 }},+ { 8364, 1, 4, 8, { 0 }},+ { 165, 1, 4, 7, { 0 }},+ { 352, 1, 1, 7, { 0 }},+ { 167, 2, 4, 9, { 0 }},+ { 353, 1, 3, 7, { 0 }},+ { 169, 1, 4, 9, { 0 }},+ { 170, 2, 4, 9, { 0 }},+ { 171, 1, 6, 8, { 0 }},+ { 172, 1, 8, 7, { 0 }},+ { 174, 1, 4, 9, { 0 }},+ { 175, 2, 4, 9, { 0 }},+ { 176, 1, 4, 6, { 0 }},+ { 177, 1, 6, 7, { 0 }},+ { 178, 2, 4, 9, { 0 }},+ { 179, 2, 4, 9, { 0 }},+ { 381, 1, 1, 7, { 0 }},+ { 181, 1, 6, 7, { 0 }},+ { 182, 1, 4, 9, { 0 }},+ { 183, 2, 8, 5, { 0 }},+ { 382, 1, 3, 7, { 0 }},+ { 185, 2, 4, 9, { 0 }},+ { 186, 2, 4, 9, { 0 }},+ { 187, 1, 6, 8, { 0 }},+ { 338, 1, 4, 11, { 0 }},+ { 339, 1, 6, 11, { 0 }},+ { 376, 1, 2, 7, { 0 }},+ { 191, 1, 6, 7, { 0 }},+ { 192, 1, 1, 7, { 0 }},+ { 193, 1, 1, 7, { 0 }},+ { 194, 1, 1, 7, { 0 }},+ { 195, 1, 1, 7, { 0 }},+ { 196, 1, 2, 7, { 0 }},+ { 197, 1, 0, 7, { 0 }},+ { 198, 1, 4, 11, { 0 }},+ { 199, 1, 4, 7, { 0 }},+ { 200, 1, 1, 7, { 0 }},+ { 201, 1, 1, 7, { 0 }},+ { 202, 1, 1, 7, { 0 }},+ { 203, 1, 2, 7, { 0 }},+ { 204, 1, 1, 5, { 0 }},+ { 205, 2, 1, 5, { 0 }},+ { 206, 1, 1, 5, { 0 }},+ { 207, 1, 2, 5, { 0 }},+ { 208, 0, 4, 7, { 0 }},+ { 209, 1, 1, 7, { 0 }},+ { 210, 1, 1, 7, { 0 }},+ { 211, 1, 1, 7, { 0 }},+ { 212, 1, 1, 7, { 0 }},+ { 213, 1, 1, 7, { 0 }},+ { 214, 1, 2, 7, { 0 }},+ { 215, 1, 6, 7, { 0 }},+ { 216, 0, 4, 7, { 0 }},+ { 217, 1, 1, 7, { 0 }},+ { 218, 1, 1, 7, { 0 }},+ { 219, 1, 1, 7, { 0 }},+ { 220, 1, 2, 7, { 0 }},+ { 221, 1, 1, 7, { 0 }},+ { 222, 1, 4, 7, { 0 }},+ { 223, 1, 4, 7, { 0 }},+ { 224, 1, 3, 7, { 0 }},+ { 225, 1, 3, 7, { 0 }},+ { 226, 1, 3, 7, { 0 }},+ { 227, 1, 3, 7, { 0 }},+ { 228, 1, 4, 7, { 0 }},+ { 229, 1, 2, 7, { 0 }},+ { 230, 1, 6, 11, { 0 }},+ { 231, 1, 6, 7, { 0 }},+ { 232, 1, 3, 7, { 0 }},+ { 233, 1, 3, 7, { 0 }},+ { 234, 1, 3, 7, { 0 }},+ { 235, 1, 4, 7, { 0 }},+ { 236, 1, 3, 5, { 0 }},+ { 237, 2, 3, 5, { 0 }},+ { 238, 1, 3, 5, { 0 }},+ { 239, 1, 4, 5, { 0 }},+ { 240, 1, 4, 7, { 0 }},+ { 241, 1, 3, 7, { 0 }},+ { 242, 1, 3, 7, { 0 }},+ { 243, 1, 3, 7, { 0 }},+ { 244, 1, 3, 7, { 0 }},+ { 245, 1, 3, 7, { 0 }},+ { 246, 1, 4, 7, { 0 }},+ { 247, 1, 6, 7, { 0 }},+ { 248, 0, 6, 7, { 0 }},+ { 249, 1, 3, 7, { 0 }},+ { 250, 1, 3, 7, { 0 }},+ { 251, 1, 3, 7, { 0 }},+ { 252, 1, 4, 7, { 0 }},+ { 253, 1, 3, 7, { 0 }},+ { 254, 1, 4, 7, { 0 }},+ { 255, 1, 4, 7, { 0 }},+};++// Style loading function: Dark+static void GuiLoadStyleDark(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int darkFontDataSize = 0;+ unsigned char *data = DecompressData(darkFontData, DARK_STYLE_FONT_ATLAS_COMP_SIZE, &darkFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, darkFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, darkFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/enefete/style_enefete.h view
@@ -0,0 +1,600 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleEnefete(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define ENEFETE_STYLE_PROPS_COUNT 17++// Custom style name: Enefete+static const GuiStyleProp enefeteStyleProps[ENEFETE_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x1980d5ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x4df3ebff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0x103e60ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xe7e2f7ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x23d4ddff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xf1f1f1ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x6413a6ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xea66d9ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x9f00bbff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x4b909eff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x73c7d0ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x448894ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x1d3f6cff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x29c9e5ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)++#define ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE 2462++// Font atlas image pixels data: DEFLATE compressed+static unsigned char enefeteFontData[ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,+ 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,+ 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,+ 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,+ 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,+ 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,+ 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,+ 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,+ 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,+ 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,+ 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,+ 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,+ 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,+ 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,+ 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,+ 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,+ 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,+ 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,+ 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,+ 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,+ 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,+ 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,+ 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,+ 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,+ 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,+ 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,+ 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,+ 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,+ 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,+ 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,+ 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,+ 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,+ 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,+ 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,+ 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,+ 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,+ 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,+ 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,+ 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,+ 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,+ 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,+ 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,+ 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,+ 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,+ 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,+ 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,+ 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,+ 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,+ 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,+ 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,+ 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,+ 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,+ 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,+ 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,+ 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,+ 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,+ 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,+ 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,+ 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,+ 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,+ 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,+ 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,+ 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,+ 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,+ 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,+ 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,+ 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,+ 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,+ 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,+ 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,+ 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,+ 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,+ 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,+ 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,+ 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,+ 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,+ 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,+ 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,+ 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,+ 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,+ 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,+ 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,+ 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,+ 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,+ 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,+ 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,+ 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,+ 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,+ 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,+ 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,+ 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,+ 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,+ 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,+ 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,+ 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,+ 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,+ 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,+ 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,+ 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,+ 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,+ 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,+ 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,+ 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,+ 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,+ 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,+ 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,+ 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,+ 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,+ 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,+ 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,+ 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,+ 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,+ 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,+ 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,+ 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,+ 0x0f };++// Font glyphs rectangles data (on atlas)+static const Rectangle enefeteFontRecs[189] = {+ { 4, 4, 4 , 16 },+ { 16, 4, 2 , 10 },+ { 26, 4, 5 , 3 },+ { 39, 4, 7 , 10 },+ { 54, 4, 7 , 13 },+ { 69, 4, 7 , 10 },+ { 84, 4, 7 , 10 },+ { 99, 4, 2 , 3 },+ { 109, 4, 3 , 12 },+ { 120, 4, 3 , 12 },+ { 131, 4, 5 , 6 },+ { 144, 4, 6 , 5 },+ { 158, 4, 2 , 4 },+ { 168, 4, 5 , 1 },+ { 181, 4, 2 , 2 },+ { 191, 4, 4 , 10 },+ { 203, 4, 6 , 10 },+ { 217, 4, 4 , 10 },+ { 229, 4, 6 , 10 },+ { 243, 4, 6 , 10 },+ { 257, 4, 6 , 10 },+ { 271, 4, 6 , 10 },+ { 285, 4, 6 , 10 },+ { 299, 4, 6 , 10 },+ { 313, 4, 6 , 10 },+ { 327, 4, 6 , 10 },+ { 341, 4, 2 , 6 },+ { 351, 4, 2 , 8 },+ { 361, 4, 7 , 7 },+ { 376, 4, 5 , 3 },+ { 389, 4, 7 , 7 },+ { 404, 4, 6 , 10 },+ { 418, 4, 7 , 12 },+ { 433, 4, 7 , 10 },+ { 448, 4, 7 , 10 },+ { 463, 4, 7 , 10 },+ { 478, 4, 7 , 10 },+ { 493, 4, 7 , 10 },+ { 4, 28, 7 , 10 },+ { 19, 28, 7 , 10 },+ { 34, 28, 7 , 10 },+ { 49, 28, 2 , 10 },+ { 59, 28, 5 , 10 },+ { 72, 28, 7 , 10 },+ { 87, 28, 6 , 10 },+ { 101, 28, 9 , 10 },+ { 118, 28, 7 , 10 },+ { 133, 28, 7 , 10 },+ { 148, 28, 7 , 10 },+ { 163, 28, 7 , 12 },+ { 178, 28, 7 , 10 },+ { 193, 28, 7 , 10 },+ { 208, 28, 6 , 10 },+ { 222, 28, 7 , 10 },+ { 237, 28, 7 , 10 },+ { 252, 28, 8 , 10 },+ { 268, 28, 7 , 10 },+ { 283, 28, 6 , 10 },+ { 297, 28, 7 , 10 },+ { 312, 28, 4 , 12 },+ { 324, 28, 4 , 10 },+ { 336, 28, 4 , 12 },+ { 348, 28, 6 , 3 },+ { 362, 28, 7 , 1 },+ { 377, 28, 4 , 3 },+ { 389, 28, 6 , 7 },+ { 403, 28, 6 , 10 },+ { 417, 28, 6 , 7 },+ { 431, 28, 6 , 10 },+ { 445, 28, 6 , 7 },+ { 459, 28, 4 , 10 },+ { 471, 28, 6 , 9 },+ { 485, 28, 6 , 10 },+ { 499, 28, 2 , 10 },+ { 4, 52, 5 , 12 },+ { 17, 52, 6 , 10 },+ { 31, 52, 3 , 10 },+ { 42, 52, 8 , 7 },+ { 58, 52, 6 , 7 },+ { 72, 52, 6 , 7 },+ { 86, 52, 6 , 9 },+ { 100, 52, 6 , 9 },+ { 114, 52, 5 , 7 },+ { 127, 52, 6 , 7 },+ { 141, 52, 4 , 10 },+ { 153, 52, 6 , 7 },+ { 167, 52, 6 , 7 },+ { 181, 52, 8 , 7 },+ { 197, 52, 6 , 7 },+ { 211, 52, 6 , 9 },+ { 225, 52, 6 , 7 },+ { 239, 52, 5 , 12 },+ { 252, 52, 2 , 12 },+ { 262, 52, 5 , 12 },+ { 275, 52, 7 , 3 },+ { 290, 52, 2 , 9 },+ { 300, 52, 6 , 11 },+ { 314, 52, 7 , 10 },+ { 329, 52, 7 , 9 },+ { 344, 52, 6 , 10 },+ { 358, 52, 7 , 11 },+ { 373, 52, 6 , 12 },+ { 387, 52, 6 , 10 },+ { 401, 52, 7 , 10 },+ { 416, 52, 5 , 5 },+ { 429, 52, 7 , 6 },+ { 444, 52, 6 , 3 },+ { 458, 52, 7 , 10 },+ { 473, 52, 9 , 10 },+ { 490, 52, 4 , 4 },+ { 4, 76, 6 , 7 },+ { 18, 76, 4 , 5 },+ { 30, 76, 4 , 5 },+ { 42, 76, 7 , 11 },+ { 57, 76, 6 , 9 },+ { 71, 76, 7 , 12 },+ { 86, 76, 2 , 2 },+ { 96, 76, 6 , 10 },+ { 110, 76, 3 , 5 },+ { 121, 76, 4 , 5 },+ { 133, 76, 7 , 6 },+ { 148, 76, 9 , 10 },+ { 165, 76, 8 , 7 },+ { 181, 76, 6 , 11 },+ { 195, 76, 6 , 11 },+ { 209, 76, 7 , 11 },+ { 224, 76, 7 , 11 },+ { 239, 76, 7 , 11 },+ { 254, 76, 7 , 11 },+ { 269, 76, 7 , 11 },+ { 284, 76, 7 , 11 },+ { 299, 76, 9 , 10 },+ { 316, 76, 7 , 12 },+ { 331, 76, 7 , 11 },+ { 346, 76, 7 , 11 },+ { 361, 76, 7 , 11 },+ { 376, 76, 7 , 11 },+ { 391, 76, 3 , 11 },+ { 402, 76, 3 , 11 },+ { 413, 76, 5 , 11 },+ { 426, 76, 5 , 11 },+ { 439, 76, 8 , 10 },+ { 455, 76, 7 , 11 },+ { 470, 76, 7 , 11 },+ { 485, 76, 7 , 11 },+ { 4, 100, 7 , 11 },+ { 19, 100, 7 , 11 },+ { 34, 100, 7 , 11 },+ { 49, 100, 7 , 7 },+ { 64, 100, 7 , 13 },+ { 79, 100, 7 , 11 },+ { 94, 100, 7 , 11 },+ { 109, 100, 7 , 11 },+ { 124, 100, 7 , 11 },+ { 139, 100, 6 , 11 },+ { 153, 100, 7 , 10 },+ { 168, 100, 7 , 10 },+ { 183, 100, 6 , 10 },+ { 197, 100, 6 , 10 },+ { 211, 100, 6 , 10 },+ { 225, 100, 6 , 10 },+ { 239, 100, 6 , 10 },+ { 253, 100, 6 , 11 },+ { 267, 100, 8 , 7 },+ { 283, 100, 6 , 9 },+ { 297, 100, 6 , 10 },+ { 311, 100, 6 , 10 },+ { 325, 100, 6 , 10 },+ { 339, 100, 6 , 10 },+ { 353, 100, 3 , 10 },+ { 364, 100, 3 , 10 },+ { 375, 100, 5 , 10 },+ { 388, 100, 5 , 10 },+ { 401, 100, 6 , 10 },+ { 415, 100, 6 , 10 },+ { 429, 100, 6 , 10 },+ { 443, 100, 6 , 10 },+ { 457, 100, 6 , 10 },+ { 471, 100, 6 , 10 },+ { 485, 100, 6 , 10 },+ { 4, 124, 6 , 7 },+ { 18, 124, 7 , 11 },+ { 33, 124, 6 , 10 },+ { 47, 124, 6 , 10 },+ { 61, 124, 6 , 10 },+ { 75, 124, 6 , 10 },+ { 89, 124, 6 , 12 },+ { 103, 124, 6 , 12 },+ { 117, 124, 6 , 12 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo enefeteFontGlyphs[189] = {+ { 32, 0, 12, 4, { 0 }},+ { 33, 0, 2, 3, { 0 }},+ { 34, 0, 2, 6, { 0 }},+ { 35, 0, 2, 8, { 0 }},+ { 36, 0, 1, 8, { 0 }},+ { 37, 0, 2, 8, { 0 }},+ { 38, 0, 2, 8, { 0 }},+ { 39, 0, 2, 3, { 0 }},+ { 40, 0, 2, 4, { 0 }},+ { 41, 0, 2, 4, { 0 }},+ { 42, 0, 4, 6, { 0 }},+ { 43, 0, 6, 7, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 8, 6, { 0 }},+ { 46, 0, 10, 3, { 0 }},+ { 47, 0, 2, 5, { 0 }},+ { 48, 0, 2, 7, { 0 }},+ { 49, 0, 2, 7, { 0 }},+ { 50, 0, 2, 7, { 0 }},+ { 51, 0, 2, 7, { 0 }},+ { 52, 0, 2, 7, { 0 }},+ { 53, 0, 2, 7, { 0 }},+ { 54, 0, 2, 7, { 0 }},+ { 55, 0, 2, 7, { 0 }},+ { 56, 0, 2, 7, { 0 }},+ { 57, 0, 2, 7, { 0 }},+ { 58, 0, 4, 3, { 0 }},+ { 59, 0, 4, 3, { 0 }},+ { 60, 0, 4, 8, { 0 }},+ { 61, 0, 6, 6, { 0 }},+ { 62, 0, 4, 8, { 0 }},+ { 63, 0, 2, 7, { 0 }},+ { 64, 0, 2, 8, { 0 }},+ { 65, 0, 2, 8, { 0 }},+ { 66, 0, 2, 8, { 0 }},+ { 67, 0, 2, 8, { 0 }},+ { 68, 0, 2, 8, { 0 }},+ { 69, 0, 2, 8, { 0 }},+ { 70, 0, 2, 8, { 0 }},+ { 71, 0, 2, 8, { 0 }},+ { 72, 0, 2, 8, { 0 }},+ { 73, 0, 2, 3, { 0 }},+ { 74, 0, 2, 6, { 0 }},+ { 75, 0, 2, 8, { 0 }},+ { 76, 0, 2, 7, { 0 }},+ { 77, 0, 2, 10, { 0 }},+ { 78, 0, 2, 8, { 0 }},+ { 79, 0, 2, 8, { 0 }},+ { 80, 0, 2, 8, { 0 }},+ { 81, 0, 2, 8, { 0 }},+ { 82, 0, 2, 8, { 0 }},+ { 83, 0, 2, 8, { 0 }},+ { 84, 0, 2, 7, { 0 }},+ { 85, 0, 2, 8, { 0 }},+ { 86, 0, 2, 8, { 0 }},+ { 87, 0, 2, 9, { 0 }},+ { 88, 0, 2, 8, { 0 }},+ { 89, 0, 2, 7, { 0 }},+ { 90, 0, 2, 8, { 0 }},+ { 91, 0, 2, 5, { 0 }},+ { 92, 0, 2, 5, { 0 }},+ { 93, 0, 2, 5, { 0 }},+ { 94, 0, 2, 7, { 0 }},+ { 95, 0, 14, 8, { 0 }},+ { 96, 0, 2, 5, { 0 }},+ { 97, 0, 5, 7, { 0 }},+ { 98, 0, 2, 7, { 0 }},+ { 99, 0, 5, 7, { 0 }},+ { 100, 0, 2, 7, { 0 }},+ { 101, 0, 5, 7, { 0 }},+ { 102, 0, 2, 5, { 0 }},+ { 103, 0, 5, 7, { 0 }},+ { 104, 0, 2, 7, { 0 }},+ { 105, 0, 2, 3, { 0 }},+ { 106, 0, 2, 6, { 0 }},+ { 107, 0, 2, 7, { 0 }},+ { 108, 0, 2, 4, { 0 }},+ { 109, 0, 5, 9, { 0 }},+ { 110, 0, 5, 7, { 0 }},+ { 111, 0, 5, 7, { 0 }},+ { 112, 0, 5, 7, { 0 }},+ { 113, 0, 5, 7, { 0 }},+ { 114, 0, 5, 6, { 0 }},+ { 115, 0, 5, 7, { 0 }},+ { 116, 0, 2, 5, { 0 }},+ { 117, 0, 5, 7, { 0 }},+ { 118, 0, 5, 7, { 0 }},+ { 119, 0, 5, 9, { 0 }},+ { 120, 0, 5, 7, { 0 }},+ { 121, 0, 5, 7, { 0 }},+ { 122, 0, 5, 7, { 0 }},+ { 123, 0, 2, 6, { 0 }},+ { 124, 0, 2, 3, { 0 }},+ { 125, 0, 2, 6, { 0 }},+ { 126, 0, 6, 8, { 0 }},+ { 161, 0, 5, 3, { 0 }},+ { 162, 0, 3, 7, { 0 }},+ { 163, 0, 2, 8, { 0 }},+ { 8364, 0, 3, 8, { 0 }},+ { 165, 0, 2, 7, { 0 }},+ { 352, 0, 1, 8, { 0 }},+ { 167, 0, 2, 7, { 0 }},+ { 353, 0, 2, 7, { 0 }},+ { 169, 0, 2, 8, { 0 }},+ { 170, 0, 2, 6, { 0 }},+ { 171, 0, 6, 8, { 0 }},+ { 172, 0, 7, 7, { 0 }},+ { 174, 0, 2, 8, { 0 }},+ { 175, 1, 3, 14, { 0 }},+ { 176, 0, 2, 5, { 0 }},+ { 177, 0, 4, 7, { 0 }},+ { 178, 0, 2, 5, { 0 }},+ { 179, 0, 2, 5, { 0 }},+ { 381, 0, 1, 8, { 0 }},+ { 181, 0, 5, 7, { 0 }},+ { 182, 0, 2, 8, { 0 }},+ { 183, 0, 6, 3, { 0 }},+ { 382, 0, 2, 7, { 0 }},+ { 185, 0, 2, 4, { 0 }},+ { 186, 0, 2, 5, { 0 }},+ { 187, 0, 6, 8, { 0 }},+ { 338, 0, 2, 10, { 0 }},+ { 339, 0, 5, 9, { 0 }},+ { 376, 0, 1, 7, { 0 }},+ { 191, 0, 3, 7, { 0 }},+ { 192, 0, 1, 8, { 0 }},+ { 193, 0, 1, 8, { 0 }},+ { 194, 0, 1, 8, { 0 }},+ { 195, 0, 1, 8, { 0 }},+ { 196, 0, 1, 8, { 0 }},+ { 197, 0, 1, 8, { 0 }},+ { 198, 0, 2, 10, { 0 }},+ { 199, 0, 2, 8, { 0 }},+ { 200, 0, 1, 8, { 0 }},+ { 201, 0, 1, 8, { 0 }},+ { 202, 0, 1, 8, { 0 }},+ { 203, 0, 1, 8, { 0 }},+ { 204, 0, 1, 4, { 0 }},+ { 205, 0, 1, 4, { 0 }},+ { 206, 0, 1, 6, { 0 }},+ { 207, 0, 1, 6, { 0 }},+ { 208, 0, 2, 9, { 0 }},+ { 209, 0, 1, 8, { 0 }},+ { 210, 0, 1, 8, { 0 }},+ { 211, 0, 1, 8, { 0 }},+ { 212, 0, 1, 8, { 0 }},+ { 213, 0, 1, 8, { 0 }},+ { 214, 0, 1, 8, { 0 }},+ { 215, 0, 5, 8, { 0 }},+ { 216, 0, 1, 8, { 0 }},+ { 217, 0, 1, 8, { 0 }},+ { 218, 0, 1, 8, { 0 }},+ { 219, 0, 1, 8, { 0 }},+ { 220, 0, 1, 8, { 0 }},+ { 221, 0, 1, 7, { 0 }},+ { 222, 0, 2, 8, { 0 }},+ { 223, 0, 2, 8, { 0 }},+ { 224, 0, 2, 7, { 0 }},+ { 225, 0, 2, 7, { 0 }},+ { 226, 0, 2, 7, { 0 }},+ { 227, 0, 2, 7, { 0 }},+ { 228, 0, 2, 7, { 0 }},+ { 229, 0, 1, 7, { 0 }},+ { 230, 0, 5, 9, { 0 }},+ { 231, 0, 5, 7, { 0 }},+ { 232, 0, 2, 7, { 0 }},+ { 233, 0, 2, 7, { 0 }},+ { 234, 0, 2, 7, { 0 }},+ { 235, 0, 2, 7, { 0 }},+ { 236, 0, 2, 4, { 0 }},+ { 237, 0, 2, 4, { 0 }},+ { 238, 0, 2, 6, { 0 }},+ { 239, 0, 2, 6, { 0 }},+ { 240, 0, 2, 7, { 0 }},+ { 241, 0, 2, 7, { 0 }},+ { 242, 0, 2, 7, { 0 }},+ { 243, 0, 2, 7, { 0 }},+ { 244, 0, 2, 7, { 0 }},+ { 245, 0, 2, 7, { 0 }},+ { 246, 0, 2, 7, { 0 }},+ { 247, 0, 4, 7, { 0 }},+ { 248, 0, 3, 8, { 0 }},+ { 249, 0, 2, 7, { 0 }},+ { 250, 0, 2, 7, { 0 }},+ { 251, 0, 2, 7, { 0 }},+ { 252, 0, 2, 7, { 0 }},+ { 253, 0, 2, 7, { 0 }},+ { 254, 0, 2, 7, { 0 }},+ { 255, 0, 2, 7, { 0 }},+};++// Style loading function: Enefete+static void GuiLoadStyleEnefete(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < ENEFETE_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(enefeteStyleProps[i].controlId, enefeteStyleProps[i].propertyId, enefeteStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int enefeteFontDataSize = 0;+ unsigned char *data = DecompressData(enefeteFontData, ENEFETE_STYLE_FONT_ATLAS_COMP_SIZE, &enefeteFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, enefeteFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, enefeteFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/jungle/style_jungle.h view
@@ -0,0 +1,578 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleJungle(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define JUNGLE_STYLE_PROPS_COUNT 17++// Custom style name: Jungle+static const GuiStyleProp jungleStyleProps[JUNGLE_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x60827dff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x2c3334ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0x82a29fff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0x5f9aa8ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x334e57ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x6aa9b8ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xa9cb8dff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0x3b6357ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x97af81ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x5b6462ff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x2c3334ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x666b69ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x0000000c }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x638465ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x2b3a3aff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000012 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "Pixel Intv.otf" (size: 12, spacing: 0)++#define JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE 2030++// Font atlas image pixels data: DEFLATE compressed+static unsigned char jungleFontData[JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0x9d, 0x3d, 0x8e, 0x25, 0x35, 0x14, 0x85, 0x8d, 0xe9, 0x8c, 0x10, 0x11, 0x80, 0x84, 0x20, 0x41, 0x22, 0x21, 0x61, 0x34,+ 0x12, 0x64, 0xb3, 0x00, 0x62, 0x84, 0x08, 0x10, 0x11, 0x09, 0xb0, 0x07, 0x66, 0x65, 0x93, 0x90, 0xb3, 0x01, 0x76, 0xc1,+ 0x02, 0x2e, 0x9a, 0xbf, 0x9e, 0x9f, 0xae, 0xb2, 0x7d, 0x8f, 0xaf, 0xcb, 0xae, 0x7a, 0x5f, 0x7f, 0x9a, 0xd1, 0xcc, 0xf3,+ 0x73, 0x95, 0xcb, 0xc7, 0xd7, 0x55, 0xaf, 0x7d, 0xde, 0xb5, 0x25, 0x00, 0x00, 0x00, 0x80, 0x07, 0x3c, 0xff, 0xd9, 0x7e,+ 0x6d, 0xab, 0x24, 0xbd, 0x2a, 0x69, 0x3f, 0xd6, 0xeb, 0xd7, 0x5f, 0x96, 0xe4, 0xdd, 0x77, 0x6c, 0x1f, 0x31, 0xef, 0xb4,+ 0x61, 0xaf, 0xd5, 0xfb, 0x2d, 0x4b, 0xae, 0x92, 0xfd, 0xe3, 0xef, 0xf7, 0x57, 0x72, 0x5c, 0xc3, 0xbb, 0x3f, 0xc9, 0x71,+ 0x2d, 0xe5, 0x7a, 0xa3, 0xf5, 0x2f, 0xf7, 0xc1, 0x7e, 0xd9, 0xcb, 0x3f, 0xcf, 0x7b, 0x22, 0x3b, 0x8e, 0xb9, 0xff, 0xfe,+ 0xe4, 0x1a, 0x81, 0xfe, 0x91, 0xe1, 0xeb, 0xdd, 0xd2, 0xbb, 0x6b, 0xd7, 0x60, 0xce, 0x16, 0xbc, 0x7e, 0x7d, 0xa4, 0xfe,+ 0xe9, 0xfe, 0x1c, 0xed, 0xf1, 0x5f, 0x53, 0xc5, 0xec, 0x6e, 0xb3, 0x27, 0x52, 0x51, 0x9b, 0x2c, 0x9c, 0x29, 0x62, 0x34,+ 0xa7, 0xa0, 0xde, 0xcd, 0xc5, 0x6b, 0x30, 0x41, 0x7f, 0x6d, 0x84, 0x46, 0x1d, 0x47, 0x8b, 0xff, 0xe7, 0xdc, 0xbd, 0x18,+ 0x01, 0xe5, 0xa3, 0xf6, 0xb7, 0x38, 0x2a, 0xfe, 0xd3, 0x50, 0xf5, 0x7b, 0xf4, 0x3f, 0x62, 0xfe, 0x2f, 0xbf, 0xbf, 0xdc,+ 0x67, 0xdb, 0xc7, 0xcb, 0xaf, 0xe2, 0xdf, 0x7f, 0xf7, 0x8c, 0xd0, 0xdf, 0x7f, 0xff, 0x1f, 0xab, 0x7e, 0xc4, 0xfc, 0xbf,+ 0xe2, 0x73, 0x64, 0xed, 0x3e, 0xbe, 0x3d, 0x76, 0x6c, 0x78, 0xfc, 0xcf, 0xa0, 0xa4, 0x7e, 0xed, 0xf9, 0xcf, 0x3a, 0xe6,+ 0xd9, 0xd1, 0xf1, 0xaf, 0x1c, 0xeb, 0x75, 0x4f, 0x98, 0x10, 0x9f, 0x67, 0xd5, 0xbf, 0xa4, 0x3e, 0x44, 0xcc, 0x35, 0x9e,+ 0xbb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x35, 0x57, 0x4c, 0xca, 0xeb, 0xef,+ 0x91, 0x2b, 0x91, 0xa3, 0xca, 0xda, 0xdd, 0x06, 0x1e, 0xe7, 0x4a, 0x16, 0x7a, 0x6c, 0x56, 0xbf, 0x8c, 0x72, 0xfb, 0x25,+ 0xb7, 0x37, 0xa3, 0xa5, 0x35, 0xea, 0xf9, 0x7a, 0xf4, 0xcf, 0xce, 0xb5, 0xd7, 0xb2, 0x43, 0x6f, 0xcf, 0xcf, 0xb8, 0xbf,+ 0x72, 0xdd, 0x7b, 0x7d, 0xde, 0x32, 0xdf, 0x0c, 0x90, 0x0e, 0x89, 0xff, 0x36, 0x0f, 0xd3, 0x18, 0x77, 0xe3, 0xb6, 0xcf,+ 0xac, 0xd4, 0xd6, 0x3b, 0xb7, 0xa3, 0xf0, 0xcd, 0x6a, 0xf3, 0xd8, 0xf1, 0x1d, 0xed, 0xfa, 0x54, 0x1d, 0x25, 0xca, 0x98,+ 0x54, 0x1c, 0xac, 0x11, 0xf3, 0x7f, 0x4c, 0xfc, 0x97, 0xc6, 0xa9, 0xbd, 0xf7, 0x27, 0x66, 0x1e, 0x9f, 0xa5, 0xff, 0x88,+ 0xb9, 0x3a, 0x35, 0xcc, 0x0a, 0x6a, 0x5b, 0xb4, 0xfb, 0xbf, 0xe2, 0xd4, 0x29, 0xb9, 0x95, 0xf4, 0xe7, 0xa9, 0x19, 0xf1,+ 0xdf, 0x13, 0xe3, 0xda, 0xfc, 0x5f, 0xd6, 0x3f, 0xce, 0xdd, 0x66, 0x53, 0x9e, 0xa6, 0x5b, 0x62, 0x6c, 0xad, 0xfb, 0x3f,+ 0x44, 0xfa, 0x19, 0xe7, 0x7d, 0x9e, 0x42, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x18, 0xeb, 0xc7, 0x3b, 0xca, 0x53, 0x62, 0x8d, 0x59, 0x7c, 0xf6, 0xfd, 0x5a, 0x47, 0xb9, 0xf5, 0x8e, 0xef, 0xef, 0x68,+ 0xdf, 0x47, 0xc4, 0x9a, 0xb4, 0x92, 0xc1, 0xac, 0xdf, 0x8b, 0x68, 0x4b, 0x38, 0xf2, 0x46, 0xf4, 0xdb, 0x4c, 0xfd, 0x95,+ 0xf6, 0xe8, 0xfa, 0x9b, 0x98, 0x61, 0xb0, 0x96, 0x19, 0x66, 0x2d, 0xfd, 0x15, 0xd7, 0x41, 0x8f, 0xfe, 0xf5, 0xb9, 0x2a,+ 0x15, 0xf4, 0xf0, 0xcf, 0xf1, 0xaa, 0xfe, 0x26, 0xe6, 0x7d, 0x1c, 0x73, 0x17, 0x1b, 0xa3, 0xbf, 0xd2, 0x6f, 0x57, 0x99,+ 0xff, 0xeb, 0xc7, 0xcc, 0xe2, 0xfc, 0x6f, 0xd5, 0x59, 0xc5, 0xc2, 0xdd, 0xa8, 0xfe, 0x98, 0x6a, 0xed, 0x9f, 0xdb, 0xd5,+ 0x3f, 0x0d, 0xd1, 0x7f, 0xcc, 0x19, 0xcf, 0x73, 0xff, 0x57, 0xb2, 0x57, 0xcf, 0xf0, 0xb9, 0xf5, 0x79, 0xc3, 0x6b, 0xa5,+ 0x47, 0xf4, 0xcc, 0xb8, 0xf9, 0x1f, 0x17, 0xe0, 0x79, 0x5c, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x47, 0xac, 0x51, 0xe8, 0x6b, 0x67, 0x23, 0x56, 0x00, 0x1f, 0xbe, 0x9e, 0x1b, 0xd6, 0x30, 0xdf, 0x7f,+ 0x3d, 0xef, 0x38, 0x46, 0xcc, 0x99, 0xf3, 0x4f, 0xdb, 0x8f, 0xb7, 0x35, 0x0f, 0x9a, 0xee, 0x20, 0x8c, 0x58, 0x07, 0x3c,+ 0x5e, 0xff, 0xd4, 0xb4, 0x1e, 0xfb, 0x50, 0xc9, 0x2c, 0x78, 0x86, 0xb2, 0x33, 0xe3, 0x53, 0x29, 0x43, 0x94, 0xdf, 0xcd,+ 0x54, 0xef, 0x05, 0x25, 0xd7, 0x5d, 0xed, 0x68, 0xda, 0x0e, 0xc5, 0x25, 0x77, 0x4c, 0xcd, 0xcb, 0xe2, 0xbf, 0xf2, 0xec,+ 0xbe, 0xb6, 0xdc, 0x30, 0x07, 0x8c, 0xf7, 0x48, 0x27, 0x77, 0x3c, 0xf6, 0xf9, 0xee, 0xc6, 0xeb, 0x9f, 0x1a, 0x3c, 0x7e,+ 0xd1, 0x8e, 0x14, 0xab, 0xec, 0x7e, 0xab, 0x8c, 0x80, 0xd1, 0xfa, 0xd7, 0xae, 0x55, 0x77, 0x09, 0xa5, 0xd0, 0x71, 0x13,+ 0xad, 0x7f, 0xcb, 0x38, 0x8d, 0x1e, 0xc1, 0xca, 0x08, 0x38, 0x26, 0xfe, 0xcd, 0xad, 0x7f, 0x79, 0x6e, 0x88, 0xef, 0x3d,+ 0xc5, 0x05, 0xa4, 0xcd, 0x28, 0xbd, 0x6e, 0x35, 0x45, 0xc5, 0x2c, 0xcd, 0x1c, 0x47, 0x3c, 0x41, 0x6b, 0x7b, 0x55, 0x47,+ 0x3b, 0x36, 0xb5, 0x9e, 0x38, 0x5e, 0x7f, 0x93, 0x77, 0xfc, 0xce, 0xcb, 0xed, 0x7e, 0xad, 0x45, 0x9d, 0xee, 0xd8, 0x8b,+ 0x8f, 0xff, 0xf5, 0xbe, 0x8d, 0x76, 0x44, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,+ 0xdb, 0xcc, 0x51, 0xe0, 0xcf, 0x54, 0x53, 0xaf, 0xa1, 0xee, 0x9d, 0x75, 0xe4, 0xde, 0xb9, 0xa3, 0xf6, 0xb7, 0xd3, 0xf3,+ 0x82, 0xd9, 0x90, 0x1d, 0xe0, 0xe2, 0xd7, 0xcd, 0xfa, 0xb2, 0x98, 0xd5, 0x7a, 0x48, 0xcd, 0xb8, 0xe5, 0xf5, 0x60, 0xf4,+ 0xf8, 0x7a, 0x54, 0xcf, 0x47, 0xbc, 0x0f, 0x2f, 0xc6, 0xdb, 0xa6, 0xc5, 0xbf, 0xe6, 0x0b, 0x59, 0x4d, 0xff, 0x74, 0x90,+ 0x3f, 0xaf, 0x47, 0xff, 0xde, 0xdd, 0x9f, 0x75, 0x47, 0x96, 0xbf, 0x57, 0xaf, 0xa0, 0x7f, 0x9b, 0x7b, 0x57, 0xf1, 0x11,+ 0x46, 0xfb, 0xf0, 0x66, 0xe9, 0x6f, 0xd2, 0xde, 0xb9, 0x3d, 0xfa, 0xf7, 0xf9, 0xe5, 0x8f, 0x8b, 0x7f, 0xfd, 0x8c, 0x69,+ 0xc8, 0xce, 0xe8, 0xbd, 0xd1, 0xea, 0xcb, 0xd4, 0x38, 0xc3, 0xa9, 0x15, 0xef, 0x97, 0x1b, 0xe5, 0xec, 0x9a, 0xeb, 0x5e,+ 0x8c, 0xf2, 0xaf, 0xf6, 0x66, 0xff, 0x9e, 0xa1, 0x3f, 0xde, 0xb1, 0x6b, 0x8f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5b, 0x5b, 0xc7, 0x89, 0xdb, 0x8f, 0xca, 0x9b, 0xd5, 0xcd, 0x36, 0x33, 0x7a, 0xa8,+ 0xb9, 0x63, 0xbc, 0xde, 0x8a, 0xd2, 0x5a, 0xe5, 0x77, 0xf6, 0xe5, 0x3d, 0x8f, 0xec, 0x13, 0x57, 0xef, 0xd4, 0xea, 0xe6,+ 0xb7, 0xea, 0x66, 0x77, 0xed, 0xd7, 0x59, 0x50, 0xb2, 0x70, 0x66, 0xbf, 0x03, 0xc0, 0x97, 0xab, 0xcd, 0xf7, 0x6a, 0x2e,+ 0x3a, 0x45, 0x62, 0x5c, 0x17, 0x6a, 0x86, 0xbe, 0xc7, 0xef, 0xf4, 0xc1, 0xa3, 0xe0, 0xba, 0xf9, 0x1d, 0x25, 0x7d, 0xb5,+ 0xf3, 0x7d, 0x66, 0xc3, 0xec, 0xae, 0xeb, 0xd3, 0x3f, 0xbb, 0x73, 0xb5, 0xf9, 0xd5, 0x89, 0xf1, 0x15, 0x6a, 0x59, 0x71,+ 0x4a, 0xc7, 0xfc, 0xb2, 0xf0, 0xbf, 0xda, 0x35, 0xd5, 0xeb, 0xbe, 0x3d, 0xf3, 0xfa, 0x6b, 0xdf, 0xdd, 0xff, 0xed, 0xad,+ 0xeb, 0x75, 0xf2, 0x68, 0x2e, 0xae, 0xde, 0x11, 0x10, 0x99, 0x4d, 0x51, 0x75, 0x64, 0xb5, 0xe8, 0xbf, 0x77, 0xce, 0x36,+ 0xfd, 0xdf, 0xfc, 0xdb, 0x57, 0xbb, 0x14, 0xff, 0x9a, 0xfe, 0x71, 0x3e, 0xf7, 0xb1, 0xf1, 0x3f, 0x22, 0x2b, 0xde, 0x5e,+ 0x49, 0x6b, 0xfc, 0x6b, 0x63, 0xa7, 0x27, 0xfe, 0x4b, 0xf7, 0x7f, 0xbf, 0xfe, 0xaa, 0x0b, 0xee, 0x68, 0xfd, 0x93, 0xec,+ 0x53, 0xd5, 0x9e, 0x1a, 0xeb, 0x3d, 0xd9, 0x33, 0x77, 0x94, 0xee, 0xff, 0xaa, 0x86, 0xd1, 0xf1, 0xbf, 0x9e, 0xfe, 0xa9,+ 0xc3, 0x59, 0xeb, 0x1d, 0x53, 0xad, 0x3d, 0x69, 0xe2, 0x0c, 0xbe, 0xff, 0xfc, 0x7f, 0xac, 0xfe, 0xb1, 0xce, 0x4a, 0x2d,+ 0xab, 0xe3, 0x8a, 0xfc, 0xf2, 0xd6, 0x27, 0xa9, 0xc7, 0xf6, 0xbd, 0x6b, 0xfe, 0xaf, 0xd5, 0xed, 0x3b, 0xf3, 0xa8, 0xba,+ 0x10, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xa3, 0xd7, 0x89, 0xf6, 0xe9,+ 0xa6, 0x43, 0xa4, 0x56, 0x6f, 0x74, 0x79, 0xcd, 0xd3, 0xf6, 0x95, 0x7d, 0x63, 0x9f, 0x3f, 0x78, 0xf5, 0x99, 0x3d, 0xb3,+ 0x5f, 0x27, 0xb4, 0x35, 0xef, 0xee, 0x70, 0xbc, 0xf5, 0xa3, 0xbc, 0xa7, 0xb4, 0x8a, 0xd1, 0xe3, 0x44, 0xfb, 0xc1, 0x9e,+ 0xd8, 0x1f, 0x1b, 0x47, 0xad, 0xd5, 0x1b, 0x5d, 0x5e, 0xd2, 0xff, 0x33, 0xfb, 0xd7, 0xfe, 0xb1, 0xa7, 0xf6, 0xc5, 0x66,+ 0xad, 0xbf, 0x0e, 0x6f, 0x6b, 0xc9, 0xcd, 0xe3, 0xd9, 0x47, 0x59, 0xcb, 0x03, 0xd5, 0xe7, 0x44, 0xf9, 0xd9, 0x3e, 0xb0,+ 0x1f, 0x37, 0x7c, 0x68, 0xb5, 0x7a, 0xa3, 0xcb, 0x4b, 0xfa, 0xff, 0x69, 0x66, 0x7f, 0xdb, 0x6f, 0xf6, 0xe1, 0x83, 0x92,+ 0x27, 0xf6, 0x64, 0x42, 0x5b, 0x93, 0xdd, 0xbd, 0x68, 0xe7, 0x5d, 0xe7, 0x3e, 0xda, 0x6a, 0xfc, 0xf7, 0x38, 0xd1, 0x3e,+ 0xb6, 0x9f, 0xec, 0x5b, 0xc1, 0x85, 0x30, 0x53, 0xff, 0xaf, 0xed, 0xbf, 0x1d, 0xfd, 0x35, 0x47, 0x45, 0x6f, 0x79, 0x6b,+ 0xfc, 0xdb, 0xa0, 0xfc, 0x6f, 0x3d, 0xfa, 0xcf, 0xea, 0xb3, 0x76, 0x6f, 0xe6, 0x56, 0x9f, 0x7c, 0x64, 0x4f, 0x17, 0xd2,+ 0xbf, 0x76, 0xff, 0x4f, 0x8e, 0x8c, 0xb3, 0xd1, 0xf7, 0xff, 0x33, 0xeb, 0x5f, 0x6a, 0xdf, 0xef, 0x0b, 0xe9, 0xdf, 0xe2,+ 0xb0, 0x1a, 0xe7, 0x31, 0x19, 0xe3, 0x44, 0x43, 0xff, 0x38, 0xfd, 0xf5, 0xd8, 0x1e, 0xef, 0x81, 0x53, 0xeb, 0x8d, 0x2e,+ 0xaf, 0xe1, 0xd1, 0x7f, 0x76, 0x5b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb4,+ 0xe4, 0x8b, 0x2b, 0xaf, 0x3e, 0xe7, 0xe2, 0xda, 0x62, 0x69, 0xd5, 0x31, 0x17, 0x4a, 0x14, 0xa7, 0x43, 0xdb, 0xce, 0xc2,+ 0x26, 0xe6, 0x3a, 0x8c, 0xbd, 0xce, 0xfa, 0xb5, 0xc4, 0x9e, 0x6f, 0x0f, 0x7f, 0xbe, 0xb8, 0xd6, 0xb6, 0xa4, 0x62, 0xf6,+ 0xb0, 0xbc, 0xab, 0x71, 0x4f, 0x9f, 0x99, 0xbc, 0x8a, 0x5e, 0x7b, 0x4f, 0xfc, 0x75, 0x1e, 0x7b, 0xbe, 0x9e, 0x7c, 0x31,+ 0x67, 0xcf, 0x70, 0xe1, 0xd1, 0xff, 0xd6, 0x68, 0x75, 0x52, 0x79, 0x33, 0xa0, 0xac, 0x5a, 0xa6, 0xe6, 0x0f, 0x3d, 0xdb,+ 0x75, 0x46, 0xea, 0xaf, 0xc4, 0xd5, 0x59, 0xca, 0x3c, 0xd7, 0x79, 0x54, 0xd9, 0xc8, 0xe3, 0xaa, 0xfa, 0x9f, 0x59, 0xe3,+ 0xde, 0xfb, 0xff, 0xad, 0xeb, 0x7f, 0xf6, 0xb9, 0xaf, 0xc5, 0x21, 0x6f, 0xe2, 0x3e, 0xe1, 0x23, 0xca, 0x8e, 0xd4, 0xbf,+ 0xc7, 0x9d, 0x76, 0xb6, 0x18, 0x6f, 0xbd, 0x9e, 0x5b, 0x8a, 0xff, 0x51, 0xcf, 0xd5, 0xe7, 0xd3, 0xdf, 0xd0, 0xff, 0xa6,+ 0xf5, 0x4f, 0x37, 0xf9, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa5, 0xf6, 0x3b, 0x55,+ 0xab, 0xec, 0x0c, 0x6a, 0x8b, 0xfb, 0x02, 0xdb, 0xae, 0x6f, 0x0d, 0xcf, 0x5f, 0x96, 0xf6, 0xce, 0xec, 0xfb, 0x9d, 0xaf,+ 0xde, 0x77, 0x65, 0xaf, 0xe1, 0x3a, 0xbe, 0x40, 0x3d, 0x73, 0xd6, 0xd1, 0x9e, 0xbf, 0xd2, 0x4e, 0xbb, 0xca, 0x0e, 0xd6,+ 0x31, 0xeb, 0x1e, 0xd7, 0xf1, 0xff, 0x6d, 0xbd, 0x9e, 0x4f, 0xb0, 0x5e, 0x32, 0x72, 0xdd, 0x4b, 0x1d, 0x5b, 0x56, 0xe8,+ 0xdb, 0xb5, 0xd6, 0xbd, 0x6a, 0x25, 0xf9, 0x02, 0xde, 0xa6, 0xbe, 0x11, 0xac, 0xf8, 0xa6, 0x29, 0xbb, 0x1d, 0xdf, 0xcb,+ 0x7e, 0xcc, 0x9d, 0xbb, 0x0f, 0xce, 0xa4, 0xf1, 0xc8, 0xfb, 0x7f, 0xdd, 0xdf, 0x1d, 0x79, 0xdf, 0x58, 0x4b, 0xff, 0x33,+ 0x5c, 0x43, 0xdd, 0xef, 0x63, 0x43, 0xf4, 0xaf, 0xd7, 0x39, 0xb7, 0xfe, 0xab, 0xcd, 0x0d, 0xb3, 0xbc, 0x3b, 0xba, 0xfe,+ 0xd7, 0xf5, 0x7e, 0xcd, 0x68, 0xe7, 0x2c, 0xed, 0x95, 0x71, 0x67, 0x85, 0xac, 0xd1, 0x57, 0xf0, 0xbd, 0xcd, 0x68, 0x27,+ 0xbe, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x46, 0xf3, 0x39, 0xcd, 0xce, 0xe1, 0xb7, 0xba,+ 0x9b, 0xef, 0xd8, 0xf3, 0xf5, 0x79, 0x00, 0x95, 0x96, 0x1e, 0x9b, 0xc3, 0xaf, 0x7f, 0x75, 0xe5, 0xec, 0x19, 0xfc, 0xea,+ 0xab, 0x5c, 0x57, 0x5e, 0x3f, 0x68, 0x8b, 0xff, 0x5b, 0x76, 0x71, 0x6b, 0x33, 0xc0, 0xd1, 0xb9, 0x8d, 0x7a, 0xca, 0xfa,+ 0xb2, 0xa2, 0xcc, 0x70, 0x1d, 0x7a, 0x33, 0xcd, 0xa8, 0x65, 0xbd, 0x2e, 0xc0, 0xf5, 0x33, 0xe3, 0xf5, 0xdd, 0xff, 0x57,+ 0x5b, 0xcd, 0x8f, 0x2e, 0xd3, 0xf5, 0x3f, 0x4b, 0xfc, 0x47, 0x39, 0xd9, 0xd6, 0x58, 0xcd, 0x5f, 0x4b, 0xff, 0x24, 0xcc,+ 0xb9, 0x47, 0x97, 0x79, 0xbe, 0xaf, 0x30, 0x7f, 0x0e, 0x9b, 0xa1, 0xbf, 0x75, 0xc6, 0xff, 0x95, 0xf3, 0x57, 0x5d, 0x25,+ 0x8b, 0x25, 0xd9, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xcd, 0xfb, 0x67, 0x15,+ 0x3f, 0xda, 0x3a, 0xde, 0x40, 0xc5, 0xfb, 0x12, 0x7d, 0x05, 0x3d, 0x59, 0xfc, 0x4c, 0xf0, 0xb5, 0x8d, 0x76, 0x0e, 0x95,+ 0xf3, 0xf8, 0xad, 0xe4, 0x0d, 0xdc, 0xef, 0xbb, 0x1c, 0xee, 0xfb, 0x8c, 0xcf, 0xe2, 0x97, 0x96, 0xd4, 0xff, 0x7c, 0x0e,+ 0xb7, 0xed, 0x92, 0x7c, 0x82, 0xbe, 0x5b, 0x71, 0xfd, 0xf6, 0xfc, 0x2b, 0xdc, 0x6a, 0x76, 0xbc, 0x51, 0x65, 0x4a, 0xcd,+ 0x99, 0x99, 0x36, 0xcf, 0x93, 0xc7, 0x4d, 0xf3, 0x76, 0x1d, 0xeb, 0x52, 0x9a, 0xe5, 0x7d, 0xba, 0x05, 0xfd, 0xd3, 0xf2,+ 0xee, 0x36, 0xf4, 0x47, 0x7f, 0x6b, 0xf0, 0x30, 0x9f, 0x47, 0xff, 0x73, 0x3b, 0xdc, 0xe6, 0x65, 0x1b, 0x36, 0xf9, 0x1b,+ 0x0a, 0x3c, 0xeb, 0x5f, 0xe3, 0xd3, 0x8a, 0xf2, 0xfd, 0x2c, 0xf4, 0xbf, 0xee, 0xe7, 0xd4, 0xf3, 0x7d, 0x36, 0x04, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xb2,+ 0x0c, 0xa2, 0x3f, 0xfa, 0xdf, 0xb8, 0xfe, 0xff, 0x03 };++// Font glyphs rectangles data (on atlas)+static const Rectangle jungleFontRecs[189] = {+ { 4, 4, 5 , 12 },+ { 17, 4, 2 , 7 },+ { 27, 4, 5 , 3 },+ { 40, 4, 5 , 5 },+ { 53, 4, 6 , 7 },+ { 67, 4, 7 , 7 },+ { 82, 4, 5 , 7 },+ { 95, 4, 3 , 3 },+ { 106, 4, 4 , 8 },+ { 118, 4, 4 , 8 },+ { 130, 4, 5 , 5 },+ { 143, 4, 5 , 5 },+ { 156, 4, 2 , 3 },+ { 166, 4, 5 , 1 },+ { 179, 4, 2 , 2 },+ { 189, 4, 7 , 7 },+ { 204, 4, 7 , 6 },+ { 219, 4, 6 , 6 },+ { 233, 4, 6 , 6 },+ { 4, 24, 6 , 6 },+ { 18, 24, 6 , 6 },+ { 32, 24, 6 , 6 },+ { 46, 24, 6 , 6 },+ { 60, 24, 6 , 6 },+ { 74, 24, 6 , 6 },+ { 88, 24, 6 , 6 },+ { 102, 24, 2 , 5 },+ { 112, 24, 2 , 6 },+ { 122, 24, 3 , 5 },+ { 133, 24, 5 , 3 },+ { 146, 24, 3 , 5 },+ { 157, 24, 6 , 7 },+ { 171, 24, 7 , 7 },+ { 186, 24, 6 , 7 },+ { 200, 24, 6 , 7 },+ { 214, 24, 6 , 7 },+ { 228, 24, 6 , 7 },+ { 4, 44, 6 , 7 },+ { 18, 44, 6 , 7 },+ { 32, 44, 6 , 7 },+ { 46, 44, 6 , 7 },+ { 60, 44, 6 , 7 },+ { 74, 44, 6 , 7 },+ { 88, 44, 6 , 7 },+ { 102, 44, 6 , 7 },+ { 116, 44, 7 , 7 },+ { 131, 44, 6 , 7 },+ { 145, 44, 6 , 7 },+ { 159, 44, 6 , 7 },+ { 173, 44, 7 , 8 },+ { 188, 44, 6 , 7 },+ { 202, 44, 6 , 7 },+ { 216, 44, 6 , 7 },+ { 230, 44, 6 , 7 },+ { 4, 64, 6 , 7 },+ { 18, 64, 7 , 7 },+ { 33, 64, 6 , 7 },+ { 47, 64, 6 , 7 },+ { 61, 64, 6 , 7 },+ { 75, 64, 4 , 8 },+ { 87, 64, 7 , 7 },+ { 102, 64, 4 , 8 },+ { 114, 64, 4 , 2 },+ { 126, 64, 6 , 1 },+ { 140, 64, 2 , 2 },+ { 150, 64, 6 , 5 },+ { 164, 64, 6 , 7 },+ { 178, 64, 6 , 5 },+ { 192, 64, 6 , 7 },+ { 206, 64, 6 , 5 },+ { 220, 64, 6 , 7 },+ { 234, 64, 6 , 7 },+ { 4, 84, 6 , 7 },+ { 18, 84, 6 , 7 },+ { 32, 84, 5 , 8 },+ { 45, 84, 6 , 7 },+ { 59, 84, 6 , 7 },+ { 73, 84, 7 , 5 },+ { 88, 84, 6 , 5 },+ { 102, 84, 6 , 5 },+ { 116, 84, 6 , 7 },+ { 130, 84, 6 , 7 },+ { 144, 84, 6 , 5 },+ { 158, 84, 6 , 5 },+ { 172, 84, 6 , 6 },+ { 186, 84, 6 , 5 },+ { 200, 84, 6 , 5 },+ { 214, 84, 7 , 5 },+ { 229, 84, 6 , 5 },+ { 4, 104, 6 , 7 },+ { 18, 104, 6 , 5 },+ { 32, 104, 4 , 8 },+ { 44, 104, 2 , 8 },+ { 54, 104, 4 , 8 },+ { 66, 104, 5 , 2 },+ { 79, 104, 2 , 7 },+ { 89, 104, 6 , 6 },+ { 103, 104, 6 , 7 },+ { 117, 104, 6 , 7 },+ { 131, 104, 6 , 7 },+ { 145, 104, 8 , 8 },+ { 161, 104, 6 , 9 },+ { 175, 104, 8 , 8 },+ { 191, 104, 7 , 7 },+ { 206, 104, 8 , 8 },+ { 222, 104, 6 , 5 },+ { 236, 104, 8 , 8 },+ { 4, 124, 7 , 7 },+ { 19, 124, 8 , 8 },+ { 35, 124, 4 , 4 },+ { 47, 124, 8 , 8 },+ { 63, 124, 8 , 8 },+ { 79, 124, 8 , 8 },+ { 95, 124, 8 , 8 },+ { 111, 124, 6 , 7 },+ { 125, 124, 5 , 8 },+ { 138, 124, 3 , 3 },+ { 149, 124, 8 , 8 },+ { 165, 124, 8 , 8 },+ { 181, 124, 8 , 8 },+ { 197, 124, 6 , 5 },+ { 211, 124, 10 , 7 },+ { 229, 124, 10 , 5 },+ { 4, 144, 8 , 8 },+ { 20, 144, 6 , 7 },+ { 34, 144, 6 , 10 },+ { 48, 144, 6 , 10 },+ { 62, 144, 6 , 10 },+ { 76, 144, 6 , 10 },+ { 90, 144, 6 , 10 },+ { 104, 144, 6 , 10 },+ { 118, 144, 10 , 7 },+ { 136, 144, 6 , 9 },+ { 150, 144, 6 , 10 },+ { 164, 144, 6 , 10 },+ { 178, 144, 6 , 10 },+ { 192, 144, 6 , 10 },+ { 206, 144, 6 , 10 },+ { 220, 144, 6 , 10 },+ { 234, 144, 6 , 10 },+ { 4, 164, 6 , 10 },+ { 18, 164, 6 , 7 },+ { 32, 164, 6 , 10 },+ { 46, 164, 6 , 10 },+ { 60, 164, 6 , 10 },+ { 74, 164, 6 , 10 },+ { 88, 164, 6 , 10 },+ { 102, 164, 6 , 10 },+ { 116, 164, 6 , 5 },+ { 130, 164, 6 , 7 },+ { 144, 164, 6 , 10 },+ { 158, 164, 6 , 10 },+ { 172, 164, 6 , 10 },+ { 186, 164, 6 , 10 },+ { 200, 164, 6 , 10 },+ { 214, 164, 6 , 7 },+ { 228, 164, 6 , 7 },+ { 4, 184, 6 , 8 },+ { 18, 184, 6 , 8 },+ { 32, 184, 6 , 8 },+ { 46, 184, 6 , 8 },+ { 60, 184, 6 , 8 },+ { 74, 184, 6 , 8 },+ { 88, 184, 9 , 5 },+ { 105, 184, 6 , 7 },+ { 119, 184, 6 , 8 },+ { 133, 184, 6 , 8 },+ { 147, 184, 6 , 8 },+ { 161, 184, 6 , 8 },+ { 175, 184, 6 , 8 },+ { 189, 184, 6 , 8 },+ { 203, 184, 6 , 8 },+ { 217, 184, 6 , 8 },+ { 231, 184, 6 , 7 },+ { 4, 204, 6 , 8 },+ { 18, 204, 6 , 8 },+ { 32, 204, 6 , 8 },+ { 46, 204, 6 , 8 },+ { 60, 204, 6 , 8 },+ { 74, 204, 6 , 8 },+ { 88, 204, 5 , 5 },+ { 101, 204, 6 , 5 },+ { 115, 204, 6 , 8 },+ { 129, 204, 6 , 8 },+ { 143, 204, 6 , 8 },+ { 157, 204, 6 , 8 },+ { 171, 204, 6 , 10 },+ { 185, 204, 6 , 9 },+ { 199, 204, 6 , 10 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo jungleFontGlyphs[189] = {+ { 32, 0, 9, 5, { 0 }},+ { 33, 0, 2, 3, { 0 }},+ { 34, 0, 2, 6, { 0 }},+ { 35, 0, 3, 6, { 0 }},+ { 36, 0, 2, 7, { 0 }},+ { 37, 0, 2, 8, { 0 }},+ { 38, 0, 2, 6, { 0 }},+ { 39, 0, 2, 4, { 0 }},+ { 40, 0, 2, 5, { 0 }},+ { 41, 0, 2, 5, { 0 }},+ { 42, 0, 2, 6, { 0 }},+ { 43, 0, 3, 6, { 0 }},+ { 44, 0, 7, 3, { 0 }},+ { 45, 0, 5, 6, { 0 }},+ { 46, 0, 7, 3, { 0 }},+ { 47, 0, 2, 8, { 0 }},+ { 48, 0, 3, 8, { 0 }},+ { 49, 0, 3, 7, { 0 }},+ { 50, 0, 3, 7, { 0 }},+ { 51, 0, 3, 7, { 0 }},+ { 52, 0, 3, 7, { 0 }},+ { 53, 0, 3, 7, { 0 }},+ { 54, 0, 3, 7, { 0 }},+ { 55, 0, 3, 7, { 0 }},+ { 56, 0, 3, 7, { 0 }},+ { 57, 0, 3, 7, { 0 }},+ { 58, 0, 4, 3, { 0 }},+ { 59, 0, 4, 3, { 0 }},+ { 60, 0, 3, 4, { 0 }},+ { 61, 0, 4, 6, { 0 }},+ { 62, 0, 3, 4, { 0 }},+ { 63, 0, 2, 7, { 0 }},+ { 64, 0, 2, 8, { 0 }},+ { 65, 0, 2, 7, { 0 }},+ { 66, 0, 2, 7, { 0 }},+ { 67, 0, 2, 7, { 0 }},+ { 68, 0, 2, 7, { 0 }},+ { 69, 0, 2, 7, { 0 }},+ { 70, 0, 2, 7, { 0 }},+ { 71, 0, 2, 7, { 0 }},+ { 72, 0, 2, 7, { 0 }},+ { 73, 0, 2, 7, { 0 }},+ { 74, 0, 2, 7, { 0 }},+ { 75, 0, 2, 7, { 0 }},+ { 76, 0, 2, 7, { 0 }},+ { 77, 0, 2, 8, { 0 }},+ { 78, 0, 2, 7, { 0 }},+ { 79, 0, 2, 7, { 0 }},+ { 80, 0, 2, 7, { 0 }},+ { 81, 0, 2, 7, { 0 }},+ { 82, 0, 2, 7, { 0 }},+ { 83, 0, 2, 7, { 0 }},+ { 84, 0, 2, 7, { 0 }},+ { 85, 0, 2, 7, { 0 }},+ { 86, 0, 2, 7, { 0 }},+ { 87, 0, 2, 8, { 0 }},+ { 88, 0, 2, 7, { 0 }},+ { 89, 0, 2, 7, { 0 }},+ { 90, 0, 2, 7, { 0 }},+ { 91, 0, 2, 5, { 0 }},+ { 92, 0, 2, 8, { 0 }},+ { 93, 0, 2, 5, { 0 }},+ { 94, 0, -1, 5, { 0 }},+ { 95, 0, 10, 7, { 0 }},+ { 96, 0, -1, 3, { 0 }},+ { 97, 0, 4, 7, { 0 }},+ { 98, 0, 2, 7, { 0 }},+ { 99, 0, 4, 7, { 0 }},+ { 100, 0, 2, 7, { 0 }},+ { 101, 0, 4, 7, { 0 }},+ { 102, 0, 2, 7, { 0 }},+ { 103, 0, 4, 7, { 0 }},+ { 104, 0, 2, 7, { 0 }},+ { 105, 0, 2, 7, { 0 }},+ { 106, 0, 2, 6, { 0 }},+ { 107, 0, 2, 7, { 0 }},+ { 108, 0, 2, 7, { 0 }},+ { 109, 0, 4, 8, { 0 }},+ { 110, 0, 4, 7, { 0 }},+ { 111, 0, 4, 7, { 0 }},+ { 112, 0, 4, 7, { 0 }},+ { 113, 0, 4, 7, { 0 }},+ { 114, 0, 4, 7, { 0 }},+ { 115, 0, 4, 7, { 0 }},+ { 116, 0, 3, 7, { 0 }},+ { 117, 0, 4, 7, { 0 }},+ { 118, 0, 4, 7, { 0 }},+ { 119, 0, 4, 8, { 0 }},+ { 120, 0, 4, 7, { 0 }},+ { 121, 0, 4, 7, { 0 }},+ { 122, 0, 4, 7, { 0 }},+ { 123, 0, 2, 5, { 0 }},+ { 124, 0, 2, 3, { 0 }},+ { 125, 0, 2, 5, { 0 }},+ { 126, 0, -1, 6, { 0 }},+ { 161, 0, 2, 3, { 0 }},+ { 162, 0, 3, 7, { 0 }},+ { 163, 0, 2, 7, { 0 }},+ { 8364, 0, 2, 7, { 0 }},+ { 165, 0, 2, 7, { 0 }},+ { 352, 0, 1, 8, { 0 }},+ { 167, 0, 1, 7, { 0 }},+ { 353, 0, 1, 8, { 0 }},+ { 169, 0, 2, 8, { 0 }},+ { 170, 0, 1, 8, { 0 }},+ { 171, 0, 3, 7, { 0 }},+ { 172, 0, 1, 8, { 0 }},+ { 174, 0, 2, 8, { 0 }},+ { 175, 0, 1, 8, { 0 }},+ { 176, 0, 1, 2, { 0 }},+ { 177, 0, 1, 8, { 0 }},+ { 178, 0, 1, 8, { 0 }},+ { 179, 0, 1, 8, { 0 }},+ { 381, 0, 1, 8, { 0 }},+ { 181, 0, 4, 7, { 0 }},+ { 182, 0, 1, 4, { 0 }},+ { 183, 0, 4, 4, { 0 }},+ { 382, 0, 1, 8, { 0 }},+ { 185, 0, 1, 8, { 0 }},+ { 186, 0, 1, 8, { 0 }},+ { 187, 0, 3, 7, { 0 }},+ { 338, 0, 2, 11, { 0 }},+ { 339, 0, 4, 11, { 0 }},+ { 376, 0, 1, 8, { 0 }},+ { 191, 0, 2, 7, { 0 }},+ { 192, 0, -1, 7, { 0 }},+ { 193, 0, -1, 7, { 0 }},+ { 194, 0, -1, 7, { 0 }},+ { 195, 0, -1, 7, { 0 }},+ { 196, 0, -1, 7, { 0 }},+ { 197, 0, -1, 7, { 0 }},+ { 198, 0, 2, 11, { 0 }},+ { 199, 0, 2, 7, { 0 }},+ { 200, 0, -1, 7, { 0 }},+ { 201, 0, -1, 7, { 0 }},+ { 202, 0, -1, 7, { 0 }},+ { 203, 0, -1, 7, { 0 }},+ { 204, 0, -1, 7, { 0 }},+ { 205, 0, -1, 7, { 0 }},+ { 206, 0, -1, 7, { 0 }},+ { 207, 0, -1, 7, { 0 }},+ { 208, 0, 2, 7, { 0 }},+ { 209, 0, -1, 7, { 0 }},+ { 210, 0, -1, 7, { 0 }},+ { 211, 0, -1, 7, { 0 }},+ { 212, 0, -1, 7, { 0 }},+ { 213, 0, -1, 7, { 0 }},+ { 214, 0, -1, 7, { 0 }},+ { 215, 0, 3, 7, { 0 }},+ { 216, 0, 2, 7, { 0 }},+ { 217, 0, -1, 7, { 0 }},+ { 218, 0, -1, 7, { 0 }},+ { 219, 0, -1, 7, { 0 }},+ { 220, 0, -1, 7, { 0 }},+ { 221, 0, -1, 7, { 0 }},+ { 222, 0, 2, 7, { 0 }},+ { 223, 0, 2, 7, { 0 }},+ { 224, 0, 1, 7, { 0 }},+ { 225, 0, 1, 7, { 0 }},+ { 226, 0, 1, 7, { 0 }},+ { 227, 0, 1, 7, { 0 }},+ { 228, 0, 1, 7, { 0 }},+ { 229, 0, 1, 7, { 0 }},+ { 230, 0, 4, 10, { 0 }},+ { 231, 0, 4, 7, { 0 }},+ { 232, 0, 1, 7, { 0 }},+ { 233, 0, 1, 7, { 0 }},+ { 234, 0, 1, 7, { 0 }},+ { 235, 0, 1, 7, { 0 }},+ { 236, 0, 1, 7, { 0 }},+ { 237, 0, 1, 7, { 0 }},+ { 238, 0, 1, 7, { 0 }},+ { 239, 0, 1, 7, { 0 }},+ { 240, 0, 2, 7, { 0 }},+ { 241, 0, 1, 7, { 0 }},+ { 242, 0, 1, 7, { 0 }},+ { 243, 0, 1, 7, { 0 }},+ { 244, 0, 1, 7, { 0 }},+ { 245, 0, 1, 7, { 0 }},+ { 246, 0, 1, 7, { 0 }},+ { 247, 0, 3, 6, { 0 }},+ { 248, 0, 4, 7, { 0 }},+ { 249, 0, 1, 7, { 0 }},+ { 250, 0, 1, 7, { 0 }},+ { 251, 0, 1, 7, { 0 }},+ { 252, 0, 1, 7, { 0 }},+ { 253, 0, 1, 7, { 0 }},+ { 254, 0, 2, 7, { 0 }},+ { 255, 0, 1, 7, { 0 }},+};++// Style loading function: Jungle+static void GuiLoadStyleJungle(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < JUNGLE_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(jungleStyleProps[i].controlId, jungleStyleProps[i].propertyId, jungleStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int jungleFontDataSize = 0;+ unsigned char *data = DecompressData(jungleFontData, JUNGLE_STYLE_FONT_ATLAS_COMP_SIZE, &jungleFontDataSize);+ Image imFont = { data, 256, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 12;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, jungleFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, jungleFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 254, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/lavanda/style_lavanda.h view
@@ -0,0 +1,607 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleLavanda(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define LAVANDA_STYLE_PROPS_COUNT 16++// Custom style name: Lavanda+static const GuiStyleProp lavandaStyleProps[LAVANDA_STYLE_PROPS_COUNT] = {+ { 0, 0, 0xab9bd3ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x3e4350ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xdadaf4ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xee84a0ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xf4b7c7ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xb7657bff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xd5c8dbff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0x966ec0ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0xd7ccf7ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x8fa2bdff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x6b798dff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x8292a9ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 18, 0x84adb7ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x5b5b81ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "Cartridge.ttf" (size: 16, spacing: 1)++#define LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE 2636++// Font atlas image pixels data: DEFLATE compressed+static unsigned char lavandaFontData[LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0xdb, 0xd2, 0xa4, 0xba, 0x0d, 0x06, 0x50, 0xde, 0xff, 0xa5, 0xbf, 0x5c, 0xa4, 0x52, 0x49, 0xaa, 0x66, 0x63, 0x24,+ 0x0b, 0x9a, 0xee, 0x59, 0xb3, 0xee, 0x7e, 0xa6, 0x4f, 0x06, 0xf9, 0x04, 0x96, 0x73, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7f,+ 0xfc, 0x4b, 0x4e, 0xfe, 0x6f, 0x2e, 0xbf, 0xd3, 0x7f, 0xfe, 0x9e, 0xc5, 0xff, 0xf8, 0xff, 0xff, 0x75, 0xed, 0x7d, 0x73,+ 0xf9, 0xf3, 0x3b, 0x47, 0xf2, 0xc7, 0xef, 0x97, 0x8d, 0xd7, 0xff, 0xd3, 0x3b, 0xd4, 0xff, 0xff, 0x7f, 0xff, 0x55, 0xca,+ 0xf1, 0xfc, 0x35, 0x47, 0xf1, 0x73, 0xb2, 0xf8, 0x9c, 0xab, 0xbf, 0xb0, 0x56, 0xfa, 0xb5, 0x73, 0x9e, 0xd3, 0x2b, 0xb2,+ 0xf3, 0xca, 0xf3, 0xd7, 0x1d, 0xe5, 0xb2, 0x3a, 0x96, 0x25, 0x5c, 0x3d, 0xcb, 0xef, 0x8b, 0xff, 0x5c, 0x78, 0xe5, 0xf9,+ 0xf1, 0x6c, 0xd4, 0x09, 0xeb, 0x72, 0xac, 0xd6, 0x18, 0x3b, 0xa5, 0x7a, 0xf6, 0x1d, 0x2b, 0xff, 0xff, 0x5a, 0x6d, 0xbb,+ 0x5f, 0x3b, 0xae, 0x4a, 0xbf, 0xfe, 0xad, 0xaf, 0x94, 0x5c, 0x06, 0xfe, 0x7f, 0x5a, 0xdf, 0x7e, 0xe2, 0xfa, 0xcf, 0xf6,+ 0xb5, 0x7d, 0xa5, 0xad, 0x9c, 0xb8, 0x46, 0xab, 0xf1, 0x9f, 0x56, 0x8b, 0x90, 0x45, 0x99, 0xde, 0x1d, 0xff, 0x9d, 0x76,+ 0x34, 0x37, 0x95, 0x6a, 0xb5, 0xbe, 0xad, 0x5f, 0x37, 0x29, 0xb6, 0xb4, 0xbd, 0xf8, 0x5f, 0x7f, 0x4e, 0xc6, 0xca, 0x6d,+ 0xdd, 0x7b, 0xa9, 0x97, 0x76, 0xef, 0xb7, 0x75, 0x6b, 0x95, 0x34, 0x7a, 0x40, 0xfd, 0xfa, 0x7a, 0xaa, 0xc4, 0x6b, 0x51,+ 0x7a, 0xa5, 0x75, 0xcb, 0x58, 0xbd, 0x9f, 0x72, 0x6b, 0x95, 0x47, 0xca, 0xf2, 0x68, 0xb7, 0x3a, 0xd5, 0x5f, 0x94, 0x72,+ 0x5c, 0x56, 0xfa, 0xe5, 0xfd, 0xab, 0x30, 0xa5, 0xd1, 0x59, 0x6e, 0x6b, 0xff, 0xd7, 0xad, 0x71, 0x9a, 0x57, 0x72, 0xca,+ 0x7d, 0x83, 0x94, 0x47, 0x95, 0xeb, 0x73, 0xbc, 0x1e, 0x8b, 0xcc, 0xc7, 0x7f, 0xaf, 0x1f, 0xf3, 0xa7, 0x72, 0xef, 0xf6,+ 0x12, 0xe6, 0xeb, 0xc6, 0xb7, 0xc7, 0x7f, 0x1a, 0x7d, 0x8c, 0xea, 0x6b, 0x52, 0x9e, 0x7b, 0x39, 0x6f, 0x23, 0xaf, 0x5f,+ 0x99, 0x19, 0xba, 0x26, 0x3b, 0xad, 0x41, 0x1a, 0xe3, 0xc5, 0xdd, 0x96, 0x7c, 0x7a, 0xce, 0xea, 0xc9, 0xf8, 0xcf, 0x85,+ 0x19, 0x89, 0xd5, 0x95, 0x97, 0x65, 0x29, 0xe4, 0x86, 0xf6, 0xff, 0x0d, 0x73, 0xaa, 0x4f, 0xc5, 0x7f, 0x96, 0x73, 0x5b,+ 0x13, 0xd7, 0x74, 0x46, 0xce, 0x43, 0x3e, 0x70, 0x16, 0xae, 0xc4, 0xff, 0xd1, 0x6c, 0xc9, 0x7f, 0x3b, 0xfe, 0x8f, 0x8b,+ 0xbd, 0xf8, 0xa3, 0x31, 0x0b, 0xf8, 0x5b, 0xf1, 0x9f, 0x46, 0xcc, 0x64, 0x6c, 0x64, 0xde, 0xeb, 0x33, 0xcc, 0xc6, 0xff,+ 0x7b, 0x6b, 0xe1, 0x55, 0xff, 0x3f, 0x17, 0xef, 0x30, 0xfd, 0x4e, 0xfc, 0x1f, 0xa3, 0xfd, 0xff, 0xf5, 0x15, 0x33, 0x31,+ 0x6b, 0xf4, 0x77, 0xc4, 0x7f, 0x9a, 0xf5, 0x70, 0x06, 0x67, 0x6e, 0xbe, 0x39, 0xfe, 0x3b, 0xd1, 0x93, 0x76, 0x5d, 0x79,+ 0xde, 0xba, 0xe5, 0xa4, 0xc7, 0x56, 0xad, 0x19, 0xee, 0x9e, 0xff, 0xef, 0xdf, 0xb7, 0xc9, 0xf6, 0xab, 0xf3, 0xf0, 0xf8,+ 0xff, 0xb9, 0xf8, 0x3f, 0xca, 0x33, 0xd8, 0xe7, 0xf7, 0x5a, 0xea, 0xf5, 0x4f, 0x1a, 0xf7, 0xbb, 0x8f, 0x91, 0xdf, 0xf2,+ 0xb6, 0xf3, 0x70, 0xed, 0x35, 0x29, 0xcf, 0x6d, 0x9c, 0xdf, 0x01, 0xfb, 0xe7, 0xd9, 0x88, 0xce, 0xbc, 0xec, 0xfb, 0xea,+ 0xd8, 0xbc, 0xa6, 0x8d, 0xfd, 0x5b, 0x4a, 0x81, 0x67, 0x9e, 0x31, 0x40, 0xfc, 0x8b, 0x7f, 0x78, 0xfb, 0x73, 0xcb, 0xe2,+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdf, 0x5a, 0xa1, 0x57, 0x5b, 0x15, 0xbe,+ 0x93, 0xcb, 0xb8, 0x93, 0x9d, 0x6e, 0xbd, 0x42, 0x3d, 0xad, 0x9c, 0x04, 0xbd, 0xd7, 0xe5, 0x34, 0x0b, 0x5a, 0x46, 0xf2,+ 0x13, 0x74, 0xf3, 0x4e, 0x55, 0x32, 0x08, 0x54, 0xf7, 0x32, 0xe8, 0xee, 0x1b, 0x50, 0xfb, 0x8c, 0xce, 0x6a, 0xfd, 0x0c,+ 0x65, 0x41, 0xe8, 0xe4, 0x16, 0xde, 0x5b, 0x95, 0x5a, 0xcf, 0xd1, 0xb6, 0x93, 0xf5, 0x23, 0xad, 0x55, 0x73, 0x93, 0xf1,+ 0x9f, 0x4b, 0xb9, 0x0e, 0x3a, 0x19, 0x6a, 0x3a, 0x59, 0x6a, 0x32, 0x9c, 0x5f, 0xe7, 0x5a, 0x94, 0x5e, 0xcb, 0x39, 0x95,+ 0xe2, 0x77, 0xaa, 0xef, 0xca, 0x90, 0x46, 0xa4, 0xd5, 0xca, 0xb0, 0xb3, 0x3e, 0x72, 0xa7, 0x55, 0xd9, 0xbb, 0x7a, 0x53,+ 0xca, 0x45, 0x7c, 0x77, 0xde, 0x9d, 0x94, 0xe3, 0xe7, 0xd9, 0xf8, 0x4f, 0xe3, 0x17, 0xe5, 0x52, 0xce, 0xe5, 0x6e, 0x46,+ 0xb6, 0x6e, 0x26, 0xa7, 0x5e, 0x16, 0x81, 0x7e, 0xfc, 0x5f, 0x3b, 0x03, 0xbf, 0x1d, 0xff, 0x3b, 0xfb, 0xc7, 0x4c, 0xc4,+ 0x7f, 0xb6, 0x3f, 0x39, 0x23, 0xe5, 0x5a, 0x79, 0x97, 0x55, 0xfc, 0x3c, 0x19, 0xff, 0xfd, 0x8c, 0x85, 0x67, 0xbf, 0x38,+ 0x5b, 0xf1, 0x3f, 0xf9, 0xba, 0xa3, 0x99, 0x5f, 0x6b, 0x3f, 0xfe, 0xd3, 0xec, 0xb9, 0xce, 0xf5, 0x3d, 0xa7, 0xf2, 0x06,+ 0x77, 0xae, 0xcf, 0x5c, 0xc8, 0xd7, 0xbb, 0xdb, 0x33, 0xa8, 0xe5, 0xae, 0xce, 0xb2, 0x35, 0xde, 0x8d, 0xff, 0x3c, 0xd8,+ 0xff, 0xaf, 0x8c, 0xc8, 0x32, 0xde, 0xfe, 0x7f, 0x57, 0xfc, 0xdf, 0xd5, 0xff, 0xbf, 0xd2, 0x92, 0x75, 0xf7, 0xf5, 0x7a,+ 0x3a, 0xfe, 0xef, 0x98, 0x97, 0xca, 0x48, 0xcb, 0xd5, 0xaf, 0x31, 0xae, 0xf6, 0xff, 0x33, 0xb4, 0x2b, 0x55, 0x6f, 0xdc,+ 0x92, 0x9b, 0xdb, 0xff, 0x34, 0x46, 0x4a, 0xbb, 0xf1, 0x7f, 0x5c, 0xca, 0x83, 0x9a, 0xe6, 0xb9, 0xae, 0xd4, 0xe1, 0x3b,+ 0x3b, 0xef, 0xed, 0xf4, 0xe0, 0xd3, 0xdc, 0x79, 0x2e, 0x8d, 0x91, 0xea, 0x6f, 0xc4, 0xff, 0xce, 0x2e, 0x5d, 0x4f, 0xf5,+ 0xdc, 0x8f, 0x0b, 0x6d, 0xde, 0x1b, 0xe3, 0x7f, 0x7e, 0xfe, 0x6f, 0xfd, 0x1d, 0xf2, 0xf0, 0xf8, 0x3f, 0x8d, 0x28, 0x7e,+ 0x5f, 0xfc, 0xd7, 0xdb, 0xa3, 0x99, 0xfd, 0x90, 0xa7, 0x6b, 0x80, 0xce, 0xee, 0x99, 0x9d, 0x9d, 0x53, 0x53, 0xda, 0x89,+ 0x6c, 0xae, 0x47, 0x32, 0xd5, 0xff, 0x7f, 0x2e, 0xfe, 0xd3, 0xba, 0x0e, 0x3b, 0xdf, 0xbf, 0xbf, 0x3b, 0x40, 0xb6, 0x5a,+ 0x95, 0x8c, 0xc6, 0xff, 0xc4, 0x2c, 0x5d, 0xb7, 0x4e, 0x7a, 0x7e, 0x3f, 0xf4, 0xe7, 0xee, 0x59, 0xa7, 0xb9, 0xab, 0x5b,+ 0x46, 0xee, 0x8c, 0x67, 0x64, 0x2e, 0x2d, 0x5b, 0xf1, 0xbf, 0x7f, 0x2e, 0xaa, 0xfb, 0x32, 0xae, 0xfb, 0xc6, 0xf5, 0x79,+ 0x91, 0x6e, 0xfc, 0xf7, 0x32, 0xd4, 0x5f, 0xfd, 0x1d, 0xff, 0x3c, 0x57, 0x72, 0x8c, 0xdf, 0x91, 0x4e, 0xab, 0xae, 0xea,+ 0xf6, 0x2c, 0xd2, 0xda, 0x35, 0xff, 0x7d, 0xf1, 0xff, 0x44, 0xad, 0x31, 0x33, 0xf3, 0xd9, 0xb9, 0x17, 0x99, 0xf2, 0x35,+ 0x3d, 0x3d, 0xc2, 0xfa, 0xfc, 0x19, 0xbd, 0x6f, 0x47, 0xa3, 0x37, 0x65, 0xe3, 0x9d, 0x88, 0xff, 0xa3, 0x71, 0xbf, 0x62,+ 0xff, 0x4e, 0xdf, 0x77, 0x66, 0x35, 0xce, 0x8d, 0x4f, 0x25, 0xcc, 0xbd, 0xbf, 0x67, 0x10, 0x3f, 0x17, 0x75, 0x7f, 0x6b,+ 0xa9, 0xfd, 0x1d, 0xf1, 0xff, 0x4c, 0x8d, 0x3d, 0x3d, 0x12, 0x81, 0x4f, 0x8e, 0xa9, 0x33, 0x32, 0x02, 0xe7, 0xb7, 0xda,+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa9, 0xf5, 0x63, 0x33, 0xf9, 0x89, 0xd6,+ 0x6b, 0x9a, 0x6b, 0x2b, 0x21, 0xd2, 0x58, 0xaf, 0xbc, 0x97, 0x47, 0xbf, 0x9a, 0xd5, 0xe5, 0x7c, 0xbd, 0x4c, 0x2e, 0xae,+ 0xa1, 0x59, 0xad, 0x10, 0xc9, 0xf6, 0x5a, 0xbc, 0xee, 0xae, 0x06, 0xab, 0x4f, 0xeb, 0x64, 0x65, 0x38, 0xdf, 0x4d, 0xa0,+ 0xbb, 0x0f, 0xc0, 0x59, 0x96, 0x83, 0x94, 0x3f, 0xef, 0xec, 0x95, 0x29, 0xe7, 0x0a, 0x4b, 0x61, 0xed, 0x54, 0x5a, 0x57,+ 0x68, 0x27, 0xa3, 0xc3, 0xff, 0x7e, 0x5e, 0xe5, 0x6c, 0x65, 0x79, 0xa5, 0x55, 0xb2, 0xf1, 0xd5, 0xf3, 0x9d, 0xac, 0x32,+ 0x10, 0xf6, 0xf3, 0xe8, 0x67, 0x70, 0x05, 0x7e, 0x86, 0xfe, 0x5a, 0x59, 0x25, 0x96, 0xad, 0x3a, 0x3e, 0x43, 0x75, 0xed,+ 0x6e, 0x79, 0xa5, 0x51, 0x73, 0xa7, 0x5d, 0xe3, 0x1f, 0xad, 0x0c, 0x09, 0x19, 0xc8, 0x08, 0x90, 0x56, 0x09, 0x9d, 0xb5,+ 0x42, 0x69, 0xaf, 0x42, 0xac, 0x67, 0x39, 0x4a, 0xf9, 0x3b, 0x1e, 0x8d, 0x3c, 0xa8, 0xb3, 0xd9, 0x97, 0x76, 0xf6, 0xfd,+ 0x98, 0xc9, 0x98, 0x39, 0xb5, 0x86, 0xbe, 0x97, 0x9b, 0xa9, 0xfe, 0xd9, 0x9d, 0xab, 0x2a, 0x1b, 0xbd, 0xd0, 0x14, 0x7f,+ 0x5d, 0x2e, 0xb7, 0x71, 0x7f, 0x6e, 0xf5, 0xea, 0x71, 0x53, 0xcf, 0xa9, 0x34, 0x95, 0x3b, 0xe9, 0xae, 0xf8, 0x3f, 0xc6,+ 0xb3, 0x9c, 0xf5, 0x7a, 0x21, 0xbb, 0x3d, 0xf5, 0xbd, 0xf8, 0x5f, 0xef, 0x52, 0xb4, 0x5f, 0xe3, 0xdf, 0x19, 0xff, 0xbd,+ 0x5c, 0x88, 0x59, 0xf6, 0xba, 0xbb, 0x7b, 0xaf, 0xd5, 0xfa, 0xf1, 0x69, 0x67, 0x97, 0xed, 0xe5, 0xd1, 0xc8, 0x22, 0xb7,+ 0x6c, 0x6f, 0xdd, 0xfe, 0x7e, 0xff, 0x7f, 0xdd, 0x8f, 0x3f, 0xab, 0x1b, 0xef, 0xc8, 0xff, 0x77, 0x7f, 0xfc, 0xd7, 0xb2,+ 0x26, 0xf7, 0xda, 0xf0, 0x6b, 0x79, 0x74, 0x27, 0xb3, 0xdf, 0x7d, 0x2a, 0xfe, 0xeb, 0xe3, 0xea, 0xe9, 0x31, 0x45, 0xe7,+ 0x0c, 0xe5, 0x42, 0x2e, 0xc3, 0xb4, 0xf2, 0xa7, 0x9e, 0x8f, 0x7a, 0x67, 0xb3, 0xf0, 0xdc, 0xf9, 0x3e, 0x57, 0xc6, 0x62,+ 0xcf, 0xc5, 0x7f, 0x36, 0x46, 0xe0, 0x7b, 0xed, 0x56, 0x2e, 0xb7, 0x22, 0xf7, 0xc7, 0xff, 0xdc, 0x9e, 0x95, 0xfb, 0x79,+ 0xfa, 0x7a, 0x7d, 0xfc, 0x6c, 0xcc, 0x82, 0x75, 0xce, 0xe8, 0xb5, 0xb9, 0x8e, 0x3c, 0x32, 0xeb, 0x9d, 0xad, 0xb8, 0xb9,+ 0x7f, 0x4e, 0xbe, 0x36, 0x1b, 0x34, 0x1f, 0xff, 0x47, 0x71, 0xfc, 0x7d, 0x5c, 0xdc, 0xab, 0x63, 0x77, 0xdc, 0x9a, 0xad,+ 0xfe, 0xf8, 0xec, 0x9c, 0x55, 0xfd, 0xbb, 0x3f, 0xdf, 0xff, 0xdf, 0xcb, 0x1a, 0x9b, 0x56, 0x3f, 0x38, 0x1b, 0x75, 0x69,+ 0x27, 0xf3, 0xf2, 0x4e, 0x8c, 0x4d, 0xee, 0x53, 0x36, 0xf1, 0x1d, 0xcf, 0x47, 0x11, 0xd3, 0xf1, 0x5f, 0x2f, 0x85, 0x7c,+ 0xb4, 0x1f, 0xd4, 0xbf, 0x5a, 0xfb, 0x11, 0x98, 0xc1, 0xb3, 0xf8, 0xfc, 0xfc, 0x5f, 0xda, 0x75, 0x5f, 0x36, 0x33, 0x9e,+ 0x57, 0xdb, 0x8e, 0x67, 0xf3, 0x09, 0xe6, 0xa5, 0xf9, 0x0b, 0xfb, 0xb9, 0xff, 0xf3, 0x48, 0xa4, 0x4d, 0xe7, 0x9c, 0xbe,+ 0xbf, 0x1e, 0xd9, 0xbb, 0x77, 0x96, 0xdb, 0xcf, 0x62, 0x6e, 0x7f, 0xf7, 0x2c, 0x9f, 0x33, 0xe8, 0xde, 0xdf, 0xc8, 0xe0,+ 0xfd, 0x44, 0x8e, 0xad, 0x79, 0x9a, 0x7c, 0xf8, 0x3b, 0x1e, 0xce, 0xef, 0x43, 0xf1, 0xff, 0xe9, 0x72, 0xef, 0xcf, 0xd5,+ 0xc9, 0x7a, 0xfb, 0xfd, 0xf1, 0xcf, 0x3b, 0xe3, 0xff, 0x78, 0x49, 0xfc, 0xf3, 0x7c, 0x0d, 0x2e, 0xfe, 0xdf, 0x77, 0x2e,+ 0x77, 0x9f, 0xff, 0x7d, 0xfb, 0xaf, 0xd3, 0x96, 0xdf, 0x55, 0xaa, 0xca, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x58, 0xaf, 0x1c, 0xca, 0x50, 0x46, 0xa0, 0xe3, 0xff, 0x72, 0x97, 0xac, 0x73, 0x4d, 0x76, 0xf2,+ 0xc6, 0xf7, 0x57, 0x53, 0xa5, 0x7d, 0x6c, 0x27, 0x17, 0x4b, 0x2e, 0xad, 0x00, 0xc9, 0xc8, 0x7e, 0x09, 0xfd, 0x52, 0x4a,+ 0x29, 0x9b, 0x68, 0x25, 0x7f, 0x5b, 0x1a, 0x2b, 0x83, 0x7b, 0x59, 0x9f, 0x3e, 0x75, 0x9e, 0x57, 0x19, 0x57, 0xfa, 0xbf,+ 0x26, 0x37, 0xac, 0x1e, 0xbc, 0xfa, 0x3d, 0x7a, 0x59, 0x58, 0x73, 0x69, 0xa5, 0x5b, 0xda, 0xb9, 0x5c, 0xfb, 0xeb, 0x29,+ 0xd3, 0x5c, 0x4f, 0x99, 0xed, 0xd2, 0x5e, 0x45, 0x63, 0x2f, 0x5f, 0x6a, 0xb7, 0x8e, 0xdc, 0xcf, 0xf0, 0x9d, 0xed, 0x77,+ 0xbe, 0xb2, 0x47, 0x41, 0xbe, 0xe8, 0x3c, 0x77, 0xeb, 0x86, 0xfe, 0xef, 0xcc, 0xed, 0xb1, 0xb3, 0x9b, 0xf9, 0xef, 0xca,+ 0x55, 0xdf, 0xdb, 0x87, 0xe6, 0x8d, 0xab, 0x38, 0x77, 0xea, 0xf0, 0x6e, 0x1e, 0xb3, 0x6f, 0x58, 0xdf, 0x9b, 0x8f, 0xfe,+ 0xae, 0xe7, 0xce, 0xf3, 0x3a, 0xcf, 0xe1, 0x1b, 0x7e, 0x6b, 0x25, 0xc3, 0x6b, 0xa7, 0xfd, 0xcf, 0xa5, 0xf2, 0xba, 0x92,+ 0xdd, 0xb4, 0xb7, 0xeb, 0xd5, 0x67, 0x8e, 0x1e, 0x9b, 0xd9, 0xb6, 0x3a, 0xd9, 0xae, 0xcf, 0x77, 0xac, 0xaa, 0x1f, 0xd9,+ 0x6d, 0xff, 0xbb, 0x7f, 0xed, 0xec, 0x43, 0xf4, 0x89, 0xf3, 0xdc, 0xdb, 0x1d, 0x2d, 0x8b, 0x51, 0xf7, 0x95, 0x32, 0xae,+ 0x1d, 0xdb, 0xed, 0x25, 0xef, 0x8d, 0xff, 0xab, 0xed, 0xff, 0x51, 0xbe, 0xea, 0x77, 0x7a, 0xda, 0x6f, 0x3b, 0xba, 0x93,+ 0x71, 0xf3, 0xa9, 0x23, 0x77, 0xc4, 0x7f, 0x4e, 0xb3, 0xf1, 0xe7, 0xd2, 0x2c, 0xc3, 0x4e, 0x66, 0xe7, 0xfa, 0xd1, 0x5c,+ 0x2a, 0x8f, 0xf3, 0x36, 0xf4, 0xfb, 0xe2, 0x7f, 0xef, 0xbd, 0xd7, 0xf1, 0x5d, 0xcf, 0x50, 0x7b, 0xb4, 0xe7, 0xe1, 0xee,+ 0x8b, 0xe1, 0xa3, 0xfd, 0xad, 0xf2, 0x9a, 0x28, 0xaf, 0xe5, 0x04, 0xbd, 0xbb, 0xfd, 0xbf, 0x96, 0xdd, 0xfc, 0x3d, 0x47,+ 0xaf, 0xb5, 0x49, 0xef, 0x88, 0xff, 0xdc, 0x3a, 0x26, 0x4c, 0x69, 0xa6, 0xf5, 0x28, 0xee, 0x7d, 0x94, 0xd7, 0xb5, 0x0b,+ 0xeb, 0x3d, 0x35, 0xae, 0xb4, 0x29, 0xb3, 0x11, 0xdb, 0x3b, 0xf2, 0xa6, 0xfe, 0xff, 0x2f, 0xc5, 0xff, 0x1d, 0x31, 0xfe,+ 0x4c, 0xfc, 0xef, 0xf5, 0x00, 0xfa, 0xfb, 0x2d, 0x75, 0x6a, 0x86, 0x9d, 0xbd, 0x6d, 0x76, 0x8f, 0x76, 0x6b, 0x87, 0xfc,+ 0xa1, 0x36, 0xec, 0xcd, 0xb4, 0x7e, 0x5b, 0xff, 0xff, 0xfc, 0xfe, 0x4f, 0xda, 0xf3, 0xcb, 0xef, 0x8b, 0xff, 0x7e, 0x0b,+ 0x70, 0x4f, 0xfc, 0xe7, 0xc1, 0x79, 0xd2, 0xb4, 0x67, 0x3d, 0xd3, 0xb8, 0x6f, 0xfc, 0xc6, 0x71, 0x61, 0xe5, 0xec, 0x77,+ 0xf6, 0xd0, 0xfc, 0xee, 0xf8, 0x5f, 0xcf, 0x2f, 0xfd, 0x4a, 0xff, 0x3f, 0x1b, 0xb3, 0xa0, 0xd3, 0xf1, 0xff, 0x3d, 0xf9,+ 0x46, 0x33, 0x36, 0xee, 0xf8, 0xbe, 0x56, 0xa3, 0x1b, 0x57, 0x3b, 0xa3, 0x89, 0xeb, 0x73, 0xae, 0xcf, 0xec, 0x76, 0x92,+ 0x57, 0x9d, 0xab, 0x3b, 0xee, 0x58, 0x7e, 0x66, 0xfe, 0xef, 0x5b, 0x22, 0x5f, 0xfc, 0xaf, 0xe6, 0xd0, 0xcf, 0xc7, 0xcf,+ 0xb5, 0x23, 0x95, 0xe7, 0x0c, 0x3f, 0x17, 0xff, 0x9f, 0x9b, 0xe7, 0xb9, 0x67, 0x37, 0x93, 0xce, 0x33, 0x36, 0xc7, 0x2d,+ 0xcf, 0xce, 0xbd, 0xef, 0x59, 0x8b, 0xe3, 0x0b, 0xe2, 0x7f, 0x66, 0x36, 0xb4, 0x53, 0x12, 0x59, 0xec, 0x8b, 0x9c, 0xe2,+ 0x33, 0xd7, 0x77, 0xf5, 0xff, 0x67, 0x5b, 0xc5, 0x4f, 0x3e, 0xe7, 0xf1, 0xfc, 0x95, 0xde, 0x3d, 0x06, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf6, 0xda, 0xba, 0x7a, 0xd6, 0xbd, 0x34, 0xd7, 0xef, 0xf6, 0xd7,+ 0xa9, 0xd6, 0x77, 0x0d, 0xb8, 0xf2, 0x9e, 0x29, 0xaf, 0xbf, 0xa9, 0x7d, 0x52, 0xe5, 0x5b, 0xdf, 0x93, 0x75, 0xff, 0x58,+ 0xe4, 0x18, 0xc8, 0xc8, 0x35, 0x91, 0x72, 0x4e, 0x87, 0xa3, 0x99, 0x95, 0x28, 0xe5, 0xab, 0x2e, 0x8d, 0xbf, 0xa7, 0xbc,+ 0x32, 0xf3, 0x68, 0x7c, 0xef, 0x37, 0xaf, 0xb9, 0xef, 0x66, 0xf2, 0xec, 0xef, 0x50, 0x31, 0xbd, 0xea, 0x31, 0xcd, 0x3c,+ 0xdc, 0x19, 0x5b, 0xef, 0x9a, 0x8d, 0x15, 0xcd, 0x9d, 0x48, 0xaf, 0xd4, 0xd7, 0x69, 0xc7, 0x46, 0xad, 0x3e, 0xcb, 0xe8,+ 0x75, 0x3a, 0xb7, 0x43, 0x4c, 0x46, 0x33, 0x69, 0xbe, 0x79, 0x5d, 0x5e, 0x9a, 0xd9, 0x35, 0xf2, 0x05, 0xeb, 0x90, 0xb3,+ 0xb1, 0x5b, 0x4a, 0x1a, 0x3b, 0x9d, 0x7c, 0x66, 0xa5, 0xf3, 0xde, 0x95, 0xf9, 0xce, 0x55, 0xa3, 0xd5, 0x7c, 0x6e, 0x4f,+ 0x5d, 0x75, 0xbd, 0x9c, 0x1f, 0x19, 0x7f, 0xc7, 0x67, 0xe2, 0xbf, 0x93, 0x77, 0x37, 0xcb, 0x3e, 0xe5, 0xb3, 0xab, 0x9e,+ 0xbb, 0xd9, 0xc6, 0xd2, 0xda, 0x6d, 0x60, 0xff, 0xef, 0x9f, 0xc8, 0xba, 0x73, 0x6f, 0xfb, 0x3f, 0xdf, 0xc7, 0xae, 0x66,+ 0x38, 0xe8, 0x5d, 0xdd, 0xdd, 0x9d, 0x2e, 0xf2, 0x33, 0xf1, 0xbf, 0xce, 0xba, 0x98, 0x91, 0xd9, 0x84, 0x4f, 0x1c, 0x4b,+ 0x73, 0xd7, 0xa7, 0x0c, 0x8d, 0x17, 0xd6, 0xb9, 0x2e, 0x9f, 0x88, 0xff, 0x9c, 0xf4, 0xce, 0xd3, 0xd8, 0xd9, 0x62, 0xea,+ 0xef, 0x93, 0xb3, 0x15, 0xfd, 0x5d, 0x6b, 0xe6, 0xe2, 0x3f, 0xc3, 0x3b, 0xb0, 0xbd, 0x3d, 0xfe, 0xa7, 0x67, 0x00, 0xfa,+ 0x31, 0x9e, 0xf6, 0x68, 0x6d, 0x62, 0x94, 0xdb, 0xf9, 0xfb, 0x73, 0x59, 0xf7, 0xcf, 0xf2, 0x2a, 0xa7, 0x75, 0x45, 0x64,+ 0x60, 0x1e, 0x25, 0xed, 0x1e, 0xf6, 0xfd, 0xf1, 0xbf, 0xb3, 0xe7, 0x4f, 0xbe, 0x2e, 0xfe, 0x57, 0x35, 0x5a, 0x3d, 0xbf,+ 0x6d, 0x5a, 0xb1, 0xda, 0x3b, 0x96, 0x8d, 0xd9, 0x9f, 0x2c, 0xb3, 0xe6, 0xdf, 0xd3, 0xfb, 0xaf, 0x7d, 0xdb, 0x99, 0xf8,+ 0x9f, 0x89, 0xce, 0x4f, 0xc6, 0x7f, 0x36, 0xf6, 0x8e, 0x99, 0x6c, 0xdd, 0xd2, 0xcc, 0x14, 0x9a, 0x97, 0xce, 0xff, 0x75,+ 0x46, 0x34, 0xf3, 0x7b, 0x75, 0xdc, 0x71, 0x6c, 0x6f, 0xe6, 0x2b, 0x37, 0x8e, 0x7d, 0x8f, 0x0f, 0xb4, 0xff, 0x13, 0x35,+ 0xc3, 0x67, 0xdb, 0xff, 0x63, 0xf4, 0x7a, 0x5c, 0xff, 0xfa, 0x3c, 0xd0, 0xa3, 0x7c, 0x4b, 0xfc, 0xe7, 0x4b, 0xe3, 0xff,+ 0xb8, 0xb0, 0xa3, 0xdc, 0x5b, 0x6b, 0x80, 0x3c, 0x3a, 0xfe, 0x7f, 0x57, 0xfc, 0xcf, 0xde, 0x01, 0xc9, 0xf2, 0x1e, 0x67,+ 0x2d, 0xca, 0xd3, 0xb8, 0xd3, 0x98, 0xe2, 0x6e, 0x6a, 0xef, 0x79, 0xfe, 0x27, 0xcd, 0xd1, 0x49, 0x35, 0x1e, 0xef, 0x39,+ 0x76, 0xcf, 0xac, 0x6b, 0xca, 0x73, 0x8a, 0x19, 0xb9, 0xce, 0x9f, 0xcc, 0xba, 0xbb, 0x1a, 0xc5, 0x3d, 0xff, 0xeb, 0x77,+ 0xef, 0xa7, 0x66, 0xe8, 0xc8, 0xe4, 0xb3, 0x44, 0x6f, 0x79, 0x3a, 0x60, 0xfa, 0x1e, 0xda, 0x37, 0xe4, 0x21, 0xce, 0xcf,+ 0x67, 0x4c, 0xbf, 0xef, 0xa9, 0x01, 0xee, 0xed, 0xe9, 0x7d, 0xcf, 0xb3, 0xc1, 0x88, 0x7e, 0xd6, 0xcf, 0xa8, 0xfc, 0xe6,+ 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0xa6, 0xfd, 0xfb, 0x9f, 0x72, 0x00, 0xf1, 0x0f, 0xfc, 0x75, 0xf1, 0xff, 0x2f };++// Font glyphs rectangles data (on atlas)+static const Rectangle lavandaFontRecs[189] = {+ { 4, 4, 5 , 16 },+ { 17, 4, 1 , 9 },+ { 26, 4, 3 , 3 },+ { 37, 4, 7 , 8 },+ { 52, 4, 5 , 11 },+ { 65, 4, 10 , 8 },+ { 83, 4, 7 , 9 },+ { 98, 4, 1 , 3 },+ { 107, 4, 3 , 12 },+ { 118, 4, 3 , 12 },+ { 129, 4, 5 , 4 },+ { 142, 4, 5 , 5 },+ { 155, 4, 2 , 3 },+ { 165, 4, 3 , 1 },+ { 176, 4, 1 , 1 },+ { 185, 4, 4 , 12 },+ { 197, 4, 5 , 9 },+ { 210, 4, 3 , 9 },+ { 221, 4, 5 , 9 },+ { 234, 4, 5 , 9 },+ { 247, 4, 5 , 9 },+ { 260, 4, 5 , 9 },+ { 273, 4, 5 , 9 },+ { 286, 4, 5 , 9 },+ { 299, 4, 5 , 9 },+ { 312, 4, 5 , 9 },+ { 325, 4, 1 , 4 },+ { 334, 4, 2 , 6 },+ { 344, 4, 4 , 5 },+ { 356, 4, 4 , 3 },+ { 368, 4, 4 , 5 },+ { 380, 4, 5 , 9 },+ { 393, 4, 7 , 10 },+ { 408, 4, 7 , 9 },+ { 423, 4, 6 , 9 },+ { 437, 4, 5 , 9 },+ { 450, 4, 6 , 9 },+ { 464, 4, 5 , 9 },+ { 477, 4, 5 , 9 },+ { 490, 4, 6 , 9 },+ { 4, 28, 5 , 10 },+ { 17, 28, 1 , 9 },+ { 26, 28, 6 , 9 },+ { 40, 28, 6 , 9 },+ { 54, 28, 5 , 9 },+ { 67, 28, 8 , 11 },+ { 83, 28, 6 , 10 },+ { 97, 28, 7 , 9 },+ { 112, 28, 5 , 9 },+ { 125, 28, 7 , 11 },+ { 140, 28, 5 , 9 },+ { 153, 28, 6 , 9 },+ { 167, 28, 7 , 9 },+ { 182, 28, 6 , 9 },+ { 196, 28, 6 , 10 },+ { 210, 28, 9 , 10 },+ { 227, 28, 6 , 11 },+ { 241, 28, 5 , 10 },+ { 254, 28, 5 , 9 },+ { 267, 28, 3 , 12 },+ { 278, 28, 4 , 12 },+ { 290, 28, 3 , 12 },+ { 301, 28, 5 , 4 },+ { 314, 28, 6 , 1 },+ { 328, 28, 3 , 3 },+ { 339, 28, 6 , 7 },+ { 353, 28, 5 , 9 },+ { 366, 28, 4 , 7 },+ { 378, 28, 5 , 10 },+ { 391, 28, 4 , 7 },+ { 403, 28, 3 , 10 },+ { 414, 28, 4 , 11 },+ { 426, 28, 5 , 11 },+ { 439, 28, 1 , 9 },+ { 448, 28, 5 , 12 },+ { 461, 28, 5 , 9 },+ { 474, 28, 1 , 9 },+ { 483, 28, 8 , 9 },+ { 4, 52, 5 , 9 },+ { 17, 52, 4 , 7 },+ { 29, 52, 5 , 10 },+ { 42, 52, 5 , 10 },+ { 55, 52, 5 , 7 },+ { 68, 52, 5 , 7 },+ { 81, 52, 3 , 9 },+ { 92, 52, 5 , 7 },+ { 105, 52, 5 , 8 },+ { 118, 52, 9 , 8 },+ { 135, 52, 5 , 9 },+ { 148, 52, 6 , 9 },+ { 162, 52, 4 , 7 },+ { 174, 52, 5 , 12 },+ { 187, 52, 1 , 12 },+ { 196, 52, 5 , 12 },+ { 209, 52, 6 , 2 },+ { 223, 52, 1 , 9 },+ { 232, 52, 5 , 10 },+ { 245, 52, 6 , 9 },+ { 259, 52, 7 , 9 },+ { 274, 52, 5 , 9 },+ { 287, 52, 6 , 12 },+ { 301, 52, 5 , 10 },+ { 314, 52, 5 , 10 },+ { 327, 52, 8 , 8 },+ { 343, 52, 4 , 7 },+ { 355, 52, 6 , 5 },+ { 369, 52, 6 , 3 },+ { 383, 52, 8 , 8 },+ { 399, 52, 5 , 1 },+ { 412, 52, 4 , 4 },+ { 424, 52, 5 , 7 },+ { 437, 52, 3 , 4 },+ { 448, 52, 3 , 4 },+ { 459, 52, 5 , 12 },+ { 472, 52, 5 , 10 },+ { 485, 52, 7 , 11 },+ { 500, 52, 1 , 1 },+ { 4, 76, 4 , 10 },+ { 16, 76, 2 , 4 },+ { 26, 76, 4 , 7 },+ { 38, 76, 6 , 5 },+ { 52, 76, 11 , 9 },+ { 71, 76, 7 , 7 },+ { 86, 76, 5 , 12 },+ { 99, 76, 5 , 9 },+ { 112, 76, 7 , 12 },+ { 127, 76, 7 , 12 },+ { 142, 76, 7 , 12 },+ { 157, 76, 7 , 12 },+ { 172, 76, 7 , 11 },+ { 187, 76, 7 , 12 },+ { 202, 76, 10 , 9 },+ { 220, 76, 5 , 12 },+ { 233, 76, 5 , 12 },+ { 246, 76, 5 , 12 },+ { 259, 76, 5 , 12 },+ { 272, 76, 5 , 11 },+ { 285, 76, 2 , 12 },+ { 295, 76, 2 , 12 },+ { 305, 76, 3 , 12 },+ { 316, 76, 3 , 11 },+ { 327, 76, 7 , 9 },+ { 342, 76, 6 , 12 },+ { 356, 76, 7 , 12 },+ { 371, 76, 7 , 12 },+ { 386, 76, 7 , 12 },+ { 401, 76, 7 , 12 },+ { 416, 76, 7 , 11 },+ { 431, 76, 5 , 5 },+ { 444, 76, 7 , 9 },+ { 459, 76, 6 , 12 },+ { 473, 76, 6 , 12 },+ { 487, 76, 6 , 12 },+ { 4, 100, 6 , 11 },+ { 18, 100, 5 , 13 },+ { 31, 100, 5 , 9 },+ { 44, 100, 5 , 11 },+ { 57, 100, 6 , 10 },+ { 71, 100, 6 , 10 },+ { 85, 100, 6 , 10 },+ { 99, 100, 6 , 10 },+ { 113, 100, 6 , 9 },+ { 127, 100, 6 , 11 },+ { 141, 100, 7 , 7 },+ { 156, 100, 4 , 10 },+ { 168, 100, 4 , 10 },+ { 180, 100, 4 , 10 },+ { 192, 100, 4 , 10 },+ { 204, 100, 4 , 9 },+ { 216, 100, 2 , 10 },+ { 226, 100, 2 , 10 },+ { 236, 100, 3 , 10 },+ { 247, 100, 3 , 9 },+ { 258, 100, 5 , 9 },+ { 271, 100, 5 , 12 },+ { 284, 100, 4 , 10 },+ { 296, 100, 4 , 10 },+ { 308, 100, 4 , 10 },+ { 320, 100, 5 , 10 },+ { 333, 100, 4 , 9 },+ { 345, 100, 5 , 5 },+ { 358, 100, 6 , 7 },+ { 372, 100, 5 , 10 },+ { 385, 100, 5 , 10 },+ { 398, 100, 5 , 10 },+ { 411, 100, 5 , 9 },+ { 424, 100, 6 , 12 },+ { 438, 100, 5 , 12 },+ { 451, 100, 6 , 11 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo lavandaFontGlyphs[189] = {+ { 32, 0, 12, 5, { 0 }},+ { 33, 0, 3, 2, { 0 }},+ { 34, 0, 3, 4, { 0 }},+ { 35, 0, 3, 8, { 0 }},+ { 36, 0, 2, 6, { 0 }},+ { 37, 0, 4, 11, { 0 }},+ { 38, 0, 3, 8, { 0 }},+ { 39, 0, 3, 2, { 0 }},+ { 40, 0, 2, 4, { 0 }},+ { 41, 0, 2, 4, { 0 }},+ { 42, 0, 3, 6, { 0 }},+ { 43, 0, 5, 6, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 7, 4, { 0 }},+ { 46, 0, 11, 2, { 0 }},+ { 47, 0, 2, 5, { 0 }},+ { 48, 0, 3, 6, { 0 }},+ { 49, 0, 3, 4, { 0 }},+ { 50, 0, 3, 6, { 0 }},+ { 51, 0, 3, 6, { 0 }},+ { 52, 0, 3, 6, { 0 }},+ { 53, 0, 3, 6, { 0 }},+ { 54, 0, 3, 6, { 0 }},+ { 55, 0, 3, 6, { 0 }},+ { 56, 0, 3, 6, { 0 }},+ { 57, 0, 3, 6, { 0 }},+ { 58, 0, 7, 2, { 0 }},+ { 59, 0, 7, 3, { 0 }},+ { 60, 0, 5, 5, { 0 }},+ { 61, 0, 6, 5, { 0 }},+ { 62, 0, 5, 5, { 0 }},+ { 63, 0, 3, 6, { 0 }},+ { 64, 0, 4, 8, { 0 }},+ { 65, 0, 3, 8, { 0 }},+ { 66, 0, 3, 7, { 0 }},+ { 67, 0, 3, 6, { 0 }},+ { 68, 0, 3, 7, { 0 }},+ { 69, 0, 3, 6, { 0 }},+ { 70, 0, 3, 6, { 0 }},+ { 71, 0, 3, 7, { 0 }},+ { 72, 0, 2, 6, { 0 }},+ { 73, 0, 3, 2, { 0 }},+ { 74, 0, 3, 7, { 0 }},+ { 75, 0, 3, 7, { 0 }},+ { 76, 0, 3, 6, { 0 }},+ { 77, 0, 3, 9, { 0 }},+ { 78, 0, 2, 7, { 0 }},+ { 79, 0, 3, 8, { 0 }},+ { 80, 0, 3, 6, { 0 }},+ { 81, 0, 3, 8, { 0 }},+ { 82, 0, 3, 6, { 0 }},+ { 83, 0, 3, 7, { 0 }},+ { 84, 0, 3, 8, { 0 }},+ { 85, 0, 3, 7, { 0 }},+ { 86, 0, 2, 7, { 0 }},+ { 87, 0, 2, 10, { 0 }},+ { 88, 0, 3, 7, { 0 }},+ { 89, 0, 3, 6, { 0 }},+ { 90, 0, 3, 6, { 0 }},+ { 91, 0, 2, 4, { 0 }},+ { 92, 0, 2, 5, { 0 }},+ { 93, 0, 2, 4, { 0 }},+ { 94, 0, 3, 6, { 0 }},+ { 95, 0, 13, 7, { 0 }},+ { 96, 0, 3, 4, { 0 }},+ { 97, 0, 5, 7, { 0 }},+ { 98, 0, 3, 6, { 0 }},+ { 99, 0, 5, 5, { 0 }},+ { 100, 0, 2, 6, { 0 }},+ { 101, 0, 5, 5, { 0 }},+ { 102, 0, 2, 4, { 0 }},+ { 103, 0, 4, 5, { 0 }},+ { 104, 0, 3, 6, { 0 }},+ { 105, 0, 3, 2, { 0 }},+ { 106, -1, 3, 5, { 0 }},+ { 107, 0, 3, 6, { 0 }},+ { 108, 0, 3, 2, { 0 }},+ { 109, 0, 5, 9, { 0 }},+ { 110, 0, 5, 6, { 0 }},+ { 111, 0, 5, 5, { 0 }},+ { 112, 0, 5, 6, { 0 }},+ { 113, 0, 5, 6, { 0 }},+ { 114, 0, 5, 6, { 0 }},+ { 115, 0, 5, 6, { 0 }},+ { 116, 0, 3, 4, { 0 }},+ { 117, 0, 5, 6, { 0 }},+ { 118, 0, 4, 6, { 0 }},+ { 119, 0, 4, 10, { 0 }},+ { 120, 0, 5, 6, { 0 }},+ { 121, -1, 5, 6, { 0 }},+ { 122, 0, 5, 5, { 0 }},+ { 123, 0, 2, 6, { 0 }},+ { 124, 0, 2, 2, { 0 }},+ { 125, 0, 2, 6, { 0 }},+ { 126, 0, 7, 7, { 0 }},+ { 161, 0, 5, 2, { 0 }},+ { 162, 0, 4, 6, { 0 }},+ { 163, 0, 3, 7, { 0 }},+ { 8364, 0, 3, 8, { 0 }},+ { 165, 0, 3, 6, { 0 }},+ { 352, 0, 0, 7, { 0 }},+ { 167, 0, 3, 6, { 0 }},+ { 353, 0, 2, 6, { 0 }},+ { 169, 0, 4, 9, { 0 }},+ { 170, 0, 3, 5, { 0 }},+ { 171, 0, 6, 7, { 0 }},+ { 172, 0, 6, 7, { 0 }},+ { 174, 0, 4, 9, { 0 }},+ { 175, 0, 2, 6, { 0 }},+ { 176, 0, 3, 5, { 0 }},+ { 177, 0, 5, 6, { 0 }},+ { 178, 0, 3, 4, { 0 }},+ { 179, 0, 3, 4, { 0 }},+ { 381, 0, 0, 6, { 0 }},+ { 181, 0, 5, 6, { 0 }},+ { 182, 0, 3, 8, { 0 }},+ { 183, 0, 7, 2, { 0 }},+ { 382, 0, 2, 5, { 0 }},+ { 185, 0, 3, 3, { 0 }},+ { 186, 0, 3, 5, { 0 }},+ { 187, 0, 6, 7, { 0 }},+ { 338, 0, 3, 12, { 0 }},+ { 339, 0, 5, 8, { 0 }},+ { 376, 0, 1, 6, { 0 }},+ { 191, 0, 5, 6, { 0 }},+ { 192, 0, 0, 8, { 0 }},+ { 193, 0, 0, 8, { 0 }},+ { 194, 0, 0, 8, { 0 }},+ { 195, 0, 0, 8, { 0 }},+ { 196, 0, 1, 8, { 0 }},+ { 197, 0, 0, 8, { 0 }},+ { 198, 0, 3, 11, { 0 }},+ { 199, 0, 3, 6, { 0 }},+ { 200, 0, 0, 6, { 0 }},+ { 201, 0, 0, 6, { 0 }},+ { 202, 0, 0, 6, { 0 }},+ { 203, 0, 1, 6, { 0 }},+ { 204, -1, 0, 2, { 0 }},+ { 205, 0, 0, 3, { 0 }},+ { 206, -1, 0, 3, { 0 }},+ { 207, -1, 1, 3, { 0 }},+ { 208, -1, 3, 7, { 0 }},+ { 209, 0, 0, 7, { 0 }},+ { 210, 0, 0, 8, { 0 }},+ { 211, 0, 0, 8, { 0 }},+ { 212, 0, 0, 8, { 0 }},+ { 213, 0, 0, 8, { 0 }},+ { 214, 0, 1, 8, { 0 }},+ { 215, 0, 5, 6, { 0 }},+ { 216, 0, 3, 8, { 0 }},+ { 217, 0, 0, 7, { 0 }},+ { 218, 0, 0, 7, { 0 }},+ { 219, 0, 0, 7, { 0 }},+ { 220, 0, 1, 7, { 0 }},+ { 221, 0, 0, 6, { 0 }},+ { 222, 0, 3, 6, { 0 }},+ { 223, 0, 3, 6, { 0 }},+ { 224, 0, 2, 7, { 0 }},+ { 225, 0, 2, 7, { 0 }},+ { 226, 0, 2, 7, { 0 }},+ { 227, 0, 2, 7, { 0 }},+ { 228, 0, 3, 7, { 0 }},+ { 229, 0, 1, 7, { 0 }},+ { 230, 0, 5, 8, { 0 }},+ { 231, 0, 5, 5, { 0 }},+ { 232, 0, 2, 5, { 0 }},+ { 233, 0, 2, 5, { 0 }},+ { 234, 0, 2, 5, { 0 }},+ { 235, 0, 3, 5, { 0 }},+ { 236, -1, 2, 2, { 0 }},+ { 237, 0, 2, 3, { 0 }},+ { 238, -1, 2, 3, { 0 }},+ { 239, -1, 3, 3, { 0 }},+ { 240, 0, 3, 6, { 0 }},+ { 241, 0, 2, 6, { 0 }},+ { 242, 0, 2, 5, { 0 }},+ { 243, 0, 2, 5, { 0 }},+ { 244, 0, 2, 5, { 0 }},+ { 245, 0, 2, 6, { 0 }},+ { 246, 0, 3, 5, { 0 }},+ { 247, 0, 5, 6, { 0 }},+ { 248, -1, 5, 6, { 0 }},+ { 249, 0, 2, 6, { 0 }},+ { 250, 0, 2, 6, { 0 }},+ { 251, 0, 2, 6, { 0 }},+ { 252, 0, 3, 6, { 0 }},+ { 253, -1, 2, 6, { 0 }},+ { 254, 0, 3, 6, { 0 }},+ { 255, -1, 3, 6, { 0 }},+};++// Style loading function: Lavanda+static void GuiLoadStyleLavanda(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < LAVANDA_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(lavandaStyleProps[i].controlId, lavandaStyleProps[i].propertyId, lavandaStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int lavandaFontDataSize = 0;+ unsigned char *data = DecompressData(lavandaFontData, LAVANDA_STYLE_FONT_ATLAS_COMP_SIZE, &lavandaFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, lavandaFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, lavandaFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/sunny/style_sunny.h view
@@ -0,0 +1,616 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleSunny(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define SUNNY_STYLE_PROPS_COUNT 33++// Custom style name: Sunny+static const GuiStyleProp sunnyStyleProps[SUNNY_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x9c760aff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x594006ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xf6d519ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xf6ee89ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0xf5f3d1ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xf4cd19ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0xf7e580ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xf7f2c1ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x52470aff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0xc0be92ff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0xd3d3a1ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0xbcbc89ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x725706ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0xf0be4bff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING + { 1, 2, 0x504506ff }, // LABEL_TEXT_COLOR_NORMAL + { 1, 5, 0xfdeb9bff }, // LABEL_TEXT_COLOR_FOCUSED + { 1, 8, 0xf5e8a4ff }, // LABEL_TEXT_COLOR_PRESSED + { 2, 2, 0xebc21fff }, // BUTTON_TEXT_COLOR_NORMAL + { 3, 2, 0xebc21fff }, // TOGGLE_TEXT_COLOR_NORMAL + { 4, 2, 0x81700fff }, // SLIDER_TEXT_COLOR_NORMAL + { 4, 5, 0xf4e49aff }, // SLIDER_TEXT_COLOR_FOCUSED + { 7, 2, 0xebc21fff }, // COMBOBOX_TEXT_COLOR_NORMAL + { 8, 2, 0xefd87bff }, // DROPDOWNBOX_TEXT_COLOR_NORMAL + { 8, 5, 0xd4b219ff }, // DROPDOWNBOX_TEXT_COLOR_FOCUSED + { 9, 2, 0x7a680bff }, // TEXTBOX_TEXT_COLOR_NORMAL + { 9, 5, 0xad931fff }, // TEXTBOX_TEXT_COLOR_FOCUSED + { 10, 2, 0x62570eff }, // VALUEBOX_TEXT_COLOR_NORMAL + { 10, 5, 0xf2df88ff }, // VALUEBOX_TEXT_COLOR_FOCUSED + { 12, 2, 0xf4e798ff }, // LISTVIEW_TEXT_COLOR_NORMAL + { 15, 2, 0xebc21fff }, // STATUSBAR_TEXT_COLOR_NORMAL +};++// WARNING: This style uses a custom font: "GenericMobileSystemNuevo.ttf" (size: 16, spacing: 0)++#define SUNNY_STYLE_FONT_ATLAS_COMP_SIZE 2462++// Font atlas image pixels data: DEFLATE compressed+static unsigned char sunnyFontData[SUNNY_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x59, 0xb2, 0xeb, 0x34, 0x10, 0x00, 0x50, 0x6d, 0x83, 0xfd, 0xef, 0x8d, 0x6d, 0x88, 0xa2, 0x28, 0x0a, 0xb8, 0x8f,+ 0x58, 0x52, 0x77, 0xcb, 0x53, 0x0e, 0xa7, 0xf8, 0xb9, 0x7e, 0x49, 0x6c, 0xd9, 0x6d, 0x0d, 0xb6, 0x5a, 0xbd, 0x01, 0x00,+ 0x00, 0x00, 0x5f, 0xef, 0xcf, 0xff, 0xfe, 0xff, 0x6f, 0xff, 0xb7, 0xe5, 0x78, 0xdb, 0xdf, 0xff, 0x62, 0xb4, 0xa5, 0x7f,+ 0xdc, 0x93, 0x7e, 0xb0, 0x6d, 0xee, 0xb7, 0x62, 0xfb, 0xd5, 0x97, 0xca, 0xa6, 0x1f, 0x94, 0x5a, 0x4b, 0xff, 0xbd, 0x1d,+ 0x96, 0x7d, 0x0f, 0x94, 0x5e, 0x3b, 0xdc, 0xe7, 0xcf, 0x9f, 0x1c, 0x6f, 0xa9, 0xdc, 0xcf, 0x95, 0x32, 0xad, 0x3c, 0x3f,+ 0x2b, 0x25, 0xd8, 0x96, 0xb7, 0x1e, 0x97, 0x54, 0x9b, 0x2a, 0xc7, 0xf1, 0x37, 0xf7, 0x9b, 0xc4, 0xff, 0xf1, 0xd1, 0xfc,+ 0x1d, 0x83, 0x47, 0x67, 0x7f, 0xfe, 0xda, 0x68, 0xd3, 0xf7, 0x84, 0x7f, 0x7e, 0xbb, 0x2e, 0x42, 0xb3, 0xdf, 0xd2, 0x87,+ 0x77, 0xc2, 0x95, 0x12, 0x3a, 0x2e, 0xbd, 0x16, 0x8a, 0x89, 0xd1, 0x77, 0x46, 0xf6, 0x65, 0x66, 0xdb, 0xdc, 0xfe, 0xc5,+ 0xae, 0xf9, 0xf1, 0xf7, 0x1d, 0x5f, 0x69, 0x47, 0x67, 0x78, 0x74, 0xe5, 0x1e, 0x1f, 0xdf, 0xfa, 0x59, 0xcd, 0x44, 0xfd,+ 0x9e, 0xf8, 0xef, 0xff, 0x8a, 0xb3, 0x1e, 0x8c, 0xc1, 0x7c, 0xdd, 0xb0, 0x5e, 0x2b, 0x1c, 0xdf, 0xb3, 0xf6, 0x95, 0xf0,+ 0x51, 0x39, 0xf5, 0xc0, 0x35, 0xbc, 0x7e, 0xce, 0xa2, 0xbf, 0xb3, 0x23, 0xfe, 0x2b, 0xa2, 0xb8, 0x4d, 0xd4, 0x88, 0x91,+ 0x36, 0xc5, 0x71, 0x8b, 0x33, 0x1f, 0xe1, 0xa3, 0x7d, 0x89, 0xb4, 0x67, 0xf2, 0x65, 0xb9, 0xda, 0xe6, 0xd8, 0x17, 0xff,+ 0x15, 0xf5, 0xed, 0x7a, 0x5d, 0xb2, 0xaf, 0x7c, 0x67, 0xea, 0xeb, 0xfb, 0xc7, 0xff, 0xfa, 0xb1, 0x55, 0xc4, 0x7f, 0xcd,+ 0x59, 0x59, 0x8f, 0xff, 0x2e, 0xfe, 0xa7, 0xeb, 0xff, 0xcf, 0xa5, 0xde, 0x83, 0xfd, 0xaf, 0x7c, 0xaf, 0xbd, 0xaa, 0x9d,+ 0x7f, 0x6d, 0xfc, 0x8f, 0xfa, 0x83, 0x6d, 0x39, 0xfe, 0x63, 0xbd, 0xcf, 0x48, 0x6f, 0xa3, 0xaa, 0xfd, 0xbf, 0xb7, 0xf5,+ 0x70, 0xdc, 0x7b, 0x8c, 0x44, 0xf8, 0xda, 0x98, 0x47, 0xcd, 0x37, 0x5f, 0x11, 0xff, 0x6d, 0x62, 0x6f, 0xfa, 0xb0, 0xff,+ 0x3f, 0x7b, 0x87, 0x5f, 0x8b, 0xff, 0xba, 0xba, 0xe3, 0xca, 0xf8, 0xef, 0xc1, 0x11, 0xb1, 0xea, 0x7e, 0x7c, 0xfc, 0xd8,+ 0xd6, 0xc6, 0xe7, 0xce, 0xeb, 0xff, 0x8f, 0xda, 0x81, 0x99, 0xf8, 0xff, 0x96, 0xf6, 0xff, 0x4c, 0x4b, 0x7b, 0x54, 0x8a,+ 0xf3, 0xf7, 0xb3, 0x2b, 0x6a, 0xf3, 0x6b, 0xe3, 0xbf, 0x4f, 0x8d, 0x61, 0xdf, 0x3b, 0xfe, 0xdb, 0x72, 0x2f, 0xaf, 0xf2,+ 0xda, 0x8d, 0x5e, 0x51, 0xa3, 0x2b, 0x77, 0xe6, 0xae, 0x76, 0xcf, 0xf8, 0x8f, 0x5d, 0xcf, 0x7d, 0xd8, 0xca, 0xef, 0x89,+ 0xf8, 0x6f, 0xaf, 0x89, 0xff, 0x1e, 0x1c, 0xed, 0xf8, 0xdc, 0xde, 0x8b, 0x8d, 0xc7, 0x45, 0x5a, 0xf2, 0x99, 0x36, 0x4a,+ 0x55, 0xfc, 0xdf, 0xe3, 0x4c, 0xaa, 0xff, 0x2b, 0xc6, 0xff, 0xdb, 0x61, 0x0b, 0xff, 0xbb, 0xe2, 0xff, 0xf8, 0xf9, 0x5f,+ 0xbb, 0xfd, 0xb3, 0xba, 0x68, 0xfc, 0xd7, 0x8c, 0xff, 0x9f, 0x7f, 0xb7, 0x9e, 0xe9, 0xb9, 0xe6, 0xe2, 0xff, 0x4e, 0xcf,+ 0xff, 0xf6, 0xc6, 0xff, 0xe8, 0xa9, 0xf7, 0x9b, 0xda, 0xff, 0x95, 0xe3, 0xf8, 0xf1, 0x77, 0x6e, 0xf6, 0xbd, 0x53, 0xd4,+ 0x42, 0x6f, 0x72, 0xdd, 0x33, 0xfa, 0xa3, 0xcf, 0x81, 0x72, 0xa3, 0x74, 0x57, 0xbf, 0xff, 0x53, 0x5f, 0x82, 0xe7, 0xed,+ 0x4f, 0xbf, 0x71, 0x9b, 0x91, 0x77, 0xbd, 0x25, 0xeb, 0xea, 0x3a, 0xf3, 0xf9, 0x6c, 0xfc, 0xb7, 0x9c, 0x1f, 0x76, 0xd6,+ 0x6c, 0x4a, 0xe2, 0x19, 0x63, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe4, 0xf9,+ 0x0b, 0x91, 0xb9, 0x86, 0xd1, 0x3c, 0x04, 0xb5, 0xf9, 0x10, 0xfa, 0x8f, 0x3c, 0xac, 0xab, 0xdf, 0x3d, 0x3b, 0xd7, 0x32,+ 0x33, 0x4f, 0xb3, 0xf6, 0xb3, 0x55, 0x99, 0x25, 0x6a, 0x67, 0x9e, 0x8f, 0xf3, 0xdd, 0xac, 0x66, 0x6b, 0x8e, 0x65, 0x41,+ 0x5b, 0xcf, 0x69, 0x9e, 0xc9, 0xc3, 0x57, 0x3d, 0xb7, 0xba, 0x26, 0x3f, 0xda, 0xfc, 0x9c, 0xf7, 0x9a, 0x4c, 0x23, 0x75,+ 0xf1, 0xbf, 0x7e, 0x1e, 0xfa, 0x8f, 0xfd, 0xe8, 0x17, 0x64, 0x62, 0xa8, 0xdf, 0x3a, 0xf7, 0xf7, 0x3b, 0xc5, 0xff, 0xec,+ 0x3d, 0x38, 0x7b, 0xf5, 0xc6, 0x67, 0xdc, 0x8d, 0xb2, 0x4f, 0x5c, 0x9f, 0x5b, 0xa5, 0x15, 0xe5, 0x47, 0xad, 0x8f, 0xff,+ 0x76, 0x52, 0xfd, 0x1f, 0x8d, 0xff, 0x3e, 0x5c, 0xcd, 0xe6, 0xbe, 0xf1, 0xbf, 0x9e, 0x77, 0x22, 0xfb, 0xab, 0xb9, 0x95,+ 0x1c, 0xe2, 0xb9, 0xc6, 0xf3, 0xf1, 0x9f, 0xcb, 0x14, 0x74, 0x6e, 0xdd, 0x7a, 0x7d, 0xfc, 0x47, 0x4b, 0xe4, 0xaa, 0xf8,+ 0x8f, 0x5f, 0x25, 0x7d, 0x98, 0xcd, 0xfa, 0x8e, 0xf1, 0xdf, 0xbf, 0x3e, 0xfe, 0xeb, 0x73, 0xf9, 0x46, 0x23, 0x20, 0x92,+ 0x07, 0x7d, 0xa6, 0x5f, 0xbd, 0xda, 0xb3, 0x8b, 0xf7, 0xbb, 0xa2, 0xf5, 0xff, 0xe8, 0xf3, 0x33, 0x47, 0x72, 0x75, 0xfc,+ 0xb7, 0x61, 0x84, 0xf7, 0x44, 0x94, 0xc6, 0x47, 0x40, 0x32, 0x39, 0xaf, 0xae, 0x89, 0xff, 0x16, 0x5a, 0x31, 0x30, 0x5e,+ 0xcf, 0xdf, 0x3d, 0xfe, 0xab, 0xfb, 0x06, 0xd1, 0x11, 0x83, 0xea, 0x7d, 0xbc, 0x5f, 0xff, 0xbf, 0x17, 0xb4, 0x12, 0x77,+ 0xc4, 0x7f, 0xb6, 0x7c, 0xa2, 0xd1, 0x14, 0x8b, 0xff, 0xf9, 0xda, 0x3d, 0xb6, 0x9a, 0x40, 0x6c, 0xdb, 0x7b, 0xe3, 0xbf,+ 0x36, 0x7f, 0xea, 0xfa, 0x58, 0xf1, 0x9b, 0xe2, 0x3f, 0xda, 0xff, 0x9f, 0xef, 0x71, 0xdd, 0x2b, 0xfe, 0xdb, 0xc4, 0xfa,+ 0x3c, 0x67, 0xc7, 0xff, 0x28, 0xdb, 0xea, 0xdb, 0xe2, 0x3f, 0x1a, 0x5b, 0xd1, 0xf5, 0x8c, 0x5a, 0xb8, 0xa6, 0x7b, 0x7b,+ 0xfd, 0xdf, 0x5e, 0x1a, 0xff, 0xf1, 0xf5, 0x65, 0x9e, 0x15, 0xff, 0xd5, 0xad, 0x86, 0xeb, 0xf3, 0xea, 0x45, 0x47, 0x1b,+ 0xe3, 0xa3, 0x94, 0xef, 0x6e, 0xff, 0xf7, 0x0d, 0xad, 0xf0, 0xec, 0xf3, 0xff, 0xab, 0xe2, 0x7f, 0xd7, 0xf3, 0xbf, 0x36,+ 0xbd, 0xe6, 0xdf, 0xae, 0xbd, 0x12, 0xff, 0xd5, 0xf1, 0x5f, 0xb9, 0x76, 0xe2, 0xda, 0xbf, 0xa8, 0x7e, 0xff, 0xa7, 0x7e,+ 0x24, 0x6d, 0xff, 0xfb, 0x3f, 0x7b, 0xca, 0xa7, 0x4d, 0xad, 0x98, 0xb6, 0xfe, 0xab, 0x6d, 0x72, 0x55, 0xe3, 0xd8, 0x3e,+ 0xd7, 0xbf, 0x7d, 0x73, 0xf7, 0xf8, 0x8f, 0xbd, 0x6d, 0x10, 0xfd, 0x64, 0xfc, 0x13, 0xf7, 0x59, 0x0b, 0xec, 0x3b, 0xdf,+ 0xa2, 0x54, 0x0a, 0xd5, 0x25, 0xa4, 0x54, 0x71, 0x07, 0x78, 0xd7, 0x7b, 0xe6, 0xbb, 0xfe, 0x3d, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xcd, 0x5e, 0x99, 0xcd, 0xb9, 0xfd, 0xeb, 0x5f, 0x7b, 0x68, 0xbe,+ 0x6b, 0x4f, 0x7e, 0xae, 0x2f, 0xe7, 0xc1, 0x58, 0x9b, 0x77, 0x5a, 0x91, 0x83, 0xa1, 0x3a, 0x8f, 0xd4, 0xb8, 0x5c, 0x66,+ 0xcf, 0xf4, 0x78, 0x26, 0xf1, 0xea, 0x15, 0x12, 0x99, 0xd7, 0x93, 0xc9, 0xa8, 0x93, 0x59, 0x4b, 0x20, 0x9e, 0x09, 0xb1,+ 0x2d, 0x7e, 0x6b, 0xec, 0xac, 0xfd, 0x3a, 0xbf, 0x3a, 0x9a, 0xef, 0xb3, 0x26, 0xfe, 0x63, 0xb9, 0x25, 0xaf, 0xc8, 0xb4,+ 0x16, 0xbf, 0x9a, 0x6a, 0xf7, 0xb0, 0xbe, 0x54, 0xe6, 0xf6, 0x36, 0xf7, 0xf7, 0xcc, 0x9c, 0xfe, 0x5c, 0xee, 0x81, 0xd5,+ 0x92, 0xe8, 0x53, 0xd9, 0x52, 0x56, 0x3f, 0xf9, 0xf9, 0x73, 0xc7, 0xdb, 0xfa, 0x54, 0xe6, 0x88, 0xd5, 0x6f, 0xfd, 0x6d,+ 0xf0, 0xf9, 0x7e, 0x78, 0xe7, 0xad, 0x9d, 0xd1, 0xfa, 0x94, 0xf8, 0x5f, 0xbf, 0x77, 0x9f, 0x1d, 0xff, 0xf1, 0xfb, 0x54,+ 0x2b, 0xcc, 0xd2, 0xb3, 0xbe, 0x36, 0x46, 0x64, 0xe6, 0x6e, 0x3e, 0x47, 0xd0, 0x19, 0x19, 0x35, 0x7e, 0x8d, 0xa6, 0x95,+ 0xb3, 0x36, 0x17, 0xfd, 0x9f, 0xe2, 0xf7, 0xa8, 0xb5, 0xb5, 0x2f, 0xfe, 0x6b, 0x32, 0xf2, 0x3d, 0x27, 0xfe, 0x67, 0x7a,+ 0x1b, 0xe7, 0xc5, 0xff, 0xf8, 0xef, 0x75, 0x59, 0xb5, 0x2b, 0x73, 0xed, 0x8c, 0x72, 0x2d, 0xb7, 0xd0, 0x19, 0xe9, 0xc1,+ 0xfb, 0x4a, 0x2f, 0xce, 0x67, 0xde, 0x7f, 0xfc, 0x3f, 0x5b, 0x53, 0xcf, 0xc6, 0xff, 0xfa, 0x2f, 0xfe, 0x36, 0xd1, 0x7e,+ 0xa8, 0x6e, 0xff, 0xaf, 0x5c, 0x2f, 0x4f, 0x8a, 0xff, 0x36, 0x95, 0x8b, 0xec, 0xde, 0xf5, 0x7f, 0x65, 0x4e, 0xad, 0xfa,+ 0xf8, 0x8f, 0x45, 0x78, 0xa4, 0x26, 0x9f, 0x5f, 0xf1, 0x60, 0xed, 0xbc, 0x8d, 0x5b, 0xf9, 0x3d, 0xd1, 0xfe, 0xdf, 0x11,+ 0xff, 0xd5, 0xe3, 0x7f, 0xf1, 0x35, 0x3c, 0xf6, 0x8c, 0x74, 0x45, 0xc6, 0xff, 0xda, 0x09, 0xfd, 0xff, 0x51, 0x3b, 0x31,+ 0x5a, 0x2a, 0xf5, 0x6b, 0x53, 0x55, 0x66, 0xdb, 0x5e, 0x8d, 0xff, 0x4c, 0xfd, 0x1f, 0x1d, 0x87, 0xc8, 0xb4, 0x10, 0xdb,+ 0x60, 0xe4, 0x60, 0xf4, 0x9b, 0xeb, 0x59, 0x43, 0x73, 0xed, 0xff, 0x1d, 0xf1, 0x7f, 0x56, 0xff, 0xbf, 0x25, 0x47, 0x35,+ 0xeb, 0xda, 0xff, 0x2d, 0xd1, 0xca, 0xcc, 0xdc, 0x6d, 0x22, 0xa5, 0xbd, 0x5e, 0x66, 0x57, 0xd6, 0xff, 0xb9, 0xd5, 0xe6,+ 0xda, 0xb6, 0x7c, 0xa7, 0x91, 0xf6, 0xff, 0x9e, 0xa7, 0x70, 0xcf, 0xae, 0xff, 0xcf, 0x7c, 0x3a, 0xb9, 0x73, 0x7f, 0xee,+ 0x93, 0x77, 0x6e, 0x4f, 0x1e, 0xe9, 0x3b, 0xf4, 0xff, 0x23, 0xe3, 0xff, 0xd1, 0x9c, 0xc7, 0xe3, 0xda, 0xb8, 0x0f, 0x46,+ 0xd3, 0xbe, 0x35, 0xfe, 0xef, 0x91, 0x9b, 0xf9, 0x7b, 0xe3, 0xbf, 0xa5, 0xf2, 0x4f, 0x5f, 0x11, 0xff, 0x73, 0x2d, 0xab,+ 0xd8, 0x8a, 0x88, 0xb9, 0x15, 0x93, 0xa3, 0x7d, 0xba, 0x76, 0xea, 0x95, 0x9e, 0x79, 0xfe, 0xb7, 0xe7, 0xfd, 0x9f, 0xda,+ 0x37, 0x0d, 0x9e, 0xfb, 0x3e, 0xd4, 0x3b, 0x8e, 0xe0, 0x8c, 0xfb, 0xf9, 0x78, 0xd5, 0x82, 0xbe, 0xe9, 0x98, 0x62, 0x4f,+ 0x75, 0xa3, 0xcf, 0x89, 0xf7, 0xdd, 0xef, 0xa3, 0xef, 0xff, 0x44, 0xcb, 0x54, 0xa6, 0xe5, 0x6f, 0xb9, 0x83, 0x5d, 0x19,+ 0xff, 0xfb, 0x5b, 0x49, 0x55, 0xef, 0x30, 0x7c, 0xdb, 0x95, 0xa2, 0x64, 0xbe, 0xe5, 0xbc, 0xae, 0x8f, 0xf4, 0xbe, 0xa5,+ 0x24, 0x5c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3b, 0xe7, 0x8a, 0xf5, 0xb2,+ 0x4c, 0x0b, 0xb3, 0x79, 0xae, 0xfa, 0xc2, 0xcc, 0xcd, 0x36, 0xcc, 0xdd, 0x9c, 0xfd, 0x9e, 0x9f, 0xab, 0x1a, 0xf4, 0xc1,+ 0xbf, 0x68, 0x81, 0x3d, 0xed, 0xe1, 0x79, 0xc8, 0xeb, 0x6b, 0x34, 0xfc, 0xdc, 0xe3, 0x96, 0x28, 0x91, 0x36, 0x31, 0x4f,+ 0x75, 0x6d, 0xae, 0xde, 0xee, 0x63, 0xae, 0xc9, 0x96, 0x1e, 0xc9, 0xfb, 0x37, 0x9b, 0xbd, 0x64, 0x47, 0xa9, 0xe4, 0x66,+ 0xbb, 0xf7, 0xa5, 0xbf, 0xc7, 0x72, 0x3f, 0xf4, 0xc3, 0x18, 0xaa, 0xb9, 0x3f, 0xcd, 0x65, 0xe8, 0x5b, 0x9f, 0xb3, 0x3e,+ 0x97, 0xdf, 0xb3, 0x6d, 0xcc, 0x89, 0xbd, 0x7e, 0xb5, 0xc7, 0x23, 0x25, 0xb7, 0x75, 0x6e, 0xae, 0xfe, 0x8e, 0x63, 0x8e,+ 0xe7, 0xb3, 0x9d, 0xff, 0x9e, 0x4c, 0xed, 0x37, 0x9e, 0x85, 0x99, 0xa9, 0x27, 0xda, 0xd4, 0xdd, 0x7a, 0x2d, 0xca, 0xa3,+ 0x77, 0x99, 0xf5, 0xf8, 0xaf, 0x99, 0x83, 0xde, 0x87, 0xc7, 0x13, 0x5b, 0x81, 0x63, 0x26, 0xbf, 0xf7, 0xfb, 0x5a, 0x8b,+ 0xf9, 0xf8, 0xff, 0xd6, 0x36, 0xf6, 0xfd, 0x4a, 0xa0, 0x2f, 0xd6, 0xf1, 0x9f, 0x23, 0x6c, 0xa6, 0x15, 0x5f, 0x13, 0xff,+ 0xeb, 0xf7, 0xad, 0xfd, 0xf1, 0xdf, 0x43, 0xdf, 0x10, 0x6d, 0xcf, 0xde, 0x73, 0x6b, 0x2e, 0xfe, 0xc7, 0x57, 0xd0, 0x9e,+ 0xad, 0x55, 0xab, 0x28, 0xe5, 0x72, 0x94, 0xb7, 0x60, 0xef, 0x21, 0x9b, 0x11, 0x68, 0x35, 0x1b, 0x5b, 0x0f, 0xf5, 0x46,+ 0xf6, 0xd4, 0xff, 0xf9, 0xfe, 0xff, 0x7c, 0xbb, 0x2d, 0x3e, 0x7e, 0x90, 0xb9, 0x96, 0x76, 0xb4, 0xc3, 0xcf, 0xd8, 0x1a,+ 0xc9, 0x1b, 0x77, 0xd5, 0xd6, 0xdd, 0xf1, 0xdf, 0xff, 0xb3, 0x8e, 0xe2, 0x51, 0x44, 0xad, 0xdf, 0x1d, 0xee, 0xd7, 0xb2,+ 0x88, 0x8f, 0xff, 0xad, 0x1e, 0x43, 0xc5, 0x11, 0xcf, 0xf5, 0x0b, 0x67, 0xa3, 0xb4, 0xae, 0xfe, 0xcf, 0x9c, 0xf5, 0x2b,+ 0xb7, 0x66, 0x46, 0xf7, 0xde, 0x1a, 0xff, 0x73, 0xe5, 0x76, 0x45, 0xfc, 0x57, 0xe7, 0x13, 0x9c, 0x69, 0x4d, 0x44, 0xb3,+ 0x34, 0x5f, 0xd1, 0x97, 0x9c, 0xcd, 0xce, 0x9f, 0x5b, 0x7f, 0xf6, 0x4d, 0xf1, 0xdf, 0x8a, 0xda, 0xff, 0x67, 0x6e, 0xbd,+ 0x47, 0xfb, 0xbf, 0xbf, 0xa0, 0xfe, 0xcf, 0x3e, 0xd7, 0x99, 0x3f, 0x86, 0x73, 0x8e, 0x36, 0x9e, 0x81, 0x3f, 0xf3, 0x04,+ 0xe3, 0xca, 0xbe, 0x70, 0x76, 0x6b, 0x36, 0xfe, 0xbf, 0xb5, 0xfe, 0x7f, 0x43, 0xfc, 0xe7, 0x9f, 0x65, 0xaf, 0x8c, 0xff,+ 0x9d, 0x75, 0x44, 0xf9, 0xf6, 0x51, 0xee, 0xd9, 0xff, 0x3b, 0xeb, 0xff, 0x9a, 0x35, 0xe7, 0x9f, 0x16, 0xff, 0x33, 0xa3,+ 0x4c, 0x4f, 0x8d, 0xff, 0x8a, 0x18, 0xa9, 0x1a, 0xff, 0xaf, 0xbe, 0x03, 0xb4, 0xad, 0x99, 0xeb, 0x9f, 0x17, 0xe1, 0xe3,+ 0xf8, 0x8f, 0xbc, 0xff, 0xf3, 0xee, 0xf8, 0x9f, 0x7b, 0x37, 0xe6, 0xd9, 0xf1, 0xdf, 0x93, 0x2b, 0xd6, 0xbc, 0xf3, 0xf9,+ 0x70, 0x6c, 0xfd, 0xe9, 0xe7, 0xc5, 0x7f, 0xfc, 0xed, 0x8c, 0xb7, 0x3f, 0xff, 0xcb, 0xbd, 0x1d, 0xb0, 0xf7, 0xf9, 0xdf,+ 0x13, 0xde, 0x2b, 0xe1, 0x4d, 0xf7, 0x42, 0xe7, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0xa0, 0x6a, 0x46, 0x46, 0x3c, 0x67, 0xcf, 0xdc, 0x4c, 0xb1, 0x6b, 0x72, 0xdf, 0x47, 0x32, 0x15, 0xcc, 0xec, 0x4f, 0x3c,+ 0xff, 0x41, 0x24, 0xdb, 0xfe, 0xd1, 0xb9, 0x89, 0xe6, 0x1c, 0xcf, 0xe4, 0x32, 0xda, 0x75, 0x8c, 0xeb, 0x59, 0xe1, 0xe7,+ 0x7f, 0x61, 0x2e, 0xf7, 0x63, 0x2c, 0x2e, 0xee, 0x71, 0xae, 0x33, 0xf3, 0xee, 0x76, 0x67, 0x8a, 0xef, 0xc9, 0x5c, 0xef,+ 0xf5, 0x7b, 0x95, 0xcd, 0xd3, 0x1f, 0xdb, 0xe7, 0x48, 0x09, 0xf7, 0xc4, 0x4a, 0x2c, 0x6d, 0xe2, 0x4a, 0xaa, 0xce, 0xef,+ 0x93, 0x59, 0x99, 0x63, 0xfe, 0x8e, 0x5c, 0x99, 0xb3, 0xbf, 0x25, 0xf2, 0xf5, 0xdf, 0xe5, 0x5c, 0xdf, 0xb5, 0x65, 0x71,+ 0x9c, 0xf1, 0xe8, 0xbe, 0xad, 0xa4, 0x1e, 0xca, 0x6e, 0xfa, 0x9c, 0x7c, 0x04, 0xb1, 0x3a, 0xf7, 0xbd, 0xed, 0xe2, 0xf7,+ 0x1f, 0x73, 0x26, 0xb7, 0xc0, 0x4c, 0x1d, 0xde, 0x02, 0xf1, 0x7f, 0xc7, 0xfc, 0x55, 0xb9, 0xcc, 0x57, 0x33, 0xa5, 0x78,+ 0xd6, 0xb6, 0x23, 0xbf, 0x07, 0x56, 0x62, 0xbb, 0xf2, 0x18, 0xf7, 0xe7, 0xec, 0x38, 0xce, 0x26, 0xf2, 0xe4, 0x73, 0xdd,+ 0xb6, 0xe7, 0x82, 0x89, 0xd6, 0xff, 0x4f, 0x8d, 0xff, 0xd1, 0x6a, 0x04, 0x9f, 0xd7, 0x25, 0x3b, 0x6f, 0x5b, 0xc5, 0x5a,+ 0x06, 0xab, 0x3d, 0xa0, 0x1d, 0xdb, 0xae, 0xcc, 0xd9, 0x75, 0xf6, 0xb1, 0xc6, 0xcb, 0xe8, 0xca, 0xf8, 0x9f, 0xe9, 0xd7,+ 0x7d, 0x5b, 0xfd, 0xdf, 0x2f, 0xdf, 0x36, 0x7f, 0x17, 0xbb, 0xfb, 0xb5, 0xbd, 0x7f, 0xcd, 0x8e, 0x27, 0xc4, 0xf8, 0x5d,+ 0xe3, 0xff, 0xaa, 0x8c, 0xc7, 0x35, 0x2b, 0x2d, 0x45, 0xfb, 0xff, 0x4f, 0xb8, 0x26, 0x7a, 0x72, 0x2d, 0xe3, 0xd8, 0x0a,+ 0xce, 0xd5, 0xdb, 0xc4, 0xff, 0xdd, 0xeb, 0xff, 0x99, 0xb1, 0x95, 0xfb, 0xe5, 0xaf, 0xcc, 0xae, 0xd3, 0xfb, 0xee, 0xeb,+ 0xa5, 0x85, 0x9e, 0x79, 0xed, 0xd8, 0x26, 0xfe, 0xc5, 0xbf, 0xf8, 0xbf, 0xe2, 0x7a, 0xe9, 0x5f, 0xd1, 0xff, 0x17, 0xff,+ 0xe2, 0x3f, 0xf2, 0xcc, 0xec, 0xfe, 0xfd, 0xff, 0x5d, 0x4f, 0x2a, 0xdf, 0x36, 0xfe, 0x1f, 0x7d, 0xda, 0xfb, 0xa4, 0xf1,+ 0xff, 0xdd, 0xcf, 0xff, 0xae, 0xf8, 0xdd, 0xdc, 0x3e, 0xbf, 0xff, 0x19, 0xf7, 0x3b, 0xf2, 0xc5, 0xf3, 0xfc, 0xeb, 0x50,+ 0x19, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe7, 0x00, 0xaf, 0xbe,+ 0xa7, 0x7f, 0x66, 0xbe, 0xf7, 0xc8, 0x9c, 0xcf, 0xb9, 0xef, 0x04, 0xf1, 0x1f, 0x9b, 0xa7, 0x73, 0x66, 0xbe, 0xf7, 0xfc,+ 0xdc, 0x7c, 0xe7, 0x1a, 0xde, 0x37, 0x53, 0x5c, 0x6c, 0x43, 0x2e, 0xc2, 0xa3, 0x39, 0x3a, 0xef, 0xb2, 0xed, 0x1d, 0x2b,+ 0x73, 0xc0, 0xbd, 0x6a, 0xd5, 0xa7, 0xc4, 0x7f, 0xdb, 0x96, 0xef, 0x12, 0xbe, 0xb1, 0xff, 0x2f, 0xfe, 0x41, 0xfc, 0x8b,+ 0x7f, 0xd0, 0xfe, 0x17, 0xff, 0x60, 0xfc, 0xff, 0xaa, 0x58, 0x9d, 0x59, 0x27, 0xe6, 0xc9, 0x4f, 0x31, 0xe0, 0x7e, 0x77,+ 0x80, 0xf8, 0xdd, 0xa1, 0x7a, 0x5b, 0x1b, 0xde, 0x37, 0x3c, 0x23, 0x84, 0xb3, 0xe2, 0xff, 0x9a, 0x51, 0x8a, 0xd5, 0xf8,+ 0xd7, 0xfe, 0x87, 0x37, 0xf5, 0x46, 0x22, 0xef, 0xff, 0x89, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe9, 0xaf, 0xff, 0x94, 0x03, 0x88, 0x7f, 0xe0, 0xeb, 0xe2, 0xff,+ 0x0f };++// Font glyphs rectangles data (on atlas)+static const Rectangle sunnyFontRecs[189] = {+ { 4, 4, 4 , 16 },+ { 16, 4, 2 , 10 },+ { 26, 4, 5 , 3 },+ { 39, 4, 7 , 10 },+ { 54, 4, 7 , 13 },+ { 69, 4, 7 , 10 },+ { 84, 4, 7 , 10 },+ { 99, 4, 2 , 3 },+ { 109, 4, 3 , 12 },+ { 120, 4, 3 , 12 },+ { 131, 4, 5 , 6 },+ { 144, 4, 6 , 5 },+ { 158, 4, 2 , 4 },+ { 168, 4, 5 , 1 },+ { 181, 4, 2 , 2 },+ { 191, 4, 4 , 10 },+ { 203, 4, 6 , 10 },+ { 217, 4, 4 , 10 },+ { 229, 4, 6 , 10 },+ { 243, 4, 6 , 10 },+ { 257, 4, 6 , 10 },+ { 271, 4, 6 , 10 },+ { 285, 4, 6 , 10 },+ { 299, 4, 6 , 10 },+ { 313, 4, 6 , 10 },+ { 327, 4, 6 , 10 },+ { 341, 4, 2 , 6 },+ { 351, 4, 2 , 8 },+ { 361, 4, 7 , 7 },+ { 376, 4, 5 , 3 },+ { 389, 4, 7 , 7 },+ { 404, 4, 6 , 10 },+ { 418, 4, 7 , 12 },+ { 433, 4, 7 , 10 },+ { 448, 4, 7 , 10 },+ { 463, 4, 7 , 10 },+ { 478, 4, 7 , 10 },+ { 493, 4, 7 , 10 },+ { 4, 28, 7 , 10 },+ { 19, 28, 7 , 10 },+ { 34, 28, 7 , 10 },+ { 49, 28, 2 , 10 },+ { 59, 28, 5 , 10 },+ { 72, 28, 7 , 10 },+ { 87, 28, 6 , 10 },+ { 101, 28, 9 , 10 },+ { 118, 28, 7 , 10 },+ { 133, 28, 7 , 10 },+ { 148, 28, 7 , 10 },+ { 163, 28, 7 , 12 },+ { 178, 28, 7 , 10 },+ { 193, 28, 7 , 10 },+ { 208, 28, 6 , 10 },+ { 222, 28, 7 , 10 },+ { 237, 28, 7 , 10 },+ { 252, 28, 8 , 10 },+ { 268, 28, 7 , 10 },+ { 283, 28, 6 , 10 },+ { 297, 28, 7 , 10 },+ { 312, 28, 4 , 12 },+ { 324, 28, 4 , 10 },+ { 336, 28, 4 , 12 },+ { 348, 28, 6 , 3 },+ { 362, 28, 7 , 1 },+ { 377, 28, 4 , 3 },+ { 389, 28, 6 , 7 },+ { 403, 28, 6 , 10 },+ { 417, 28, 6 , 7 },+ { 431, 28, 6 , 10 },+ { 445, 28, 6 , 7 },+ { 459, 28, 4 , 10 },+ { 471, 28, 6 , 9 },+ { 485, 28, 6 , 10 },+ { 499, 28, 2 , 10 },+ { 4, 52, 5 , 12 },+ { 17, 52, 6 , 10 },+ { 31, 52, 3 , 10 },+ { 42, 52, 8 , 7 },+ { 58, 52, 6 , 7 },+ { 72, 52, 6 , 7 },+ { 86, 52, 6 , 9 },+ { 100, 52, 6 , 9 },+ { 114, 52, 5 , 7 },+ { 127, 52, 6 , 7 },+ { 141, 52, 4 , 10 },+ { 153, 52, 6 , 7 },+ { 167, 52, 6 , 7 },+ { 181, 52, 8 , 7 },+ { 197, 52, 6 , 7 },+ { 211, 52, 6 , 9 },+ { 225, 52, 6 , 7 },+ { 239, 52, 5 , 12 },+ { 252, 52, 2 , 12 },+ { 262, 52, 5 , 12 },+ { 275, 52, 7 , 3 },+ { 290, 52, 2 , 9 },+ { 300, 52, 6 , 11 },+ { 314, 52, 7 , 10 },+ { 329, 52, 7 , 9 },+ { 344, 52, 6 , 10 },+ { 358, 52, 7 , 11 },+ { 373, 52, 6 , 12 },+ { 387, 52, 6 , 10 },+ { 401, 52, 7 , 10 },+ { 416, 52, 5 , 5 },+ { 429, 52, 7 , 6 },+ { 444, 52, 6 , 3 },+ { 458, 52, 7 , 10 },+ { 473, 52, 9 , 10 },+ { 490, 52, 4 , 4 },+ { 4, 76, 6 , 7 },+ { 18, 76, 4 , 5 },+ { 30, 76, 4 , 5 },+ { 42, 76, 7 , 11 },+ { 57, 76, 6 , 9 },+ { 71, 76, 7 , 12 },+ { 86, 76, 2 , 2 },+ { 96, 76, 6 , 10 },+ { 110, 76, 3 , 5 },+ { 121, 76, 4 , 5 },+ { 133, 76, 7 , 6 },+ { 148, 76, 9 , 10 },+ { 165, 76, 8 , 7 },+ { 181, 76, 6 , 11 },+ { 195, 76, 6 , 11 },+ { 209, 76, 7 , 11 },+ { 224, 76, 7 , 11 },+ { 239, 76, 7 , 11 },+ { 254, 76, 7 , 11 },+ { 269, 76, 7 , 11 },+ { 284, 76, 7 , 11 },+ { 299, 76, 9 , 10 },+ { 316, 76, 7 , 12 },+ { 331, 76, 7 , 11 },+ { 346, 76, 7 , 11 },+ { 361, 76, 7 , 11 },+ { 376, 76, 7 , 11 },+ { 391, 76, 3 , 11 },+ { 402, 76, 3 , 11 },+ { 413, 76, 5 , 11 },+ { 426, 76, 5 , 11 },+ { 439, 76, 8 , 10 },+ { 455, 76, 7 , 11 },+ { 470, 76, 7 , 11 },+ { 485, 76, 7 , 11 },+ { 4, 100, 7 , 11 },+ { 19, 100, 7 , 11 },+ { 34, 100, 7 , 11 },+ { 49, 100, 7 , 7 },+ { 64, 100, 7 , 13 },+ { 79, 100, 7 , 11 },+ { 94, 100, 7 , 11 },+ { 109, 100, 7 , 11 },+ { 124, 100, 7 , 11 },+ { 139, 100, 6 , 11 },+ { 153, 100, 7 , 10 },+ { 168, 100, 7 , 10 },+ { 183, 100, 6 , 10 },+ { 197, 100, 6 , 10 },+ { 211, 100, 6 , 10 },+ { 225, 100, 6 , 10 },+ { 239, 100, 6 , 10 },+ { 253, 100, 6 , 11 },+ { 267, 100, 8 , 7 },+ { 283, 100, 6 , 9 },+ { 297, 100, 6 , 10 },+ { 311, 100, 6 , 10 },+ { 325, 100, 6 , 10 },+ { 339, 100, 6 , 10 },+ { 353, 100, 3 , 10 },+ { 364, 100, 3 , 10 },+ { 375, 100, 5 , 10 },+ { 388, 100, 5 , 10 },+ { 401, 100, 6 , 10 },+ { 415, 100, 6 , 10 },+ { 429, 100, 6 , 10 },+ { 443, 100, 6 , 10 },+ { 457, 100, 6 , 10 },+ { 471, 100, 6 , 10 },+ { 485, 100, 6 , 10 },+ { 4, 124, 6 , 7 },+ { 18, 124, 7 , 11 },+ { 33, 124, 6 , 10 },+ { 47, 124, 6 , 10 },+ { 61, 124, 6 , 10 },+ { 75, 124, 6 , 10 },+ { 89, 124, 6 , 12 },+ { 103, 124, 6 , 12 },+ { 117, 124, 6 , 12 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo sunnyFontGlyphs[189] = {+ { 32, 0, 12, 4, { 0 }},+ { 33, 0, 2, 3, { 0 }},+ { 34, 0, 2, 6, { 0 }},+ { 35, 0, 2, 8, { 0 }},+ { 36, 0, 1, 8, { 0 }},+ { 37, 0, 2, 8, { 0 }},+ { 38, 0, 2, 8, { 0 }},+ { 39, 0, 2, 3, { 0 }},+ { 40, 0, 2, 4, { 0 }},+ { 41, 0, 2, 4, { 0 }},+ { 42, 0, 4, 6, { 0 }},+ { 43, 0, 6, 7, { 0 }},+ { 44, 0, 10, 3, { 0 }},+ { 45, 0, 8, 6, { 0 }},+ { 46, 0, 10, 3, { 0 }},+ { 47, 0, 2, 5, { 0 }},+ { 48, 0, 2, 7, { 0 }},+ { 49, 0, 2, 7, { 0 }},+ { 50, 0, 2, 7, { 0 }},+ { 51, 0, 2, 7, { 0 }},+ { 52, 0, 2, 7, { 0 }},+ { 53, 0, 2, 7, { 0 }},+ { 54, 0, 2, 7, { 0 }},+ { 55, 0, 2, 7, { 0 }},+ { 56, 0, 2, 7, { 0 }},+ { 57, 0, 2, 7, { 0 }},+ { 58, 0, 4, 3, { 0 }},+ { 59, 0, 4, 3, { 0 }},+ { 60, 0, 4, 8, { 0 }},+ { 61, 0, 6, 6, { 0 }},+ { 62, 0, 4, 8, { 0 }},+ { 63, 0, 2, 7, { 0 }},+ { 64, 0, 2, 8, { 0 }},+ { 65, 0, 2, 8, { 0 }},+ { 66, 0, 2, 8, { 0 }},+ { 67, 0, 2, 8, { 0 }},+ { 68, 0, 2, 8, { 0 }},+ { 69, 0, 2, 8, { 0 }},+ { 70, 0, 2, 8, { 0 }},+ { 71, 0, 2, 8, { 0 }},+ { 72, 0, 2, 8, { 0 }},+ { 73, 0, 2, 3, { 0 }},+ { 74, 0, 2, 6, { 0 }},+ { 75, 0, 2, 8, { 0 }},+ { 76, 0, 2, 7, { 0 }},+ { 77, 0, 2, 10, { 0 }},+ { 78, 0, 2, 8, { 0 }},+ { 79, 0, 2, 8, { 0 }},+ { 80, 0, 2, 8, { 0 }},+ { 81, 0, 2, 8, { 0 }},+ { 82, 0, 2, 8, { 0 }},+ { 83, 0, 2, 8, { 0 }},+ { 84, 0, 2, 7, { 0 }},+ { 85, 0, 2, 8, { 0 }},+ { 86, 0, 2, 8, { 0 }},+ { 87, 0, 2, 9, { 0 }},+ { 88, 0, 2, 8, { 0 }},+ { 89, 0, 2, 7, { 0 }},+ { 90, 0, 2, 8, { 0 }},+ { 91, 0, 2, 5, { 0 }},+ { 92, 0, 2, 5, { 0 }},+ { 93, 0, 2, 5, { 0 }},+ { 94, 0, 2, 7, { 0 }},+ { 95, 0, 14, 8, { 0 }},+ { 96, 0, 2, 5, { 0 }},+ { 97, 0, 5, 7, { 0 }},+ { 98, 0, 2, 7, { 0 }},+ { 99, 0, 5, 7, { 0 }},+ { 100, 0, 2, 7, { 0 }},+ { 101, 0, 5, 7, { 0 }},+ { 102, 0, 2, 5, { 0 }},+ { 103, 0, 5, 7, { 0 }},+ { 104, 0, 2, 7, { 0 }},+ { 105, 0, 2, 3, { 0 }},+ { 106, 0, 2, 6, { 0 }},+ { 107, 0, 2, 7, { 0 }},+ { 108, 0, 2, 4, { 0 }},+ { 109, 0, 5, 9, { 0 }},+ { 110, 0, 5, 7, { 0 }},+ { 111, 0, 5, 7, { 0 }},+ { 112, 0, 5, 7, { 0 }},+ { 113, 0, 5, 7, { 0 }},+ { 114, 0, 5, 6, { 0 }},+ { 115, 0, 5, 7, { 0 }},+ { 116, 0, 2, 5, { 0 }},+ { 117, 0, 5, 7, { 0 }},+ { 118, 0, 5, 7, { 0 }},+ { 119, 0, 5, 9, { 0 }},+ { 120, 0, 5, 7, { 0 }},+ { 121, 0, 5, 7, { 0 }},+ { 122, 0, 5, 7, { 0 }},+ { 123, 0, 2, 6, { 0 }},+ { 124, 0, 2, 3, { 0 }},+ { 125, 0, 2, 6, { 0 }},+ { 126, 0, 6, 8, { 0 }},+ { 161, 0, 5, 3, { 0 }},+ { 162, 0, 3, 7, { 0 }},+ { 163, 0, 2, 8, { 0 }},+ { 8364, 0, 3, 8, { 0 }},+ { 165, 0, 2, 7, { 0 }},+ { 352, 0, 1, 8, { 0 }},+ { 167, 0, 2, 7, { 0 }},+ { 353, 0, 2, 7, { 0 }},+ { 169, 0, 2, 8, { 0 }},+ { 170, 0, 2, 6, { 0 }},+ { 171, 0, 6, 8, { 0 }},+ { 172, 0, 7, 7, { 0 }},+ { 174, 0, 2, 8, { 0 }},+ { 175, 1, 3, 14, { 0 }},+ { 176, 0, 2, 5, { 0 }},+ { 177, 0, 4, 7, { 0 }},+ { 178, 0, 2, 5, { 0 }},+ { 179, 0, 2, 5, { 0 }},+ { 381, 0, 1, 8, { 0 }},+ { 181, 0, 5, 7, { 0 }},+ { 182, 0, 2, 8, { 0 }},+ { 183, 0, 6, 3, { 0 }},+ { 382, 0, 2, 7, { 0 }},+ { 185, 0, 2, 4, { 0 }},+ { 186, 0, 2, 5, { 0 }},+ { 187, 0, 6, 8, { 0 }},+ { 338, 0, 2, 10, { 0 }},+ { 339, 0, 5, 9, { 0 }},+ { 376, 0, 1, 7, { 0 }},+ { 191, 0, 3, 7, { 0 }},+ { 192, 0, 1, 8, { 0 }},+ { 193, 0, 1, 8, { 0 }},+ { 194, 0, 1, 8, { 0 }},+ { 195, 0, 1, 8, { 0 }},+ { 196, 0, 1, 8, { 0 }},+ { 197, 0, 1, 8, { 0 }},+ { 198, 0, 2, 10, { 0 }},+ { 199, 0, 2, 8, { 0 }},+ { 200, 0, 1, 8, { 0 }},+ { 201, 0, 1, 8, { 0 }},+ { 202, 0, 1, 8, { 0 }},+ { 203, 0, 1, 8, { 0 }},+ { 204, 0, 1, 4, { 0 }},+ { 205, 0, 1, 4, { 0 }},+ { 206, 0, 1, 6, { 0 }},+ { 207, 0, 1, 6, { 0 }},+ { 208, 0, 2, 9, { 0 }},+ { 209, 0, 1, 8, { 0 }},+ { 210, 0, 1, 8, { 0 }},+ { 211, 0, 1, 8, { 0 }},+ { 212, 0, 1, 8, { 0 }},+ { 213, 0, 1, 8, { 0 }},+ { 214, 0, 1, 8, { 0 }},+ { 215, 0, 5, 8, { 0 }},+ { 216, 0, 1, 8, { 0 }},+ { 217, 0, 1, 8, { 0 }},+ { 218, 0, 1, 8, { 0 }},+ { 219, 0, 1, 8, { 0 }},+ { 220, 0, 1, 8, { 0 }},+ { 221, 0, 1, 7, { 0 }},+ { 222, 0, 2, 8, { 0 }},+ { 223, 0, 2, 8, { 0 }},+ { 224, 0, 2, 7, { 0 }},+ { 225, 0, 2, 7, { 0 }},+ { 226, 0, 2, 7, { 0 }},+ { 227, 0, 2, 7, { 0 }},+ { 228, 0, 2, 7, { 0 }},+ { 229, 0, 1, 7, { 0 }},+ { 230, 0, 5, 9, { 0 }},+ { 231, 0, 5, 7, { 0 }},+ { 232, 0, 2, 7, { 0 }},+ { 233, 0, 2, 7, { 0 }},+ { 234, 0, 2, 7, { 0 }},+ { 235, 0, 2, 7, { 0 }},+ { 236, 0, 2, 4, { 0 }},+ { 237, 0, 2, 4, { 0 }},+ { 238, 0, 2, 6, { 0 }},+ { 239, 0, 2, 6, { 0 }},+ { 240, 0, 2, 7, { 0 }},+ { 241, 0, 2, 7, { 0 }},+ { 242, 0, 2, 7, { 0 }},+ { 243, 0, 2, 7, { 0 }},+ { 244, 0, 2, 7, { 0 }},+ { 245, 0, 2, 7, { 0 }},+ { 246, 0, 2, 7, { 0 }},+ { 247, 0, 4, 7, { 0 }},+ { 248, 0, 3, 8, { 0 }},+ { 249, 0, 2, 7, { 0 }},+ { 250, 0, 2, 7, { 0 }},+ { 251, 0, 2, 7, { 0 }},+ { 252, 0, 2, 7, { 0 }},+ { 253, 0, 2, 7, { 0 }},+ { 254, 0, 2, 7, { 0 }},+ { 255, 0, 2, 7, { 0 }},+};++// Style loading function: Sunny+static void GuiLoadStyleSunny(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < SUNNY_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(sunnyStyleProps[i].controlId, sunnyStyleProps[i].propertyId, sunnyStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int sunnyFontDataSize = 0;+ unsigned char *data = DecompressData(sunnyFontData, SUNNY_STYLE_FONT_ATLAS_COMP_SIZE, &sunnyFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, sunnyFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, sunnyFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
+ raygui/styles/terminal/style_terminal.h view
@@ -0,0 +1,569 @@+//////////////////////////////////////////////////////////////////////////////////+// //+// StyleAsCode exporter v2.0 - Style data exported as a values array //+// //+// USAGE: On init call: GuiLoadStyleTerminal(); //+// //+// more info and bugs-report: github.com/raysan5/raygui //+// feedback and support: ray[at]raylibtech.com //+// //+// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //+// //+//////////////////////////////////////////////////////////////////////////////////++#define TERMINAL_STYLE_PROPS_COUNT 17++// Custom style name: Terminal+static const GuiStyleProp terminalStyleProps[TERMINAL_STYLE_PROPS_COUNT] = {+ { 0, 0, 0x1c8d00ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x161313ff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0x38f620ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xc3fbc6ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x43bf2eff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0xdcfadcff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x1f5b19ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0x43ff28ff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x1e6f15ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x223b22ff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x182c18ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x244125ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0xe6fce3ff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x0c1505ff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING +};++// WARNING: This style uses a custom font: "Mecha.ttf" (size: 16, spacing: 0)++#define TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE 1860++// Font atlas image pixels data: DEFLATE compressed+static unsigned char terminalFontData[TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,+ 0xdd, 0x41, 0x92, 0xa4, 0x36, 0x10, 0x05, 0x50, 0xee, 0x7f, 0xe9, 0xf4, 0x62, 0x62, 0x16, 0x76, 0xb8, 0x1b, 0x94, 0x4a,+ 0x89, 0x04, 0x9e, 0x5f, 0x78, 0xd3, 0xd5, 0x53, 0x4d, 0x01, 0xbf, 0x24, 0x84, 0x94, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x7c,+ 0x5e, 0xfc, 0xef, 0x4f, 0xe2, 0xc7, 0xdf, 0x8c, 0xcb, 0xef, 0xf3, 0xe7, 0xa7, 0xf1, 0xe3, 0x5f, 0xf9, 0xfb, 0xdf, 0x95,+ 0x77, 0xba, 0xfe, 0x5b, 0x31, 0xb4, 0x75, 0x73, 0x5b, 0x95, 0x7b, 0x9f, 0xd1, 0xdf, 0xfe, 0x7d, 0x7b, 0xaa, 0xde, 0xad,+ 0xf6, 0x95, 0xb1, 0xb3, 0x23, 0xbf, 0xe7, 0xae, 0x6e, 0x61, 0x6c, 0xdf, 0x2b, 0xc7, 0xa6, 0x7d, 0x1c, 0x0d, 0xf2, 0x7f,+ 0x7e, 0xcc, 0x46, 0xf2, 0x14, 0xe9, 0xf4, 0x8e, 0x7f, 0x3b, 0xad, 0xfc, 0x0e, 0x1d, 0xdd, 0xc6, 0xdc, 0x3e, 0x89, 0x92,+ 0xf7, 0x9f, 0xf9, 0x3b, 0x51, 0xb6, 0xd7, 0x72, 0xff, 0x26, 0x86, 0xdb, 0x88, 0xf9, 0x4f, 0x78, 0xbe, 0x8f, 0x63, 0xd1,+ 0x71, 0xef, 0x99, 0xff, 0xfc, 0x51, 0xcb, 0x9f, 0x29, 0x57, 0xb7, 0x3c, 0xd7, 0xa6, 0xaf, 0x3a, 0x27, 0xe5, 0xff, 0xec,+ 0x9b, 0xfa, 0xe7, 0x16, 0xb4, 0xa2, 0xdd, 0x90, 0xff, 0x5c, 0x06, 0x62, 0x22, 0x47, 0xbb, 0xf2, 0x5f, 0xdb, 0xd6, 0xc8,+ 0xff, 0x33, 0xda, 0xff, 0xb3, 0x6d, 0xff, 0xf7, 0x79, 0x2b, 0xff, 0xd9, 0xa3, 0x90, 0x6d, 0xff, 0x63, 0x7a, 0xfb, 0x3b,+ 0xe7, 0x7f, 0x74, 0xdc, 0x43, 0xfe, 0xcf, 0xaf, 0xe8, 0x73, 0xbf, 0x7d, 0xb6, 0x27, 0xe4, 0x7f, 0x5d, 0xfe, 0x7f, 0xeb,+ 0xb3, 0x9d, 0xf5, 0xf4, 0x76, 0xe4, 0xff, 0xd8, 0x9e, 0xff, 0xb3, 0xeb, 0xa8, 0xeb, 0xfb, 0x62, 0xc7, 0x08, 0xd4, 0x91,+ 0x1c, 0xdb, 0x89, 0xc1, 0x0c, 0xdf, 0xd3, 0x0b, 0x3b, 0xcb, 0x7f, 0x66, 0x4f, 0x66, 0xf2, 0x7f, 0x76, 0x5c, 0x8e, 0x5f,+ 0x7a, 0x30, 0xab, 0xf6, 0x7e, 0x45, 0xfe, 0x67, 0x46, 0xe4, 0x9e, 0x9d, 0xff, 0x38, 0xd9, 0x57, 0x31, 0x31, 0xbe, 0xb9,+ 0xb3, 0xcf, 0x30, 0xd3, 0x4f, 0xeb, 0x7b, 0x1c, 0xde, 0xd3, 0xff, 0x8f, 0xd6, 0xed, 0xbf, 0xfc, 0xcf, 0x5d, 0xff, 0xbf,+ 0x2d, 0xff, 0xb1, 0xfd, 0x58, 0xc5, 0x85, 0x33, 0x56, 0xfe, 0xe7, 0xf6, 0xf0, 0x79, 0x8f, 0x23, 0x16, 0x5d, 0xbf, 0x74,+ 0xcd, 0x7f, 0xee, 0xd3, 0x7d, 0xb1, 0xfd, 0x8f, 0x1b, 0x8f, 0x8f, 0xfc, 0xaf, 0xd8, 0x9b, 0x23, 0x77, 0xd8, 0x66, 0xe7,+ 0x2f, 0xc8, 0xbf, 0xfc, 0xcb, 0x7f, 0xef, 0xfe, 0x7f, 0x0c, 0x8e, 0xdc, 0xc6, 0xe3, 0xc7, 0xff, 0xe2, 0x52, 0x6f, 0x69,+ 0x7e, 0xb6, 0xe0, 0x78, 0x9f, 0x2b, 0xf7, 0x6e, 0xf9, 0xd9, 0x75, 0x4f, 0xb9, 0xfe, 0xdf, 0x39, 0x93, 0xf2, 0x28, 0x99,+ 0x87, 0xb2, 0x7e, 0xfe, 0xdf, 0x33, 0xe7, 0x28, 0x77, 0xcf, 0x3f, 0xb0, 0x7a, 0x95, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x65, 0x0d, 0x4d, 0x94, 0xad, 0x7b, 0x8c, 0x16, 0x95, 0xe7, 0xf7, 0xd4, 0x58,+ 0xbf, 0xb6, 0x87, 0xaa, 0xde, 0x71, 0xec, 0x59, 0x02, 0x63, 0xeb, 0x30, 0x73, 0x2b, 0xff, 0x56, 0xaf, 0x6e, 0x9b, 0x59,+ 0xdd, 0x58, 0xb3, 0x65, 0x15, 0xb5, 0x2d, 0xee, 0x49, 0xc7, 0xca, 0x75, 0xe2, 0x71, 0x69, 0x75, 0x70, 0x6d, 0x92, 0x56,+ 0xaf, 0xd8, 0xce, 0xac, 0x7d, 0xdf, 0x99, 0xff, 0xb1, 0x33, 0x70, 0xfc, 0x73, 0x46, 0x62, 0x35, 0x55, 0x6d, 0x0d, 0x98,+ 0x63, 0xe9, 0xb9, 0x19, 0x8b, 0xd6, 0x90, 0x8d, 0xef, 0x83, 0x3d, 0xe9, 0x90, 0xff, 0x2f, 0xe7, 0x3f, 0x57, 0x23, 0x7b,+ 0xc7, 0xb3, 0x50, 0xe4, 0x5f, 0xfe, 0xe5, 0xff, 0xad, 0xf9, 0x8f, 0xe2, 0xfe, 0x77, 0xbe, 0x5a, 0x47, 0xcd, 0x95, 0x55,+ 0x6d, 0x4a, 0xe4, 0x5f, 0xfe, 0x7f, 0xef, 0x6d, 0xc7, 0xc5, 0x56, 0x6c, 0xa4, 0xc5, 0xdb, 0x59, 0xb3, 0x64, 0x5f, 0x15,+ 0xad, 0xd1, 0x6f, 0x93, 0x28, 0x4c, 0xf0, 0x57, 0xf2, 0x9f, 0xaf, 0x7b, 0xbe, 0x67, 0xdc, 0x2b, 0xb3, 0xe5, 0x99, 0xda,+ 0x57, 0xf5, 0xf9, 0x3f, 0x7b, 0x1e, 0x42, 0xe6, 0xfb, 0xe9, 0x5b, 0xf9, 0x1f, 0xfd, 0x6c, 0xf2, 0x7f, 0x6c, 0x7e, 0xb6,+ 0xcc, 0xfd, 0x35, 0x16, 0x23, 0xd9, 0xd2, 0x57, 0x6d, 0x75, 0xa4, 0x46, 0xdb, 0xaa, 0x7e, 0x9e, 0xab, 0xd2, 0xf8, 0xde,+ 0xfc, 0x47, 0xc1, 0x7d, 0xae, 0xb9, 0x56, 0x52, 0xfe, 0xe5, 0xff, 0x98, 0xac, 0xc0, 0xdb, 0x3d, 0xff, 0x2b, 0xae, 0xbf,+ 0x2b, 0x9f, 0xe6, 0xfa, 0xcc, 0xf6, 0xff, 0x59, 0xf7, 0xff, 0xbe, 0x92, 0xff, 0xb3, 0x63, 0x79, 0x77, 0xfe, 0x3b, 0xd5,+ 0x4c, 0xcd, 0x8c, 0x30, 0xce, 0xfc, 0x9b, 0x8e, 0xf9, 0xdf, 0x35, 0x9f, 0x47, 0xfe, 0x77, 0xe5, 0xff, 0xe7, 0xa7, 0x8d,+ 0xcb, 0x7f, 0xaf, 0xfc, 0xaf, 0xeb, 0xff, 0x3f, 0x3b, 0xff, 0xeb, 0x7a, 0x5f, 0xab, 0xfb, 0x73, 0xb5, 0x5b, 0x9e, 0x99,+ 0x01, 0xf7, 0xdb, 0xfc, 0xbb, 0x48, 0x57, 0x6d, 0xaf, 0x98, 0x87, 0x37, 0x33, 0x3b, 0x68, 0xf7, 0x95, 0x41, 0xf5, 0xbf,+ 0xa9, 0x1f, 0xb3, 0xe8, 0x9b, 0x7f, 0x78, 0x46, 0xfe, 0xbf, 0xb0, 0xaf, 0x71, 0x3c, 0xee, 0x69, 0x59, 0x57, 0xfe, 0x3e,+ 0xce, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xd3, 0x2a, 0xac, 0xaa, 0xba, 0x8d, 0x3b,+ 0xab, 0x65, 0xe4, 0xd6, 0xf9, 0xc5, 0xe5, 0xba, 0x2e, 0x99, 0x55, 0xe4, 0x23, 0x6b, 0xf9, 0x6a, 0xd6, 0x34, 0xe6, 0xcf,+ 0x81, 0x48, 0xad, 0x96, 0x3b, 0x3f, 0x53, 0x32, 0x35, 0xec, 0xd7, 0xcd, 0xb6, 0xff, 0xbd, 0x7e, 0x43, 0xbe, 0x92, 0xc8,+ 0xaa, 0xf5, 0x05, 0x75, 0xf5, 0x9f, 0x8e, 0x82, 0xd5, 0x8a, 0xd9, 0x35, 0xf4, 0xf7, 0xe6, 0x7f, 0x74, 0xf5, 0xdb, 0xf5,+ 0x9f, 0x55, 0xd4, 0x5b, 0x89, 0xc4, 0xca, 0xbc, 0xca, 0xfc, 0x57, 0x9c, 0xe3, 0x51, 0xf6, 0xbe, 0xb1, 0xb8, 0x4e, 0xc1,+ 0x95, 0x56, 0xe2, 0xd9, 0x6b, 0xa2, 0xe2, 0xd5, 0xf9, 0xaf, 0xad, 0x96, 0x5b, 0xff, 0x9d, 0x90, 0xaf, 0x4f, 0x70, 0x5f,+ 0xfe, 0xff, 0x6e, 0x57, 0x75, 0xfe, 0x33, 0xef, 0x5b, 0x53, 0xd9, 0x6a, 0x2e, 0xff, 0x3d, 0x56, 0xf6, 0xc5, 0xf2, 0x9e,+ 0x47, 0x26, 0xff, 0x63, 0xfd, 0xb6, 0x15, 0xf9, 0xcf, 0x57, 0xe6, 0x39, 0x36, 0x65, 0xfd, 0x28, 0x4e, 0xf9, 0xfa, 0xfc,+ 0xd7, 0x9f, 0x69, 0xf1, 0x9f, 0xff, 0xbb, 0xac, 0xb6, 0x7d, 0x4b, 0xfe, 0x73, 0xd5, 0x69, 0x66, 0xf3, 0x9f, 0xbd, 0xe2,+ 0xbd, 0xbb, 0xfd, 0x5f, 0x73, 0x4d, 0xb0, 0x3e, 0xff, 0x91, 0xaa, 0x0c, 0xde, 0x27, 0xff, 0xb1, 0x20, 0xb9, 0xf2, 0x9f,+ 0x6d, 0x03, 0xdf, 0x90, 0xff, 0xea, 0xe7, 0x7c, 0x74, 0xc8, 0x7f, 0x6e, 0xc4, 0x2b, 0x4a, 0x73, 0x1a, 0xed, 0xdb, 0xff,+ 0x63, 0xdb, 0xf8, 0x5f, 0xff, 0xfc, 0x47, 0x49, 0xbf, 0xf0, 0xce, 0xfc, 0xd7, 0x57, 0xcb, 0xcd, 0x56, 0x0d, 0xbc, 0x3e,+ 0xd6, 0xd7, 0xa7, 0xfd, 0xaf, 0xbf, 0x1e, 0x5e, 0xd1, 0xfe, 0x1f, 0x0b, 0xee, 0x52, 0xac, 0xbf, 0xaa, 0xee, 0x9f, 0xff,+ 0xaa, 0xeb, 0xc2, 0xcc, 0x73, 0x93, 0x46, 0xef, 0xff, 0xc5, 0xe9, 0x59, 0x3c, 0x7a, 0xe7, 0x68, 0x3c, 0x4f, 0x31, 0xf8,+ 0xf4, 0xa2, 0xfe, 0xd7, 0xff, 0x95, 0xed, 0xff, 0x9a, 0x51, 0xef, 0xae, 0xa3, 0xe9, 0xd7, 0x9e, 0x2f, 0xde, 0x63, 0x8b,+ 0xf3, 0x4f, 0xdc, 0x8a, 0xed, 0x57, 0x56, 0x7d, 0x8e, 0xf1, 0xfc, 0x67, 0x5f, 0x93, 0xff, 0x8a, 0x8a, 0xd3, 0xf5, 0xed,+ 0xe1, 0xf7, 0xe6, 0xbc, 0xcc, 0xdc, 0x75, 0xef, 0xb1, 0xb5, 0xd5, 0xe7, 0xc5, 0x3b, 0xf2, 0x5f, 0xf7, 0xd9, 0x63, 0xc9,+ 0xb7, 0x4a, 0xa6, 0x96, 0x77, 0x2c, 0x9f, 0x0f, 0x23, 0xff, 0xcf, 0xcd, 0x7f, 0xdc, 0x70, 0xcf, 0xf0, 0x58, 0x3c, 0x1e,+ 0xdd, 0x61, 0x0f, 0xef, 0xcd, 0x3f, 0xfd, 0xce, 0x88, 0xee, 0xf9, 0x5f, 0x3f, 0x2f, 0xf4, 0xcb, 0xed, 0x81, 0x2a, 0xf9,+ 0x3c, 0xf1, 0x5a, 0x56, 0xfe, 0x73, 0xfd, 0x96, 0xd9, 0xf9, 0xff, 0x20, 0xff, 0xdf, 0xdd, 0xeb, 0xd0, 0x7f, 0x76, 0x03,+ 0xf2, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfb, 0x67, 0xbb, 0x45, 0x6a, 0x7d, 0x5b, 0x0c, 0x56,+ 0x32, 0x88, 0x74, 0xa5, 0xf8, 0x6c, 0x7d, 0x8c, 0x18, 0x5c, 0xf7, 0x35, 0x5f, 0x37, 0xf8, 0xfa, 0xf3, 0x15, 0x66, 0xd6,+ 0x0f, 0xae, 0x3f, 0x8e, 0x75, 0x15, 0xd6, 0xeb, 0x8f, 0x52, 0xe6, 0xef, 0x47, 0x79, 0xed, 0xb5, 0xfe, 0x99, 0x99, 0xdf,+ 0xcf, 0x99, 0x95, 0xbe, 0xb5, 0x67, 0xd4, 0xb5, 0x63, 0x5b, 0xb7, 0xba, 0x33, 0x26, 0x92, 0x3e, 0x3e, 0x4f, 0xfb, 0xf7,+ 0xaa, 0x9f, 0x5d, 0x8f, 0x63, 0x2e, 0x4b, 0x51, 0xba, 0x06, 0x37, 0xf7, 0xd7, 0x9f, 0xb6, 0xaf, 0xaf, 0x57, 0x01, 0xd8,+ 0xdd, 0x5f, 0xc8, 0x3f, 0x35, 0x28, 0x6e, 0x9f, 0x8b, 0xbf, 0xae, 0xa2, 0x4e, 0x5d, 0xad, 0xe2, 0xbb, 0x8f, 0xe3, 0x71,+ 0xfa, 0x0c, 0x93, 0x68, 0xb8, 0xbe, 0xe5, 0xac, 0xff, 0x18, 0x2d, 0xf7, 0x75, 0x5c, 0xee, 0x23, 0xe6, 0xf3, 0x9f, 0x7f,+ 0x3e, 0x53, 0x14, 0x57, 0xe6, 0xcd, 0x57, 0xc7, 0xac, 0xde, 0xfa, 0x7c, 0xfb, 0x9f, 0xb9, 0x52, 0x88, 0xe5, 0x9f, 0xaa,+ 0xf6, 0x3b, 0x39, 0x4e, 0x6a, 0xb9, 0xae, 0x3e, 0x2b, 0x56, 0xbc, 0x12, 0x1b, 0xce, 0xad, 0xdc, 0xf5, 0xde, 0xb5, 0x33,+ 0x64, 0x26, 0xff, 0x7d, 0x8f, 0xcd, 0xd1, 0xe6, 0x95, 0xdd, 0xf9, 0x7f, 0xee, 0x2b, 0xef, 0xc9, 0x7f, 0x9f, 0xb3, 0xef,+ 0xb7, 0xcf, 0x33, 0xfb, 0xac, 0xc2, 0x0e, 0x47, 0xe0, 0xac, 0x4e, 0xec, 0x5b, 0xf3, 0x1f, 0x3f, 0x8e, 0x0c, 0xf6, 0xff,+ 0x4e, 0xfe, 0xb9, 0x5f, 0xf0, 0xb4, 0xfc, 0x57, 0xb6, 0xcb, 0x15, 0x6d, 0xf9, 0xde, 0x6b, 0x66, 0xed, 0xbf, 0xf6, 0xff,+ 0xdb, 0xf9, 0xbf, 0xff, 0x2a, 0x6c, 0x6f, 0x66, 0xfa, 0xed, 0xb3, 0x3e, 0xf9, 0x1f, 0x19, 0xf3, 0x92, 0xff, 0xb7, 0xe7,+ 0xff, 0x09, 0xdf, 0x4d, 0xb3, 0xf7, 0xff, 0xde, 0x31, 0xfe, 0x57, 0xf5, 0x8a, 0xf6, 0x7f, 0x6e, 0x8c, 0xfd, 0xee, 0x6d,+ 0xcb, 0x1f, 0xf3, 0xb7, 0x1c, 0x85, 0xd1, 0x3e, 0x80, 0xfe, 0xbf, 0xfc, 0xbf, 0x27, 0xff, 0x47, 0x7a, 0xf6, 0xc1, 0xb3,+ 0xae, 0x33, 0x46, 0x8e, 0xc7, 0x73, 0xf2, 0x5f, 0x79, 0xc7, 0xee, 0x29, 0xe3, 0x7f, 0x4f, 0xfb, 0x66, 0x78, 0x63, 0xfe,+ 0xef, 0xbd, 0xd7, 0xda, 0x63, 0xe6, 0xef, 0x33, 0xfb, 0x32, 0x4f, 0xce, 0xff, 0xb3, 0xfb, 0x64, 0xc7, 0x6d, 0x57, 0x85,+ 0x51, 0xb8, 0xa7, 0x79, 0x46, 0xfe, 0x63, 0x53, 0xfe, 0x47, 0xc6, 0x06, 0xde, 0x9d, 0xff, 0xf1, 0xd6, 0x2a, 0x6e, 0x1f,+ 0x63, 0x96, 0xff, 0xbb, 0xf3, 0xbf, 0x7f, 0xeb, 0x77, 0xf5, 0xc4, 0x62, 0x49, 0xd2, 0xc7, 0x8f, 0xc9, 0x13, 0xfb, 0xa4,+ 0x3b, 0xb7, 0x4d, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xcc, 0x00, 0x1e, 0x7b, 0xb5,+ 0x43, 0x05, 0xfd, 0x23, 0x5d, 0x6d, 0xbd, 0xee, 0xf3, 0x1e, 0x89, 0xaa, 0xee, 0x99, 0x6d, 0xe8, 0x5c, 0x41, 0xdf, 0xac,+ 0xdb, 0xb7, 0x7e, 0x03, 0xf4, 0xae, 0xa0, 0x7f, 0x5e, 0xe5, 0x63, 0xfd, 0xe7, 0xad, 0x9c, 0x3f, 0xdf, 0xbb, 0x82, 0x7e,+ 0xbf, 0xb5, 0xab, 0xf4, 0xfb, 0x26, 0xd9, 0x59, 0x41, 0x7f, 0xbc, 0xbf, 0x71, 0x6c, 0xdc, 0xae, 0x6c, 0x35, 0x83, 0xae,+ 0x15, 0xf4, 0xbb, 0xaf, 0x05, 0xe3, 0xfe, 0xb5, 0x59, 0x63, 0xcf, 0xb4, 0xa8, 0xaa, 0xa0, 0xf1, 0xb4, 0x0a, 0xfa, 0x67,+ 0x19, 0x7b, 0x52, 0x9d, 0x6c, 0xf9, 0xb7, 0xfe, 0xf7, 0xbe, 0xfc, 0xf7, 0xad, 0x93, 0x91, 0xad, 0x52, 0xd3, 0xbb, 0x82,+ 0xa6, 0xfc, 0xcb, 0xbf, 0xfc, 0xaf, 0xaa, 0x91, 0x20, 0xff, 0x3c, 0x3d, 0xff, 0x3b, 0x2b, 0xe8, 0xa8, 0xa0, 0xb9, 0xbb,+ 0x22, 0xd0, 0x21, 0xff, 0xae, 0xff, 0x1f, 0xf1, 0x04, 0x3d, 0xf9, 0x5f, 0xf3, 0x8a, 0xfc, 0x7f, 0xfd, 0xde, 0x9f, 0x0a,+ 0xda, 0x2b, 0xf3, 0x1f, 0x4d, 0xc7, 0xff, 0xf6, 0xdf, 0xf1, 0xe1, 0x89, 0xf9, 0xd7, 0xff, 0xcf, 0xe7, 0xe2, 0xfe, 0x0a,+ 0x9a, 0xf9, 0x34, 0xcb, 0xbf, 0xfe, 0x7f, 0xc5, 0xfc, 0x9f, 0x9a, 0xb6, 0x47, 0x05, 0xcd, 0xb9, 0x6d, 0x93, 0x7f, 0xd0,+ 0x2b, 0xd4, 0xff, 0x07, 0xbd, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf9, 0xf3, 0x9f, 0xfd, 0x00, 0xf2, 0x0f, 0x7c, 0x2e, 0xff, 0xff, 0x00 };++// Font glyphs rectangles data (on atlas)+static const Rectangle terminalFontRecs[189] = {+ { 4, 4, 4 , 16 },+ { 16, 4, 1 , 11 },+ { 25, 4, 3 , 3 },+ { 36, 4, 6 , 11 },+ { 50, 4, 5 , 11 },+ { 63, 4, 5 , 11 },+ { 76, 4, 5 , 11 },+ { 89, 4, 1 , 2 },+ { 98, 4, 2 , 13 },+ { 108, 4, 2 , 13 },+ { 118, 4, 3 , 3 },+ { 129, 4, 5 , 5 },+ { 142, 4, 1 , 3 },+ { 151, 4, 5 , 1 },+ { 164, 4, 1 , 1 },+ { 173, 4, 6 , 12 },+ { 187, 4, 5 , 11 },+ { 200, 4, 2 , 11 },+ { 210, 4, 5 , 11 },+ { 223, 4, 5 , 11 },+ { 236, 4, 5 , 11 },+ { 249, 4, 5 , 11 },+ { 262, 4, 5 , 11 },+ { 275, 4, 5 , 11 },+ { 288, 4, 5 , 11 },+ { 301, 4, 5 , 11 },+ { 314, 4, 1 , 8 },+ { 323, 4, 1 , 10 },+ { 332, 4, 4 , 5 },+ { 344, 4, 5 , 3 },+ { 357, 4, 4 , 5 },+ { 369, 4, 5 , 11 },+ { 382, 4, 11 , 11 },+ { 401, 4, 5 , 11 },+ { 414, 4, 5 , 11 },+ { 427, 4, 5 , 11 },+ { 440, 4, 5 , 11 },+ { 453, 4, 5 , 11 },+ { 466, 4, 5 , 11 },+ { 479, 4, 5 , 11 },+ { 492, 4, 5 , 11 },+ { 4, 28, 1 , 11 },+ { 13, 28, 5 , 11 },+ { 26, 28, 5 , 11 },+ { 39, 28, 5 , 11 },+ { 52, 28, 7 , 11 },+ { 67, 28, 5 , 11 },+ { 80, 28, 5 , 11 },+ { 93, 28, 5 , 11 },+ { 106, 28, 5 , 13 },+ { 119, 28, 5 , 11 },+ { 132, 28, 5 , 11 },+ { 145, 28, 5 , 11 },+ { 158, 28, 5 , 11 },+ { 171, 28, 5 , 11 },+ { 184, 28, 7 , 11 },+ { 199, 28, 5 , 11 },+ { 212, 28, 5 , 11 },+ { 225, 28, 5 , 11 },+ { 238, 28, 2 , 13 },+ { 248, 28, 6 , 12 },+ { 262, 28, 2 , 13 },+ { 272, 28, 5 , 4 },+ { 285, 28, 5 , 1 },+ { 298, 28, 2 , 2 },+ { 308, 28, 5 , 8 },+ { 321, 28, 5 , 11 },+ { 334, 28, 5 , 8 },+ { 347, 28, 5 , 11 },+ { 360, 28, 5 , 8 },+ { 373, 28, 4 , 11 },+ { 385, 28, 5 , 10 },+ { 398, 28, 5 , 11 },+ { 411, 28, 1 , 11 },+ { 420, 28, 1 , 13 },+ { 429, 28, 5 , 11 },+ { 442, 28, 1 , 11 },+ { 451, 28, 7 , 8 },+ { 466, 28, 5 , 8 },+ { 479, 28, 5 , 8 },+ { 492, 28, 5 , 10 },+ { 4, 52, 5 , 10 },+ { 17, 52, 4 , 8 },+ { 29, 52, 5 , 8 },+ { 42, 52, 3 , 11 },+ { 53, 52, 5 , 8 },+ { 66, 52, 5 , 8 },+ { 79, 52, 7 , 8 },+ { 94, 52, 5 , 8 },+ { 107, 52, 5 , 10 },+ { 120, 52, 5 , 8 },+ { 133, 52, 3 , 13 },+ { 144, 52, 1 , 15 },+ { 153, 52, 3 , 13 },+ { 164, 52, 5 , 3 },+ { 177, 52, 1 , 11 },+ { 186, 52, 5 , 11 },+ { 199, 52, 5 , 10 },+ { 212, 52, 5 , 10 },+ { 225, 52, 5 , 10 },+ { 238, 52, 0 , 0 },+ { 246, 52, 0 , 0 },+ { 254, 52, 0 , 0 },+ { 262, 52, 7 , 8 },+ { 277, 52, 0 , 0 },+ { 285, 52, 0 , 0 },+ { 293, 52, 5 , 3 },+ { 306, 52, 7 , 8 },+ { 321, 52, 5 , 1 },+ { 334, 52, 3 , 3 },+ { 345, 52, 5 , 7 },+ { 358, 52, 0 , 0 },+ { 366, 52, 0 , 0 },+ { 374, 52, 0 , 0 },+ { 382, 52, 5 , 10 },+ { 395, 52, 7 , 11 },+ { 410, 52, 1 , 1 },+ { 419, 52, 0 , 0 },+ { 427, 52, 0 , 0 },+ { 435, 52, 0 , 0 },+ { 443, 52, 0 , 0 },+ { 451, 52, 0 , 0 },+ { 459, 52, 0 , 0 },+ { 467, 52, 5 , 13 },+ { 480, 52, 5 , 11 },+ { 493, 52, 5 , 14 },+ { 4, 76, 5 , 14 },+ { 17, 76, 5 , 14 },+ { 30, 76, 5 , 14 },+ { 43, 76, 5 , 13 },+ { 56, 76, 5 , 13 },+ { 69, 76, 9 , 11 },+ { 86, 76, 5 , 13 },+ { 99, 76, 5 , 14 },+ { 112, 76, 5 , 14 },+ { 125, 76, 5 , 14 },+ { 138, 76, 5 , 13 },+ { 151, 76, 2 , 14 },+ { 161, 76, 2 , 14 },+ { 171, 76, 3 , 14 },+ { 182, 76, 3 , 13 },+ { 193, 76, 5 , 11 },+ { 206, 76, 5 , 14 },+ { 219, 76, 5 , 14 },+ { 232, 76, 5 , 14 },+ { 245, 76, 5 , 14 },+ { 258, 76, 5 , 14 },+ { 271, 76, 5 , 13 },+ { 284, 76, 5 , 5 },+ { 297, 76, 5 , 13 },+ { 310, 76, 5 , 14 },+ { 323, 76, 5 , 14 },+ { 336, 76, 5 , 14 },+ { 349, 76, 5 , 13 },+ { 362, 76, 5 , 14 },+ { 375, 76, 5 , 11 },+ { 388, 76, 5 , 11 },+ { 401, 76, 5 , 11 },+ { 414, 76, 5 , 11 },+ { 427, 76, 5 , 11 },+ { 440, 76, 5 , 11 },+ { 453, 76, 5 , 10 },+ { 466, 76, 5 , 10 },+ { 479, 76, 9 , 8 },+ { 496, 76, 5 , 10 },+ { 4, 100, 5 , 11 },+ { 17, 100, 5 , 11 },+ { 30, 100, 5 , 11 },+ { 43, 100, 5 , 10 },+ { 56, 100, 2 , 11 },+ { 66, 100, 2 , 11 },+ { 76, 100, 3 , 11 },+ { 87, 100, 3 , 10 },+ { 98, 100, 5 , 11 },+ { 111, 100, 5 , 11 },+ { 124, 100, 5 , 11 },+ { 137, 100, 5 , 11 },+ { 150, 100, 5 , 11 },+ { 163, 100, 5 , 11 },+ { 176, 100, 5 , 10 },+ { 189, 100, 5 , 5 },+ { 202, 100, 5 , 10 },+ { 215, 100, 5 , 11 },+ { 228, 100, 5 , 11 },+ { 241, 100, 5 , 11 },+ { 254, 100, 5 , 10 },+ { 267, 100, 5 , 13 },+ { 280, 100, 4 , 8 },+ { 292, 100, 5 , 12 },+};++// Font glyphs info data+// NOTE: No glyphs.image data provided+static const GlyphInfo terminalFontGlyphs[189] = {+ { 32, 0, 14, 4, { 0 }},+ { 33, 1, 3, 3, { 0 }},+ { 34, 1, 3, 5, { 0 }},+ { 35, 1, 3, 8, { 0 }},+ { 36, 1, 3, 7, { 0 }},+ { 37, 1, 3, 7, { 0 }},+ { 38, 1, 3, 7, { 0 }},+ { 39, 1, 3, 3, { 0 }},+ { 40, 1, 2, 4, { 0 }},+ { 41, 1, 2, 4, { 0 }},+ { 42, 1, 3, 5, { 0 }},+ { 43, 1, 7, 7, { 0 }},+ { 44, 1, 13, 3, { 0 }},+ { 45, 1, 9, 7, { 0 }},+ { 46, 1, 13, 3, { 0 }},+ { 47, 1, 2, 8, { 0 }},+ { 48, 1, 3, 7, { 0 }},+ { 49, 1, 3, 4, { 0 }},+ { 50, 1, 3, 7, { 0 }},+ { 51, 1, 3, 7, { 0 }},+ { 52, 1, 3, 7, { 0 }},+ { 53, 1, 3, 7, { 0 }},+ { 54, 1, 3, 7, { 0 }},+ { 55, 1, 3, 7, { 0 }},+ { 56, 1, 3, 7, { 0 }},+ { 57, 1, 3, 7, { 0 }},+ { 58, 1, 6, 3, { 0 }},+ { 59, 1, 6, 3, { 0 }},+ { 60, 1, 7, 6, { 0 }},+ { 61, 1, 8, 7, { 0 }},+ { 62, 1, 7, 6, { 0 }},+ { 63, 1, 3, 7, { 0 }},+ { 64, 2, 3, 15, { 0 }},+ { 65, 1, 3, 7, { 0 }},+ { 66, 1, 3, 7, { 0 }},+ { 67, 1, 3, 7, { 0 }},+ { 68, 1, 3, 7, { 0 }},+ { 69, 1, 3, 7, { 0 }},+ { 70, 1, 3, 7, { 0 }},+ { 71, 1, 3, 7, { 0 }},+ { 72, 1, 3, 7, { 0 }},+ { 73, 1, 3, 3, { 0 }},+ { 74, 1, 3, 7, { 0 }},+ { 75, 1, 3, 7, { 0 }},+ { 76, 1, 3, 7, { 0 }},+ { 77, 1, 3, 9, { 0 }},+ { 78, 1, 3, 7, { 0 }},+ { 79, 1, 3, 7, { 0 }},+ { 80, 1, 3, 7, { 0 }},+ { 81, 1, 3, 7, { 0 }},+ { 82, 1, 3, 7, { 0 }},+ { 83, 1, 3, 7, { 0 }},+ { 84, 1, 3, 7, { 0 }},+ { 85, 1, 3, 7, { 0 }},+ { 86, 1, 3, 7, { 0 }},+ { 87, 1, 3, 9, { 0 }},+ { 88, 1, 3, 7, { 0 }},+ { 89, 1, 3, 7, { 0 }},+ { 90, 1, 3, 7, { 0 }},+ { 91, 1, 2, 4, { 0 }},+ { 92, 1, 2, 8, { 0 }},+ { 93, 1, 2, 4, { 0 }},+ { 94, 1, 3, 7, { 0 }},+ { 95, 1, 15, 7, { 0 }},+ { 96, 1, 0, 4, { 0 }},+ { 97, 1, 6, 7, { 0 }},+ { 98, 1, 3, 7, { 0 }},+ { 99, 1, 6, 7, { 0 }},+ { 100, 1, 3, 7, { 0 }},+ { 101, 1, 6, 7, { 0 }},+ { 102, 1, 3, 6, { 0 }},+ { 103, 1, 6, 7, { 0 }},+ { 104, 1, 3, 7, { 0 }},+ { 105, 1, 3, 3, { 0 }},+ { 106, 1, 3, 3, { 0 }},+ { 107, 1, 3, 7, { 0 }},+ { 108, 1, 3, 3, { 0 }},+ { 109, 1, 6, 9, { 0 }},+ { 110, 1, 6, 7, { 0 }},+ { 111, 1, 6, 7, { 0 }},+ { 112, 1, 6, 7, { 0 }},+ { 113, 1, 6, 7, { 0 }},+ { 114, 1, 6, 6, { 0 }},+ { 115, 1, 6, 7, { 0 }},+ { 116, 1, 3, 5, { 0 }},+ { 117, 1, 6, 7, { 0 }},+ { 118, 1, 6, 7, { 0 }},+ { 119, 1, 6, 9, { 0 }},+ { 120, 1, 6, 7, { 0 }},+ { 121, 1, 6, 7, { 0 }},+ { 122, 1, 6, 7, { 0 }},+ { 123, 1, 2, 5, { 0 }},+ { 124, 1, 1, 3, { 0 }},+ { 125, 1, 2, 5, { 0 }},+ { 126, 1, 8, 7, { 0 }},+ { 161, 1, 3, 3, { 0 }},+ { 162, 1, 3, 7, { 0 }},+ { 163, 1, 3, 7, { 0 }},+ { 8364, 1, 3, 7, { 0 }},+ { 165, 1, 3, 7, { 0 }},+ { 352, 0, 14, 4, { 0 }},+ { 167, 0, 14, 4, { 0 }},+ { 353, 0, 14, 4, { 0 }},+ { 169, 1, 3, 9, { 0 }},+ { 170, 0, 14, 4, { 0 }},+ { 171, 0, 14, 4, { 0 }},+ { 172, 1, 8, 7, { 0 }},+ { 174, 1, 3, 9, { 0 }},+ { 175, 1, 1, 7, { 0 }},+ { 176, 1, 0, 5, { 0 }},+ { 177, 1, 7, 7, { 0 }},+ { 178, 0, 14, 4, { 0 }},+ { 179, 0, 14, 4, { 0 }},+ { 381, 0, 14, 4, { 0 }},+ { 181, 1, 6, 7, { 0 }},+ { 182, 1, 3, 9, { 0 }},+ { 183, 1, 8, 3, { 0 }},+ { 382, 0, 14, 4, { 0 }},+ { 185, 0, 14, 4, { 0 }},+ { 186, 0, 14, 4, { 0 }},+ { 187, 0, 14, 4, { 0 }},+ { 338, 0, 14, 4, { 0 }},+ { 339, 0, 14, 4, { 0 }},+ { 376, 1, 1, 7, { 0 }},+ { 191, 1, 3, 7, { 0 }},+ { 192, 1, 0, 7, { 0 }},+ { 193, 1, 0, 7, { 0 }},+ { 194, 1, 0, 7, { 0 }},+ { 195, 1, 0, 7, { 0 }},+ { 196, 1, 1, 7, { 0 }},+ { 197, 1, 1, 7, { 0 }},+ { 198, 1, 3, 11, { 0 }},+ { 199, 1, 3, 7, { 0 }},+ { 200, 1, 0, 7, { 0 }},+ { 201, 1, 0, 7, { 0 }},+ { 202, 1, 0, 7, { 0 }},+ { 203, 1, 1, 7, { 0 }},+ { 204, 0, 0, 3, { 0 }},+ { 205, 1, 0, 3, { 0 }},+ { 206, 0, 0, 3, { 0 }},+ { 207, 0, 1, 3, { 0 }},+ { 208, 1, 3, 7, { 0 }},+ { 209, 1, 0, 7, { 0 }},+ { 210, 1, 0, 7, { 0 }},+ { 211, 1, 0, 7, { 0 }},+ { 212, 1, 0, 7, { 0 }},+ { 213, 1, 0, 7, { 0 }},+ { 214, 1, 1, 7, { 0 }},+ { 215, 1, 7, 7, { 0 }},+ { 216, 1, 2, 7, { 0 }},+ { 217, 1, 0, 7, { 0 }},+ { 218, 1, 0, 7, { 0 }},+ { 219, 1, 0, 7, { 0 }},+ { 220, 1, 1, 7, { 0 }},+ { 221, 1, 0, 7, { 0 }},+ { 222, 1, 3, 7, { 0 }},+ { 223, 1, 3, 7, { 0 }},+ { 224, 1, 3, 7, { 0 }},+ { 225, 1, 3, 7, { 0 }},+ { 226, 1, 3, 7, { 0 }},+ { 227, 1, 3, 7, { 0 }},+ { 228, 1, 4, 7, { 0 }},+ { 229, 1, 4, 7, { 0 }},+ { 230, 1, 6, 11, { 0 }},+ { 231, 1, 6, 7, { 0 }},+ { 232, 1, 3, 7, { 0 }},+ { 233, 1, 3, 7, { 0 }},+ { 234, 1, 3, 7, { 0 }},+ { 235, 1, 4, 7, { 0 }},+ { 236, 0, 3, 3, { 0 }},+ { 237, 1, 3, 3, { 0 }},+ { 238, 0, 3, 3, { 0 }},+ { 239, 0, 4, 3, { 0 }},+ { 240, 1, 3, 7, { 0 }},+ { 241, 1, 3, 7, { 0 }},+ { 242, 1, 3, 7, { 0 }},+ { 243, 1, 3, 7, { 0 }},+ { 244, 1, 3, 7, { 0 }},+ { 245, 1, 3, 7, { 0 }},+ { 246, 1, 4, 7, { 0 }},+ { 247, 1, 7, 7, { 0 }},+ { 248, 1, 5, 7, { 0 }},+ { 249, 1, 3, 7, { 0 }},+ { 250, 1, 3, 7, { 0 }},+ { 251, 1, 3, 7, { 0 }},+ { 252, 1, 4, 7, { 0 }},+ { 253, 1, 3, 7, { 0 }},+ { 254, 1, 6, 6, { 0 }},+ { 255, 1, 4, 7, { 0 }},+};++// Style loading function: Terminal+static void GuiLoadStyleTerminal(void)+{+ // Load style properties provided+ // NOTE: Default properties are propagated+ for (int i = 0; i < TERMINAL_STYLE_PROPS_COUNT; i++)+ {+ GuiSetStyle(terminalStyleProps[i].controlId, terminalStyleProps[i].propertyId, terminalStyleProps[i].propertyValue);+ }++ // Custom font loading+ // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function+ int terminalFontDataSize = 0;+ unsigned char *data = DecompressData(terminalFontData, TERMINAL_STYLE_FONT_ATLAS_COMP_SIZE, &terminalFontDataSize);+ Image imFont = { data, 512, 256, 1, 2 };++ Font font = { 0 };+ font.baseSize = 16;+ font.glyphCount = 189;++ // Load texture from image+ font.texture = LoadTextureFromImage(imFont);+ UnloadImage(imFont); // Uncompressed image data can be unloaded from memory++ // Copy char recs data from global fontRecs+ // NOTE: Required to avoid issues if trying to free font+ font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));+ memcpy(font.recs, terminalFontRecs, font.glyphCount*sizeof(Rectangle));++ // Copy font char info data from global fontChars+ // NOTE: Required to avoid issues if trying to free font+ font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));+ memcpy(font.glyphs, terminalFontGlyphs, font.glyphCount*sizeof(GlyphInfo));++ GuiSetFont(font);++ // Setup a white rectangle on the font to be used on shapes drawing,+ // it makes possible to draw shapes and text (full UI) in a single draw call+ Rectangle fontWhiteRec = { 510, 254, 1, 1 };+ SetShapesTexture(font.texture, fontWhiteRec);++ //-----------------------------------------------------------------++ // TODO: Custom user style setup: Set specific properties here (if required)+ // i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT+}
raylib/examples/audio/audio_mixed_processor.c view
@@ -97,7 +97,7 @@ DrawRectangle(199, 199, 402, 34, LIGHTGRAY); for (int i = 0; i < 400; i++) {- DrawLine(201 + i, 232 - averageVolume[i] * 32, 201 + i, 232, MAROON);+ DrawLine(201 + i, 232 - (int)averageVolume[i] * 32, 201 + i, 232, MAROON); } DrawRectangleLines(199, 199, 402, 34, GRAY);
raylib/examples/core/core_2d_camera_mouse_zoom.c view
@@ -31,6 +31,8 @@ Camera2D camera = { 0 }; camera.zoom = 1.0f; + int zoomMode = 0; // 0-Mouse Wheel, 1-Mouse Move+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -39,42 +41,69 @@ { // Update //----------------------------------------------------------------------------------+ if (IsKeyPressed(KEY_ONE)) zoomMode = 0;+ else if (IsKeyPressed(KEY_TWO)) zoomMode = 1;+ // Translate based on mouse right click if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) { Vector2 delta = GetMouseDelta(); delta = Vector2Scale(delta, -1.0f/camera.zoom);- camera.target = Vector2Add(camera.target, delta); } - // Zoom based on mouse wheel- float wheel = GetMouseWheelMove();- if (wheel != 0)+ if (zoomMode == 0) {- // Get the world point that is under the mouse- Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);- - // Set the offset to where the mouse is- camera.offset = GetMousePosition();+ // Zoom based on mouse wheel+ float wheel = GetMouseWheelMove();+ if (wheel != 0)+ {+ // Get the world point that is under the mouse+ Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); - // Set the target to match, so that the camera maps the world space point - // under the cursor to the screen space point under the cursor at any zoom- camera.target = mouseWorldPos;+ // Set the offset to where the mouse is+ camera.offset = GetMousePosition(); - // Zoom increment- const float zoomIncrement = 0.125f;+ // Set the target to match, so that the camera maps the world space point + // under the cursor to the screen space point under the cursor at any zoom+ camera.target = mouseWorldPos; - camera.zoom += (wheel*zoomIncrement);- if (camera.zoom < zoomIncrement) camera.zoom = zoomIncrement;+ // Zoom increment+ float scaleFactor = 1.0f + (0.25f*fabsf(wheel));+ if (wheel < 0) scaleFactor = 1.0f/scaleFactor;+ camera.zoom = Clamp(camera.zoom*scaleFactor, 0.125f, 64.0f);+ } }+ else+ {+ // Zoom based on mouse left click+ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))+ {+ // Get the world point that is under the mouse+ Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); + // Set the offset to where the mouse is+ camera.offset = GetMousePosition();++ // Set the target to match, so that the camera maps the world space point + // under the cursor to the screen space point under the cursor at any zoom+ camera.target = mouseWorldPos;+ }+ if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))+ {+ // Zoom increment+ float deltaX = GetMouseDelta().x;+ float scaleFactor = 1.0f + (0.01f*fabsf(deltaX));+ if (deltaX < 0) scaleFactor = 1.0f/scaleFactor;+ camera.zoom = Clamp(camera.zoom*scaleFactor, 0.125f, 64.0f);+ }+ } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing();- ClearBackground(BLACK);+ ClearBackground(RAYWHITE); BeginMode2D(camera); @@ -87,11 +116,13 @@ rlPopMatrix(); // Draw a reference circle- DrawCircle(100, 100, 50, YELLOW);+ DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON); EndMode2D(); - DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, WHITE);+ DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, DARKGRAY);+ if (zoomMode == 0) DrawText("Mouse right button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY);+ else DrawText("Mouse right button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY); EndDrawing(); //----------------------------------------------------------------------------------
raylib/examples/core/core_2d_camera_platformer.c view
@@ -133,10 +133,10 @@ for (int i = 0; i < envItemsLength; i++) DrawRectangleRec(envItems[i].rect, envItems[i].color); - Rectangle playerRect = { player.position.x - 20, player.position.y - 40, 40, 40 };+ Rectangle playerRect = { player.position.x - 20, player.position.y - 40, 40.0f, 40.0f }; DrawRectangleRec(playerRect, RED); - DrawCircle(player.position.x, player.position.y, 5, GOLD);+ DrawCircleV(player.position, 5.0f, GOLD); EndMode2D();
raylib/examples/core/core_custom_frame_control.c view
@@ -2,7 +2,7 @@ * * raylib [core] example - custom frame control *-* NOTE: WARNING: This is an example for advance users willing to have full control over+* NOTE: WARNING: This is an example for advanced users willing to have full control over * the frame processes. By default, EndDrawing() calls the following processes: * 1. Draw remaining batch data: rlDrawRenderBatchActive() * 2. SwapScreenBuffer()
raylib/examples/core/core_input_gamepad.c view
@@ -22,7 +22,7 @@ // NOTE: Gamepad name ID depends on drivers and OS #define XBOX360_LEGACY_NAME_ID "Xbox Controller" #define XBOX360_NAME_ID "Xbox 360 Controller"-#define PS3_NAME_ID "PLAYSTATION(R)3 Controller"+#define PS3_NAME_ID "Sony PLAYSTATION(R)3 Controller" //------------------------------------------------------------------------------------ // Program main entry point@@ -67,7 +67,7 @@ { DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK); - if (true)+ if (TextIsEqual(GetGamepadName(gamepad), XBOX360_LEGACY_NAME_ID) || TextIsEqual(GetGamepadName(gamepad), XBOX360_NAME_ID)) { DrawTexture(texXboxPad, 0, 0, DARKGRAY);
raylib/examples/core/core_input_mouse_wheel.c view
@@ -36,7 +36,7 @@ { // Update //----------------------------------------------------------------------------------- boxPositionY -= (GetMouseWheelMove()*scrollSpeed);+ boxPositionY -= (int)(GetMouseWheelMove()*scrollSpeed); //---------------------------------------------------------------------------------- // Draw
raylib/examples/core/core_random_sequence.c view
@@ -41,7 +41,7 @@ int rectCount = 20; float rectSize = (float)screenWidth/rectCount;- ColorRect* rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);+ ColorRect* rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); SetTargetFPS(60); //--------------------------------------------------------------------------------------@@ -62,7 +62,7 @@ rectCount++; rectSize = (float)screenWidth/rectCount; free(rectangles);- rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);+ rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); } if(IsKeyPressed(KEY_DOWN))@@ -71,7 +71,7 @@ rectCount--; rectSize = (float)screenWidth/rectCount; free(rectangles);- rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);+ rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f * screenHeight); } } @@ -121,17 +121,17 @@ } static ColorRect* GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight){- int *seq = LoadRandomSequence(rectCount, 0, rectCount-1);- ColorRect* rectangles = (ColorRect *)malloc(rectCount*sizeof(ColorRect));+ int *seq = LoadRandomSequence((unsigned int)rectCount, 0, (unsigned int)rectCount-1);+ ColorRect* rectangles = (ColorRect *)malloc((int)rectCount*sizeof(ColorRect)); float rectSeqWidth = rectCount * rectWidth;- int startX = (screenWidth - rectSeqWidth) * 0.5f;+ float startX = (screenWidth - rectSeqWidth) * 0.5f; for(int x=0;x<rectCount;x++){- int rectHeight = Remap(seq[x], 0, rectCount-1, 0, screenHeight);+ int rectHeight = (int)Remap((float)seq[x], 0, rectCount-1, 0, screenHeight); rectangles[x].c = GenerateRandomColor(); rectangles[x].r = CLITERAL(Rectangle){- startX + x * rectWidth, screenHeight - rectHeight, rectWidth, rectHeight+ startX + x * rectWidth, screenHeight - rectHeight, rectWidth, (float)rectHeight }; } UnloadRandomSequence(seq);
raylib/examples/core/core_smooth_pixelperfect.c view
@@ -69,18 +69,18 @@ rotation += 60.0f*GetFrameTime(); // Rotate the rectangles, 60 degrees per second // Make the camera move to demonstrate the effect- cameraX = (sinf(GetTime())*50.0f) - 10.0f;- cameraY = cosf(GetTime())*30.0f;+ cameraX = (sinf((float)GetTime())*50.0f) - 10.0f;+ cameraY = cosf((float)GetTime())*30.0f; // Set the camera's target to the values computed above screenSpaceCamera.target = (Vector2){ cameraX, cameraY }; // Round worldSpace coordinates, keep decimals into screenSpace coordinates- worldSpaceCamera.target.x = (int)screenSpaceCamera.target.x;+ worldSpaceCamera.target.x = truncf(screenSpaceCamera.target.x); screenSpaceCamera.target.x -= worldSpaceCamera.target.x; screenSpaceCamera.target.x *= virtualRatio; - worldSpaceCamera.target.y = (int)screenSpaceCamera.target.y;+ worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y); screenSpaceCamera.target.y -= worldSpaceCamera.target.y; screenSpaceCamera.target.y *= virtualRatio; //----------------------------------------------------------------------------------
raylib/examples/core/core_storage_values.c view
@@ -177,7 +177,7 @@ if (fileData != NULL) {- if (dataSize < (position*4)) TraceLog(LOG_WARNING, "FILEIO: [%s] Failed to find storage position: %i", STORAGE_DATA_FILE, position);+ if (dataSize < ((int)(position*4))) TraceLog(LOG_WARNING, "FILEIO: [%s] Failed to find storage position: %i", STORAGE_DATA_FILE, position); else { int *dataPtr = (int *)fileData;
raylib/examples/models/models_billboard.c view
@@ -44,10 +44,12 @@ // NOTE: Billboard locked on axis-Y Vector3 billUp = { 0.0f, 1.0f, 0.0f }; + // Set the height of the rotating billboard to 1.0 with the aspect ratio fixed+ Vector2 size = { source.width/source.height, 1.0f };+ // Rotate around origin // Here we choose to rotate around the image center- // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture- Vector2 rotateOrigin = { 0.0f };+ Vector2 origin = Vector2Scale(size, 0.5f); // Distance is needed for the correct billboard draw order // Larger distance (further away from the camera) should be drawn prior to smaller distance.@@ -84,11 +86,11 @@ if (distanceStatic > distanceRotating) { DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE);- DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE);+ DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); } else {- DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE);+ DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE); }
raylib/examples/models/models_cubicmap.c view
@@ -47,6 +47,8 @@ UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM + bool pause = false; // Pause camera orbital rotation (and zoom)+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -55,7 +57,9 @@ { // Update //----------------------------------------------------------------------------------- UpdateCamera(&camera, CAMERA_ORBITAL);+ if (IsKeyPressed(KEY_P)) pause = !pause;++ if (!pause) UpdateCamera(&camera, CAMERA_ORBITAL); //---------------------------------------------------------------------------------- // Draw
raylib/examples/models/models_draw_cube_texture.c view
@@ -67,7 +67,7 @@ DrawCubeTexture(texture, (Vector3){ -2.0f, 2.0f, 0.0f }, 2.0f, 4.0f, 2.0f, WHITE); // Draw cube with an applied texture, but only a defined rectangle piece of the texture- DrawCubeTextureRec(texture, (Rectangle){ 0, texture.height/2, texture.width/2, texture.height/2 }, + DrawCubeTextureRec(texture, (Rectangle){ 0.0f, texture.height/2.0f, texture.width/2.0f, texture.height/2.0f }, (Vector3){ 2.0f, 1.0f, 0.0f }, 2.0f, 2.0f, 2.0f, WHITE); DrawGrid(10, 1.0f); // Draw a grid
raylib/examples/models/models_loading_gltf.c view
@@ -30,11 +30,11 @@ const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf");+ InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf animations"); // Define the camera to look into our 3d world Camera camera = { 0 };- camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position+ camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y@@ -42,17 +42,14 @@ // Load gltf model Model model = LoadModel("resources/models/gltf/robot.glb");-+ Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position+ // Load gltf model animations int animsCount = 0; unsigned int animIndex = 0; unsigned int animCurrentFrame = 0; ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/robot.glb", &animsCount); - Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position-- DisableCursor(); // Limit cursor to relative movement inside the window- SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -61,7 +58,8 @@ { // Update //----------------------------------------------------------------------------------- UpdateCamera(&camera, CAMERA_THIRD_PERSON);+ UpdateCamera(&camera, CAMERA_ORBITAL);+ // Select current animation if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) animIndex = (animIndex + 1)%animsCount; else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) animIndex = (animIndex + animsCount - 1)%animsCount;@@ -79,10 +77,8 @@ ClearBackground(RAYWHITE); BeginMode3D(camera);- DrawModel(model, position, 1.0f, WHITE); // Draw animated model DrawGrid(10, 1.0f);- EndMode3D(); DrawText("Use the LEFT/RIGHT mouse buttons to switch animation", 10, 10, 20, GRAY);@@ -101,3 +97,6 @@ return 0; }+++
raylib/examples/models/models_skybox.c view
@@ -49,7 +49,8 @@ Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Model skybox = LoadModelFromMesh(cube); - bool useHDR = true;+ // Set this to true to use an HDR Texture, Note that raylib must be built with HDR Support for this to work SUPPORT_FILEFORMAT_HDR+ bool useHDR = false; // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading@@ -157,8 +158,6 @@ DrawGrid(10, 1.0f); EndMode3D();- - //DrawTextureEx(panorama, (Vector2){ 0, 0 }, 0.0f, 0.5f, WHITE); if (useHDR) DrawText(TextFormat("Panorama image from hdrihaven.com: %s", GetFileName(skyboxFileName)), 10, GetScreenHeight() - 20, 10, BLACK); else DrawText(TextFormat(": %s", GetFileName(skyboxFileName)), 10, GetScreenHeight() - 20, 10, BLACK);@@ -208,7 +207,7 @@ rlEnableShader(shader.id); // Define projection matrix and send it to shader- Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, rlGetCullDistanceNear(), rlGetCullDistanceFar()); rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); // Define view matrix for every side of the cubemap
raylib/examples/models/models_waving_cubes.c view
@@ -89,6 +89,8 @@ }; // Pick a color with a hue depending on cube position for the rainbow color effect+ // NOTE: This function is quite costly to be done per cube and frame, + // pre-catching the results into a separate array could improve performance Color cubeColor = ColorFromHSV((float)(((x + y + z)*18)%360), 0.75f, 0.9f); // Calculate cube size
raylib/examples/shaders/shaders_basic_lighting.c view
@@ -52,10 +52,6 @@ camera.fovy = 45.0f; // Camera field-of-view Y camera.projection = CAMERA_PERSPECTIVE; // Camera projection type - // Load plane model from a generated mesh- Model model = LoadModelFromMesh(GenMeshPlane(10.0f, 10.0f, 3, 3));- Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 4.0f, 2.0f));- // Load basic lighting shader Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/lighting.vs", GLSL_VERSION), TextFormat("resources/shaders/glsl%i/lighting.fs", GLSL_VERSION));@@ -69,10 +65,6 @@ int ambientLoc = GetShaderLocation(shader, "ambient"); SetShaderValue(shader, ambientLoc, (float[4]){ 0.1f, 0.1f, 0.1f, 1.0f }, SHADER_UNIFORM_VEC4); - // Assign out lighting shader to model- model.materials[0].shader = shader;- cube.materials[0].shader = shader;- // Create lights Light lights[MAX_LIGHTS] = { 0 }; lights[0] = CreateLight(LIGHT_POINT, (Vector3){ -2, 1, -2 }, Vector3Zero(), YELLOW, shader);@@ -112,9 +104,13 @@ BeginMode3D(camera); - DrawModel(model, Vector3Zero(), 1.0f, WHITE);- DrawModel(cube, Vector3Zero(), 1.0f, WHITE);+ BeginShaderMode(shader); + DrawPlane(Vector3Zero(), (Vector2) { 10.0, 10.0 }, WHITE);+ DrawCube(Vector3Zero(), 2.0, 4.0, 2.0, WHITE);++ EndShaderMode();+ // Draw spheres to show where the lights are for (int i = 0; i < MAX_LIGHTS; i++) {@@ -136,8 +132,6 @@ // De-Initialization //--------------------------------------------------------------------------------------- UnloadModel(model); // Unload the model- UnloadModel(cube); // Unload the model UnloadShader(shader); // Unload shader CloseWindow(); // Close window and OpenGL context
raylib/examples/shaders/shaders_deferred_render.c view
@@ -281,7 +281,7 @@ .id = gBuffer.positionTexture, .width = screenWidth, .height = screenHeight,- }, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);+ }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); DrawText("POSITION TEXTURE", 10, screenHeight - 30, 20, DARKGREEN); } break;@@ -291,7 +291,7 @@ .id = gBuffer.normalTexture, .width = screenWidth, .height = screenHeight,- }, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);+ }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); DrawText("NORMAL TEXTURE", 10, screenHeight - 30, 20, DARKGREEN); } break;@@ -301,7 +301,7 @@ .id = gBuffer.albedoSpecTexture, .width = screenWidth, .height = screenHeight,- }, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);+ }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); DrawText("ALBEDO TEXTURE", 10, screenHeight - 30, 20, DARKGREEN); } break;
raylib/examples/shaders/shaders_palette_switch.c view
@@ -109,7 +109,7 @@ if (currentPalette >= MAX_PALETTES) currentPalette = 0; else if (currentPalette < 0) currentPalette = MAX_PALETTES - 1; - // Send new value to the shader to be used on drawing. + // Send palette data to the shader to be used on drawing // NOTE: We are sending RGB triplets w/o the alpha channel SetShaderValueV(shader, paletteLoc, palettes[currentPalette], SHADER_UNIFORM_IVEC3, COLORS_PER_PALETTE); //----------------------------------------------------------------------------------
raylib/examples/shapes/shapes_draw_rectangle_rounded.c view
@@ -62,7 +62,7 @@ if (drawRect) DrawRectangleRec(rec, Fade(GOLD, 0.6f)); if (drawRoundedRect) DrawRectangleRounded(rec, roundness, (int)segments, Fade(MAROON, 0.2f));- if (drawRoundedLines) DrawRectangleRoundedLines(rec, roundness, (int)segments, lineThick, Fade(MAROON, 0.4f));+ if (drawRoundedLines) DrawRectangleRoundedLinesEx(rec, roundness, (int)segments, lineThick, Fade(MAROON, 0.4f)); // Draw GUI controls //------------------------------------------------------------------------------
raylib/examples/shapes/shapes_lines_bezier.c view
@@ -69,8 +69,8 @@ DrawLineBezier(startPoint, endPoint, 4.0f, BLUE); // Draw start-end spline circles with some details- DrawCircleV(startPoint, CheckCollisionPointCircle(mouse, startPoint, 10.0f)? 14 : 8, moveStartPoint? RED : BLUE);- DrawCircleV(endPoint, CheckCollisionPointCircle(mouse, endPoint, 10.0f)? 14 : 8, moveEndPoint? RED : BLUE);+ DrawCircleV(startPoint, CheckCollisionPointCircle(mouse, startPoint, 10.0f)? 14.0f : 8.0f, moveStartPoint? RED : BLUE);+ DrawCircleV(endPoint, CheckCollisionPointCircle(mouse, endPoint, 10.0f)? 14.0f : 8.0f, moveEndPoint? RED : BLUE); EndDrawing(); //----------------------------------------------------------------------------------
raylib/examples/shapes/shapes_splines_drawing.c view
@@ -56,6 +56,10 @@ { 710.0f, 260.0f }, }; + // Array required for spline bezier-cubic, + // including control points interleaved with start-end segment points+ Vector2 pointsInterleaved[3*(MAX_SPLINE_POINTS - 1) + 1] = { 0 };+ int pointCount = 5; int selectedPoint = -1; int focusedPoint = -1;@@ -63,7 +67,7 @@ Vector2 *focusedControlPoint = NULL; // Cubic Bezier control points initialization- ControlPoint control[MAX_SPLINE_POINTS] = { 0 };+ ControlPoint control[MAX_SPLINE_POINTS-1] = { 0 }; for (int i = 0; i < pointCount - 1; i++) { control[i].start = (Vector2){ points[i].x + 50, points[i].y };@@ -88,6 +92,9 @@ if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && (pointCount < MAX_SPLINE_POINTS)) { points[pointCount] = GetMousePosition();+ int i = pointCount - 1;+ control[i].start = (Vector2){ points[i].x + 50, points[i].y };+ control[i].end = (Vector2){ points[i + 1].x - 50, points[i + 1].y }; pointCount++; } @@ -114,7 +121,7 @@ if ((splineTypeActive == SPLINE_BEZIER) && (focusedPoint == -1)) { // Spline control point focus and selection logic- for (int i = 0; i < pointCount; i++)+ for (int i = 0; i < pointCount - 1; i++) { if (CheckCollisionPointCircle(GetMousePosition(), control[i].start, 6.0f)) {@@ -185,13 +192,32 @@ } else if (splineTypeActive == SPLINE_BEZIER) {+ // NOTE: Cubic-bezier spline requires the 2 control points of each segnment to be + // provided interleaved with the start and end point of every segment+ for (int i = 0; i < (pointCount - 1); i++) + {+ pointsInterleaved[3*i] = points[i];+ pointsInterleaved[3*i + 1] = control[i].start;+ pointsInterleaved[3*i + 2] = control[i].end;+ }+ + pointsInterleaved[3*(pointCount - 1)] = points[pointCount - 1];+ // Draw spline: cubic-bezier (with control points)- for (int i = 0; i < pointCount - 1; i++)+ DrawSplineBezierCubic(pointsInterleaved, 3*(pointCount - 1) + 1, splineThickness, RED);+ + /*+ for (int i = 0; i < 3*(pointCount - 1); i += 3) { // Drawing individual segments, not considering thickness connection compensation- DrawSplineSegmentBezierCubic(points[i], control[i].start, control[i].end, points[i + 1], splineThickness, RED);+ DrawSplineSegmentBezierCubic(pointsInterleaved[i], pointsInterleaved[i + 1], pointsInterleaved[i + 2], pointsInterleaved[i + 3], splineThickness, MAROON);+ }+ */ - // Every cubic bezier point should have two control points+ // Draw spline control points+ for (int i = 0; i < pointCount - 1; i++)+ {+ // Every cubic bezier point have two control points DrawCircleV(control[i].start, 6, GOLD); DrawCircleV(control[i].end, 6, GOLD); if (focusedControlPoint == &control[i].start) DrawCircleV(control[i].start, 8, GREEN);@@ -216,7 +242,7 @@ (splineTypeActive != SPLINE_BEZIER) && (i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY); - DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), points[i].x, points[i].y + 10, 10, BLACK);+ DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), (int)points[i].x, (int)points[i].y + 10, 10, BLACK); } }
raylib/examples/text/text_codepoints_loading.c view
@@ -52,7 +52,7 @@ // Set bilinear scale filter for better font scaling SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); - SetTextLineSpacing(54); // Set line spacing for multiline text (when line breaks are included '\n')+ SetTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n') // Free codepoints, atlas has already been generated free(codepointsNoDups);
raylib/examples/text/text_font_loading.c view
@@ -47,7 +47,7 @@ // NOTE: We define a font base size of 32 pixels tall and up-to 250 characters Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250); - SetTextLineSpacing(48); // Set line spacing for multiline text (when line breaks are included '\n')+ SetTextLineSpacing(16); // Set line spacing for multiline text (when line breaks are included '\n') bool useTtf = false;
+ raylib/examples/textures/textures_image_channel.c view
@@ -0,0 +1,106 @@+/*******************************************************************************************+*+* raylib [textures] example - Retrive image channel (mask)+*+* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)+*+* Example originally created with raylib 5.1-dev, last time updated with raylib 5.1-dev+*+* Example contributed by Bruno Cabral (github.com/brccabral) and reviewed by Ramon Santamaria (@raysan5)+*+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,+* BSD-like license that allows static linking with closed source software+*+* Copyright (c) 2024-2024 Bruno Cabral (github.com/brccabral) and Ramon Santamaria (@raysan5)+*+********************************************************************************************/++#include <raylib.h>++//------------------------------------------------------------------------------------+// Program main entry point+//------------------------------------------------------------------------------------+int main(void)+{+ // Initialization+ //--------------------------------------------------------------------------------------++ const int screenWidth = 800;+ const int screenHeight = 450;++ InitWindow(screenWidth, screenHeight, "raylib [textures] example - extract channel from image");++ Image fudesumiImage = LoadImage("resources/fudesumi.png");++ Image imageAlpha = ImageFromChannel(fudesumiImage, 3);+ ImageAlphaMask(&imageAlpha, imageAlpha);++ Image imageRed = ImageFromChannel(fudesumiImage, 0);+ ImageAlphaMask(&imageRed, imageAlpha);++ Image imageGreen = ImageFromChannel(fudesumiImage, 1);+ ImageAlphaMask(&imageGreen, imageAlpha);++ Image imageBlue = ImageFromChannel(fudesumiImage, 2);+ ImageAlphaMask(&imageBlue, imageAlpha);++ Image backgroundImage = GenImageChecked(screenWidth, screenHeight, screenWidth/20, screenHeight/20, ORANGE, YELLOW);++ Texture2D fudesumiTexture = LoadTextureFromImage(fudesumiImage);+ Texture2D textureAlpha = LoadTextureFromImage(imageAlpha);+ Texture2D textureRed = LoadTextureFromImage(imageRed);+ Texture2D textureGreen = LoadTextureFromImage(imageGreen);+ Texture2D textureBlue = LoadTextureFromImage(imageBlue);+ Texture2D backgroundTexture = LoadTextureFromImage(backgroundImage);++ UnloadImage(fudesumiImage);+ UnloadImage(imageAlpha);+ UnloadImage(imageRed);+ UnloadImage(imageGreen);+ UnloadImage(imageBlue);+ UnloadImage(backgroundImage);++ SetTargetFPS(60); // Set our game to run at 60 frames-per-second++ Rectangle fudesumiRec = {0, 0, fudesumiImage.width, fudesumiImage.height};++ Rectangle fudesumiPos = {50, 10, fudesumiImage.width*0.8f, fudesumiImage.height*0.8f};+ Rectangle redPos = { 410, 10, fudesumiPos.width / 2, fudesumiPos.height / 2 };+ Rectangle greenPos = { 600, 10, fudesumiPos.width / 2, fudesumiPos.height / 2 };+ Rectangle bluePos = { 410, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 };+ Rectangle alphaPos = { 600, 230, fudesumiPos.width / 2, fudesumiPos.height / 2 };++ //--------------------------------------------------------------------------------------++ // Main game loop+ while (!WindowShouldClose()) // Detect window close button or ESC key+ {+ // Draw+ //----------------------------------------------------------------------------------+ BeginDrawing();++ DrawTexture(backgroundTexture, 0, 0, WHITE);+ DrawTexturePro(fudesumiTexture, fudesumiRec, fudesumiPos, (Vector2) {0, 0}, 0, WHITE);++ DrawTexturePro(textureRed, fudesumiRec, redPos, (Vector2) {0, 0}, 0, RED);+ DrawTexturePro(textureGreen, fudesumiRec, greenPos, (Vector2) {0, 0}, 0, GREEN);+ DrawTexturePro(textureBlue, fudesumiRec, bluePos, (Vector2) {0, 0}, 0, BLUE);+ DrawTexturePro(textureAlpha, fudesumiRec, alphaPos, (Vector2) {0, 0}, 0, WHITE);++ EndDrawing();+ //----------------------------------------------------------------------------------+ }++ // De-Initialization+ //--------------------------------------------------------------------------------------+ UnloadTexture(backgroundTexture);+ UnloadTexture(fudesumiTexture);+ UnloadTexture(textureRed);+ UnloadTexture(textureGreen);+ UnloadTexture(textureBlue);+ UnloadTexture(textureAlpha);+ CloseWindow(); // Close window and OpenGL context+ //--------------------------------------------------------------------------------------++ return 0;+}
raylib/parser/raylib_parser.c view
@@ -202,9 +202,12 @@ { if (argc > 1) ProcessCommandLine(argc, argv); - if (inFileName[0] == '\0') MemoryCopy(inFileName, "../src/raylib.h\0", 16);- if (outFileName[0] == '\0') MemoryCopy(outFileName, "raylib_api.txt\0", 15);- if (apiDefine[0] == '\0') MemoryCopy(apiDefine, "RLAPI\0", 6);+ const char *raylibhPath = "../src/raylib.h\0";+ const char *raylibapiPath = "raylib_api.txt\0";+ const char *rlapiPath = "RLAPI\0";+ if (inFileName[0] == '\0') MemoryCopy(inFileName, raylibhPath, TextLength(raylibhPath) + 1);+ if (outFileName[0] == '\0') MemoryCopy(outFileName, raylibapiPath, TextLength(raylibapiPath) + 1);+ if (apiDefine[0] == '\0') MemoryCopy(apiDefine, rlapiPath, TextLength(rlapiPath) + 1); int length = 0; char *buffer = LoadFileText(inFileName, &length);@@ -1006,8 +1009,14 @@ { funcEnd = c + 2; - // Check if previous word is void- if ((linePtr[c - 4] == 'v') && (linePtr[c - 3] == 'o') && (linePtr[c - 2] == 'i') && (linePtr[c - 1] == 'd')) break;+ // Check if there are no parameters+ if ((funcEnd - funcParamsStart == 2) ||+ ((linePtr[c - 4] == 'v') &&+ (linePtr[c - 3] == 'o') &&+ (linePtr[c - 2] == 'i') &&+ (linePtr[c - 1] == 'd'))) {+ break;+ } // Get parameter type + name, extract info char funcParamTypeName[128] = { 0 };@@ -1091,7 +1100,7 @@ printf(" NOTE: If not specified, defaults to: raylib_api.txt\n\n"); printf(" -f, --format <type> : Define output format for parser data.\n"); printf(" Supported types: DEFAULT, JSON, XML, LUA, CODE\n\n");- printf(" -d, --define <DEF> : Define functions specifiers (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc.)\n");+ printf(" -d, --define <DEF> : Define functions specifiers (i.e. RLAPI for raylib.h, RMAPI for raymath.h, etc.)\n"); printf(" NOTE: If no specifier defined, defaults to: RLAPI\n\n"); printf(" -t, --truncate <after> : Define string to truncate input after (i.e. \"RLGL IMPLEMENTATION\" for rlgl.h)\n"); printf(" NOTE: If not specified, the full input file is parsed.\n\n");@@ -1101,7 +1110,7 @@ printf(" Process <raylib.h> to generate <api.json>\n\n"); printf(" > raylib_parser --output raylib_data.info --format XML\n"); printf(" Process <raylib.h> to generate <raylib_data.info> as XML text data\n\n");- printf(" > raylib_parser --input raymath.h --output raymath_data.info --format XML\n");+ printf(" > raylib_parser --input raymath.h --output raymath_data.info --format XML --define RMAPI\n"); printf(" Process <raymath.h> to generate <raymath_data.info> as XML text data\n\n"); } @@ -1237,7 +1246,7 @@ while ((bufferPtr[index] == ' ') || (bufferPtr[index] == '\t')) index++; int j = 0;- while (bufferPtr[index + j] != '\n')+ while (bufferPtr[index + j] != '\n' && bufferPtr[index + j] != '\0') { lines[i][j] = bufferPtr[index + j]; j++;@@ -1271,8 +1280,10 @@ } else if ((typeName[k] == '.') && (typeNameLen == 3)) // Handle varargs ...); {- MemoryCopy(type, "...", 3);- MemoryCopy(name, "args", 4);+ const char *varargsDots = "...";+ const char *varargsArg = "args";+ MemoryCopy(type, varargsDots, TextLength(varargsDots));+ MemoryCopy(name, varargsArg, TextLength(varargsArg)); break; } }
raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h view
@@ -134,7 +134,7 @@ RLAPI void MemFree(void *ptr); // Internal memory free // Set custom callbacks-// WARNING: Callbacks setup is intended for advance users+// WARNING: Callbacks setup is intended for advanced users RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
raylib/src/config.h view
@@ -66,7 +66,7 @@ #define SUPPORT_COMPRESSION_API 1 // Support automatic generated events, loading and recording of those events when required #define SUPPORT_AUTOMATION_EVENTS 1-// Support custom frame control, only for advance users+// Support custom frame control, only for advanced users // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // Enabling this flag allows manual control of the frame processes, use at your own risk //#define SUPPORT_CUSTOM_FRAME_CONTROL 1@@ -112,14 +112,22 @@ #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance +// Default shader vertex attribute locations+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5+ // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience-#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1-#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2-#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5+#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD+#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL+#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix@@ -180,9 +188,9 @@ // NOTE: If enabled, uses external module functions to load default raylib font #define SUPPORT_DEFAULT_FONT 1 // Selected desired font fileformats to be supported for loading-#define SUPPORT_FILEFORMAT_FNT 1 #define SUPPORT_FILEFORMAT_TTF 1-#define SUPPORT_FILEFORMAT_BDF 1+#define SUPPORT_FILEFORMAT_FNT 1+//#define SUPPORT_FILEFORMAT_BDF 1 // Support text management functions // If not defined, still some functions are supported: TextLength(), TextFormat()
+ raylib/src/external/RGFW.h view
@@ -0,0 +1,6633 @@+/*+* Copyright (C) 2023-24 ColleagueRiley+*+* libpng license+*+* This software is provided 'as-is', without any express or implied+* warranty. In no event will the authors be held liable for any damages+* arising from the use of this software.+*+* Permission is granted to anyone to use this software for any purpose,+* including commercial applications, and to alter it and redistribute it+* freely, subject to the following restrictions:+*+* 1. The origin of this software must not be misrepresented; you must not+* claim that you wrote the original software. If you use this software+* in a product, an acknowledgment in the product documentation would be+* appreciated but is not required.+* 2. Altered source versions must be plainly marked as such, and must not be+* misrepresented as being the original software.+* 3. This notice may not be removed or altered from any source distribution.+*+*+*/++/*+ (MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)+ #define RGFW_IMPLEMENTATION - makes it so source code is included with header+*/++/*+ #define RGFW_IMPLEMENTATION - (required) makes it so the source code is included+ #define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found+ #define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl)+ #define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format)+ #define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api)+ #define RGFW_OPENGL_ES1 - (optional) use EGL to load and use Opengl ES (version 1) for backend rendering (instead of the system's opengl api)+ This version doesn't work for desktops (I'm pretty sure)+ #define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2)+ #define RGFW_OPENGL_ES3 - (optional) use OpenGL ES (version 3)+ #define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix)+ #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX)++ #define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress)+ #define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically (using GetProcAddress)++ #define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS+ #define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime+ #define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor+ #define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) Use XCursor, but don't link it in code, (you'll have to link it with -lXcursor)++ #define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included)++ #define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data)+ #define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used+ #define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used+ #define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used+*/++/*+ Credits :+ EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing ++ stb - This project is heavily inspired by the stb single header files++ GLFW:+ certain parts of winapi and X11 are very poorly documented,+ GLFW's source code was referenced and used throughout the project (used code is marked in some way),+ this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well)++ GLFW Copyright, https::/github.com/GLFW/GLFW++ Copyright (c) 2002-2006 Marcus Geelnard+ Copyright (c) 2006-2019 Camilla Löwy++ contributors : (feel free to put yourself here if you contribute)+ krisvers -> code review+ EimaMei (SaCode) -> code review+ Code-Nycticebus -> bug fixes+ Rob Rohan -> X11 bugs and missing features+ AICDG (@THISISAGOODNAME) -> vulkan support (example)+*/++#ifndef RGFW_MALLOC+#include <stdlib.h>+#include <time.h>+#define RGFW_MALLOC malloc+#define RGFW_CALLOC calloc+#define RGFW_FREE free+#endif++#if !_MSC_VER+#ifndef inline+#ifndef __APPLE__+#define inline __inline+#endif+#endif+#endif++/* for windows 95 testing (not that it works well) */+#ifdef RGFW_WIN95+#define RGFW_NO_MONITOR+#define RGFW_NO_PASSTHROUGH+#endif++#ifndef RGFWDEF+#ifdef __APPLE__+#define RGFWDEF static inline+#else+#define RGFWDEF inline+#endif+#endif++#ifndef RGFW_ENUM+#define RGFW_ENUM(type, name) type name; enum+#endif++#ifndef RGFW_UNUSED+#define RGFW_UNUSED(x) (void)(x);+#endif++#ifdef __cplusplus+extern "C" {+#endif++ /* makes sure the header file part is only defined once by default */+#ifndef RGFW_HEADER++#define RGFW_HEADER++#if !defined(u8)+ #if defined(_MSC_VER) || defined(__SYMBIAN32__)+ typedef unsigned char u8;+ typedef signed char i8;+ typedef unsigned short u16;+ typedef signed short i16;+ typedef unsigned int u32;+ typedef signed int i32;+ typedef unsigned long u64;+ typedef signed long i64;+ #else+ #include <stdint.h>++ typedef uint8_t u8;+ typedef int8_t i8;+ typedef uint16_t u16;+ typedef int16_t i16;+ typedef uint32_t u32;+ typedef int32_t i32;+ typedef uint64_t u64;+ typedef int64_t i64;+ #endif+#endif++#if !defined(b8)+ typedef u8 b8;+#endif++#if defined(RGFW_X11) && defined(__APPLE__)+#define RGFW_MACOS_X11+#undef __APPLE__+#endif++#if defined(_WIN32) && !defined(RGFW_X11) /* (if you're using X11 on windows some how) */++ /* this name looks better */+ /* plus it helps with cross-compiling because RGFW_X11 won't be accidently defined */+ +#define RGFW_WINDOWS++#if defined(_WIN32) && !defined(WIN32)+#define WIN32+#endif++#if defined(_WIN64)++#ifndef WIN64+#define WIN64+#endif++#define _AMD64_+#undef _X86_+#else+#undef _AMD64_+#ifndef _X86_+#define _X86_+#endif+#endif++#ifndef RGFW_NO_XINPUT+#ifdef __MINGW32__+#include <xinput.h>+#else+#include <XInput.h>+#endif+#endif++#else +#if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)+#define RGFW_MACOS_X11+#define RGFW_X11+#include <X11/Xlib.h>+#endif+#endif ++#if defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)+#define RGFW_MACOS+#endif++#if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL)+#define RGFW_EGL+#endif+#if defined(RGFW_EGL) && defined(__APPLE__)+ #warning EGL is not supported for Cocoa, switching back to the native opengl api+#undef RGFW_EGL+#endif++#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)+#define RGFW_OPENGL+#endif++#if defined(RGFW_X11) && (defined(RGFW_OPENGL))+#ifndef GLX_MESA_swap_control+#define GLX_MESA_swap_control+#endif+#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */+#endif++#ifdef RGFW_EGL+#include <EGL/egl.h>+#endif++#ifdef RGFW_OSMESA+#ifndef __APPLE__+#include <GL/osmesa.h>+#else+#include <OpenGL/osmesa.h>+#endif+#endif++#if defined(RGFW_DIRECTX) && defined(RGFW_WINDOWS)+#include <d3d11.h>+#include <dxgi.h>+#include <dxgi.h>+#include <d3dcompiler.h>++#ifndef __cplusplus+#define __uuidof(T) IID_##T+#endif+#endif++#ifndef RGFW_ALPHA+#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */+#endif++/*! Optional arguments for making a windows */+#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */+#define RGFW_NO_BORDER (1L<<3) /*!< the window doesn't have border */+#define RGFW_NO_RESIZE (1L<<4) /*!< the window cannot be resized by the user */+#define RGFW_ALLOW_DND (1L<<5) /*!< the window supports drag and drop*/+#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/+#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */+#define RGFW_CENTER (1L<<10) /*! center the window on the screen */+#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */+#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */+#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */+#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */++#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/+#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/+++/*! event codes */+#define RGFW_keyPressed 2 /* a key has been pressed */+#define RGFW_keyReleased 3 /*!< a key has been released*/+/*! key event note+ the code of the key pressed is stored in+ RGFW_Event.keyCode+ !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!++ while a string version is stored in+ RGFW_Event.KeyString++ RGFW_Event.lockState holds the current lockState+ this means if CapsLock, NumLock are active or not+*/+#define RGFW_mouseButtonPressed 4 /*!< a mouse button has been pressed (left,middle,right)*/+#define RGFW_mouseButtonReleased 5 /*!< a mouse button has been released (left,middle,right)*/+#define RGFW_mousePosChanged 6 /*!< the position of the mouse has been changed*/+/*! mouse event note+ the x and y of the mouse can be found in the vector, RGFW_Event.point++ RGFW_Event.button holds which mouse button was pressed+*/+#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */+#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */+#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/+/*! joystick event note+ RGFW_Event.joystick holds which joystick was altered, if any+ RGFW_Event.button holds which joystick button was pressed++ RGFW_Event.axis holds the data of all the axis+ RGFW_Event.axisCount says how many axis there are+*/+#define RGFW_windowMoved 10 /*!< the window was moved (by the user) */+#define RGFW_windowResized 11 /*!< the window was resized (by the user) */++#define RGFW_focusIn 12 /*!< window is in focus now */+#define RGFW_focusOut 13 /*!< window is out of focus now */++#define RGFW_mouseEnter 14 /* mouse entered the window */+#define RGFW_mouseLeave 15 /* mouse left the window */++#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */++/* attribs change event note+ The event data is sent straight to the window structure+ with win->r.x, win->r.y, win->r.w and win->r.h+*/+#define RGFW_quit 33 /*!< the user clicked the quit button*/ +#define RGFW_dnd 34 /*!< a file has been dropped into the window*/+#define RGFW_dnd_init 35 /*!< the start of a dnd event, when the place where the file drop is known */+/* dnd data note+ The x and y coords of the drop are stored in the vector RGFW_Event.point++ RGFW_Event.droppedFilesCount holds how many files were dropped++ This is also the size of the array which stores all the dropped file string,+ RGFW_Event.droppedFiles+*/++/*! mouse button codes (RGFW_Event.button) */+#define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/+#define RGFW_mouseMiddle 2 /*!< mouse-wheel-button is pressed*/+#define RGFW_mouseRight 3 /*!< right mouse button is pressed*/+#define RGFW_mouseScrollUp 4 /*!< mouse wheel is scrolling up*/+#define RGFW_mouseScrollDown 5 /*!< mouse wheel is scrolling down*/++#ifndef RGFW_MAX_PATH+#define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */+#endif+#ifndef RGFW_MAX_DROPS+#define RGFW_MAX_DROPS 260 /* max items you can drop at once */+#endif+++/* for RGFW_Event.lockstate */+#define RGFW_CAPSLOCK (1L << 1)+#define RGFW_NUMLOCK (1L << 2)++/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */+#ifndef RGFW_joystick_codes++typedef RGFW_ENUM(u8, RGFW_joystick_codes) {+ RGFW_JS_A = 0, /* or PS X button */+ RGFW_JS_B = 1, /* or PS circle button */+ RGFW_JS_Y = 2, /* or PS triangle button */+ RGFW_JS_X = 3, /* or PS square button */+ RGFW_JS_START = 9, /* start button */+ RGFW_JS_SELECT = 8, /* select button */+ RGFW_JS_HOME = 10, /* home button */+ RGFW_JS_UP = 13, /* dpad up */+ RGFW_JS_DOWN = 14, /* dpad down*/+ RGFW_JS_LEFT = 15, /* dpad left */+ RGFW_JS_RIGHT = 16, /* dpad right */+ RGFW_JS_L1 = 4, /* left bump */+ RGFW_JS_L2 = 5, /* left trigger*/+ RGFW_JS_R1 = 6, /* right bumper */+ RGFW_JS_R2 = 7, /* right trigger */+};++#endif++/* basic vector type, if there's not already a point/vector type of choice */+#ifndef RGFW_vector+typedef struct { i32 x, y; } RGFW_vector;+#endif++ /* basic rect type, if there's not already a rect type of choice */+#ifndef RGFW_rect+ typedef struct { i32 x, y, w, h; } RGFW_rect;+#endif++ /* basic area type, if there's not already a area type of choice */+#ifndef RGFW_area+ typedef struct { u32 w, h; } RGFW_area;+#endif++#define RGFW_VECTOR(x, y) (RGFW_vector){x, y}+#define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h}+#define RGFW_AREA(w, h) (RGFW_area){w, h}++ #ifndef RGFW_NO_MONITOR+ typedef struct RGFW_monitor {+ char name[128]; /* monitor name */+ RGFW_rect rect; /* monitor Workarea */+ float scaleX, scaleY; /* monitor content scale*/+ float physW, physH; /* monitor physical size */+ } RGFW_monitor;++ /*+ NOTE : Monitor functions should be ran only as many times as needed (not in a loop)+ */++ /* get an array of all the monitors (max 6) */+ RGFWDEF RGFW_monitor* RGFW_getMonitors(void);+ /* get the primary monitor */+ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);+ #endif++ /* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */+ typedef struct RGFW_Event {+ char keyName[16]; /* key name of event*/++ /*! drag and drop data */+ /* 260 max paths with a max length of 260 */+#ifdef RGFW_ALLOC_DROPFILES+ char** droppedFiles;+#else+ char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/+#endif+ u32 droppedFilesCount; /*!< house many files were dropped */++ u32 type; /*!< which event has been sent?*/+ RGFW_vector point; /*!< mouse x, y of event (or drop point) */+ + u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/+ u64 frameTime, frameTime2; /* this is used for counting the fps */+ + u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */++ b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */++ u8 lockState;++ u16 joystick; /* which joystick this event applies to (if applicable to any) */++ u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/+ double scroll; /* the raw mouse scroll value */++ u8 axisesCount; /* number of axises */+ RGFW_vector axis[2]; /* x, y of axises (-100 to 100) */+ } RGFW_Event; /*!< Event structure for checking/getting events */++ /* source data for the window (used by the APIs) */+ typedef struct RGFW_window_src {+#ifdef RGFW_WINDOWS+ HWND window; /*!< source window */+ HDC hdc; /*!< source HDC */+ u32 hOffset; /*!< height offset for window */+#endif+#ifdef RGFW_X11+ Display* display; /*!< source display */+ Window window; /*!< source window */+#endif+#ifdef RGFW_MACOS+ u32 display;+ void* displayLink;+ void* window;+ b8 dndPassed;+#endif++#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA)+#ifdef RGFW_MACOS+ void* rSurf; /*!< source graphics context */+#endif+#ifdef RGFW_WINDOWS+ HGLRC rSurf; /*!< source graphics context */+#endif+#ifdef RGFW_X11+ GLXContext rSurf; /*!< source graphics context */+#endif+#else++#ifdef RGFW_OSMESA+ OSMesaContext rSurf;+#endif+#endif++#ifdef RGFW_WINDOWS+ RGFW_area maxSize, minSize;+#if defined(RGFW_DIRECTX)+ IDXGISwapChain* swapchain;+ ID3D11RenderTargetView* renderTargetView;+ ID3D11DepthStencilView* pDepthStencilView;+#endif+#endif++#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)+ void* view; /*apple viewpoint thingy*/+#endif++#ifdef RGFW_EGL+ EGLSurface EGL_surface;+ EGLDisplay EGL_display;+ EGLContext EGL_context;+#endif++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) +#ifdef RGFW_WINDOWS+ HBITMAP bitmap;+#endif+#ifdef RGFW_X11+ XImage* bitmap;+ GC gc;+#endif+#ifdef RGFW_MACOS+ void* bitmap; /* API's bitmap for storing or managing */+ void* image;+#endif+#if defined(RGFW_BUFFER) && defined(RGFW_WINDOWS)+ HDC hdcMem; /* window stored in memory that winapi needs to render buffers */+#endif+#endif++ u8 jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */++ i32 joysticks[4]; /* limit of 4 joysticks at a time */+ u16 joystickCount; /* the actual amount of joysticks */++ RGFW_area scale; /* window scaling */++#ifdef RGFW_MACOS+ b8 cursorChanged; /* for steve jobs */+#endif++ u32 winArgs; /* windows args (for RGFW to check) */+ /*+ !< if dnd is enabled or on (based on window creating args)+ cursorChanged+ */+ } RGFW_window_src;++ typedef struct RGFW_window {+ RGFW_window_src src;++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */+ /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */+#endif++ RGFW_Event event; /*!< current event */++ RGFW_rect r; /* the x, y, w and h of the struct */++ u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/+ /*[the fps is capped when events are checked]*/+ } RGFW_window; /*!< Window structure for managing the window */++#if defined(RGFW_X11) || defined(RGFW_MACOS)+ typedef u64 RGFW_thread; /* thread type unix */+#else+ typedef void* RGFW_thread; /* thread type for window */+#endif++ /* this has to be set before createWindow is called, else the fulscreen size is used */+ RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */++ RGFW_window* RGFW_createWindow(+ const char* name, /* name of the window */+ RGFW_rect rect, /* rect of window */+ u16 args /* extra arguments (NULL / (u16)0 means no args used)*/+ ); /*!< function to create a window struct */++ /* get the size of the screen to an area struct */+ RGFWDEF RGFW_area RGFW_getScreenSize(void);++ /*+ this function checks an *individual* event (and updates window structure attributes)+ this means, using this function without a while loop may cause event lag++ ex.++ while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]++ this function is optional if you choose to use event callbacks, + although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`+ */++ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/++ /* + check all the events until there are none left, + this should only be used if you're using callbacks only+ */+ RGFWDEF void RGFW_window_checkEvents(RGFW_window* win);+++ /*! window managment functions*/+ RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */++ RGFWDEF void RGFW_window_move(RGFW_window* win,+ RGFW_vector v/* new pos*/+ );++ #ifndef RGFW_NO_MONITOR+ /* move to a specific monitor */+ RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m);+ #endif+ RGFWDEF void RGFW_window_resize(RGFW_window* win,+ RGFW_area a/* new size*/+ );++ /* set the minimum size a user can shrink a window */+ RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);+ /* set the minimum size a user can extend a window */+ RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);++ RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */+ RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/+ RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/++ RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); /* if the window should have a border or not (borderless) based on bool value of `border` */+ + RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); /* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/++ #ifndef RGFW_NO_PASSTHROUGH+ RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); /* turn on / off mouse passthrough */+ #endif ++ RGFWDEF void RGFW_window_setName(RGFW_window* win,+ char* name+ );++ void RGFW_window_setIcon(RGFW_window* win, /*!< source window */+ u8* icon /*!< icon bitmap */,+ RGFW_area a /*!< width and height of the bitmap*/,+ i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */+ ); /*!< image resized by default */++ /*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/+ RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);++ /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */+ RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);++ RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to1` the default mouse image */+ /*+ holds the mouse in place by moving the mouse back each time it moves+ you can still use win->event.point to see how much it moved before it was put back in place++ this is useful for a 3D camera+ */+ RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);+ /* undo hold */+ RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);++ /* hide the window */+ RGFWDEF void RGFW_window_hide(RGFW_window* win);+ /* show the window */+ RGFWDEF void RGFW_window_show(RGFW_window* win);++ /*+ makes it so `RGFW_window_shouldClose` returns true+ by setting the window event.type to RGFW_quit+ */+ RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);++ /* where the mouse is on the screen */+ RGFWDEF RGFW_vector RGFW_getGlobalMousePoint(void);++ /* where the mouse is on the window */+ RGFWDEF RGFW_vector RGFW_window_getMousePoint(RGFW_window* win);++ /* show the mouse or hide the mouse*/+ RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);+ /* move the mouse to a set x, y pos*/+ RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v);++ /* if the window should close (RGFW_close was sent or escape was pressed) */+ RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);+ /* if window is fullscreen'd */+ RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);+ /* if window is hidden */+ RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);+ /* if window is minimized */+ RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);+ /* if window is maximized */+ RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);+++ #ifndef RGFW_NO_MONITOR+ /*+ scale the window to the monitor,+ this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation+ */+ RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);+ /* get the struct of the window's monitor */+ RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);+ #endif++ /*!< make the window the current opengl drawing context */+ RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);++ /*error handling*/+ RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */++ /*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/+ RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/++ RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/++ RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/+ RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/++ RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key);++ RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button);+ RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button);+ RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button);+ RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button);++/*! clipboard functions*/+ RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */+ RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */++ RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */++ /* + + + Event callbacks, + these are completely optional, you can use the normal + RGFW_checkEvent() method if you prefer that++ */++ /* RGFW_windowMoved, the window and its new rect value */+ typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);+ /* RGFW_windowResized, the window and its new rect value */+ typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);+ /* RGFW_quit, the window that was closed */+ typedef void (* RGFW_windowquitfunc)(RGFW_window* win);+ /* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */+ typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);+ /* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */+ typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_vector point, b8 status);+ /* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */+ typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_vector point);+ /* RGFW_dnd_init, the window, the point of the drop on the windows */+ typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_vector point);+ /* RGFW_windowRefresh, the window that needs to be refreshed */+ typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);+ /* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */+ typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);+ /* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */+ typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);+ /* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */+ typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);+ /* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */+ typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount);+ + /* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */+ #ifdef RGFW_ALLOC_DROPFILES+ typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);+ #else+ typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);+ #endif++ RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);+ RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);+ RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);+ RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func);+ RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);+ RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func);+ RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);+ RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func);+ RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func);+ RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func);+ RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);+ RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);+ RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);+++#ifndef RGFW_NO_THREADS+ /*! threading functions*/++ /*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */+ /*+ I'd suggest you use sili's threading functions instead+ if you're going to use sili+ which is a good idea generally+ */++ #if defined(__unix__) || defined(__APPLE__) + typedef void* (* RGFW_threadFunc_ptr)(void*);+ #else+ typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); + #endif++ RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/+ RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/+ RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */+ RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */+#endif++ /*! gamepad/joystick functions (linux-only currently) */++ /*! joystick count starts at 0*/+ /*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/+ RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);+ RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);++ RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);++ /*! native opengl functions */+#ifdef RGFW_OPENGL+/*! Get max OpenGL version */+ RGFWDEF u8* RGFW_getMaxGLVersion(void);+ /* OpenGL init hints */+ RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */+ RGFWDEF void RGFW_setGLSamples(i32 samples); /* set number of sampiling buffers (4 by default) */+ RGFWDEF void RGFW_setGLStereo(i32 stereo); /* use GL_STEREO (GL_FALSE by default) */+ RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /* number of aux buffers (0 by default) */++ /*! Set OpenGL version hint */+ RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor);+ RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */+ RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /* to be called by RGFW_window_makeCurrent */+#endif+ /* supports openGL, directX, OSMesa, EGL and software rendering */+ RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */+ RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);++ RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);+ RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);+#ifdef RGFW_DIRECTX+ typedef struct {+ IDXGIFactory* pFactory;+ IDXGIAdapter* pAdapter;+ ID3D11Device* pDevice;+ ID3D11DeviceContext* pDeviceContext;+ } RGFW_directXinfo;++ /*+ RGFW stores a global instance of RGFW_directXinfo,+ you can use this function to get a pointer the instance+ */+ RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);+#endif++ /*! Supporting functions */+ RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/+ RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */+ RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */+ RGFWDEF void RGFW_sleep(u64 microsecond); /* sleep for a set time */++ typedef RGFW_ENUM(u8, RGFW_Key) {+ RGFW_KEY_NULL = 0,+ RGFW_Escape,+ RGFW_F1,+ RGFW_F2,+ RGFW_F3,+ RGFW_F4,+ RGFW_F5,+ RGFW_F6,+ RGFW_F7,+ RGFW_F8,+ RGFW_F9,+ RGFW_F10,+ RGFW_F11,+ RGFW_F12,++ RGFW_Backtick,++ RGFW_0,+ RGFW_1,+ RGFW_2,+ RGFW_3,+ RGFW_4,+ RGFW_5,+ RGFW_6,+ RGFW_7,+ RGFW_8,+ RGFW_9,++ RGFW_Minus,+ RGFW_Equals,+ RGFW_BackSpace,+ RGFW_Tab,+ RGFW_CapsLock,+ RGFW_ShiftL,+ RGFW_ControlL,+ RGFW_AltL,+ RGFW_SuperL,+ RGFW_ShiftR,+ RGFW_ControlR,+ RGFW_AltR,+ RGFW_SuperR,+ RGFW_Space,++ RGFW_a,+ RGFW_b,+ RGFW_c,+ RGFW_d,+ RGFW_e,+ RGFW_f,+ RGFW_g,+ RGFW_h,+ RGFW_i,+ RGFW_j,+ RGFW_k,+ RGFW_l,+ RGFW_m,+ RGFW_n,+ RGFW_o,+ RGFW_p,+ RGFW_q,+ RGFW_r,+ RGFW_s,+ RGFW_t,+ RGFW_u,+ RGFW_v,+ RGFW_w,+ RGFW_x,+ RGFW_y,+ RGFW_z,++ RGFW_Period,+ RGFW_Comma,+ RGFW_Slash,+ RGFW_Bracket,+ RGFW_CloseBracket,+ RGFW_Semicolon,+ RGFW_Return,+ RGFW_Quote,+ RGFW_BackSlash,++ RGFW_Up,+ RGFW_Down,+ RGFW_Left,+ RGFW_Right,++ RGFW_Delete,+ RGFW_Insert,+ RGFW_End,+ RGFW_Home,+ RGFW_PageUp,+ RGFW_PageDown,++ RGFW_Numlock,+ RGFW_KP_Slash,+ RGFW_Multiply,+ RGFW_KP_Minus,+ RGFW_KP_1,+ RGFW_KP_2,+ RGFW_KP_3,+ RGFW_KP_4,+ RGFW_KP_5,+ RGFW_KP_6,+ RGFW_KP_7,+ RGFW_KP_8,+ RGFW_KP_9,+ RGFW_KP_0,+ RGFW_KP_Period,+ RGFW_KP_Return,++ final_key,+ };++ typedef RGFW_ENUM(u8, RGFW_mouseIcons) {+ RGFW_MOUSE_NORMAL = 0,+ RGFW_MOUSE_ARROW,+ RGFW_MOUSE_IBEAM,+ RGFW_MOUSE_CROSSHAIR,+ RGFW_MOUSE_POINTING_HAND,+ RGFW_MOUSE_RESIZE_EW,+ RGFW_MOUSE_RESIZE_NS,+ RGFW_MOUSE_RESIZE_NWSE,+ RGFW_MOUSE_RESIZE_NESW,+ RGFW_MOUSE_RESIZE_ALL,+ RGFW_MOUSE_NOT_ALLOWED,+ };++#endif /* RGFW_HEADER */++ /*+ Example to get you started :++ linux : gcc main.c -lX11 -lXcursor -lGL+ windows : gcc main.c -lopengl32 -lshell32 -lgdi32+ macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo++ #define RGFW_IMPLEMENTATION+ #include "RGFW.h"++ u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};++ int main() {+ RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);++ RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);++ for (;;) {+ RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag+ if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape))+ break;++ RGFW_window_swapBuffers(win);++ glClearColor(0xFF, 0XFF, 0xFF, 0xFF);+ glClear(GL_COLOR_BUFFER_BIT);+ }++ RGFW_window_close(win);+ }++ compiling :++ if you wish to compile the library all you have to do is create a new file with this in it++ rgfw.c+ #define RGFW_IMPLEMENTATION+ #include "RGFW.h"++ then you can use gcc (or whatever compile you wish to use) to compile the library into object file++ ex. gcc -c RGFW.c -fPIC++ after you compile the library into an object file, you can also turn the object file into an static or shared library++ (commands ar and gcc can be replaced with whatever equivalent your system uses)+ static : ar rcs RGFW.a RGFW.o+ shared :+ windows:+ gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll+ linux:+ gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so+ macos:+ gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo+ */++#ifdef RGFW_X11+#define RGFW_OS_BASED_VALUE(l, w, m) l+#endif+#ifdef RGFW_WINDOWS+#define RGFW_OS_BASED_VALUE(l, w, m) w+#endif+#ifdef RGFW_MACOS+#define RGFW_OS_BASED_VALUE(l, w, m) m+#endif+#ifdef RGFW_IMPLEMENTATION++#include <stdio.h>+#include <string.h>+#include <math.h>+#include <assert.h>++/*+RGFW_IMPLEMENTATION starts with generic RGFW defines++This is the start of keycode data++Why not use macros instead of the numbers itself?+Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z)+Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size+MacOS -> windows and linux already don't have keycodes as macros, so there's no point+*/++ u8 RGFW_keycodes[] = {+ [RGFW_OS_BASED_VALUE(49, 192, 50)] = RGFW_Backtick,++ [RGFW_OS_BASED_VALUE(19, 0x30, 29)] = RGFW_0,+ [RGFW_OS_BASED_VALUE(10, 0x31, 18)] = RGFW_1,+ [RGFW_OS_BASED_VALUE(11, 0x32, 19)] = RGFW_2,+ [RGFW_OS_BASED_VALUE(12, 0x33, 20)] = RGFW_3,+ [RGFW_OS_BASED_VALUE(13, 0x34, 21)] = RGFW_4,+ [RGFW_OS_BASED_VALUE(14, 0x35, 23)] = RGFW_5,+ [RGFW_OS_BASED_VALUE(15, 0x36, 22)] = RGFW_6,+ [RGFW_OS_BASED_VALUE(16, 0x37, 26)] = RGFW_7,+ [RGFW_OS_BASED_VALUE(17, 0x38, 28)] = RGFW_8,+ [RGFW_OS_BASED_VALUE(18, 0x39, 25)] = RGFW_9,++ [RGFW_OS_BASED_VALUE(65, 0x20, 49)] = RGFW_Space,++ [RGFW_OS_BASED_VALUE(38, 0x41, 0)] = RGFW_a,+ [RGFW_OS_BASED_VALUE(56, 0x42, 11)] = RGFW_b,+ [RGFW_OS_BASED_VALUE(54, 0x43, 8)] = RGFW_c,+ [RGFW_OS_BASED_VALUE(40, 0x44, 2)] = RGFW_d,+ [RGFW_OS_BASED_VALUE(26, 0x45, 14)] = RGFW_e,+ [RGFW_OS_BASED_VALUE(41, 0x46, 3)] = RGFW_f,+ [RGFW_OS_BASED_VALUE(42, 0x47, 5)] = RGFW_g,+ [RGFW_OS_BASED_VALUE(43, 0x48, 4)] = RGFW_h,+ [RGFW_OS_BASED_VALUE(31, 0x49, 34)] = RGFW_i,+ [RGFW_OS_BASED_VALUE(44, 0x4A, 38)] = RGFW_j,+ [RGFW_OS_BASED_VALUE(45, 0x4B, 40)] = RGFW_k,+ [RGFW_OS_BASED_VALUE(46, 0x4C, 37)] = RGFW_l,+ [RGFW_OS_BASED_VALUE(58, 0x4D, 46)] = RGFW_m,+ [RGFW_OS_BASED_VALUE(57, 0x4E, 45)] = RGFW_n,+ [RGFW_OS_BASED_VALUE(32, 0x4F, 31)] = RGFW_o,+ [RGFW_OS_BASED_VALUE(33, 0x50, 35)] = RGFW_p,+ [RGFW_OS_BASED_VALUE(24, 0x51, 12)] = RGFW_q,+ [RGFW_OS_BASED_VALUE(27, 0x52, 15)] = RGFW_r,+ [RGFW_OS_BASED_VALUE(39, 0x53, 1)] = RGFW_s,+ [RGFW_OS_BASED_VALUE(28, 0x54, 17)] = RGFW_t,+ [RGFW_OS_BASED_VALUE(30, 0x55, 32)] = RGFW_u,+ [RGFW_OS_BASED_VALUE(55, 0x56, 9)] = RGFW_v,+ [RGFW_OS_BASED_VALUE(25, 0x57, 13)] = RGFW_w,+ [RGFW_OS_BASED_VALUE(53, 0x58, 7)] = RGFW_x,+ [RGFW_OS_BASED_VALUE(29, 0x59, 16)] = RGFW_y,+ [RGFW_OS_BASED_VALUE(52, 0x5A, 6)] = RGFW_z,++ [RGFW_OS_BASED_VALUE(60, 190, 47)] = RGFW_Period,+ [RGFW_OS_BASED_VALUE(59, 188, 43)] = RGFW_Comma,+ [RGFW_OS_BASED_VALUE(61, 191, 44)] = RGFW_Slash,+ [RGFW_OS_BASED_VALUE(34, 219, 33)] = RGFW_Bracket,+ [RGFW_OS_BASED_VALUE(35, 221, 30)] = RGFW_CloseBracket,+ [RGFW_OS_BASED_VALUE(47, 186, 41)] = RGFW_Semicolon,+ [RGFW_OS_BASED_VALUE(48, 222, 39)] = RGFW_Quote,+ [RGFW_OS_BASED_VALUE(51, 322, 42)] = RGFW_BackSlash,+ + [RGFW_OS_BASED_VALUE(36, 0x0D, 36)] = RGFW_Return,+ [RGFW_OS_BASED_VALUE(119, 0x2E, 118)] = RGFW_Delete,+ [RGFW_OS_BASED_VALUE(77, 0x90, 72)] = RGFW_Numlock,+ [RGFW_OS_BASED_VALUE(106, 0x6F, 82)] = RGFW_KP_Slash,+ [RGFW_OS_BASED_VALUE(63, 0x6A, 76)] = RGFW_Multiply,+ [RGFW_OS_BASED_VALUE(82, 0x6D, 67)] = RGFW_KP_Minus,+ [RGFW_OS_BASED_VALUE(87, 0x61, 84)] = RGFW_KP_1,+ [RGFW_OS_BASED_VALUE(88, 0x62, 85)] = RGFW_KP_2,+ [RGFW_OS_BASED_VALUE(89, 0x63, 86)] = RGFW_KP_3,+ [RGFW_OS_BASED_VALUE(83, 0x64, 87)] = RGFW_KP_4,+ [RGFW_OS_BASED_VALUE(84, 0x65, 88)] = RGFW_KP_5,+ [RGFW_OS_BASED_VALUE(85, 0x66, 89)] = RGFW_KP_6,+ [RGFW_OS_BASED_VALUE(79, 0x67, 90)] = RGFW_KP_7,+ [RGFW_OS_BASED_VALUE(80, 0x68, 92)] = RGFW_KP_8,+ [RGFW_OS_BASED_VALUE(81, 0x69, 93)] = RGFW_KP_9,+ [RGFW_OS_BASED_VALUE(90, 0x60, 83)] = RGFW_KP_0,+ [RGFW_OS_BASED_VALUE(91, 0x6E, 65)] = RGFW_KP_Period,+ [RGFW_OS_BASED_VALUE(104, 0x92, 77)] = RGFW_KP_Return,+ + [RGFW_OS_BASED_VALUE(20, 189, 27)] = RGFW_Minus,+ [RGFW_OS_BASED_VALUE(21, 187, 24)] = RGFW_Equals,+ [RGFW_OS_BASED_VALUE(22, 8, 51)] = RGFW_BackSpace,+ [RGFW_OS_BASED_VALUE(23, 0x09, 48)] = RGFW_Tab,+ [RGFW_OS_BASED_VALUE(66, 20, 57)] = RGFW_CapsLock,+ [RGFW_OS_BASED_VALUE(50, 0xA0, 56)] = RGFW_ShiftL,+ [RGFW_OS_BASED_VALUE(37, 0x11, 59)] = RGFW_ControlL,+ [RGFW_OS_BASED_VALUE(64, 164, 58)] = RGFW_AltL,+ [RGFW_OS_BASED_VALUE(133, 0x5B, 55)] = RGFW_SuperL,+ + #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS)+ [RGFW_OS_BASED_VALUE(105, 0x11, 59)] = RGFW_ControlR,+ [RGFW_OS_BASED_VALUE(135, 0xA4, 55)] = RGFW_SuperR,+ #endif++ #if !defined(RGFW_MACOS)+ [RGFW_OS_BASED_VALUE(62, 0x5C, 56)] = RGFW_ShiftR,+ [RGFW_OS_BASED_VALUE(108, 165, 58)] = RGFW_AltR,+ #endif++ [RGFW_OS_BASED_VALUE(67, 0x70, 127)] = RGFW_F1,+ [RGFW_OS_BASED_VALUE(68, 0x71, 121)] = RGFW_F2,+ [RGFW_OS_BASED_VALUE(69, 0x72, 100)] = RGFW_F3,+ [RGFW_OS_BASED_VALUE(70, 0x73, 119)] = RGFW_F4,+ [RGFW_OS_BASED_VALUE(71, 0x74, 97)] = RGFW_F5,+ [RGFW_OS_BASED_VALUE(72, 0x75, 98)] = RGFW_F6,+ [RGFW_OS_BASED_VALUE(73, 0x76, 99)] = RGFW_F7,+ [RGFW_OS_BASED_VALUE(74, 0x77, 101)] = RGFW_F8,+ [RGFW_OS_BASED_VALUE(75, 0x78, 102)] = RGFW_F9,+ [RGFW_OS_BASED_VALUE(76, 0x79, 110)] = RGFW_F10,+ [RGFW_OS_BASED_VALUE(95, 0x7A, 104)] = RGFW_F11,+ [RGFW_OS_BASED_VALUE(96, 0x7B, 112)] = RGFW_F12,+ [RGFW_OS_BASED_VALUE(111, 0x26, 126)] = RGFW_Up,+ [RGFW_OS_BASED_VALUE(116, 0x28, 125)] = RGFW_Down,+ [RGFW_OS_BASED_VALUE(113, 0x25, 123)] = RGFW_Left,+ [RGFW_OS_BASED_VALUE(114, 0x27, 124)] = RGFW_Right,+ [RGFW_OS_BASED_VALUE(118, 0x2D, 115)] = RGFW_Insert,+ [RGFW_OS_BASED_VALUE(115, 0x23, 120)] = RGFW_End,+ [RGFW_OS_BASED_VALUE(112, 336, 117)] = RGFW_PageUp,+ [RGFW_OS_BASED_VALUE(117, 325, 122)] = RGFW_PageDown,+ [RGFW_OS_BASED_VALUE(9, 0x1B, 53)] = RGFW_Escape,+ [RGFW_OS_BASED_VALUE(110, 0x24, 116)] = RGFW_Home,+ };++ typedef struct {+ b8 current : 1;+ b8 prev : 1;+ } RGFW_keyState;++ RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };+ + RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);++ u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {+ if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))+ return 0;+ + return RGFW_keycodes[keycode];+ }++ RGFWDEF void RGFW_resetKey(void);+ void RGFW_resetKey(void) {+ size_t len = final_key;+ + size_t i; + for (i = 0; i < len; i++) + RGFW_keyboard[i].prev = 0;+ }++/*+ this is the end of keycode data+*/+++/* + event callback defines start here+*/+++ /*+ These exist to avoid the + if (func == NULL) check + for (allegedly) better performance+ */+ void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }+ void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }+ void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); }+ void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);}+ void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_vector point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);}+ void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}+ void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}+ void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); }+ void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);}+ void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);}+ void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); }+ void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); }++ #ifdef RGFW_ALLOC_DROPFILES+ void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}+ #else+ void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}+ #endif++ RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY;+ RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY;+ RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY;+ RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY;+ RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY;+ RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY;+ RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY;+ RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY;+ RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY;+ RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY;+ RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY;+ RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY;+ RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY;++ void RGFW_window_checkEvents(RGFW_window* win) { while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { if (win->event.type == RGFW_quit) return; }}+ + void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; }+ void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; }+ void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; }+ void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; }+ void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; }+ void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; }+ void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; }+ void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; }+ void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; }+ void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; }+ void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; }+ void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; }+ void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; }+/* + no more event call back defines+*/++#define RGFW_ASSERT(check, str) {\+ if (!(check)) { \+ printf(str); \+ assert(check); \+ } \+}++ b8 RGFW_error = 0;+ b8 RGFW_Error() { return RGFW_error; }++#define SET_ATTRIB(a, v) { \+ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \+ attribs[index++] = a; \+ attribs[index++] = v; \+}+ + RGFW_area RGFW_bufferSize = {0, 0};+ void RGFW_setBufferSize(RGFW_area size) {+ RGFW_bufferSize = size;+ }+++ RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);++ RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {+ RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */++#ifdef RGFW_ALLOC_DROPFILES+ win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);+ u32 i;+ for (i = 0; i < RGFW_MAX_DROPS; i++)+ win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));+#endif++ #ifndef RGFW_X11 + RGFW_area screenR = RGFW_getScreenSize();+ #else+ win->src.display = XOpenDisplay(NULL);+ assert(win->src.display != NULL);++ Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);+ RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height);+ #endif+ + if (args & RGFW_FULLSCREEN)+ rect = RGFW_RECT(0, 0, screenR.w, screenR.h);++ if (args & RGFW_CENTER)+ rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h);++ /* set and init the new window's data */+ win->r = rect;+ win->fpsCap = 0;+ win->event.inFocus = 1;+ win->event.droppedFilesCount = 0;+ win->src.joystickCount = 0;+ win->src.winArgs = 0;+ win->event.lockState = 0;++ return win;+ }++ #ifndef RGFW_NO_MONITOR+ void RGFW_window_scaleToMonitor(RGFW_window* win) {+ RGFW_monitor monitor = RGFW_window_getMonitor(win);++ RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h));+ }+ #endif++RGFW_window* RGFW_root = NULL;+++#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */+#define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */++ void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }+ + b8 RGFW_mouseButtons[5] = { 0 };+ b8 RGFW_mouseButtons_prev[5];++ b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {+ assert(win != NULL);+ return RGFW_mouseButtons[button] && (win != NULL) && win->event.inFocus; + }+ b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) {+ assert(win != NULL); + return RGFW_mouseButtons_prev[button] && (win != NULL) && win->event.inFocus; + }+ b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) {+ return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));+ }+ b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) {+ return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); + }++ b8 RGFW_isPressed(RGFW_window* win, u8 key) {+ assert(win != NULL);+ return RGFW_keyboard[key].current && win->event.inFocus;+ }++ b8 RGFW_wasPressed(RGFW_window* win, u8 key) {+ assert(win != NULL);+ return RGFW_keyboard[key].prev && win->event.inFocus;+ }++ b8 RGFW_isHeld(RGFW_window* win, u8 key) {+ return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));+ }++ b8 RGFW_isClicked(RGFW_window* win, u8 key) {+ return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key));+ }++ b8 RGFW_isReleased(RGFW_window* win, u8 key) {+ return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); + }+ + void RGFW_window_makeCurrent(RGFW_window* win) {+ assert(win != NULL);++#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);+#endif++#ifdef RGFW_OPENGL+ RGFW_window_makeCurrent_OpenGL(win);+#endif+ }++ void RGFW_window_setGPURender(RGFW_window* win, i8 set) {+ if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER))+ win->src.winArgs |= RGFW_NO_GPU_RENDER;++ else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER)+ win->src.winArgs ^= RGFW_NO_GPU_RENDER;+ }++ void RGFW_window_setCPURender(RGFW_window* win, i8 set) {+ if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER))+ win->src.winArgs |= RGFW_NO_CPU_RENDER;++ else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER)+ win->src.winArgs ^= RGFW_NO_CPU_RENDER;+ }++ void RGFW_window_maximize(RGFW_window* win) {+ assert(win != NULL);++ RGFW_area screen = RGFW_getScreenSize();++ RGFW_window_move(win, RGFW_VECTOR(0, 0));+ RGFW_window_resize(win, screen);+ }++ b8 RGFW_window_shouldClose(RGFW_window* win) {+ assert(win != NULL);+ return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape));+ }++ void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); }++ #ifndef RGFW_NO_MONITOR+ void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {+ RGFW_window_move(win, RGFW_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y));+ }+ #endif++ RGFWDEF void RGFW_clipCursor(RGFW_rect);+ + #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) + void RGFW_clipCursor(RGFW_rect r) { RGFW_UNUSED(r) }+ #endif++ void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {+ if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) {+ RGFW_clipCursor(win->r);+ win->src.winArgs |= RGFW_HOLD_MOUSE;+ }+ + if (!area.w && !area.h)+ area = RGFW_AREA(win->r.w / 2, win->r.h / 2);+ + #ifndef RGFW_MACOS+ RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h)));+ #endif+ }++ void RGFW_window_mouseUnhold(RGFW_window* win) {+ if ((win->src.winArgs & RGFW_HOLD_MOUSE)) {+ win->src.winArgs ^= RGFW_HOLD_MOUSE;++ RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0));+ }+ }++ void RGFW_window_checkFPS(RGFW_window* win) {+ u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;++ u64 fps = round(1e+9 / deltaTime);+ win->event.fps = fps;++ if (win->fpsCap && fps > win->fpsCap) {+ u64 frameTimeNS = 1e+9 / win->fpsCap;+ u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;++ if (sleepTimeMS > 0) {+ RGFW_sleep(sleepTimeMS);+ win->event.frameTime = 0;+ }+ }++ win->event.frameTime = RGFW_getTimeNS();+ + if (win->fpsCap == 0)+ return;+ + deltaTime = RGFW_getTimeNS() - win->event.frameTime2;+ win->event.fps = round(1e+9 / deltaTime);+ win->event.frameTime2 = RGFW_getTimeNS();+ }+ + u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; }+ + #if defined(RGFW_X11) || defined(RGFW_WINDOWS)+ void RGFW_window_showMouse(RGFW_window* win, i8 show) {+ static u8 RGFW_blk[] = { 0, 0, 0, 0 };+ if (show == 0)+ RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);+ else+ RGFW_window_setMouseDefault(win);+ }+ #endif++ RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock); + void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {+ if (capital && !(win->event.lockState & RGFW_CAPSLOCK))+ win->event.lockState |= RGFW_CAPSLOCK;+ else if (!capital && (win->event.lockState & RGFW_CAPSLOCK)) + win->event.lockState ^= RGFW_CAPSLOCK;+ + if (numlock && !(win->event.lockState & RGFW_NUMLOCK))+ win->event.lockState |= RGFW_NUMLOCK;+ else if (!numlock && (win->event.lockState & RGFW_NUMLOCK))+ win->event.lockState ^= RGFW_NUMLOCK;+ }++ #if defined(RGFW_X11) || defined(RGFW_MACOS)+ struct timespec;++ int nanosleep(const struct timespec* duration, struct timespec* rem);+ int clock_gettime(clockid_t clk_id, struct timespec* tp);+ int setenv(const char *name, const char *value, int overwrite);++ void RGFW_window_setDND(RGFW_window* win, b8 allow) {+ if (allow && !(win->src.winArgs & RGFW_ALLOW_DND))+ win->src.winArgs |= RGFW_ALLOW_DND;++ else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND))+ win->src.winArgs ^= RGFW_ALLOW_DND;+ }+ #endif++/*+ graphics API spcific code (end of generic code)+ starts here +*/+++/* + OpenGL defines start here (Normal, EGL, OSMesa)+*/++#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)+#ifndef __APPLE__+#include <GL/gl.h>+#else+#ifndef GL_SILENCE_DEPRECATION+#define GL_SILENCE_DEPRECATION+#endif+#include <OpenGL/gl.h>+#include <OpenGL/OpenGL.h>+#endif++/* EGL, normal OpenGL only */+#if !defined(RGFW_OSMESA) + i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;+ + #ifndef RGFW_EGL+ i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;+ #else+ i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;+ #endif+++ void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }+ void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }+ void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }+ void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }++ void RGFW_setGLVersion(i32 major, i32 minor) {+ RGFW_majorVersion = major;+ RGFW_minorVersion = minor;+ }++ u8* RGFW_getMaxGLVersion(void) {+ RGFW_window* dummy = RGFW_createWindow("dummy", RGFW_RECT(0, 0, 1, 1), 0);++ const char* versionStr = (const char*) glGetString(GL_VERSION);++ static u8 version[2];+ version[0] = versionStr[0] - '0',+ version[1] = versionStr[2] - '0';++ RGFW_window_close(dummy);++ return version;+ }++/* OPENGL normal only (no EGL / OSMesa) */+#ifndef RGFW_EGL++#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73)+#define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11)+#define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12)+#define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5) +#define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13)+#define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55)+#define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6)+#define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7)++#if defined(RGFW_X11) || defined(RGFW_WINDOWS)+#define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0)+#define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0)+#define RGFW_GL_USE_OPENGL RGFW_OS_BASED_VALUE(GLX_USE_GL, 0x2010, 0)+#define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0)+#define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0)+#define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0)+#define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0)+#define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0)+#endif++#ifdef RGFW_WINDOWS+#define WGL_COLOR_BITS_ARB 0x2014+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+#define WGL_SAMPLE_BUFFERS_ARB 0x2041+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9+#define WGL_PIXEL_TYPE_ARB 0x2013+#define WGL_TYPE_RGBA_ARB 0x202B++#define WGL_TRANSPARENT_ARB 0x200A+#endif++ static u32* RGFW_initAttribs(u32 useSoftware) {+ RGFW_UNUSED(useSoftware);+ static u32 attribs[] = {+ #ifndef RGFW_MACOS+ RGFW_GL_RENDER_TYPE,+ RGFW_GL_FULL_FORMAT,+ #endif+ RGFW_GL_ALPHA_SIZE , 8,+ RGFW_GL_DEPTH_SIZE , 24,+ RGFW_GL_DOUBLEBUFFER ,+ #ifndef RGFW_MACOS+ 1,+ #endif++ #if defined(RGFW_X11) || defined(RGFW_WINDOWS)+ RGFW_GL_USE_OPENGL, 1,+ RGFW_GL_DRAW, 1,+ RGFW_GL_RED_SIZE , 8,+ RGFW_GL_GREEN_SIZE , 8,+ RGFW_GL_BLUE_SIZE , 8,+ RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA,+ #endif ++ #ifdef RGFW_X11+ GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,+ #endif++ #ifdef RGFW_MACOS+ 72,+ 8, 24,+ #endif++ #ifdef RGFW_WINDOWS+ WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,+ WGL_TRANSPARENT_ARB, TRUE,+ WGL_COLOR_BITS_ARB, 32,+ #endif++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0+ };++ size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;++#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \+ if (attVal) { \+ attribs[index] = attrib;\+ attribs[index + 1] = attVal;\+ index += 2;\+ }++ RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);+ RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);+ RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);++#ifndef RGFW_X11+ RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);+#endif ++#ifdef RGFW_MACOS+ if (useSoftware) {+ RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);+ } else {+ attribs[index] = RGFW_GL_RENDER_TYPE;+ index += 1;+ }+#endif++#ifdef RGFW_MACOS+ attribs[index] = 99;+ attribs[index + 1] = 0x1000;++ if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {+ attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);+ }++#endif++ RGFW_GL_ADD_ATTRIB(0, 0);++ return attribs;+ }++/* EGL only (no OSMesa nor normal OPENGL) */+#elif defined(RGFW_EGL)++#include <EGL/egl.h>++#if defined(RGFW_LINK_EGL)+ typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);++ PFNEGLINITIALIZEPROC eglInitializeSource;+ PFNEGLGETCONFIGSPROC eglGetConfigsSource;+ PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;+ PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;+ PFNEGLCREATECONTEXTPROC eglCreateContextSource;+ PFNEGLMAKECURRENTPROC eglMakeCurrentSource;+ PFNEGLGETDISPLAYPROC eglGetDisplaySource;+ PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;+ PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;+ PFNEGLBINDAPIPROC eglBindAPISource;+ PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;+ PFNEGLTERMINATEPROC eglTerminateSource;+ PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;++#define eglInitialize eglInitializeSource+#define eglGetConfigs eglGetConfigsSource+#define eglChooseConfig eglChooseConfigSource+#define eglCreateWindowSurface eglCreateWindowSurfaceSource+#define eglCreateContext eglCreateContextSource+#define eglMakeCurrent eglMakeCurrentSource+#define eglGetDisplay eglGetDisplaySource+#define eglSwapBuffers eglSwapBuffersSource+#define eglSwapInterval eglSwapIntervalSource+#define eglBindAPI eglBindAPISource+#define eglDestroyContext eglDestroyContextSource+#define eglTerminate eglTerminateSource+#define eglDestroySurface eglDestroySurfaceSource;+#endif+++#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098+#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb++#ifndef RGFW_GL_ADD_ATTRIB+#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \+ if (attVal) { \+ attribs[index] = attrib;\+ attribs[index + 1] = attVal;\+ index += 2;\+ }+#endif+++ void RGFW_createOpenGLContext(RGFW_window* win) {+#if defined(RGFW_LINK_EGL)+ eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");+ eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");+ eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");+ eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");+ eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");+ eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");+ eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");+ eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");+ eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");+ eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");+ eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");+ eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");+ eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");+#endif /* RGFW_LINK_EGL */++ #ifdef RGFW_WINDOWS+ win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);+ #else+ win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);+ #endif++ EGLint major, minor;++ eglInitialize(win->src.EGL_display, &major, &minor);++ #ifndef EGL_OPENGL_ES1_BIT+ #define EGL_OPENGL_ES1_BIT 0x1+ #endif++ EGLint egl_config[] = {+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,+ EGL_RENDERABLE_TYPE,+ #ifdef RGFW_OPENGL_ES1+ EGL_OPENGL_ES1_BIT,+ #elif defined(RGFW_OPENGL_ES3)+ EGL_OPENGL_ES3_BIT,+ #elif defined(RGFW_OPENGL_ES2)+ EGL_OPENGL_ES2_BIT,+ #else+ EGL_OPENGL_BIT,+ #endif+ EGL_NONE, EGL_NONE+ };++ EGLConfig config;+ EGLint numConfigs;+ eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);+++ win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);++ EGLint attribs[] = {+ EGL_CONTEXT_CLIENT_VERSION,+ #ifdef RGFW_OPENGL_ES1+ 1,+ #else+ 2,+ #endif+ EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE+ };++ size_t index = 4;+ RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);+ RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);++ if (RGFW_majorVersion) {+ attribs[1] = RGFW_majorVersion;+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);+ }++ #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)+ eglBindAPI(EGL_OPENGL_ES_API);+ #else+ eglBindAPI(EGL_OPENGL_API); + #endif++ win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);++ eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+ }++ #ifdef RGFW_APPLE+ void* RGFWnsglFramework = NULL;+ #elif defined(RGFW_WINDOWS)+ static HMODULE wglinstance = NULL;+ #endif++ void* RGFW_getProcAddress(const char* procname) { + #if defined(RGFW_WINDOWS)+ void* proc = (void*) GetProcAddress(wglinstance, procname); ++ if (proc)+ return proc;+ #endif++ return (void*) eglGetProcAddress(procname); + }++ void RGFW_closeEGL(RGFW_window* win) {+ eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);+ eglDestroyContext(win->src.EGL_display, win->src.EGL_context);++ eglTerminate(win->src.EGL_display);+ }++ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+ assert(win != NULL);+ + eglSwapInterval(win->src.EGL_display, swapInterval);++ win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;++ }+#endif /* RGFW_EGL */++/* + end of RGFW_EGL defines+*/++/* OPENGL Normal / EGL defines only (no OS MESA) Ends here */++#elif defined(RGFW_OSMESA) /* OSmesa only */+RGFWDEF void RGFW_OSMesa_reorganize(void);++/* reorganize buffer for osmesa */+void RGFW_OSMesa_reorganize(void) {+ u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);++ i32 half_height = win->r.h / 2;+ i32 stride = win->r.w * 3;++ i32 y;+ for (y = 0; y < half_height; ++y) {+ i32 top_offset = y * stride;+ i32 bottom_offset = (win->r.h - y - 1) * stride;+ memcpy(row, win->buffer + top_offset, stride);+ memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);+ memcpy(win->buffer + bottom_offset, row, stride);+ }++ RGFW_FREE(row);+}+#endif /* RGFW_OSMesa */++#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/++/*+This is where OS specific stuff starts+*/+++/*+++Start of Linux / Unix defines+++*/++#ifdef RGFW_X11+#ifndef RGFW_NO_X11_CURSOR+#include <X11/Xcursor/Xcursor.h>+#endif+#include <dlfcn.h>++#ifndef RGFW_NO_DPI+#include <X11/extensions/Xrandr.h>+#include <X11/Xresource.h>+#endif++#include <X11/Xutil.h>+#include <X11/Xatom.h>+#include <X11/keysymdef.h>+#include <unistd.h>++#include <X11/XKBlib.h> /* for converting keycode to string */+#include <X11/cursorfont.h> /* for hiding */+#include <X11/extensions/shapeconst.h>+#include <X11/extensions/shape.h>++#include <limits.h> /* for data limits (mainly used in drag and drop functions) */+#include <fcntl.h>++#ifdef __linux__+#include <linux/joystick.h>+#endif++ u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; + /*atoms needed for drag and drop*/+ Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate;++ Atom wm_delete_window = 0;++#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+ typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);+ typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);+ typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);+#endif+#ifdef RGFW_OPENGL+ typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);+#endif++#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+ PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;+ PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;+ PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;++#define XcursorImageLoadCursor XcursorImageLoadCursorSrc+#define XcursorImageCreate XcursorImageCreateSrc+#define XcursorImageDestroy XcursorImageDestroySrc++ void* X11Cursorhandle = NULL;+#endif++ u32 RGFW_windowsOpen = 0;++#ifdef RGFW_OPENGL+ void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }+#endif++ RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi);+ void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+ RGFW_bufferSize = RGFW_getScreenSize();+ + win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);++ #ifdef RGFW_OSMESA+ win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);+ OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+ #endif++ win->src.bitmap = XCreateImage(+ win->src.display, vi->visual,+ vi->depth,+ ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h,+ 32, 0+ );++ win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);++ #else+ RGFW_UNUSED(win); /* if buffer rendering is not being used */+ RGFW_UNUSED(vi)+ #endif+ }++++ void RGFW_window_setBorder(RGFW_window* win, u8 border) {+ static Atom _MOTIF_WM_HINTS = 0;+ if (_MOTIF_WM_HINTS == 0 )+ _MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False);+ + struct __x11WindowHints {+ unsigned long flags, functions, decorations, status;+ long input_mode;+ } hints;+ hints.flags = (1L << 1);+ hints.decorations = !border;++ XChangeProperty(+ win->src.display, win->src.window,+ _MOTIF_WM_HINTS, _MOTIF_WM_HINTS,+ 32, PropModeReplace, (u8*)&hints, 5+ );+ }++ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)+ if (X11Cursorhandle == NULL) {+#if defined(__CYGWIN__)+ X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);+#elif defined(__OpenBSD__) || defined(__NetBSD__)+ X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);+#else+ X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);+#endif++ XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");+ XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");+ XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");+ }+#endif++ XInitThreads(); /* init X11 threading*/++ if (args & RGFW_OPENGL_SOFTWARE)+ setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);++ RGFW_window* win = RGFW_window_basic_init(rect, args);++ u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/++#ifdef RGFW_OPENGL+ u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);+ i32 fbcount;+ GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);++ i32 best_fbc = -1;++ if (fbcount == 0) {+ printf("Failed to find any valid GLX configs\n");+ return NULL;+ }++ u32 i;+ for (i = 0; i < (u32)fbcount; i++) {+ XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);+ if (vi == NULL)+ continue;++ XFree(vi);++ i32 samp_buf, samples;+ glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);+ glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);+ if ((best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) {+ best_fbc = i;+ }+ }++ if (best_fbc == -1) {+ printf("Failed to get a valid GLX visual\n");+ return NULL;+ }++ GLXFBConfig bestFbc = fbc[best_fbc];++ /* Get a visual */+ XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);++ XFree(fbc);++ if (args & RGFW_TRANSPARENT_WINDOW) {+ XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/+ }+#else+ XVisualInfo viNorm;++ viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display));+ + viNorm.depth = 0;+ XVisualInfo* vi = &viNorm;+ + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/+#endif+ /* make X window attrubutes*/+ XSetWindowAttributes swa;+ Colormap cmap;++ swa.colormap = cmap = XCreateColormap((Display*) win->src.display,+ DefaultRootWindow(win->src.display),+ vi->visual, AllocNone);++ swa.background_pixmap = None;+ swa.border_pixel = 0;+ swa.event_mask = event_mask;+ + swa.background_pixel = 0;++ /* create the window*/+ win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h,+ 0, vi->depth, InputOutput, vi->visual,+ CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa);++ XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);++ #ifdef RGFW_OPENGL+ XFree(vi);+ #endif++ // In your .desktop app, if you set the property+ // StartupWMClass=RGFW that will assoicate the launcher icon+ // with your application - robrohan + XClassHint *hint = XAllocClassHint();+ assert(hint != NULL);+ hint->res_class = "RGFW";+ hint->res_name = (char*)name; // just use the window name as the app name+ XSetClassHint((Display*) win->src.display, win->src.window, hint);+ XFree(hint);++ if ((args & RGFW_NO_INIT_API) == 0) {+#ifdef RGFW_OPENGL+ i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };+ context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;+ context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;+ + if (RGFW_majorVersion || RGFW_minorVersion) {+ context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;+ context_attribs[3] = RGFW_majorVersion;+ context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;+ context_attribs[5] = RGFW_minorVersion;+ }++ glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;+ glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)+ glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");++ GLXContext ctx = NULL;++ if (RGFW_root != NULL)+ ctx = RGFW_root->src.rSurf;++ win->src.rSurf = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);+#endif+ if (RGFW_root == NULL)+ RGFW_root = win;++ RGFW_init_buffer(win, vi);+ }+ ++ #ifndef RGFW_NO_MONITOR+ if (args & RGFW_SCALE_TO_MONITOR)+ RGFW_window_scaleToMonitor(win);+ #endif++ if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/+ XSizeHints* sh = XAllocSizeHints();+ sh->flags = (1L << 4) | (1L << 5);+ sh->min_width = sh->max_width = win->r.w;+ sh->min_height = sh->max_height = win->r.h;++ XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);+ XFree(sh);+ }++ if (args & RGFW_NO_BORDER) {+ RGFW_window_setBorder(win, 0);+ }++ XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/++ /* make it so the user can't close the window until the program does*/+ if (wm_delete_window == 0)+ wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False);++ XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);++ /* connect the context to the window*/+#ifdef RGFW_OPENGL+ if ((args & RGFW_NO_INIT_API) == 0)+ glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);+#endif++ /* set the background*/+ XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /* set the name*/++ XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/+ XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/++ if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */+ win->src.winArgs |= RGFW_ALLOW_DND;++ XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);+ XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);+ XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);++ /* client messages */+ XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);+ XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);+ XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);+ XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);+ XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);+ XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);++ /* actions */+ XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);+ XdndActionMove = XInternAtom((Display*) win->src.display, "XdndActionMove", False);+ XdndActionLink = XInternAtom((Display*) win->src.display, "XdndActionLink", False);+ XdndActionAsk = XInternAtom((Display*) win->src.display, "XdndActionAsk", False);+ XdndActionPrivate = XInternAtom((Display*) win->src.display, "XdndActionPrivate", False);+ const Atom version = 5;++ XChangeProperty((Display*) win->src.display, (Window) win->src.window,+ XdndAware, 4, 32,+ PropModeReplace, (u8*) &version, 1); /* turns on drag and drop */+ }++ #ifdef RGFW_EGL+ if ((args & RGFW_NO_INIT_API) == 0)+ RGFW_createOpenGLContext(win);+ #endif++ RGFW_window_setMouseDefault(win);++ RGFW_windowsOpen++;++ return win; /*return newly created window*/+ }++ RGFW_area RGFW_getScreenSize(void) {+ assert(RGFW_root != NULL);++ Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);+ return RGFW_AREA(scrn->width, scrn->height);+ }++ RGFW_vector RGFW_getGlobalMousePoint(void) {+ assert(RGFW_root != NULL);++ RGFW_vector RGFWMouse;++ i32 x, y;+ u32 z;+ Window window1, window2;+ XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z);+ + return RGFWMouse;+ }++ RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {+ assert(win != NULL);++ RGFW_vector RGFWMouse;++ i32 x, y;+ u32 z;+ Window window1, window2;+ XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z);++ return RGFWMouse;+ }++ typedef struct XDND {+ long source, version;+ i32 format;+ } XDND; /* data structure for xdnd events */+ XDND xdnd;++ int xAxis = 0, yAxis = 0;++ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+ assert(win != NULL);++ if (win->event.type == 0) + RGFW_resetKey();++ if (win->event.type == RGFW_quit) {+ return NULL;+ }++ win->event.type = 0;++#ifdef __linux__+ {+ u8 i;+ for (i = 0; i < win->src.joystickCount; i++) {+ struct js_event e;+++ if (win->src.joysticks[i] == 0)+ continue;++ i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0);+ fcntl(win->src.joysticks[i], F_SETFL, flags | O_NONBLOCK);++ ssize_t bytes;+ while ((bytes = read(win->src.joysticks[i], &e, sizeof(e))) > 0) {+ switch (e.type) {+ case JS_EVENT_BUTTON:+ win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;+ win->event.button = e.number;+ win->src.jsPressed[i][e.number] = e.value;+ RGFW_jsButtonCallback(win, i, e.number, e.value);+ return &win->event;+ case JS_EVENT_AXIS:+ ioctl(win->src.joysticks[i], JSIOCGAXES, &win->event.axisesCount);++ if ((e.number == 0 || e.number % 2) && e.number != 1)+ xAxis = e.value;+ else+ yAxis = e.value;++ win->event.axis[e.number / 2].x = xAxis;+ win->event.axis[e.number / 2].y = yAxis;+ win->event.type = RGFW_jsAxisMove;+ win->event.joystick = i;+ RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);+ return &win->event;++ default: break;+ }+ }+ }+ }+#endif++ XEvent E; /* raw X11 event */++ /* if there is no unread qued events, get a new one */+ if (XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading) && win->event.type != RGFW_quit)+ XNextEvent((Display*) win->src.display, &E);+ else {+ return NULL;+ }++ u32 i;+ win->event.type = 0;+++ switch (E.type) {+ case KeyPress:+ case KeyRelease:+ /* check if it's a real key release */+ if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/+ XEvent NE;+ XPeekEvent((Display*) win->src.display, &NE);++ if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/+ break;+ }++ /* set event key data */+ KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);+ + char* str = XKeysymToString(sym);+ if (str != NULL)+ strncpy(win->event.keyName, str, 16);++ win->event.keyName[15] = '\0'; ++ RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);+ + /* get keystate data */+ win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;++ XKeyboardState keystate;+ XGetKeyboardControl((Display*) win->src.display, &keystate);++ RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));++ RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));+ break;++ case ButtonPress:+ case ButtonRelease:+ win->event.type = E.type; // the events match + + switch(win->event.button) {+ case RGFW_mouseScrollUp:+ win->event.scroll = 1;+ break;+ case RGFW_mouseScrollDown:+ win->event.scroll = -1;+ break;+ default: break;+ }++ win->event.button = E.xbutton.button;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = (E.type == ButtonPress);+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));+ break;++ case MotionNotify:+ win->event.point.x = E.xmotion.x;+ win->event.point.y = E.xmotion.y;+ win->event.type = RGFW_mousePosChanged;+ RGFW_mousePosCallback(win, win->event.point);+ break;+ + case Expose:+ win->event.type = RGFW_windowRefresh;+ RGFW_windowRefreshCallback(win);+ break;++ case ClientMessage:+ /* if the client closed the window*/+ if (E.xclient.data.l[0] == (i64) wm_delete_window) {+ win->event.type = RGFW_quit;+ RGFW_windowQuitCallback(win);+ break;+ }+ + /* reset DND values */+ if (win->event.droppedFilesCount) {+ for (i = 0; i < win->event.droppedFilesCount; i++)+ win->event.droppedFiles[i][0] = '\0';+ }++ win->event.droppedFilesCount = 0;++ /*+ much of this event (drag and drop code) is source from glfw+ */++ if ((win->src.winArgs & RGFW_ALLOW_DND) == 0)+ break;++ if (E.xclient.message_type == XdndEnter) {+ u64 count;+ Atom* formats;+ Atom real_formats[6];++ Bool list = E.xclient.data.l[1] & 1;++ xdnd.source = E.xclient.data.l[0];+ xdnd.version = E.xclient.data.l[1] >> 24;+ xdnd.format = None;++ if (xdnd.version > 5)+ break;++ if (list) {+ Atom actualType;+ i32 actualFormat;+ u64 bytesAfter;++ XGetWindowProperty((Display*) win->src.display,+ xdnd.source,+ XdndTypeList,+ 0,+ LONG_MAX,+ False,+ 4,+ &actualType,+ &actualFormat,+ (unsigned long*) &count,+ (unsigned long*) &bytesAfter,+ (u8**) &formats);+ } else {+ count = 0;++ if (E.xclient.data.l[2] != None)+ real_formats[count++] = E.xclient.data.l[2];+ if (E.xclient.data.l[3] != None)+ real_formats[count++] = E.xclient.data.l[3];+ if (E.xclient.data.l[4] != None)+ real_formats[count++] = E.xclient.data.l[4];+ + formats = real_formats;+ }++ u32 i;+ for (i = 0; i < count; i++) {+ char* name = XGetAtomName((Display*) win->src.display, formats[i]);++ char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" };+ for (; 1; name++) {+ u32 j;+ for (j = 0; j < 2; j++) {+ if (*links[j] != *name) {+ links[j] = (char*) (const char*) "\1";+ continue;+ }++ if (*links[j] == '\0' && *name == '\0')+ xdnd.format = formats[i];++ if (*links[j] != '\0' && *links[j] != '\1')+ links[j]++;+ }++ if (*name == '\0')+ break;+ }+ }++ if (list) {+ XFree(formats);+ }++ break;+ }+ if (E.xclient.message_type == XdndPosition) {+ const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;+ const i32 yabs = (E.xclient.data.l[2]) & 0xffff;+ Window dummy;+ i32 xpos, ypos;++ if (xdnd.version > 5)+ break;++ XTranslateCoordinates((Display*) win->src.display,+ XDefaultRootWindow((Display*) win->src.display),+ (Window) win->src.window,+ xabs, yabs,+ &xpos, &ypos,+ &dummy);++ win->event.point.x = xpos;+ win->event.point.y = ypos;++ XEvent reply = { ClientMessage };+ reply.xclient.window = xdnd.source;+ reply.xclient.message_type = XdndStatus;+ reply.xclient.format = 32;+ reply.xclient.data.l[0] = (long) win->src.window;+ reply.xclient.data.l[2] = 0;+ reply.xclient.data.l[3] = 0;++ if (xdnd.format) {+ reply.xclient.data.l[1] = 1;+ if (xdnd.version >= 2)+ reply.xclient.data.l[4] = XdndActionCopy;+ }++ XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);+ XFlush((Display*) win->src.display);+ break;+ }++ if (E.xclient.message_type != XdndDrop)+ break;++ if (xdnd.version > 5)+ break;++ win->event.type = RGFW_dnd_init;++ if (xdnd.format) {+ Time time = CurrentTime;++ if (xdnd.version >= 1)+ time = E.xclient.data.l[2];++ XConvertSelection((Display*) win->src.display,+ XdndSelection,+ xdnd.format,+ XdndSelection,+ (Window) win->src.window,+ time);+ } else if (xdnd.version >= 2) {+ XEvent reply = { ClientMessage };+ reply.xclient.window = xdnd.source;+ reply.xclient.message_type = XdndFinished;+ reply.xclient.format = 32;+ reply.xclient.data.l[0] = (long) win->src.window;+ reply.xclient.data.l[1] = 0;+ reply.xclient.data.l[2] = None;++ XSendEvent((Display*) win->src.display, xdnd.source,+ False, NoEventMask, &reply);+ XFlush((Display*) win->src.display);+ }++ RGFW_dndInitCallback(win, win->event.point);+ break;+ case SelectionNotify:+ /* this is only for checking for xdnd drops */+ if (E.xselection.property != XdndSelection || !(win->src.winArgs | RGFW_ALLOW_DND))+ break;++ char* data;+ u64 result;++ Atom actualType;+ i32 actualFormat;+ u64 bytesAfter;++ XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);++ if (result == 0)+ break;++ /*+ SOURCED FROM GLFW _glfwParseUriList+ Copyright (c) 2002-2006 Marcus Geelnard+ Copyright (c) 2006-2019 Camilla Löwy+ */++ const char* prefix = "file://";++ char* line;++ win->event.droppedFilesCount = 0;++ win->event.type = RGFW_dnd;++ while ((line = strtok(data, "\r\n"))) {+ char path[RGFW_MAX_PATH];++ data = NULL;++ if (line[0] == '#')+ continue;++ char* l;+ for (l = line; 1; l++) {+ if ((l - line) > 7)+ break;+ else if (*l != prefix[(l - line)])+ break;+ else if (*l == '\0' && prefix[(l - line)] == '\0') {+ line += 7;+ while (*line != '/')+ line++;+ break;+ } else if (*l == '\0')+ break;+ }++ win->event.droppedFilesCount++;++ size_t index = 0;+ while (*line) {+ if (line[0] == '%' && line[1] && line[2]) {+ const char digits[3] = { line[1], line[2], '\0' };+ path[index] = (char) strtol(digits, NULL, 16);+ line += 2;+ } else+ path[index] = *line;++ index++;+ line++;+ }+ path[index] = '\0';+ strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1);+ }++ if (data)+ XFree(data);++ if (xdnd.version >= 2) {+ XEvent reply = { ClientMessage };+ reply.xclient.window = xdnd.source;+ reply.xclient.message_type = XdndFinished;+ reply.xclient.format = 32;+ reply.xclient.data.l[0] = (long) win->src.window;+ reply.xclient.data.l[1] = result;+ reply.xclient.data.l[2] = XdndActionCopy;++ XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);+ XFlush((Display*) win->src.display);+ }++ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+ break;++ case FocusIn:+ win->event.inFocus = 1;+ win->event.type = RGFW_focusIn;+ RGFW_focusCallback(win, 1);+ break;++ break;+ case FocusOut:+ win->event.inFocus = 0;+ win->event.type = RGFW_focusOut;+ RGFW_focusCallback(win, 0);+ break;+ + case EnterNotify: {+ win->event.type = RGFW_mouseEnter;+ win->event.point.x = E.xcrossing.x;+ win->event.point.y = E.xcrossing.y;+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);+ break;+ }++ case LeaveNotify: {+ win->event.type = RGFW_mouseLeave;+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);+ break;+ }++ case ConfigureNotify: {+ /* detect resize */+ if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) {+ win->event.type = RGFW_windowResized;+ win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height);+ RGFW_windowResizeCallback(win, win->r);+ break;+ } + + /* detect move */+ if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) {+ win->event.type = RGFW_windowMoved;+ win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h);+ RGFW_windowMoveCallback(win, win->r);+ break;+ } ++ break;+ }+ default: {+ break;+ }+ }++ XFlush((Display*) win->src.display);++ if (win->event.type)+ return &win->event;+ else+ return NULL;+ }++ void RGFW_window_move(RGFW_window* win, RGFW_vector v) {+ assert(win != NULL);+ win->r.x = v.x;+ win->r.y = v.y;++ XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);+ }+++ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);+ win->r.w = a.w;+ win->r.h = a.h;++ XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);+ }++ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);++ if (a.w == 0 && a.h == 0)+ return;++ XSizeHints hints;+ long flags;++ XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);++ hints.flags |= PMinSize;+ + hints.min_width = a.w;+ hints.min_height = a.h;++ XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);+ }++ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);++ if (a.w == 0 && a.h == 0)+ return;++ XSizeHints hints;+ long flags;++ XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);++ hints.flags |= PMaxSize;++ hints.max_width = a.w;+ hints.max_height = a.h;++ XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);+ }+++ void RGFW_window_minimize(RGFW_window* win) {+ assert(win != NULL);++ XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));+ XFlush(win->src.display);+ }++ void RGFW_window_restore(RGFW_window* win) {+ assert(win != NULL);++ XMapWindow(win->src.display, (Window) win->src.window);+ XFlush(win->src.display);+ } ++ void RGFW_window_setName(RGFW_window* win, char* name) {+ assert(win != NULL);++ XStoreName((Display*) win->src.display, (Window) win->src.window, name);+ }+ + void* RGFW_libxshape = NULL;++ #ifndef RGFW_NO_PASSTHROUGH+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+ assert(win != NULL);+ + #if defined(__CYGWIN__)+ RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL);+ #elif defined(__OpenBSD__) || defined(__NetBSD__)+ RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL);+ #else+ RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL);+ #endif+ + typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);+ static PFN_XShapeCombineMask XShapeCombineMask;+ + typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);+ static PFN_XShapeCombineRegion XShapeCombineRegion;+ + if (XShapeCombineMask != NULL)+ XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask");++ if (XShapeCombineRegion != NULL)+ XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask");++ if (passthrough) {+ Region region = XCreateRegion();+ XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);+ XDestroyRegion(region);++ return;+ }++ XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);+ }+ #endif++ /*+ the majority function is sourced from GLFW+ */++ void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {+ assert(win != NULL);++ i32 longCount = 2 + a.w * a.h;++ u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));+ u64* target = X11Icon;++ *target++ = a.w;+ *target++ = a.h;++ u32 i;++ for (i = 0; i < a.w * a.h; i++) {+ if (channels == 3)+ *target++ = ((icon[i * 3 + 0]) << 16) |+ ((icon[i * 3 + 1]) << 8) |+ ((icon[i * 3 + 2]) << 0) |+ (0xFF << 24);++ else if (channels == 4)+ *target++ = ((icon[i * 4 + 0]) << 16) |+ ((icon[i * 4 + 1]) << 8) |+ ((icon[i * 4 + 2]) << 0) |+ ((icon[i * 4 + 3]) << 24);+ }++ static Atom NET_WM_ICON = 0;+ if (NET_WM_ICON == 0)+ NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);++ XChangeProperty((Display*) win->src.display, (Window) win->src.window,+ NET_WM_ICON,+ 6, 32,+ PropModeReplace,+ (u8*) X11Icon,+ longCount);++ RGFW_FREE(X11Icon);++ XFlush((Display*) win->src.display);+ }++ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+ assert(win != NULL);++#ifndef RGFW_NO_X11_CURSOR+ XcursorImage* native = XcursorImageCreate(a.w, a.h);+ native->xhot = 0;+ native->yhot = 0;++ u8* source = (u8*) image;+ XcursorPixel* target = native->pixels;++ u32 i;+ for (i = 0; i < a.w * a.h; i++, target++, source += 4) {+ u8 alpha = 0xFF;+ if (channels == 4)+ alpha = source[3];++ *target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);+ }++ Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native);+ XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);++ XFreeCursor((Display*) win->src.display, (Cursor) cursor);+ XcursorImageDestroy(native);+#else+ RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels)+#endif+ }++ void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {+ assert(win != NULL);++ XEvent event;+ XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),+ &event.xbutton.root, &event.xbutton.window,+ &event.xbutton.x_root, &event.xbutton.y_root,+ &event.xbutton.x, &event.xbutton.y,+ &event.xbutton.state);++ if (event.xbutton.x == v.x && event.xbutton.y == v.y)+ return;++ XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y);+ }++ RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {+ RGFW_UNUSED(win);+ }++ void RGFW_window_setMouseDefault(RGFW_window* win) {+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+ }++ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+ assert(win != NULL);++ if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))+ return;+ + mouse = RGFW_mouseIconSrc[mouse];++ Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse);+ XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);++ XFreeCursor((Display*) win->src.display, (Cursor) cursor);+ }++ void RGFW_window_hide(RGFW_window* win) {+ XMapWindow(win->src.display, win->src.window);+ }++ void RGFW_window_show(RGFW_window* win) {+ XUnmapWindow(win->src.display, win->src.window);+ }++ /*+ the majority function is sourced from GLFW+ */+ char* RGFW_readClipboard(size_t* size) {+ static Atom UTF8 = 0;+ if (UTF8 == 0)+ UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);++ XEvent event;+ int format;+ unsigned long N, sizeN;+ char* data, * s = NULL;+ Atom target;+ Atom CLIPBOARD = 0, XSEL_DATA = 0;++ if (CLIPBOARD == 0) {+ CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);+ XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);+ }++ XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);+ XSync(RGFW_root->src.display, 0);+ XNextEvent(RGFW_root->src.display, &event);++ if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)+ return NULL;++ XGetWindowProperty(event.xselection.display, event.xselection.requestor,+ event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,+ &format, &sizeN, &N, (unsigned char**) &data);++ if (target == UTF8 || target == XA_STRING) {+ s = (char*)RGFW_MALLOC(sizeof(char) * sizeN);+ strncpy(s, data, sizeN);+ s[sizeN] = '\0';+ XFree(data);+ }++ XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);++ if (s != NULL && size != NULL)+ *size = sizeN;++ return s;+ }++ /*+ almost all of this function is sourced from GLFW+ */+ void RGFW_writeClipboard(const char* text, u32 textLen) {+ static Atom CLIPBOARD = 0,+ UTF8_STRING = 0,+ SAVE_TARGETS = 0,+ TARGETS = 0,+ MULTIPLE = 0,+ ATOM_PAIR = 0,+ CLIPBOARD_MANAGER = 0;++ if (CLIPBOARD == 0) {+ CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);+ UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);+ SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);+ TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);+ MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);+ ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);+ CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);+ }++ XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);++ XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);++ for (;;) {+ XEvent event;++ XNextEvent((Display*) RGFW_root->src.display, &event);+ if (event.type != SelectionRequest)+ return;++ const XSelectionRequestEvent* request = &event.xselectionrequest;++ XEvent reply = { SelectionNotify };++ char* selectionString = NULL;+ const Atom formats[] = { UTF8_STRING, XA_STRING };+ const i32 formatCount = sizeof(formats) / sizeof(formats[0]);++ selectionString = (char*) text;++ if (request->target == TARGETS) {+ const Atom targets[] = { TARGETS,+ MULTIPLE,+ UTF8_STRING,+ XA_STRING };++ XChangeProperty((Display*) RGFW_root->src.display,+ request->requestor,+ request->property,+ 4,+ 32,+ PropModeReplace,+ (u8*) targets,+ sizeof(targets) / sizeof(targets[0]));++ reply.xselection.property = request->property;+ }++ if (request->target == MULTIPLE) {++ Atom* targets;++ Atom actualType;+ i32 actualFormat;+ u64 count, bytesAfter;++ XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);++ u64 i;+ for (i = 0; i < count; i += 2) {+ i32 j;++ for (j = 0; j < formatCount; j++) {+ if (targets[i] == formats[j])+ break;+ }++ if (j < formatCount)+ {+ XChangeProperty((Display*) RGFW_root->src.display,+ request->requestor,+ targets[i + 1],+ targets[i],+ 8,+ PropModeReplace,+ (u8*) selectionString,+ textLen);+ } else+ targets[i + 1] = None;+ }++ XChangeProperty((Display*) RGFW_root->src.display,+ request->requestor,+ request->property,+ ATOM_PAIR,+ 32,+ PropModeReplace,+ (u8*) targets,+ count);++ XFree(targets);++ reply.xselection.property = request->property;+ }++ reply.xselection.display = request->display;+ reply.xselection.requestor = request->requestor;+ reply.xselection.selection = request->selection;+ reply.xselection.target = request->target;+ reply.xselection.time = request->time;++ XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);+ }+ }++ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+ assert(win != NULL);++#ifdef __linux__+ char file[15];+ sprintf(file, "/dev/input/js%i", jsNumber);++ return RGFW_registerJoystickF(win, file);+#endif+ }++ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+ assert(win != NULL);++#ifdef __linux__++ i32 js = open(file, O_RDONLY);++ if (js && win->src.joystickCount < 4) {+ win->src.joystickCount++;++ win->src.joysticks[win->src.joystickCount - 1] = open(file, O_RDONLY);++ u8 i;+ for (i = 0; i < 16; i++)+ win->src.jsPressed[win->src.joystickCount - 1][i] = 0;++ }++ else {+#ifdef RGFW_PRINT_ERRORS+ RGFW_error = 1;+ fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);+#endif+ }++ return win->src.joystickCount - 1;+#endif+ }++ u8 RGFW_window_isFullscreen(RGFW_window* win) {+ assert(win != NULL);++ XWindowAttributes windowAttributes;+ XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);++ /* check if the window is visable */+ if (windowAttributes.map_state != IsViewable)+ return 0;++ /* check if the window covers the full screen */+ return (windowAttributes.x == 0 && windowAttributes.y == 0 &&+ windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&+ windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));+ }++ u8 RGFW_window_isHidden(RGFW_window* win) {+ assert(win != NULL);++ XWindowAttributes windowAttributes;+ XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);++ return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));+ }++ u8 RGFW_window_isMinimized(RGFW_window* win) {+ assert(win != NULL);++ static Atom prop = 0;+ if (prop == 0)+ prop = XInternAtom(win->src.display, "WM_STATE", False);++ Atom actual_type;+ i32 actual_format;+ u64 nitems, bytes_after;+ unsigned char* prop_data;++ i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,+ AnyPropertyType, &actual_type, &actual_format,+ &nitems, &bytes_after, &prop_data);++ if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {+ XFree(prop_data);+ return 1;+ }++ if (prop_data != NULL)+ XFree(prop_data);++ return 0;+ }++ u8 RGFW_window_isMaximized(RGFW_window* win) {+ assert(win != NULL);++ static Atom net_wm_state = 0;+ static Atom net_wm_state_maximized_horz = 0;+ static Atom net_wm_state_maximized_vert = 0;++ if (net_wm_state == 0) {+ net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);+ net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);+ net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);+ }++ Atom actual_type;+ i32 actual_format;+ u64 nitems, bytes_after;+ unsigned char* prop_data;++ i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,+ XA_ATOM, &actual_type, &actual_format,+ &nitems, &bytes_after, &prop_data);++ if (status != Success) {+ if (prop_data != NULL)+ XFree(prop_data);++ return 0;+ }++ Atom* atoms = (Atom*) prop_data;+ u64 i;+ for (i = 0; i < nitems; ++i) {+ if (atoms[i] == net_wm_state_maximized_horz ||+ atoms[i] == net_wm_state_maximized_vert) {+ XFree(prop_data);+ return 1;+ }+ }++ return 0;+ }++ static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {+ float xdpi = 96.f, ydpi = 96.f;++#ifndef RGFW_NO_DPI+ char* rms = XResourceManagerString(display);+ XrmDatabase db = NULL;++ if (rms && db)+ db = XrmGetStringDatabase(rms);++ if (db == 0) {+ *xscale = xdpi / 96.f;+ *yscale = ydpi / 96.f;+ return;+ }++ XrmValue value;+ char* type = NULL;++ if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0)+ xdpi = ydpi = atof(value.addr);+ XrmDestroyDatabase(db);+#endif++ * xscale = xdpi / 96.f;+ *yscale = ydpi / 96.f;+ }++ RGFW_monitor RGFW_XCreateMonitor(i32 screen) {+ RGFW_monitor monitor;++ Display* display = XOpenDisplay(NULL);++ monitor.rect = RGFW_RECT(0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen));+ monitor.physW = (monitor.rect.w * 25.4f / 96.f);+ monitor.physH = (monitor.rect.h * 25.4f / 96.f);++ strncpy(monitor.name, DisplayString(display), 128);++ XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);++ XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));++ XRRCrtcInfo* ci = NULL;+ int crtc = 0;++ if (sr->ncrtc > crtc) {+ ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);+ }++ if (ci == NULL) {+ XRRFreeScreenResources(sr);+ XCloseDisplay(display);+ return monitor;+ }++ monitor.rect.x = ci->x;+ monitor.rect.y = ci->y;++ XRRFreeCrtcInfo(ci);+ XRRFreeScreenResources(sr);++ XCloseDisplay(display);++ return monitor;+ }++ RGFW_monitor RGFW_monitors[6];+ RGFW_monitor* RGFW_getMonitors(void) {+ size_t i;+ for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++)+ RGFW_monitors[i] = RGFW_XCreateMonitor(i);++ return RGFW_monitors;+ }++ RGFW_monitor RGFW_getPrimaryMonitor(void) {+ assert(RGFW_root != NULL);++ i32 primary = -1;+ Window root = DefaultRootWindow(RGFW_root->src.display);+ XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);++ for (int i = 0; i < res->noutput; i++) {+ XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);+ if (output_info->connection == RR_Connected && output_info->crtc) {+ XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);+ if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {+ primary = i;+ XRRFreeCrtcInfo(crtc_info);+ XRRFreeOutputInfo(output_info);+ break;+ }+ XRRFreeCrtcInfo(crtc_info);+ }+ XRRFreeOutputInfo(output_info);+ }++ XRRFreeScreenResources(res);++ return RGFW_XCreateMonitor(primary);+ }++ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+ return RGFW_XCreateMonitor(DefaultScreen(win->src.display));+ }++ #ifdef RGFW_OPENGL+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+ assert(win != NULL);++ glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);+ }+ #endif+++ void RGFW_window_swapBuffers(RGFW_window* win) {+ assert(win != NULL);++ RGFW_window_makeCurrent(win);++ /* clear the window*/+ if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ #ifdef RGFW_OSMESA+ RGFW_OSMesa_reorganize();+ #endif+ RGFW_area area = RGFW_bufferSize;++#ifndef RGFW_X11_DONT_CONVERT_BGR+ win->src.bitmap->data = (char*) win->buffer;+ u32 x, y;+ for (y = 0; y < (u32)win->r.h; y++) {+ for (x = 0; x < (u32)win->r.w; x++) {+ u32 index = (y * 4 * area.w) + x * 4;++ u8 red = win->src.bitmap->data[index];+ win->src.bitmap->data[index] = win->buffer[index + 2];+ win->src.bitmap->data[index + 2] = red;++ }+ }+#endif + XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h);+#endif+ }++ if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {+ #ifdef RGFW_EGL+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+ #elif defined(RGFW_OPENGL)+ glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);+ #endif+ }++ RGFW_window_checkFPS(win);+ }++ #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+ assert(win != NULL);++ #if defined(RGFW_OPENGL) + ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);+ #endif++ win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;+ }+ #endif+++ void RGFW_window_close(RGFW_window* win) {+ assert(win != NULL);+#ifdef RGFW_EGL+ RGFW_closeEGL(win);+#endif++#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ if (win->buffer != NULL) {+ XDestroyImage((XImage*) win->src.bitmap);+ XFreeGC(win->src.display, win->src.gc);+ }+#endif++ if ((Display*) win->src.display) {+#ifdef RGFW_OPENGL+ glXDestroyContext((Display*) win->src.display, win->src.rSurf);+#endif++ if (win == RGFW_root)+ RGFW_root = NULL;++ if ((Drawable) win->src.window)+ XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/+ + XCloseDisplay((Display*) win->src.display); /* kill the display*/+ }++#ifdef RGFW_ALLOC_DROPFILES+ {+ u32 i;+ for (i = 0; i < RGFW_MAX_DROPS; i++)+ RGFW_FREE(win->event.droppedFiles[i]);+++ RGFW_FREE(win->event.droppedFiles);+ }+#endif++ RGFW_windowsOpen--;+#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)+ if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {+ dlclose(X11Cursorhandle);++ X11Cursorhandle = NULL;+ }+#endif++ if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) {+ dlclose(RGFW_libxshape);+ RGFW_libxshape = NULL;+ }++ /* set cleared display / window to NULL for error checking */+ win->src.display = (Display*) 0;+ win->src.window = (Window) 0;++ u8 i;+ for (i = 0; i < win->src.joystickCount; i++)+ close(win->src.joysticks[i]);++ RGFW_FREE(win); /* free collected window data */+ }++ u64 RGFW_getTimeNS(void) { + struct timespec ts = { 0 };+ clock_gettime(1, &ts);+ unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;++ return nanoSeconds;+ }++ u64 RGFW_getTime(void) {+ struct timespec ts = { 0 };+ clock_gettime(1, &ts);+ unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;++ return (double)(nanoSeconds) * 1e-9;+ }+/* + End of linux / unix defines+*/++#endif /* RGFW_X11 */+++/*++ Start of Windows defines+++*/++#ifdef RGFW_WINDOWS+ #include <processthreadsapi.h>+ #include <wchar.h>+ #include <locale.h>+ #include <windowsx.h>+ #include <shellapi.h>+ #include <shellscalingapi.h>+ #include <windows.h>+ #include <winuser.rh>++ #ifndef RGFW_NO_XINPUT+ typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);+ PFN_XInputGetState XInputGetStateSRC = NULL;+ #define XInputGetState XInputGetStateSRC++ typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);+ PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL;+ #define XInputGetKeystroke XInputGetKeystrokeSRC++ static HMODULE RGFW_XInput_dll = NULL;+ #endif++ u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO};++ char* createUTF8FromWideStringWin32(const WCHAR* source);++#define GL_FRONT 0x0404+#define GL_BACK 0x0405+#define GL_LEFT 0x0406+#define GL_RIGHT 0x0407++#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)++ typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);+ typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);+ typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);++ PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;+ PFN_OSMesaCreateContext OSMesaCreateContextSource;+ PFN_OSMesaDestroyContext OSMesaDestroyContextSource;++#define OSMesaCreateContext OSMesaCreateContextSource+#define OSMesaMakeCurrent OSMesaMakeCurrentSource+#define OSMesaDestroyContext OSMesaDestroyContextSource+#endif++ typedef int (*PFN_wglGetSwapIntervalEXT)(void);+ PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;+#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc++++#if defined(RGFW_DIRECTX)+ RGFW_directXinfo RGFW_dxInfo;++ RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }+#endif++ void* RGFWjoystickApi = NULL;++ /* these two wgl functions need to be preloaded */+ typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;++ /* defines for creating ARB attributes */+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092+#define WGL_DRAW_TO_WINDOW_ARB 0x2001+#define WGL_ACCELERATION_ARB 0x2003+#define WGL_NO_ACCELERATION_ARB 0x2025+#define WGL_SUPPORT_OPENGL_ARB 0x2010+#define WGL_DOUBLE_BUFFER_ARB 0x2011+#define WGL_COLOR_BITS_ARB 0x2014+#define WGL_RED_BITS_ARB 0x2015+#define WGL_RED_SHIFT_ARB 0x2016+#define WGL_GREEN_BITS_ARB 0x2017+#define WGL_GREEN_SHIFT_ARB 0x2018+#define WGL_BLUE_BITS_ARB 0x2019+#define WGL_BLUE_SHIFT_ARB 0x201a+#define WGL_ALPHA_BITS_ARB 0x201b+#define WGL_ALPHA_SHIFT_ARB 0x201c+#define WGL_ACCUM_BITS_ARB 0x201d+#define WGL_ACCUM_RED_BITS_ARB 0x201e+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021+#define WGL_DEPTH_BITS_ARB 0x2022+#define WGL_AUX_BUFFERS_ARB 0x2024+#define WGL_STEREO_ARB 0x2012+#define WGL_DEPTH_BITS_ARB 0x2022+#define WGL_STENCIL_BITS_ARB 0x2023+#define WGL_FULL_ACCELERATION_ARB 0x2027+#define WGL_CONTEXT_FLAGS_ARB 0x2094+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+#define WGL_SAMPLE_BUFFERS_ARB 0x2041+#define WGL_SAMPLES_ARB 0x2042+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9++#ifndef RGFW_EGL+static HMODULE wglinstance = NULL;+#endif++#ifdef RGFW_WGL_LOAD+ typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);+ typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);+ typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);+ typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);+ typedef HDC(WINAPI* PFN_wglGetCurrentDC)();+ typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();++ PFN_wglCreateContext wglCreateContextSRC;+ PFN_wglDeleteContext wglDeleteContextSRC;+ PFN_wglGetProcAddress wglGetProcAddressSRC;+ PFN_wglMakeCurrent wglMakeCurrentSRC;+ PFN_wglGetCurrentDC wglGetCurrentDCSRC;+ PFN_wglGetCurrentContext wglGetCurrentContextSRC;++ #define wglCreateContext wglCreateContextSRC+ #define wglDeleteContext wglDeleteContextSRC+ #define wglGetProcAddress wglGetProcAddressSRC+ #define wglMakeCurrent wglMakeCurrentSRC++ #define wglGetCurrentDC wglGetCurrentDCSRC+ #define wglGetCurrentContext wglGetCurrentContextSRC+#endif++#ifdef RGFW_OPENGL+ void* RGFW_getProcAddress(const char* procname) { + void* proc = (void*) wglGetProcAddress(procname);+ if (proc)+ return proc;++ return (void*) GetProcAddress(wglinstance, procname); + }++ typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);+ static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;+#endif++ RGFW_window RGFW_eventWindow;++ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {+ switch (message) {+ case WM_MOVE:+ RGFW_eventWindow.r.x = LOWORD(lParam);+ RGFW_eventWindow.r.y = HIWORD(lParam);+ RGFW_eventWindow.src.window = hWnd;+ return DefWindowProcA(hWnd, message, wParam, lParam);+ case WM_SIZE:+ RGFW_eventWindow.r.w = LOWORD(lParam);+ RGFW_eventWindow.r.h = HIWORD(lParam);+ RGFW_eventWindow.src.window = hWnd;+ return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling+ default:+ return DefWindowProcA(hWnd, message, wParam, lParam);+ }+ }+ + #ifndef RGFW_NO_DPI+ static HMODULE RGFW_Shcore_dll = NULL;+ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);+ PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;+ #define GetDpiForMonitor GetDpiForMonitorSRC+ #endif++ __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);++ #ifndef RGFW_NO_XINPUT+ void RGFW_loadXInput(void) {+ u32 i;+ static const char* names[] = { + "xinput1_4.dll",+ "xinput1_3.dll",+ "xinput9_1_0.dll",+ "xinput1_2.dll",+ "xinput1_1.dll"+ };++ for (i = 0; i < sizeof(names) / sizeof(const char*); i++) {+ RGFW_XInput_dll = LoadLibraryA(names[i]);++ if (RGFW_XInput_dll) {+ XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState");+ + if (XInputGetStateSRC == NULL)+ printf("Failed to load XInputGetState");+ }+ }+ }+ #endif++ RGFWDEF void RGFW_init_buffer(RGFW_window* win);+ void RGFW_init_buffer(RGFW_window* win) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+ RGFW_bufferSize = RGFW_getScreenSize();+ + BITMAPV5HEADER bi = { 0 };+ ZeroMemory(&bi, sizeof(bi));+ bi.bV5Size = sizeof(bi);+ bi.bV5Width = RGFW_bufferSize.w;+ bi.bV5Height = -((LONG) RGFW_bufferSize.h);+ bi.bV5Planes = 1;+ bi.bV5BitCount = 32;+ bi.bV5Compression = BI_BITFIELDS;+ bi.bV5BlueMask = 0x00ff0000;+ bi.bV5GreenMask = 0x0000ff00;+ bi.bV5RedMask = 0x000000ff;+ bi.bV5AlphaMask = 0xff000000;++ win->src.bitmap = CreateDIBSection(win->src.hdc,+ (BITMAPINFO*) &bi,+ DIB_RGB_COLORS,+ (void**) &win->buffer,+ NULL,+ (DWORD) 0);+ + win->src.hdcMem = CreateCompatibleDC(win->src.hdc);++ #if defined(RGFW_OSMESA)+ win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);+ OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+ #endif+#else+RGFW_UNUSED(win); /* if buffer rendering is not being used */+#endif+ }++ void RGFW_window_setDND(RGFW_window* win, b8 allow) {+ DragAcceptFiles(win->src.window, allow);+ }++ void RGFW_clipCursor(RGFW_rect rect) {+ if (!rect.x && !rect.y && rect.w && !rect.h) {+ ClipCursor(NULL);+ return;+ }++ RECT r = {rect.x, rect.y, rect.x + rect.w, rect.y + rect.h};+ ClipCursor(&r);+ }++ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+ #ifndef RGFW_NO_XINPUT+ if (RGFW_XInput_dll == NULL)+ RGFW_loadXInput();+ #endif++ #ifndef RGFW_NO_DPI+ if (RGFW_Shcore_dll == NULL) {+ RGFW_Shcore_dll = LoadLibraryA("shcore.dll");+ GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");+ }+ #endif++ if (wglinstance == NULL) {+ wglinstance = LoadLibraryA("opengl32.dll");+#ifdef RGFW_WGL_LOAD+ wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");+ wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");+ wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");+ wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");+ wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");+ wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");+#endif+ }++ timeBeginPeriod(1);++ if (name[0] == 0) name = (char*) " ";++ RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);+ RGFW_eventWindow.src.window = NULL;++ RGFW_window* win = RGFW_window_basic_init(rect, args);++ win->src.maxSize = RGFW_AREA(0, 0);+ win->src.minSize = RGFW_AREA(0, 0);+++ HINSTANCE inh = GetModuleHandleA(NULL);++ WNDCLASSA Class = { 0 }; /* Setup the Window class. */+ Class.lpszClassName = name;+ Class.hInstance = inh;+ Class.hCursor = LoadCursor(NULL, IDC_ARROW);+ Class.lpfnWndProc = WndProc;++ RegisterClassA(&Class);++ DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;++ RECT windowRect, clientRect;++ if (!(args & RGFW_NO_BORDER)) {+ window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX;++ if (!(args & RGFW_NO_RESIZE))+ window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;+ } else+ window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;++ HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);++ GetWindowRect(dummyWin, &windowRect);+ GetClientRect(dummyWin, &clientRect);++ win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);+ win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0);++ if (args & RGFW_ALLOW_DND) {+ win->src.winArgs |= RGFW_ALLOW_DND;+ RGFW_window_setDND(win, 1);+ }+ win->src.hdc = GetDC(win->src.window);++ if ((args & RGFW_NO_INIT_API) == 0) {+#ifdef RGFW_DIRECTX+ assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);++ if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {+ fprintf(stderr, "Failed to enumerate DXGI adapters\n");+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+ return NULL;+ }++ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };++ if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {+ fprintf(stderr, "Failed to create Direct3D device\n");+ RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+ return NULL;+ }++ DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };+ swapChainDesc.BufferCount = 1;+ swapChainDesc.BufferDesc.Width = win->r.w;+ swapChainDesc.BufferDesc.Height = win->r.h;+ swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;+ swapChainDesc.OutputWindow = win->src.window;+ swapChainDesc.SampleDesc.Count = 1;+ swapChainDesc.SampleDesc.Quality = 0;+ swapChainDesc.Windowed = TRUE;+ RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);++ ID3D11Texture2D* pBackBuffer;+ win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);+ RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);+ pBackBuffer->lpVtbl->Release(pBackBuffer);++ D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };+ depthStencilDesc.Width = win->r.w;+ depthStencilDesc.Height = win->r.h;+ depthStencilDesc.MipLevels = 1;+ depthStencilDesc.ArraySize = 1;+ depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;+ depthStencilDesc.SampleDesc.Count = 1;+ depthStencilDesc.SampleDesc.Quality = 0;+ depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;+ depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;++ ID3D11Texture2D* pDepthStencilTexture = NULL;+ RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);++ D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };+ depthStencilViewDesc.Format = depthStencilDesc.Format;+ depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;+ depthStencilViewDesc.Texture2D.MipSlice = 0;++ RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);++ pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);++ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);+#endif++#ifdef RGFW_OPENGL + HDC dummy_dc = GetDC(dummyWin);++ PIXELFORMATDESCRIPTOR pfd = {+ .nSize = sizeof(pfd),+ .nVersion = 1,+ .iPixelType = PFD_TYPE_RGBA,+ .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,+ .cColorBits = 24,+ .cAlphaBits = 8,+ .iLayerType = PFD_MAIN_PLANE,+ .cDepthBits = 32,+ .cStencilBits = 8,+ };++ int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);+ SetPixelFormat(dummy_dc, pixel_format, &pfd);++ HGLRC dummy_context = wglCreateContext(dummy_dc);+ wglMakeCurrent(dummy_dc, dummy_context);++ if (wglChoosePixelFormatARB == NULL) {+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB");+ wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB");+ }++ wglMakeCurrent(dummy_dc, 0);+ wglDeleteContext(dummy_context);+ ReleaseDC(dummyWin, dummy_dc);++ if (wglCreateContextAttribsARB != NULL) {+ PIXELFORMATDESCRIPTOR pfd = (PIXELFORMATDESCRIPTOR){ sizeof(pfd), 1, PFD_TYPE_RGBA, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};++ if (args & RGFW_OPENGL_SOFTWARE)+ pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;++ if (wglChoosePixelFormatARB != NULL) {+ i32* pixel_format_attribs = (i32*)RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);++ int pixel_format;+ UINT num_formats;+ wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);+ if (!num_formats) {+ printf("Failed to set the OpenGL 3.3 pixel format.\n");+ }++ DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);+ if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {+ printf("Failed to set the OpenGL 3.3 pixel format.\n");+ }+ }++ u32 index = 0;+ i32 attribs[40];++ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);++ if (RGFW_majorVersion || RGFW_minorVersion) {+ SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);+ SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);+ }++ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);++ if (RGFW_majorVersion || RGFW_minorVersion) {+ SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);+ SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);+ }++ SET_ATTRIB(0, 0);++ win->src.rSurf = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);+ } else {+ fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");++ int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);+ SetPixelFormat(win->src.hdc, pixel_format, &pfd);++ win->src.rSurf = wglCreateContext(win->src.hdc);+ }+ + wglMakeCurrent(win->src.hdc, win->src.rSurf);+#endif+ }++#ifdef RGFW_OSMESA+#ifdef RGFW_LINK_OSM ESA+ OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");+ OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");+ OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");+#endif+#endif++#ifdef RGFW_OPENGL+ if ((args & RGFW_NO_INIT_API) == 0) {+ ReleaseDC(win->src.window, win->src.hdc);+ win->src.hdc = GetDC(win->src.window);+ wglMakeCurrent(win->src.hdc, win->src.rSurf);+ }+#endif++ DestroyWindow(dummyWin);+ RGFW_init_buffer(win);+++ #ifndef RGFW_NO_MONITOR+ if (args & RGFW_SCALE_TO_MONITOR)+ RGFW_window_scaleToMonitor(win);+ #endif++#ifdef RGFW_EGL+ if ((args & RGFW_NO_INIT_API) == 0)+ RGFW_createOpenGLContext(win);+#endif++ if (args & RGFW_HIDE_MOUSE)+ RGFW_window_showMouse(win, 0);++ if (args & RGFW_TRANSPARENT_WINDOW) {+ SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);+ SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA);+ }++ ShowWindow(win->src.window, SW_SHOWNORMAL);+ + if (RGFW_root == NULL)+ RGFW_root = win;+ + #ifdef RGFW_OPENGL+ else + wglShareLists(RGFW_root->src.rSurf, win->src.rSurf);+ #endif++ return win;+ }++ void RGFW_window_setBorder(RGFW_window* win, u8 border) {+ DWORD style = GetWindowLong(win->src.window, GWL_STYLE);++ if (border == 0) {+ SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);+ SetWindowPos(+ win->src.window, HWND_TOP, 0, 0, 0, 0,+ SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE+ );+ }+ else {+ SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);+ SetWindowPos(+ win->src.window, HWND_TOP, 0, 0, 0, 0,+ SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE+ );+ }+ }+++ RGFW_area RGFW_getScreenSize(void) {+ return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));+ }++ RGFW_vector RGFW_getGlobalMousePoint(void) {+ POINT p;+ GetCursorPos(&p);++ return RGFW_VECTOR(p.x, p.y);+ }++ RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {+ POINT p;+ GetCursorPos(&p);+ ScreenToClient(win->src.window, &p);++ return RGFW_VECTOR(p.x, p.y);+ }++ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);+ win->src.minSize = a;+ }++ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);+ win->src.maxSize = a;+ }+++ void RGFW_window_minimize(RGFW_window* win) {+ assert(win != NULL);++ ShowWindow(win->src.window, SW_MINIMIZE);+ }++ void RGFW_window_restore(RGFW_window* win) {+ assert(win != NULL);++ ShowWindow(win->src.window, SW_RESTORE);+ }+++ u8 RGFW_xinput2RGFW[] = {+ RGFW_JS_A, /* or PS X button */+ RGFW_JS_B, /* or PS circle button */+ RGFW_JS_X, /* or PS square button */+ RGFW_JS_Y, /* or PS triangle button */+ RGFW_JS_R1, /* right bumper */+ RGFW_JS_L1, /* left bump */+ RGFW_JS_L2, /* left trigger*/+ RGFW_JS_R2, /* right trigger */+ 0, 0, 0, 0, 0, 0, 0, 0,+ RGFW_JS_UP, /* dpad up */+ RGFW_JS_DOWN, /* dpad down*/+ RGFW_JS_LEFT, /* dpad left */+ RGFW_JS_RIGHT, /* dpad right */+ RGFW_JS_START, /* start button */+ RGFW_JS_SELECT/* select button */+ };++ static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) {+ size_t i;+ for (i = 0; i < 4; i++) {+ XINPUT_KEYSTROKE keystroke;++ if (XInputGetKeystroke == NULL)+ return 0;++ DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke);++ if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) {+ if (result != ERROR_SUCCESS)+ return 0;++ if (keystroke.VirtualKey > VK_PAD_BACK)+ continue;++ // RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased+ e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);+ e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800];+ win->src.jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);++ return 1;+ }++ XINPUT_STATE state;+ if (XInputGetState == NULL ||+ XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED+ )+ return 0;+#define INPUT_DEADZONE ( 0.24f * (float)(0x7FFF) ) // Default to 24% of the +/- 32767 range. This is a reasonable default value but can be altered if needed.++ if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&+ state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&+ (state.Gamepad.sThumbLY < INPUT_DEADZONE &&+ state.Gamepad.sThumbLY > -INPUT_DEADZONE))+ {+ state.Gamepad.sThumbLX = 0;+ state.Gamepad.sThumbLY = 0;+ }++ if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&+ state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&+ (state.Gamepad.sThumbRY < INPUT_DEADZONE &&+ state.Gamepad.sThumbRY > -INPUT_DEADZONE))+ {+ state.Gamepad.sThumbRX = 0;+ state.Gamepad.sThumbRY = 0;+ }++ e->axisesCount = 2;+ RGFW_vector axis1 = RGFW_VECTOR(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);+ RGFW_vector axis2 = RGFW_VECTOR(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);++ if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) {+ e->type = RGFW_jsAxisMove;++ e->axis[0] = axis1;+ e->axis[1] = axis2;++ return 1;+ }++ e->axis[0] = axis1;+ e->axis[1] = axis2;+ }++ return 0;+ }++ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+ assert(win != NULL);++ if (win->event.type == RGFW_quit) {+ return NULL;+ }++ MSG msg;++ if (RGFW_eventWindow.src.window == win->src.window) {+ if (RGFW_eventWindow.r.x != -1) {+ win->r.x = RGFW_eventWindow.r.x;+ win->r.y = RGFW_eventWindow.r.y;+ win->event.type = RGFW_windowMoved;+ RGFW_windowMoveCallback(win, win->r);+ }++ if (RGFW_eventWindow.r.w != -1) {+ win->r.w = RGFW_eventWindow.r.w;+ win->r.h = RGFW_eventWindow.r.h;+ win->event.type = RGFW_windowResized;+ RGFW_windowResizeCallback(win, win->r);+ }++ RGFW_eventWindow.src.window = NULL;+ RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);++ return &win->event;+ }+++ static HDROP drop;+ + if (win->event.type == RGFW_dnd_init) {+ if (win->event.droppedFilesCount) {+ u32 i;+ for (i = 0; i < win->event.droppedFilesCount; i++)+ win->event.droppedFiles[i][0] = '\0';+ }++ win->event.droppedFilesCount = 0;+ win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);+ //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));++ u32 i;+ for (i = 0; i < win->event.droppedFilesCount; i++) {+ const UINT length = DragQueryFileW(drop, i, NULL, 0);+ WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));++ DragQueryFileW(drop, i, buffer, length + 1);+ strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH);+ win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';+ RGFW_FREE(buffer);+ }++ DragFinish(drop);+ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+ + win->event.type = RGFW_dnd;+ return &win->event;+ }++ win->event.inFocus = (GetForegroundWindow() == win->src.window);++ if (RGFW_checkXInput(win, &win->event))+ return &win->event;++ static BYTE keyboardState[256];++ if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {+ switch (msg.message) {+ case WM_CLOSE:+ case WM_QUIT:+ RGFW_windowQuitCallback(win);+ win->event.type = RGFW_quit;+ break;++ case WM_ACTIVATE:+ win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE);++ if (win->event.inFocus) {+ win->event.type = RGFW_focusIn;+ RGFW_focusCallback(win, 1);+ }+ else {+ win->event.type = RGFW_focusOut;+ RGFW_focusCallback(win, 0);+ }++ break;+ + case WM_PAINT:+ win->event.type = RGFW_windowRefresh;+ RGFW_windowRefreshCallback(win);+ break;+ + case WM_MOUSELEAVE:+ win->event.type = RGFW_mouseLeave;+ win->src.winArgs |= RGFW_MOUSE_LEFT;+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);+ break;+ + case WM_KEYUP: {+ win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);+ + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);++ static char keyName[16];+ + {+ GetKeyNameTextA((LONG) msg.lParam, keyName, 16);++ if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||+ ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {+ CharLowerBuffA(keyName, 16);+ }+ }++ RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));++ strncpy(win->event.keyName, keyName, 16);++ if (RGFW_isPressed(win, RGFW_ShiftL)) {+ ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),+ keyboardState, (LPWORD) win->event.keyName, 0);+ }++ win->event.type = RGFW_keyReleased;+ RGFW_keyboard[win->event.keyCode].current = 0;+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);+ break;+ }+ case WM_KEYDOWN: {+ win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);++ RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);++ static char keyName[16];+ + {+ GetKeyNameTextA((LONG) msg.lParam, keyName, 16);++ if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||+ ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {+ CharLowerBuffA(keyName, 16);+ }+ }+ + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));++ strncpy(win->event.keyName, keyName, 16);++ if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) {+ ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),+ keyboardState, (LPWORD) win->event.keyName, 0);+ }++ win->event.type = RGFW_keyPressed;+ RGFW_keyboard[win->event.keyCode].current = 1;+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);+ break;+ }++ case WM_MOUSEMOVE:+ win->event.type = RGFW_mousePosChanged;++ win->event.point.x = GET_X_LPARAM(msg.lParam);+ win->event.point.y = GET_Y_LPARAM(msg.lParam);++ RGFW_mousePosCallback(win, win->event.point);++ if (win->src.winArgs & RGFW_MOUSE_LEFT) {+ win->src.winArgs ^= RGFW_MOUSE_LEFT;+ win->event.type = RGFW_mouseEnter;+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);+ }++ break;++ case WM_LBUTTONDOWN:+ win->event.button = RGFW_mouseLeft;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;+ case WM_RBUTTONDOWN:+ win->event.button = RGFW_mouseRight;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;+ case WM_MBUTTONDOWN:+ win->event.button = RGFW_mouseMiddle;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;++ case WM_MOUSEWHEEL:+ if (msg.wParam > 0)+ win->event.button = RGFW_mouseScrollUp;+ else+ win->event.button = RGFW_mouseScrollDown;++ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;++ win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;++ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;++ case WM_LBUTTONUP:+ + win->event.button = RGFW_mouseLeft;+ win->event.type = RGFW_mouseButtonReleased;++ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;+ case WM_RBUTTONUP:+ win->event.button = RGFW_mouseRight;+ win->event.type = RGFW_mouseButtonReleased;++ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;+ case WM_MBUTTONUP:+ win->event.button = RGFW_mouseMiddle;+ win->event.type = RGFW_mouseButtonReleased;++ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;++ /*+ much of this event is source from glfw+ */+ case WM_DROPFILES: { + win->event.type = RGFW_dnd_init;++ drop = (HDROP) msg.wParam;+ POINT pt;++ /* Move the mouse to the position of the drop */+ DragQueryPoint(drop, &pt);++ win->event.point.x = pt.x;+ win->event.point.y = pt.y;++ RGFW_dndInitCallback(win, win->event.point);+ }+ break;+ case WM_GETMINMAXINFO:+ {+ if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)+ break;++ MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;+ mmi->ptMinTrackSize.x = win->src.minSize.w;+ mmi->ptMinTrackSize.y = win->src.minSize.h;+ mmi->ptMaxTrackSize.x = win->src.maxSize.w;+ mmi->ptMaxTrackSize.y = win->src.maxSize.h;+ return 0;+ }+ default:+ win->event.type = 0;+ break;+ }++ TranslateMessage(&msg);+ DispatchMessageA(&msg);+ }++ else+ win->event.type = 0;++ if (!IsWindow(win->src.window)) {+ win->event.type = RGFW_quit;+ RGFW_windowQuitCallback(win);+ }++ if (win->event.type)+ return &win->event;+ else+ return NULL;+ }++ u8 RGFW_window_isFullscreen(RGFW_window* win) {+ assert(win != NULL);++ WINDOWPLACEMENT placement = { 0 };+ GetWindowPlacement(win->src.window, &placement);+ return placement.showCmd == SW_SHOWMAXIMIZED;+ }++ u8 RGFW_window_isHidden(RGFW_window* win) {+ assert(win != NULL);++ return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);+ }++ u8 RGFW_window_isMinimized(RGFW_window* win) {+ assert(win != NULL);++ WINDOWPLACEMENT placement = { 0 };+ GetWindowPlacement(win->src.window, &placement);+ return placement.showCmd == SW_SHOWMINIMIZED;+ }++ u8 RGFW_window_isMaximized(RGFW_window* win) {+ assert(win != NULL);++ WINDOWPLACEMENT placement = { 0 };+ GetWindowPlacement(win->src.window, &placement);+ return placement.showCmd == SW_SHOWMAXIMIZED;+ }++ typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;+ BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {+ RGFW_UNUSED(hdcMonitor)+ RGFW_UNUSED(lprcMonitor)++ RGFW_mInfo* info = (RGFW_mInfo*) dwData;+ if (info->hMonitor == hMonitor)+ return FALSE;++ info->iIndex++;+ return TRUE;+ }+ + #ifndef RGFW_NO_MONITOR+ RGFW_monitor win32CreateMonitor(HMONITOR src) {+ RGFW_monitor monitor;+ MONITORINFO monitorInfo;++ monitorInfo.cbSize = sizeof(MONITORINFO);+ GetMonitorInfoA(src, &monitorInfo);++ RGFW_mInfo info;+ info.iIndex = 0;+ info.hMonitor = src;++ /* get the monitor's index */+ if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {+ DISPLAY_DEVICEA dd;+ dd.cb = sizeof(dd);++ /* loop through the devices until you find a device with the monitor's index */+ size_t deviceIndex;+ for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {+ char* deviceName = dd.DeviceName;+ if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {+ strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */+ break;+ }+ }+ }++ monitor.rect.x = monitorInfo.rcWork.left;+ monitor.rect.y = monitorInfo.rcWork.top;+ monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;+ monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;++#ifndef RGFW_NO_DPI+ if (GetDpiForMonitor != NULL) {+ u32 x, y;+ GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y);+ monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;+ monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;+ }+#endif++ HDC hdc = GetDC(NULL);+ /* get pixels per inch */+ i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);+ i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);+ ReleaseDC(NULL, hdc);++ /* Calculate physical height in inches */+ monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;+ monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;++ return monitor;+ }+ #endif /* RGFW_NO_MONITOR */+ ++ #ifndef RGFW_NO_MONITOR+ RGFW_monitor RGFW_monitors[6];+ BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {+ RGFW_UNUSED(hdcMonitor)+ RGFW_UNUSED(lprcMonitor)++ RGFW_mInfo* info = (RGFW_mInfo*) dwData;++ if (info->iIndex >= 6)+ return FALSE;++ RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);+ info->iIndex++;++ return TRUE;+ }++ RGFW_monitor RGFW_getPrimaryMonitor(void) {+ return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));+ }++ RGFW_monitor* RGFW_getMonitors(void) {+ RGFW_mInfo info;+ info.iIndex = 0;+ while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));++ return RGFW_monitors;+ }++ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+ HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);+ return win32CreateMonitor(src);+ }+ #endif++ HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {+ assert(win != NULL);++ u32 i;+ HDC dc;+ HICON handle;+ HBITMAP color, mask;+ BITMAPV5HEADER bi;+ ICONINFO ii;+ u8* target = NULL;+ u8* source = src;++ ZeroMemory(&bi, sizeof(bi));+ bi.bV5Size = sizeof(bi);+ bi.bV5Width = a.w;+ bi.bV5Height = -((LONG) a.h);+ bi.bV5Planes = 1;+ bi.bV5BitCount = 32;+ bi.bV5Compression = BI_BITFIELDS;+ bi.bV5RedMask = 0x00ff0000;+ bi.bV5GreenMask = 0x0000ff00;+ bi.bV5BlueMask = 0x000000ff;+ bi.bV5AlphaMask = 0xff000000;++ dc = GetDC(NULL);+ color = CreateDIBSection(dc,+ (BITMAPINFO*) &bi,+ DIB_RGB_COLORS,+ (void**) &target,+ NULL,+ (DWORD) 0);+ ReleaseDC(NULL, dc);++ mask = CreateBitmap(a.w, a.h, 1, 1, NULL);++ for (i = 0; i < a.w * a.h; i++) {+ target[0] = source[2];+ target[1] = source[1];+ target[2] = source[0];+ target[3] = source[3];+ target += 4;+ source += 4;+ }++ ZeroMemory(&ii, sizeof(ii));+ ii.fIcon = icon;+ ii.xHotspot = 0;+ ii.yHotspot = 0;+ ii.hbmMask = mask;+ ii.hbmColor = color;++ handle = CreateIconIndirect(&ii);++ DeleteObject(color);+ DeleteObject(mask);++ return handle;+ }++ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+ assert(win != NULL);+ RGFW_UNUSED(channels)++ HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);+ SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);+ SetCursor(cursor);+ DestroyCursor(cursor);+ }++ void RGFW_window_setMouseDefault(RGFW_window* win) {+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+ }++ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {+ assert(win != NULL);++ if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32)))+ return;++ char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]);++ SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));+ SetCursor(LoadCursorA(NULL, icon));+ }++ void RGFW_window_hide(RGFW_window* win) {+ ShowWindow(win->src.window, SW_HIDE);+ }++ void RGFW_window_show(RGFW_window* win) {+ ShowWindow(win->src.window, SW_RESTORE);+ }++ void RGFW_window_close(RGFW_window* win) {+ assert(win != NULL);++#ifdef RGFW_EGL+ RGFW_closeEGL(win);+#endif++ if (win == RGFW_root) {+#ifdef RGFW_DIRECTX+ RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);+ RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);+ RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);+#endif+ + if (RGFW_XInput_dll != NULL) {+ FreeLibrary(RGFW_XInput_dll);+ RGFW_XInput_dll = NULL;+ }++ #ifndef RGFW_NO_DPI+ if (RGFW_Shcore_dll != NULL) {+ FreeLibrary(RGFW_Shcore_dll);+ RGFW_Shcore_dll = NULL;+ }+ #endif++ if (wglinstance != NULL) {+ FreeLibrary(wglinstance);+ wglinstance = NULL;+ }++ RGFW_root = NULL;+ }++#ifdef RGFW_DIRECTX+ win->src.swapchain->lpVtbl->Release(win->src.swapchain);+ win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);+ win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);+#endif++#ifdef RGFW_BUFFER+ DeleteDC(win->src.hdcMem);+ DeleteObject(win->src.bitmap);+#endif++#ifdef RGFW_OPENGL+ wglDeleteContext((HGLRC) win->src.rSurf); /* delete opengl context */+#endif+ DeleteDC(win->src.hdc); /* delete device context */+ DestroyWindow(win->src.window); /* delete window */++#if defined(RGFW_OSMESA)+ if (win->buffer != NULL)+ RGFW_FREE(win->buffer);+#endif++#ifdef RGFW_ALLOC_DROPFILES+ {+ u32 i;+ for (i = 0; i < RGFW_MAX_DROPS; i++)+ RGFW_FREE(win->event.droppedFiles[i]);+++ RGFW_FREE(win->event.droppedFiles);+ }+#endif++ RGFW_FREE(win);+ }++ void RGFW_window_move(RGFW_window* win, RGFW_vector v) {+ assert(win != NULL);++ win->r.x = v.x;+ win->r.y = v.y;+ SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);+ }++ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);++ win->r.w = a.w;+ win->r.h = a.h;+ SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);+ }+++ void RGFW_window_setName(RGFW_window* win, char* name) {+ assert(win != NULL);++ SetWindowTextA(win->src.window, name);+ }++ /* sourced from GLFW */+ #ifndef RGFW_NO_PASSTHROUGH+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+ assert(win != NULL);+ + COLORREF key = 0;+ BYTE alpha = 0;+ DWORD flags = 0;+ DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);+ + if (exStyle & WS_EX_LAYERED)+ GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);++ if (passthrough)+ exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);+ else+ {+ exStyle &= ~WS_EX_TRANSPARENT;+ // NOTE: Window opacity also needs the layered window style so do not+ // remove it if the window is alpha blended+ if (exStyle & WS_EX_LAYERED)+ {+ if (!(flags & LWA_ALPHA))+ exStyle &= ~WS_EX_LAYERED;+ }+ }++ SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);++ if (passthrough) {+ SetLayeredWindowAttributes(win->src.window, key, alpha, flags);+ }+ }+ #endif++ /* much of this function is sourced from GLFW */+ void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {+ assert(win != NULL);+ #ifndef RGFW_WIN95+ RGFW_UNUSED(channels)++ HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);++ SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);++ DestroyIcon(handle);+ #else+ RGFW_UNUSED(src)+ RGFW_UNUSED(a)+ RGFW_UNUSED(channels)+ #endif+ }++ char* RGFW_readClipboard(size_t* size) {+ /* Open the clipboard */+ if (OpenClipboard(NULL) == 0)+ return (char*) "";++ /* Get the clipboard data as a Unicode string */+ HANDLE hData = GetClipboardData(CF_UNICODETEXT);+ if (hData == NULL) {+ CloseClipboard();+ return (char*) "";+ }++ wchar_t* wstr = (wchar_t*) GlobalLock(hData);++ char* text;++ {+ setlocale(LC_ALL, "en_US.UTF-8");++ size_t textLen = wcstombs(NULL, wstr, 0);+ if (textLen == 0)+ return (char*) "";++ text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1);++ wcstombs(text, wstr, (textLen) +1);++ if (size != NULL)+ *size = textLen + 1;++ text[textLen] = '\0';+ }++ /* Release the clipboard data */+ GlobalUnlock(hData);+ CloseClipboard();++ return text;+ }++ void RGFW_writeClipboard(const char* text, u32 textLen) {+ HANDLE object;+ WCHAR* buffer;++ object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));+ if (!object)+ return;++ buffer = (WCHAR*) GlobalLock(object);+ if (!buffer) {+ GlobalFree(object);+ return;+ }++ MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);+ GlobalUnlock(object);++ if (!OpenClipboard(RGFW_root->src.window)) {+ GlobalFree(object);+ return;+ }++ EmptyClipboard();+ SetClipboardData(CF_UNICODETEXT, object);+ CloseClipboard();+ }++ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+ assert(win != NULL);++ RGFW_UNUSED(jsNumber)++ return RGFW_registerJoystickF(win, (char*) "");+ }++ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+ assert(win != NULL);+ RGFW_UNUSED(file)++ return win->src.joystickCount - 1;+ }++ void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector p) {+ assert(win != NULL);++ SetCursorPos(p.x, p.y);+ }++ #ifdef RGFW_OPENGL+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+ assert(win != NULL);+ wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf);+ }+ #endif++ #ifndef RGFW_EGL+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+ assert(win != NULL);+ + #if defined(RGFW_OPENGL)+ typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);+ static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;+ static void* loadSwapFunc = (void*) 1;++ if (loadSwapFunc == NULL) {+ fprintf(stderr, "wglSwapIntervalEXT not supported\n");+ win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;+ return;+ }++ if (wglSwapIntervalEXT == NULL) {+ loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;+ }++ if (wglSwapIntervalEXT(swapInterval) == FALSE)+ fprintf(stderr, "Failed to set swap interval\n");+ #endif++ win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;++ }+ #endif++ void RGFW_window_swapBuffers(RGFW_window* win) {+ assert(win != NULL);++ RGFW_window_makeCurrent(win);++ /* clear the window*/++ if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ #ifdef RGFW_OSMESA+ RGFW_OSMesa_reorganize();+ #endif++ HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);+ BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);+ SelectObject(win->src.hdcMem, oldbmp);+#endif+ }++ if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {+ #ifdef RGFW_EGL+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+ #elif defined(RGFW_OPENGL)+ SwapBuffers(win->src.hdc);+ #endif++ #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)+ win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);+ #endif+ }++ RGFW_window_checkFPS(win);+ }++ char* createUTF8FromWideStringWin32(const WCHAR* source) {+ char* target;+ i32 size;++ size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);+ if (!size) {+ return NULL;+ }++ target = (char*) RGFW_CALLOC(size, 1);++ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {+ RGFW_FREE(target);+ return NULL;+ }++ return target;+ }++ u64 RGFW_getTimeNS(void) {+ LARGE_INTEGER frequency;+ QueryPerformanceFrequency(&frequency);++ LARGE_INTEGER counter;+ QueryPerformanceCounter(&counter);++ return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart);+ }++ u64 RGFW_getTime(void) {+ LARGE_INTEGER frequency;+ QueryPerformanceFrequency(&frequency);++ LARGE_INTEGER counter;+ QueryPerformanceCounter(&counter);+ return (u64) (counter.QuadPart / (double) frequency.QuadPart);+ }+ + void RGFW_sleep(u64 ms) {+ Sleep(ms);+ }++#ifndef RGFW_NO_THREADS+ RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); }+ void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }+ void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }+ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }+#endif+#endif /* RGFW_WINDOWS */++/*+ End of Windows defines+*/++++/* ++ Start of MacOS defines+++*/++#if defined(RGFW_MACOS)+ /*+ based on silicon.h+ start of cocoa wrapper+ */++#include <CoreVideo/CVDisplayLink.h>+#include <ApplicationServices/ApplicationServices.h>+#include <objc/runtime.h>+#include <objc/message.h>+#include <mach/mach_time.h>++ typedef CGRect NSRect;+ typedef CGPoint NSPoint;+ typedef CGSize NSSize;++ typedef void NSBitmapImageRep;+ typedef void NSCursor;+ typedef void NSDraggingInfo;+ typedef void NSWindow;+ typedef void NSApplication;+ typedef void NSScreen;+ typedef void NSEvent;+ typedef void NSString;+ typedef void NSOpenGLContext;+ typedef void NSPasteboard;+ typedef void NSColor;+ typedef void NSArray;+ typedef void NSImageRep;+ typedef void NSImage;+ typedef void NSOpenGLView;+++ typedef const char* NSPasteboardType;+ typedef unsigned long NSUInteger;+ typedef long NSInteger;+ typedef NSInteger NSModalResponse;++#ifdef __arm64__+ /* ARM just uses objc_msgSend */+#define abi_objc_msgSend_stret objc_msgSend+#define abi_objc_msgSend_fpret objc_msgSend+#else /* __i386__ */ + /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */+#define abi_objc_msgSend_stret objc_msgSend_stret+#define abi_objc_msgSend_fpret objc_msgSend_fpret+#endif++#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))+#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend)+#define objc_msgSend_uint ((NSUInteger (*)(id, SEL))objc_msgSend)+#define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend)+#define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend)+#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend)++ void NSRelease(id obj) {+ objc_msgSend_void(obj, sel_registerName("release"));+ }++ #define release NSRelease++ NSString* NSString_stringWithUTF8String(const char* str) { + return ((id(*)(id, SEL, const char*))objc_msgSend)+ ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);+ }++ const char* NSString_to_char(NSString* str) {+ return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));+ }++ void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {+ Class selected_class;++ if (strcmp(class_name, "NSView") == 0) {+ selected_class = objc_getClass("ViewClass");+ } else if (strcmp(class_name, "NSWindow") == 0) {+ selected_class = objc_getClass("WindowClass");+ } else {+ selected_class = objc_getClass(class_name);+ }++ class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);+ }++ /* Header for the array. */+ typedef struct siArrayHeader {+ size_t count;+ /* TODO(EimaMei): Add a `type_width` later on. */+ } siArrayHeader;++ /* Gets the header of the siArray. */+#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)++ void* si_array_init_reserve(size_t sizeof_element, size_t count) {+ siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));+ void* array = ptr + sizeof(siArrayHeader);++ siArrayHeader* header = SI_ARRAY_HEADER(array);+ header->count = count;++ return array;+ }++#define si_array_len(array) (SI_ARRAY_HEADER(array)->count)+#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)+ /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/+#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)+ + unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {+ return ((unsigned char* (*)(id, SEL))objc_msgSend)+ (imageRep, sel_registerName("bitmapData"));+ }++#define NS_ENUM(type, name) type name; enum++ typedef NS_ENUM(NSUInteger, NSBitmapFormat) {+ NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.)+ NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied+ NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer++ NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),+ NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),+ NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),+ NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)+ };++ NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {+ void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");++ return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)+ (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);+ }++ NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {+ void* nsclass = objc_getClass("NSColor");+ void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");+ return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)+ (nsclass, func, red, green, blue, alpha);+ }++ NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {+ void* func = sel_registerName("initWithImage:hotSpot:");+ void* nsclass = objc_getClass("NSCursor");++ return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)+ (NSAlloc(nsclass), func, newImage, aPoint);+ }++ void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {+ void* func = sel_registerName("addRepresentation:");+ objc_msgSend_void_id(image, func, imageRep);+ }++ NSImage* NSImage_initWithSize(NSSize size) {+ void* func = sel_registerName("initWithSize:");+ return ((id(*)(id, SEL, NSSize))objc_msgSend)+ (NSAlloc((id)objc_getClass("NSImage")), func, size);+ }+#define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))+ typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {+ NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */+ NSOpenGLContextParameterSurfaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */+ NSOpenGLContextParameterSurfaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */+ NSOpenGLContextParameterSurfaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */+ NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */+ NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */+ NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */+ NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */+ NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */+ NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */++ NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */+ NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */+ NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */+ NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */+ NSOpenGLContextParameterSurfaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */+ };+++ void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {+ void* func = sel_registerName("setValues:forParameter:");+ ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)+ (context, func, vals, param);+ }++ void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {+ void* func = sel_registerName("initWithAttributes:");+ return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)+ (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs);+ }++ NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {+ void* func = sel_registerName("initWithFrame:pixelFormat:");+ return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)+ (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format);+ }++ void NSCursor_performSelector(NSCursor* cursor, void* selector) {+ void* func = sel_registerName("performSelector:");+ objc_msgSend_void_SEL(cursor, func, selector);+ }++ NSPasteboard* NSPasteboard_generalPasteboard(void) {+ return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));+ }++ NSString** cstrToNSStringArray(char** strs, size_t len) {+ static NSString* nstrs[6];+ size_t i;+ for (i = 0; i < len; i++)+ nstrs[i] = NSString_stringWithUTF8String(strs[i]);++ return nstrs;+ }++ const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {+ void* func = sel_registerName("stringForType:");+ return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));+ }++ NSArray* c_array_to_NSArray(void* array, size_t len) {+ SEL func = sel_registerName("initWithObjects:count:");+ void* nsclass = objc_getClass("NSArray");+ return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend)+ (NSAlloc(nsclass), func, array, len);+ }+ + void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {+ NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);++ NSArray* array = c_array_to_NSArray(ntypes, len);+ objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);+ NSRelease(array);+ }++ NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {+ NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);++ void* func = sel_registerName("declareTypes:owner:");++ NSArray* array = c_array_to_NSArray(ntypes, len);++ NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)+ (pasteboard, func, array, owner);+ NSRelease(array);++ return output;+ }++ bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {+ void* func = sel_registerName("setString:forType:");+ return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)+ (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));+ }++ void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }++ typedef enum NSApplicationActivationPolicy {+ NSApplicationActivationPolicyRegular,+ NSApplicationActivationPolicyAccessory,+ NSApplicationActivationPolicyProhibited+ } NSApplicationActivationPolicy;++ typedef NS_ENUM(u32, NSBackingStoreType) {+ NSBackingStoreRetained = 0,+ NSBackingStoreNonretained = 1,+ NSBackingStoreBuffered = 2+ };++ typedef NS_ENUM(u32, NSWindowStyleMask) {+ NSWindowStyleMaskBorderless = 0,+ NSWindowStyleMaskTitled = 1 << 0,+ NSWindowStyleMaskClosable = 1 << 1,+ NSWindowStyleMaskMiniaturizable = 1 << 2,+ NSWindowStyleMaskResizable = 1 << 3,+ NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */+ NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,+ NSWindowStyleMaskFullScreen = 1 << 14,+ NSWindowStyleMaskFullSizeContentView = 1 << 15,+ NSWindowStyleMaskUtilityWindow = 1 << 4,+ NSWindowStyleMaskDocModalWindow = 1 << 6,+ NSWindowStyleMaskNonactivatingPanel = 1 << 7,+ NSWindowStyleMaskHUDWindow = 1 << 13+ };++ typedef const char* NSPasteboardType;+ NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType++++ typedef NS_ENUM(i32, NSDragOperation) {+ NSDragOperationNone = 0,+ NSDragOperationCopy = 1,+ NSDragOperationLink = 2,+ NSDragOperationGeneric = 4,+ NSDragOperationPrivate = 8,+ NSDragOperationMove = 16,+ NSDragOperationDelete = 32,+ NSDragOperationEvery = ULONG_MAX,++ //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery+ //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery+ };++ void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {+ void* func = sel_registerName("objectAtIndex:");+ return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);+ }++ const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {+ void* func = sel_registerName("readObjectsForClasses:options:");++ NSArray* array = c_array_to_NSArray(classArray, len);++ NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)+ (pasteboard, func, array, options);++ NSRelease(array);+ NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count"));++ const char** res = si_array_init_reserve(sizeof(const char*), count);++ void* path_func = sel_registerName("path");++ for (NSUInteger i = 0; i < count; i++) {+ void* url = NSArray_objectAtIndex(output, i);+ NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func);+ res[i] = NSString_to_char(url_str);+ }++ return res;+ }++ void* NSWindow_contentView(NSWindow* window) {+ void* func = sel_registerName("contentView");+ return objc_msgSend_id(window, func);+ }++ /*+ End of cocoa wrapper+ */++ char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"};++ void* RGFWnsglFramework = NULL;++#ifdef RGFW_OPENGL+ void* RGFW_getProcAddress(const char* procname) {+ if (RGFWnsglFramework == NULL)+ RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));++ CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);++ void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);++ CFRelease(symbolName);++ return symbol;+ }+#endif++ CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { + RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext)+ return kCVReturnSuccess; + }++ id NSWindow_delegate(RGFW_window* win) {+ return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));+ }++ u32 RGFW_OnClose(void* self) {+ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return true;++ win->event.type = RGFW_quit;+ RGFW_windowQuitCallback(win);++ return true;+ }++ /* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */+ bool acceptsFirstResponder(void) { return true; }+ bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; }++ NSDragOperation draggingEntered(id self, SEL sel, id sender) { + RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); ++ printf("hi\n");+ return NSDragOperationCopy; + }+ NSDragOperation draggingUpdated(id self, SEL sel, id sender) { + RGFW_UNUSED(sel); ++ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return true;+ + if (!(win->src.winArgs & RGFW_ALLOW_DND)) {+ return false;+ }++ win->event.type = RGFW_dnd_init;+ win->src.dndPassed = 0;++ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));++ win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));+ RGFW_dndInitCallback(win, win->event.point);++ return NSDragOperationCopy; + }+ bool prepareForDragOperation(id self) {+ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return true;+ + if (!(win->src.winArgs & RGFW_ALLOW_DND)) {+ return false;+ }++ return true;+ }++ void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; }++ /* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */+ bool performDragOperation(id self, SEL sel, id sender) {+ RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); ++ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return true;++ //NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow"));+ u32 i;+ bool found = 0;++ if (!found)+ i = 0;++ Class array[] = { objc_getClass("NSURL"), NULL };+ NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));+ + char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(pasteBoard, array, 1, NULL);++ win->event.droppedFilesCount = si_array_len(droppedFiles);++ u32 y;++ for (y = 0; y < win->event.droppedFilesCount; y++) {+ strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH);++ win->event.droppedFiles[y][RGFW_MAX_PATH - 1] = '\0';+ }++ win->event.type = RGFW_dnd;+ win->src.dndPassed = 0;++ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));+ win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));++ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);+ return true;+ }+++ NSApplication* NSApp = NULL;++ static void NSMoveToResourceDir(void) {+ /* sourced from glfw */+ char resourcesPath[255];++ CFBundleRef bundle = CFBundleGetMainBundle();+ if (!bundle)+ return;++ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);+ CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);++ if (+ CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||+ CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0+ ) {+ CFRelease(last);+ CFRelease(resourcesURL);+ return;+ }++ CFRelease(last);+ CFRelease(resourcesURL);++ chdir(resourcesPath);+ }+++ NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {+ RGFW_UNUSED(sel); ++ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return frameSize;+ + win->r.w = frameSize.width;+ win->r.h = frameSize.height;+ win->event.type = RGFW_windowResized;+ RGFW_windowResizeCallback(win, win->r);+ return frameSize;+ }++ void RGFW__osxWindowMove(void* self, SEL sel) {+ RGFW_UNUSED(sel); ++ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return;+ + NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame"));+ win->r.x = (i32) frame.origin.x;+ win->r.y = (i32) frame.origin.y;++ win->event.type = RGFW_windowMoved;+ RGFW_windowMoveCallback(win, win->r);+ }++ void RGFW__osxUpdateLayer(void* self, SEL sel) {+ RGFW_UNUSED(sel);++ RGFW_window* win = NULL;+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);+ if (win == NULL)+ return;+ + win->event.type = RGFW_windowRefresh;+ RGFW_windowRefreshCallback(win);+ }++ RGFWDEF void RGFW_init_buffer(RGFW_window* win);+ void RGFW_init_buffer(RGFW_window* win) {+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)+ RGFW_bufferSize = RGFW_getScreenSize();+ + win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);++ #ifdef RGFW_OSMESA+ win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);+ OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);+ #endif+ #else+ RGFW_UNUSED(win); /* if buffer rendering is not being used */+ #endif+ }++ NSPasteboardType const NSPasteboardTypeURL = "public.url";+ NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url";++ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {+ static u8 RGFW_loaded = 0;++ /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???+ Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).+ */+ si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);++ /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */+ si_func_to_SEL("NSWindow", acceptsFirstResponder);+ si_func_to_SEL("NSWindow", performKeyEquivalent);++ if (NSApp == NULL) {+ NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));++ ((void (*)(id, SEL, NSUInteger))objc_msgSend)+ (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);+ }++ RGFW_window* win = RGFW_window_basic_init(rect, args);+ + RGFW_window_setMouseDefault(win);++ NSRect windowRect;+ windowRect.origin.x = win->r.x;+ windowRect.origin.y = win->r.y;+ windowRect.size.width = win->r.w;+ windowRect.size.height = win->r.h;++ NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;++ if (!(args & RGFW_NO_RESIZE))+ macArgs |= NSWindowStyleMaskResizable;+ if (!(args & RGFW_NO_BORDER))+ macArgs |= NSWindowStyleMaskTitled;+ else+ macArgs = NSWindowStyleMaskBorderless;+ {+ void* nsclass = objc_getClass("NSWindow");+ void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");++ win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)+ (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);+ }++ NSString* str = NSString_stringWithUTF8String(name);+ objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);++#ifdef RGFW_OPENGL+ if ((args & RGFW_NO_INIT_API) == 0) {+ void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);+ void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);++ if (format == NULL) {+ printf("Failed to load pixel format ");++ void* attrs = RGFW_initAttribs(1);+ format = NSOpenGLPixelFormat_initWithAttributes(attrs);+ if (format == NULL)+ printf("and loading software rendering OpenGL failed\n");+ else+ printf("Switching to software rendering\n");+ }++ win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);+ objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));+ win->src.rSurf = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));+ } else+#endif+ {+ NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}};+ win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)+ (NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"),+ contentRect);+ }++ void* contentView = NSWindow_contentView(win->src.window);+ objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);++ objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);++#ifdef RGFW_OPENGL+ if ((args & RGFW_NO_INIT_API) == 0)+ objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));+#endif+ if (args & RGFW_TRANSPARENT_WINDOW) {+#ifdef RGFW_OPENGL+ if ((args & RGFW_NO_INIT_API) == 0) {+ i32 opacity = 0;+ #define NSOpenGLCPSurfaceOpacity 236+ NSOpenGLContext_setValues(win->src.rSurf, &opacity, NSOpenGLCPSurfaceOpacity);+ }+#endif++ objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);++ objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),+ NSColor_colorWithSRGB(0, 0, 0, 0));+ }++ win->src.display = CGMainDisplayID();+ CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink);+ CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);+ CVDisplayLinkStart(win->src.displayLink);++ RGFW_init_buffer(win);++ #ifndef RGFW_NO_MONITOR+ if (args & RGFW_SCALE_TO_MONITOR)+ RGFW_window_scaleToMonitor(win);+ #endif++ if (args & RGFW_HIDE_MOUSE)+ RGFW_window_showMouse(win, 0);++ if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)+ NSMoveToResourceDir();++ Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);++ class_addIvar(+ delegateClass, "RGFW_window",+ sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))),+ "L"+ );++ class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");+ class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, "");+ class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");+ class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");+ class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@");+ class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@");+ class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");+ class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");+ class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@");+ class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@");++ id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));++ object_setInstanceVariable(delegate, "RGFW_window", win);++ objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);++ if (args & RGFW_ALLOW_DND) {+ win->src.winArgs |= RGFW_ALLOW_DND;++ NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};+ NSregisterForDraggedTypes(win->src.window, types, 3);+ }++ // Show the window+ ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);++ if (!RGFW_loaded) {+ objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));++ RGFW_loaded = 1;+ }++ objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));++ objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));++ if (RGFW_root == NULL)+ RGFW_root = win;++ NSRetain(win->src.window);+ NSRetain(NSApp);++ return win;+ }++ void RGFW_window_setBorder(RGFW_window* win, u8 border) {+ NSBackingStoreType storeType = NSWindowStyleMaskBorderless;+ if (!border) {+ storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;+ }+ if (!(win->src.winArgs & RGFW_NO_RESIZE)) {+ storeType |= NSWindowStyleMaskResizable;+ }+ + ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType);++ objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border);+ }++ RGFW_area RGFW_getScreenSize(void) {+ static CGDirectDisplayID display = 0;++ if (display == 0)+ display = CGMainDisplayID();++ return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));+ }++ RGFW_vector RGFW_getGlobalMousePoint(void) {+ assert(RGFW_root != NULL);++ CGEventRef e = CGEventCreate(NULL);+ CGPoint point = CGEventGetLocation(e);+ CFRelease(e);++ return RGFW_VECTOR((u32) point.x, (u32) point.y); /* the point is loaded during event checks */+ }++ RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) {+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream"));++ return RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));+ }++ u32 RGFW_keysPressed[10]; /*10 keys at a time*/+ typedef NS_ENUM(u32, NSEventType) { /* various types of events */+ NSEventTypeLeftMouseDown = 1,+ NSEventTypeLeftMouseUp = 2,+ NSEventTypeRightMouseDown = 3,+ NSEventTypeRightMouseUp = 4,+ NSEventTypeMouseMoved = 5,+ NSEventTypeLeftMouseDragged = 6,+ NSEventTypeRightMouseDragged = 7,+ NSEventTypeMouseEntered = 8,+ NSEventTypeMouseExited = 9,+ NSEventTypeKeyDown = 10,+ NSEventTypeKeyUp = 11,+ NSEventTypeFlagsChanged = 12,+ NSEventTypeAppKitDefined = 13,+ NSEventTypeSystemDefined = 14,+ NSEventTypeApplicationDefined = 15,+ NSEventTypePeriodic = 16,+ NSEventTypeCursorUpdate = 17,+ NSEventTypeScrollWheel = 22,+ NSEventTypeTabletPoint = 23,+ NSEventTypeTabletProximity = 24,+ NSEventTypeOtherMouseDown = 25,+ NSEventTypeOtherMouseUp = 26,+ NSEventTypeOtherMouseDragged = 27,+ /* The following event types are available on some hardware on 10.5.2 and later */+ NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,+ NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,+ NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31,+ NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18,+ NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,+ NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,++ NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,+ NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,++ NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,+ NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,++ NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,+ };++ typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */+ NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,+ NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,+ NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,+ NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,+ NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,+ NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,+ NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,+ NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,+ NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,+ NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,+ NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,+ NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,+ NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,+ NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,+ NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,+ NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,+ NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,+ NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,+ NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,+ NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,+ NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,+ NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,+ NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,+ /* The following event masks are available on some hardware on 10.5.2 and later */+ NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,+ NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,+ NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,+ NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,+ NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,+ NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,++ /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.+ */+ NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,+ NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,+ NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,++ NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,++ NSEventMaskAny = ULONG_MAX,++ };++ typedef enum NSEventModifierFlags {+ NSEventModifierFlagCapsLock = 1 << 16,+ NSEventModifierFlagShift = 1 << 17,+ NSEventModifierFlagControl = 1 << 18,+ NSEventModifierFlagOption = 1 << 19,+ NSEventModifierFlagCommand = 1 << 20,+ NSEventModifierFlagNumericPad = 1 << 21+ } NSEventModifierFlags;++ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {+ assert(win != NULL);+ + if (win->event.type == RGFW_quit)+ return NULL;++ if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) {+ win->src.dndPassed = 1;+ return &win->event;+ }++ static void* eventFunc = NULL;+ if (eventFunc == NULL)+ eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");+ + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) {+ win->event.keyCode = 120;+ return &win->event;+ }++ NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)+ (NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);++ if (e == NULL)+ return NULL;++ if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {+ ((void (*)(id, SEL, id, bool))objc_msgSend)+ (NSApp, sel_registerName("postEvent:atStart:"), e, 0);++ return NULL;+ }++ if (win->event.droppedFilesCount) {+ u32 i;+ for (i = 0; i < win->event.droppedFilesCount; i++)+ win->event.droppedFiles[i][0] = '\0';+ }++ win->event.droppedFilesCount = 0;+ win->event.type = 0;++ switch (objc_msgSend_uint(e, sel_registerName("type"))) {+ case NSEventTypeMouseEntered: {+ win->event.type = RGFW_mouseEnter;+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));++ win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);+ break;+ }+ + case NSEventTypeMouseExited:+ win->event.type = RGFW_mouseLeave;+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);+ break;++ case NSEventTypeKeyDown: {+ u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);+ RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;++ win->event.type = RGFW_keyPressed;+ char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));+ strncpy(win->event.keyName, str, 16);+ RGFW_keyboard[win->event.keyCode].current = 1;++ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);+ break;+ }++ case NSEventTypeKeyUp: {+ u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);;++ RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;++ win->event.type = RGFW_keyReleased;+ char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));+ strncpy(win->event.keyName, str, 16);++ RGFW_keyboard[win->event.keyCode].current = 0;+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);+ break;+ }++ case NSEventTypeFlagsChanged: {+ u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags"));+ RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255));+ + u8 i;+ for (i = 0; i < 9; i++)+ RGFW_keyboard[i + RGFW_CapsLock].prev = 0;+ + for (i = 0; i < 5; i++) {+ u32 shift = (1 << (i + 16));+ u32 key = i + RGFW_CapsLock;++ if ((flags & shift) && !RGFW_wasPressed(win, key)) {+ RGFW_keyboard[key].current = 1;++ if (key != RGFW_CapsLock)+ RGFW_keyboard[key+ 4].current = 1;+ + win->event.type = RGFW_keyPressed;+ win->event.keyCode = key;+ break;+ } + + if (!(flags & shift) && RGFW_wasPressed(win, key)) {+ RGFW_keyboard[key].current = 0;+ + if (key != RGFW_CapsLock)+ RGFW_keyboard[key + 4].current = 0;++ win->event.type = RGFW_keyReleased;+ win->event.keyCode = key;+ break;+ }+ }++ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed);++ break;+ }+ case NSEventTypeLeftMouseDragged:+ case NSEventTypeOtherMouseDragged:+ case NSEventTypeRightMouseDragged:+ case NSEventTypeMouseMoved:+ win->event.type = RGFW_mousePosChanged;+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));+ win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));++ if ((win->src.winArgs & RGFW_HOLD_MOUSE)) {+ p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));+ p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));+ + p.x = ((win->r.w / 2)) + p.x;+ p.y = ((win->r.h / 2)) + p.y;+ win->event.point = RGFW_VECTOR((u32) p.x, (u32) (p.y));+ }++ RGFW_mousePosCallback(win, win->event.point);+ break;++ case NSEventTypeLeftMouseDown:+ win->event.button = RGFW_mouseLeft;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;++ case NSEventTypeOtherMouseDown:+ win->event.button = RGFW_mouseMiddle;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;++ case NSEventTypeRightMouseDown:+ win->event.button = RGFW_mouseRight;+ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;++ case NSEventTypeLeftMouseUp:+ win->event.button = RGFW_mouseLeft;+ win->event.type = RGFW_mouseButtonReleased;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;++ case NSEventTypeOtherMouseUp:+ win->event.button = RGFW_mouseMiddle;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ win->event.type = RGFW_mouseButtonReleased;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;++ case NSEventTypeRightMouseUp:+ win->event.button = RGFW_mouseRight;+ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 0;+ win->event.type = RGFW_mouseButtonReleased;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);+ break;++ case NSEventTypeScrollWheel: {+ double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));++ if (deltaY > 0) {+ win->event.button = RGFW_mouseScrollUp;+ }+ else if (deltaY < 0) {+ win->event.button = RGFW_mouseScrollDown;+ }++ RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button];+ RGFW_mouseButtons[win->event.button] = 1;++ win->event.scroll = deltaY;++ win->event.type = RGFW_mouseButtonPressed;+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);+ break;+ }++ default:+ break;+ }++ objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);++ return &win->event;+ }+++ void RGFW_window_move(RGFW_window* win, RGFW_vector v) {+ assert(win != NULL);++ win->r.x = v.x;+ win->r.y = v.y;+ ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)+ (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);+ }++ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {+ assert(win != NULL);++ win->r.w = a.w;+ win->r.h = a.h;+ ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)+ (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);+ }++ void RGFW_window_minimize(RGFW_window* win) {+ assert(win != NULL);++ objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);+ }++ void RGFW_window_restore(RGFW_window* win) {+ assert(win != NULL);++ objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);+ }++ void RGFW_window_setName(RGFW_window* win, char* name) {+ assert(win != NULL);++ NSString* str = NSString_stringWithUTF8String(name);+ objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);+ }++ #ifndef RGFW_NO_PASSTHROUGH+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);+ }+ #endif++ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {+ if (a.w == 0 && a.h == 0)+ return;++ ((void (*)(id, SEL, NSSize))objc_msgSend)+ (win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h});+ }++ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {+ if (a.w == 0 && a.h == 0)+ return;++ ((void (*)(id, SEL, NSSize))objc_msgSend)+ (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h});+ }++ void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {+ assert(win != NULL);++ /* code by EimaMei */+ // Make a bitmap representation, then copy the loaded image into it.+ void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);+ memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);++ // Add ze representation.+ void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h});+ NSImage_addRepresentation(dock_image, (void*) representation);++ // Finally, set the dock image to it.+ objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);+ // Free the garbage.+ release(dock_image);+ release(representation);+ }++ NSCursor* NSCursor_arrowStr(char* str) {+ void* nclass = objc_getClass("NSCursor");+ void* func = sel_registerName(str);+ return (NSCursor*) objc_msgSend_id(nclass, func);+ }++ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {+ assert(win != NULL);++ if (image == NULL) {+ objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));+ return;+ }++ /* NOTE(EimaMei): Code by yours truly. */+ // Make a bitmap representation, then copy the loaded image into it.+ void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);+ memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);++ // Add ze representation.+ void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h});+ NSImage_addRepresentation(cursor_image, representation);++ // Finally, set the cursor image.+ void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0});++ objc_msgSend_void(cursor, sel_registerName("set"));++ // Free the garbage.+ release(cursor_image);+ release(representation);+ }++ void RGFW_window_setMouseDefault(RGFW_window* win) {+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);+ }++ void RGFW_window_showMouse(RGFW_window* win, i8 show) {+ RGFW_UNUSED(win);++ if (show) {+ CGDisplayShowCursor(kCGDirectMainDisplay);+ }+ else {+ CGDisplayHideCursor(kCGDirectMainDisplay);+ }+ }++ void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) {+ if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*))))+ return;+ + char* mouseStr = RGFW_mouseIconSrc[stdMouses];+ void* mouse = NSCursor_arrowStr(mouseStr);++ if (mouse == NULL)+ return;++ RGFW_UNUSED(win);+ CGDisplayShowCursor(kCGDirectMainDisplay);+ objc_msgSend_void(mouse, sel_registerName("set"));+ }++ void RGFW_clipCursor(RGFW_rect r) { + CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));+ CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h));+ }++ void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {+ RGFW_UNUSED(win);++ CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); + }+++ void RGFW_window_hide(RGFW_window* win) {+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);+ }++ void RGFW_window_show(RGFW_window* win) {+ ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);+ }++ u8 RGFW_window_isFullscreen(RGFW_window* win) {+ assert(win != NULL);++ NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));+ return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;+ }++ u8 RGFW_window_isHidden(RGFW_window* win) {+ assert(win != NULL);++ bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));+ return visible == NO && !RGFW_window_isMinimized(win);+ }++ u8 RGFW_window_isMinimized(RGFW_window* win) {+ assert(win != NULL);++ return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;+ }++ u8 RGFW_window_isMaximized(RGFW_window* win) {+ assert(win != NULL);++ return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));+ }++ static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {+ RGFW_monitor monitor;++ CGRect bounds = CGDisplayBounds(display);+ monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);++ CGSize screenSizeMM = CGDisplayScreenSize(display);+ monitor.physW = screenSizeMM.width / 25.4;+ monitor.physH = screenSizeMM.height / 25.4;++ monitor.scaleX = (monitor.rect.w / (screenSizeMM.width)) / 2.6;+ monitor.scaleY = (monitor.rect.h / (screenSizeMM.height)) / 2.6;++ snprintf(monitor.name, 128, "%i %i %i", CGDisplayModelNumber(display), CGDisplayVendorNumber(display), CGDisplaySerialNumber(display));++ return monitor;+ }+++ static RGFW_monitor RGFW_monitors[7];++ RGFW_monitor* RGFW_getMonitors(void) {+ static CGDirectDisplayID displays[7];+ u32 count;++ if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)+ return NULL;++ for (u32 i = 0; i < count; i++)+ RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);++ return RGFW_monitors;+ }++ RGFW_monitor RGFW_getPrimaryMonitor(void) {+ CGDirectDisplayID primary = CGMainDisplayID();+ return RGFW_NSCreateMonitor(primary);+ }++ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {+ return RGFW_NSCreateMonitor(win->src.display);+ }++ char* RGFW_readClipboard(size_t* size) {+ char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString);+ + size_t clip_len = 1;++ if (clip != NULL) {+ clip_len = strlen(clip) + 1; + }++ char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len);+ + if (clip != NULL) {+ strncpy(str, clip, clip_len);+ }++ str[clip_len] = '\0';+ + if (size != NULL)+ *size = clip_len;+ return str;+ }++ void RGFW_writeClipboard(const char* text, u32 textLen) {+ RGFW_UNUSED(textLen);++ NSPasteboardType array[] = { NSPasteboardTypeString, NULL };+ NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);++ NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);+ }++ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {+ RGFW_UNUSED(jsNumber);++ assert(win != NULL);++ return RGFW_registerJoystickF(win, (char*) "");+ }++ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {+ RGFW_UNUSED(file);++ assert(win != NULL);++ return win->src.joystickCount - 1;+ }++ #ifdef RGFW_OPENGL+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {+ assert(win != NULL);+ objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));+ }+ #endif++ #if !defined(RGFW_EGL)+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {+ assert(win != NULL);+ #if defined(RGFW_OPENGL)+ + NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222);+ #endif++ win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;+ }+ #endif+ + void RGFW_window_swapBuffers(RGFW_window* win) {+ assert(win != NULL);++ RGFW_window_makeCurrent(win);++ /* clear the window*/++ if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)+ #ifdef RGFW_OSMESA+ RGFW_OSMesa_reorganize();+ #endif++ RGFW_area area = RGFW_bufferSize;+ void* view = NSWindow_contentView(win->src.window);+ void* layer = objc_msgSend_id(view, sel_registerName("layer"));++ ((void(*)(id, SEL, NSRect))objc_msgSend)(layer,+ sel_registerName("setFrame:"),+ (NSRect){{0, 0}, {win->r.w, win->r.h}});++ NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData(+ &win->buffer, win->r.w, win->r.h, 8, 4, true, false,+ "NSDeviceRGBColorSpace", 0,+ area.w * 4, 32+ );+ id image = NSAlloc((id)objc_getClass("NSImage"));+ NSImage_addRepresentation(image, rep);+ objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image);++ release(image);+ release(rep);+#endif+ }++ if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) {+ #ifdef RGFW_EGL+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);+ #elif defined(RGFW_OPENGL)+ objc_msgSend_void(win->src.rSurf, sel_registerName("flushBuffer"));+ #endif+ }++ RGFW_window_checkFPS(win);+ }++ void RGFW_window_close(RGFW_window* win) {+ assert(win != NULL);+ release(win->src.view);++#ifdef RGFW_ALLOC_DROPFILES+ {+ u32 i;+ for (i = 0; i < RGFW_MAX_DROPS; i++)+ RGFW_FREE(win->event.droppedFiles[i]);+++ RGFW_FREE(win->event.droppedFiles);+ }+#endif++ if (RGFW_root == win) {+ objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window);+ NSApp = NULL;+ }++#ifdef RGFW_BUFFER+ release(win->src.bitmap);+ release(win->src.image);+#endif++ CVDisplayLinkStop(win->src.displayLink);+ CVDisplayLinkRelease(win->src.displayLink);++ RGFW_FREE(win);+ }++ u64 RGFW_getTimeNS(void) {+ static mach_timebase_info_data_t timebase_info;+ if (timebase_info.denom == 0) {+ mach_timebase_info(&timebase_info);+ }+ return mach_absolute_time() * timebase_info.numer / timebase_info.denom;+ }++ u64 RGFW_getTime(void) {+ static mach_timebase_info_data_t timebase_info;+ if (timebase_info.denom == 0) {+ mach_timebase_info(&timebase_info);+ }+ return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);+ }+#endif /* RGFW_MACOS */++/*+ End of MaOS defines+*/++/* unix (macOS, linux) only stuff */+#if defined(RGFW_X11) || defined(RGFW_MACOS)+/* unix threading */+#ifndef RGFW_NO_THREADS+#include <pthread.h>++ RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) {+ RGFW_UNUSED(args);+ + RGFW_thread t;+ pthread_create((pthread_t*) &t, NULL, *ptr, NULL);+ return t;+ }+ void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }+ void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }+#ifdef __linux__+ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); }+#endif+#endif+/* unix sleep */+ void RGFW_sleep(u64 ms) {+ struct timespec time;+ time.tv_sec = 0;+ time.tv_nsec = ms * 1e+6;++ nanosleep(&time, NULL);+ }++#endif /* end of unix / mac stuff*/+#endif /*RGFW_IMPLEMENTATION*/++#ifdef __cplusplus+}+#endif
raylib/src/external/rl_gputex.h view
@@ -171,6 +171,10 @@ *width = header->width; *height = header->height;++ if (*width % 4 != 0) LOG("WARNING: IMAGE: DDS file width must be multiple of 4. Image will not display correctly");+ if (*height % 4 != 0) LOG("WARNING: IMAGE: DDS file height must be multiple of 4. Image will not display correctly");+ image_pixel_size = header->width*header->height; if (header->mipmap_count == 0) *mips = 1; // Parameter not used@@ -229,7 +233,7 @@ } } }- else if (header->ddspf.flags == 0x40 && header->ddspf.rgb_bit_count == 24) // DDS_RGB, no compressed+ else if ((header->ddspf.flags == 0x40) && (header->ddspf.rgb_bit_count == 24)) // DDS_RGB, no compressed { int data_size = image_pixel_size*3*sizeof(unsigned char); image_data = RL_MALLOC(data_size);@@ -238,7 +242,7 @@ *format = PIXELFORMAT_UNCOMPRESSED_R8G8B8; }- else if (header->ddspf.flags == 0x41 && header->ddspf.rgb_bit_count == 32) // DDS_RGBA, no compressed+ else if ((header->ddspf.flags == 0x41) && (header->ddspf.rgb_bit_count == 32)) // DDS_RGBA, no compressed { int data_size = image_pixel_size*4*sizeof(unsigned char); image_data = RL_MALLOC(data_size);
raylib/src/external/rprand.h view
@@ -147,8 +147,13 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //-----------------------------------------------------------------------------------static uint64_t rprand_seed = 0; // SplitMix64 actual seed-static uint32_t rprand_state[4] = { 0 }; // Xoshiro128** state, nitialized by SplitMix64+static uint64_t rprand_seed = 0xAABBCCDD; // SplitMix64 default seed (aligned to rprand_state)+static uint32_t rprand_state[4] = { // Xoshiro128** state, initialized by SplitMix64+ 0x96ea83c1,+ 0x218b21e5,+ 0xaa91febd,+ 0x976414d4+}; //---------------------------------------------------------------------------------- // Module internal functions declaration@@ -202,7 +207,7 @@ { value = ((unsigned int)rprand_xoshiro()%(abs(max - min) + 1)) + min; - for (int j = 0; j < i; j++)+ for (unsigned int j = 0; j < i; j++) { if (sequence[j] == value) {
raylib/src/external/sinfl.h view
@@ -171,7 +171,7 @@ static int sinfl_bsr(unsigned n) {-#ifdef _MSC_VER+#if defined(_MSC_VER) && !defined(__clang__) _BitScanReverse(&n, n); return n; #elif defined(__GNUC__) || defined(__clang__)
raylib/src/platforms/rcore_android.c view
@@ -81,7 +81,7 @@ // Local Variables Definition //---------------------------------------------------------------------------------- #define KEYCODE_MAP_SIZE 162-static const KeyboardKey KeycodeMap[KEYCODE_MAP_SIZE] = {+static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = { KEY_NULL, // AKEYCODE_UNKNOWN 0, // AKEYCODE_SOFT_LEFT 0, // AKEYCODE_SOFT_RIGHT@@ -660,7 +660,7 @@ CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; } }- + // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; @@ -1133,9 +1133,9 @@ CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_Y] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RZ, 0); CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_TRIGGER] = AMotionEvent_getAxisValue(- event, AMOTION_EVENT_AXIS_BRAKE, 0) * 2.0f - 1.0f;+ event, AMOTION_EVENT_AXIS_BRAKE, 0)*2.0f - 1.0f; CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_TRIGGER] = AMotionEvent_getAxisValue(- event, AMOTION_EVENT_AXIS_GAS, 0) * 2.0f - 1.0f;+ event, AMOTION_EVENT_AXIS_GAS, 0)*2.0f - 1.0f; // dpad is reported as an axis on android float dpadX = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);@@ -1201,7 +1201,7 @@ return 1; // Handled gamepad button } - KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE) ? KeycodeMap[keycode] : KEY_NULL;+ KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[keycode] : KEY_NULL; if (key != KEY_NULL) { // Save current key and its state@@ -1252,10 +1252,10 @@ CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) }; // Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height- float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x) / (float)CORE.Window.display.width;- float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y) / (float)CORE.Window.display.height;- CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x * widthRatio - (float)CORE.Window.renderOffset.x / 2;- CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y * heightRatio - (float)CORE.Window.renderOffset.y / 2;+ float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;+ float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;+ CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;+ CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2; } int32_t action = AMotionEvent_getAction(event);
− raylib/src/platforms/rcore_desktop.c
@@ -1,1836 +0,0 @@-/**********************************************************************************************-*-* rcore_desktop - Functions to manage window, graphics device and inputs-*-* PLATFORM: DESKTOP: GLFW-* - Windows (Win32, Win64)-* - Linux (X11/Wayland desktop mode)-* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)-* - OSX/macOS (x64, arm64)-*-* LIMITATIONS:-* - Limitation 01-* - Limitation 02-*-* POSSIBLE IMPROVEMENTS:-* - Improvement 01-* - Improvement 02-*-* ADDITIONAL NOTES:-* - TRACELOG() function is located in raylib [utils] module-*-* CONFIGURATION:-* #define RCORE_PLATFORM_CUSTOM_FLAG-* Custom flag for rcore on target platform -not used--*-* DEPENDENCIES:-* - rglfw: Manage graphic device, OpenGL context and inputs (Windows, Linux, OSX, FreeBSD...)-* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)-*-*-* LICENSE: zlib/libpng-*-* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors-*-* This software is provided "as-is", without any express or implied warranty. In no event-* will the authors be held liable for any damages arising from the use of this software.-*-* Permission is granted to anyone to use this software for any purpose, including commercial-* applications, and to alter it and redistribute it freely, subject to the following restrictions:-*-* 1. The origin of this software must not be misrepresented; you must not claim that you-* wrote the original software. If you use this software in a product, an acknowledgment-* in the product documentation would be appreciated but is not required.-*-* 2. Altered source versions must be plainly marked as such, and must not be misrepresented-* as being the original software.-*-* 3. This notice may not be removed or altered from any source distribution.-*-**********************************************************************************************/--#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3- // NOTE: Already provided by rlgl implementation (on glad.h)-#include "GLFW/glfw3.h" // GLFW3 library: Windows, OpenGL context and Input management- // NOTE: GLFW3 already includes gl.h (OpenGL) headers--// Support retrieving native window handlers-#if defined(_WIN32)- typedef void *PVOID;- typedef PVOID HANDLE;- typedef HANDLE HWND;- #define GLFW_EXPOSE_NATIVE_WIN32- #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h- #include "GLFW/glfw3native.h"-- #if defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)- // NOTE: Those functions require linking with winmm library- unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);- unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);- #endif-#endif-#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)- #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX-- //#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type- //#define GLFW_EXPOSE_NATIVE_WAYLAND- #include "GLFW/glfw3native.h" // Required for: glfwGetX11Window()-#endif-#if defined(__APPLE__)- #include <unistd.h> // Required for: usleep()-- //#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition- void *glfwGetCocoaWindow(GLFWwindow* handle);- #include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()-#endif--//-----------------------------------------------------------------------------------// Types and Structures Definition-//-----------------------------------------------------------------------------------typedef struct {- GLFWwindow *handle; // GLFW window handle (graphic device)-} PlatformData;--//-----------------------------------------------------------------------------------// Global Variables Definition-//-----------------------------------------------------------------------------------extern CoreData CORE; // Global CORE state context--static PlatformData platform = { 0 }; // Platform specific data--//-----------------------------------------------------------------------------------// Module Internal Functions Declaration-//-----------------------------------------------------------------------------------int InitPlatform(void); // Initialize platform (graphics, inputs and more)-void ClosePlatform(void); // Close platform--// Error callback event-static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error--// Window callbacks events-static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized-static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored-static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized-static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus-static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window-static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley); // GLFW3 Window Content Scale Callback, runs when window changes scale--// Input callbacks events-static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed-static void CharCallback(GLFWwindow *window, unsigned int codepoint); // GLFW3 Char Callback, runs on key pressed (get codepoint value)-static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed-static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move-static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel-static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area-static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback--//-----------------------------------------------------------------------------------// Module Functions Declaration-//-----------------------------------------------------------------------------------// NOTE: Functions declaration is provided by raylib.h--//-----------------------------------------------------------------------------------// Module Functions Definition: Window and Graphics Device-//------------------------------------------------------------------------------------// Check if application should close-// NOTE: By default, if KEY_ESCAPE pressed or window close icon clicked-bool WindowShouldClose(void)-{- if (CORE.Window.ready) return CORE.Window.shouldClose;- else return true;-}--// Toggle fullscreen mode-void ToggleFullscreen(void)-{- if (!CORE.Window.fullscreen)- {- // Store previous window position (in case we exit fullscreen)- glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y);-- int monitorCount = 0;- int monitorIndex = GetCurrentMonitor();- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- // Use current monitor, so we correctly get the display the window is on- GLFWmonitor *monitor = (monitorIndex < monitorCount)? monitors[monitorIndex] : NULL;-- if (monitor == NULL)- {- TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");-- CORE.Window.fullscreen = false;- CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;-- glfwSetWindowMonitor(platform.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);- }- else- {- CORE.Window.fullscreen = true;- CORE.Window.flags |= FLAG_FULLSCREEN_MODE;-- glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);- }-- }- else- {- CORE.Window.fullscreen = false;- CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;-- glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);- }-- // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)- // NOTE: V-Sync can be enabled by graphic driver configuration- if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);-}--// Toggle borderless windowed mode-void ToggleBorderlessWindowed(void)-{- // Leave fullscreen before attempting to set borderless windowed mode and get screen position from it- bool wasOnFullscreen = false;- if (CORE.Window.fullscreen)- {- CORE.Window.previousPosition = CORE.Window.position;- ToggleFullscreen();- wasOnFullscreen = true;- }-- const int monitor = GetCurrentMonitor();- int monitorCount;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);-- if (mode)- {- if (!IsWindowState(FLAG_BORDERLESS_WINDOWED_MODE))- {- // Store screen position and size- // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here- if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);- CORE.Window.previousScreen = CORE.Window.screen;-- // Set undecorated and topmost modes and flags- glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);- CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;- glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);- CORE.Window.flags |= FLAG_WINDOW_TOPMOST;-- // Get monitor position and size- int monitorPosX = 0;- int monitorPosY = 0;- glfwGetMonitorPos(monitors[monitor], &monitorPosX, &monitorPosY);- const int monitorWidth = mode->width;- const int monitorHeight = mode->height;-- // Set screen position and size- glfwSetWindowPos(platform.handle, monitorPosX, monitorPosY);- glfwSetWindowSize(platform.handle, monitorWidth, monitorHeight);-- // Refocus window- glfwFocusWindow(platform.handle);-- CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;- }- else- {- // Remove topmost and undecorated modes and flags- glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);- CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;- glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);- CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;-- // Return previous screen size and position- // NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly- glfwSetWindowSize(platform.handle, CORE.Window.previousScreen.width, CORE.Window.previousScreen.height);- glfwSetWindowPos(platform.handle, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y);-- // Refocus window- glfwFocusWindow(platform.handle);-- CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;- }- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-}--// Set window state: maximized, if resizable-void MaximizeWindow(void)-{- if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)- {- glfwMaximizeWindow(platform.handle);- CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;- }-}--// Set window state: minimized-void MinimizeWindow(void)-{- // NOTE: Following function launches callback that sets appropriate flag!- glfwIconifyWindow(platform.handle);-}--// Set window state: not minimized/maximized-void RestoreWindow(void)-{- if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)- {- // Restores the specified window if it was previously iconified (minimized) or maximized- glfwRestoreWindow(platform.handle);- CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;- CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;- }-}--// Set window configuration state using flags-void SetWindowState(unsigned int flags)-{- // Check previous state and requested state to apply required changes- // NOTE: In most cases the functions already change the flags internally-- // State change: FLAG_VSYNC_HINT- if (((CORE.Window.flags & FLAG_VSYNC_HINT) != (flags & FLAG_VSYNC_HINT)) && ((flags & FLAG_VSYNC_HINT) > 0))- {- glfwSwapInterval(1);- CORE.Window.flags |= FLAG_VSYNC_HINT;- }-- // State change: FLAG_BORDERLESS_WINDOWED_MODE- // NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running- if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) != (flags & FLAG_BORDERLESS_WINDOWED_MODE)) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))- {- ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_FULLSCREEN_MODE- if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))- {- ToggleFullscreen(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_RESIZABLE- if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != (flags & FLAG_WINDOW_RESIZABLE)) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_TRUE);- CORE.Window.flags |= FLAG_WINDOW_RESIZABLE;- }-- // State change: FLAG_WINDOW_UNDECORATED- if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) != (flags & FLAG_WINDOW_UNDECORATED)) && (flags & FLAG_WINDOW_UNDECORATED))- {- glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);- CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;- }-- // State change: FLAG_WINDOW_HIDDEN- if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) != (flags & FLAG_WINDOW_HIDDEN)) && ((flags & FLAG_WINDOW_HIDDEN) > 0))- {- glfwHideWindow(platform.handle);- CORE.Window.flags |= FLAG_WINDOW_HIDDEN;- }-- // State change: FLAG_WINDOW_MINIMIZED- if (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) != (flags & FLAG_WINDOW_MINIMIZED)) && ((flags & FLAG_WINDOW_MINIMIZED) > 0))- {- //GLFW_ICONIFIED- MinimizeWindow(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_MAXIMIZED- if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) != (flags & FLAG_WINDOW_MAXIMIZED)) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))- {- //GLFW_MAXIMIZED- MaximizeWindow(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_UNFOCUSED- if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) != (flags & FLAG_WINDOW_UNFOCUSED)) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_FALSE);- CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;- }-- // State change: FLAG_WINDOW_TOPMOST- if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) != (flags & FLAG_WINDOW_TOPMOST)) && ((flags & FLAG_WINDOW_TOPMOST) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);- CORE.Window.flags |= FLAG_WINDOW_TOPMOST;- }-- // State change: FLAG_WINDOW_ALWAYS_RUN- if (((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) != (flags & FLAG_WINDOW_ALWAYS_RUN)) && ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0))- {- CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN;- }-- // The following states can not be changed after window creation-- // State change: FLAG_WINDOW_TRANSPARENT- if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) != (flags & FLAG_WINDOW_TRANSPARENT)) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");- }-- // State change: FLAG_WINDOW_HIGHDPI- if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) != (flags & FLAG_WINDOW_HIGHDPI)) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");- }-- // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH- if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);- CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;- }-- // State change: FLAG_MSAA_4X_HINT- if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");- }-- // State change: FLAG_INTERLACED_HINT- if (((CORE.Window.flags & FLAG_INTERLACED_HINT) != (flags & FLAG_INTERLACED_HINT)) && ((flags & FLAG_INTERLACED_HINT) > 0))- {- TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");- }-}--// Clear window configuration state flags-void ClearWindowState(unsigned int flags)-{- // Check previous state and requested state to apply required changes- // NOTE: In most cases the functions already change the flags internally-- // State change: FLAG_VSYNC_HINT- if (((CORE.Window.flags & FLAG_VSYNC_HINT) > 0) && ((flags & FLAG_VSYNC_HINT) > 0))- {- glfwSwapInterval(0);- CORE.Window.flags &= ~FLAG_VSYNC_HINT;- }-- // State change: FLAG_BORDERLESS_WINDOWED_MODE- // NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running- if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))- {- ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_FULLSCREEN_MODE- if (((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) && ((flags & FLAG_FULLSCREEN_MODE) > 0))- {- ToggleFullscreen(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_RESIZABLE- if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_FALSE);- CORE.Window.flags &= ~FLAG_WINDOW_RESIZABLE;- }-- // State change: FLAG_WINDOW_HIDDEN- if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) && ((flags & FLAG_WINDOW_HIDDEN) > 0))- {- glfwShowWindow(platform.handle);- CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;- }-- // State change: FLAG_WINDOW_MINIMIZED- if (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) && ((flags & FLAG_WINDOW_MINIMIZED) > 0))- {- RestoreWindow(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_MAXIMIZED- if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))- {- RestoreWindow(); // NOTE: Window state flag updated inside function- }-- // State change: FLAG_WINDOW_UNDECORATED- if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) && ((flags & FLAG_WINDOW_UNDECORATED) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);- CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;- }-- // State change: FLAG_WINDOW_UNFOCUSED- if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_TRUE);- CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;- }-- // State change: FLAG_WINDOW_TOPMOST- if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) && ((flags & FLAG_WINDOW_TOPMOST) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);- CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;- }-- // State change: FLAG_WINDOW_ALWAYS_RUN- if (((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) > 0) && ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0))- {- CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN;- }-- // The following states can not be changed after window creation-- // State change: FLAG_WINDOW_TRANSPARENT- if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");- }-- // State change: FLAG_WINDOW_HIGHDPI- if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");- }-- // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH- if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))- {- glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);- CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;- }-- // State change: FLAG_MSAA_4X_HINT- if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))- {- TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");- }-- // State change: FLAG_INTERLACED_HINT- if (((CORE.Window.flags & FLAG_INTERLACED_HINT) > 0) && ((flags & FLAG_INTERLACED_HINT) > 0))- {- TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");- }-}--// Set icon for window-// NOTE 1: Image must be in RGBA format, 8bit per channel-// NOTE 2: Image is scaled by the OS for all required sizes-void SetWindowIcon(Image image)-{- if (image.data == NULL)- {- // Revert to the default window icon, pass in an empty image array- glfwSetWindowIcon(platform.handle, 0, NULL);- }- else- {- if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)- {- GLFWimage icon[1] = { 0 };-- icon[0].width = image.width;- icon[0].height = image.height;- icon[0].pixels = (unsigned char *)image.data;-- // NOTE 1: We only support one image icon- // NOTE 2: The specified image data is copied before this function returns- glfwSetWindowIcon(platform.handle, 1, icon);- }- else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");- }-}--// Set icon for window, multiple images-// NOTE 1: Images must be in RGBA format, 8bit per channel-// NOTE 2: The multiple images are used depending on provided sizes-// Standard Windows icon sizes: 256, 128, 96, 64, 48, 32, 24, 16-void SetWindowIcons(Image *images, int count)-{- if ((images == NULL) || (count <= 0))- {- // Revert to the default window icon, pass in an empty image array- glfwSetWindowIcon(platform.handle, 0, NULL);- }- else- {- int valid = 0;- GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));-- for (int i = 0; i < count; i++)- {- if (images[i].format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)- {- icons[valid].width = images[i].width;- icons[valid].height = images[i].height;- icons[valid].pixels = (unsigned char *)images[i].data;-- valid++;- }- else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");- }- // NOTE: Images data is copied internally before this function returns- glfwSetWindowIcon(platform.handle, valid, icons);-- RL_FREE(icons);- }-}--// Set title for window-void SetWindowTitle(const char *title)-{- CORE.Window.title = title;- glfwSetWindowTitle(platform.handle, title);-}--// Set window position on screen (windowed mode)-void SetWindowPosition(int x, int y)-{- glfwSetWindowPos(platform.handle, x, y);-}--// Set monitor for the current window-void SetWindowMonitor(int monitor)-{- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- if (CORE.Window.fullscreen)- {- TRACELOG(LOG_INFO, "GLFW: Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));-- const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);- glfwSetWindowMonitor(platform.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);- }- else- {- TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));-- const int screenWidth = CORE.Window.screen.width;- const int screenHeight = CORE.Window.screen.height;- int monitorWorkareaX = 0;- int monitorWorkareaY = 0;- int monitorWorkareaWidth = 0;- int monitorWorkareaHeight = 0;- glfwGetMonitorWorkarea(monitors[monitor], &monitorWorkareaX, &monitorWorkareaY, &monitorWorkareaWidth, &monitorWorkareaHeight);-- // If the screen size is larger than the monitor workarea, anchor it on the top left corner, otherwise, center it- if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight)) glfwSetWindowPos(platform.handle, monitorWorkareaX, monitorWorkareaY);- else- {- const int x = monitorWorkareaX + (monitorWorkareaWidth/2) - (screenWidth/2);- const int y = monitorWorkareaY + (monitorWorkareaHeight/2) - (screenHeight/2);- glfwSetWindowPos(platform.handle, x, y);- }- }- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-}--// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)-void SetWindowMinSize(int width, int height)-{- CORE.Window.screenMin.width = width;- CORE.Window.screenMin.height = height;-- int minWidth = (CORE.Window.screenMin.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.width;- int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.height;- int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.width;- int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.height;-- glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);-}--// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)-void SetWindowMaxSize(int width, int height)-{- CORE.Window.screenMax.width = width;- CORE.Window.screenMax.height = height;-- int minWidth = (CORE.Window.screenMin.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.width;- int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.height;- int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.width;- int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.height;-- glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);-}--// Set window dimensions-void SetWindowSize(int width, int height)-{- glfwSetWindowSize(platform.handle, width, height);-}--// Set window opacity, value opacity is between 0.0 and 1.0-void SetWindowOpacity(float opacity)-{- if (opacity >= 1.0f) opacity = 1.0f;- else if (opacity <= 0.0f) opacity = 0.0f;- glfwSetWindowOpacity(platform.handle, opacity);-}--// Set window focused-void SetWindowFocused(void)-{- glfwFocusWindow(platform.handle);-}--// Get native window handle-void *GetWindowHandle(void)-{-#if defined(_WIN32)- // NOTE: Returned handle is: void *HWND (windows.h)- return glfwGetWin32Window(platform.handle);-#endif-#if defined(__linux__)- // NOTE: Returned handle is: unsigned long Window (X.h)- // typedef unsigned long XID;- // typedef XID Window;- //unsigned long id = (unsigned long)glfwGetX11Window(platform.handle);- //return NULL; // TODO: Find a way to return value... cast to void *?- return (void *)platform.handle;-#endif-#if defined(__APPLE__)- // NOTE: Returned handle is: (objc_object *)- return (void *)glfwGetCocoaWindow(platform.handle);-#endif-- return NULL;-}--// Get number of monitors-int GetMonitorCount(void)-{- int monitorCount = 0;-- glfwGetMonitors(&monitorCount);-- return monitorCount;-}--// Get number of monitors-int GetCurrentMonitor(void)-{- int index = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);- GLFWmonitor *monitor = NULL;-- if (monitorCount >= 1)- {- if (IsWindowFullscreen())- {- // Get the handle of the monitor that the specified window is in full screen on- monitor = glfwGetWindowMonitor(platform.handle);-- for (int i = 0; i < monitorCount; i++)- {- if (monitors[i] == monitor)- {- index = i;- break;- }- }- }- else- {- // In case the window is between two monitors, we use below logic- // to try to detect the "current monitor" for that window, note that- // this is probably an overengineered solution for a very side case- // trying to match SDL behaviour-- int closestDist = 0x7FFFFFFF;-- // Window center position- int wcx = 0;- int wcy = 0;-- glfwGetWindowPos(platform.handle, &wcx, &wcy);- wcx += (int)CORE.Window.screen.width/2;- wcy += (int)CORE.Window.screen.height/2;-- for (int i = 0; i < monitorCount; i++)- {- // Monitor top-left position- int mx = 0;- int my = 0;-- monitor = monitors[i];- glfwGetMonitorPos(monitor, &mx, &my);- const GLFWvidmode *mode = glfwGetVideoMode(monitor);-- if (mode)- {- const int right = mx + mode->width - 1;- const int bottom = my + mode->height - 1;-- if ((wcx >= mx) &&- (wcx <= right) &&- (wcy >= my) &&- (wcy <= bottom))- {- index = i;- break;- }-- int xclosest = wcx;- if (wcx < mx) xclosest = mx;- else if (wcx > right) xclosest = right;-- int yclosest = wcy;- if (wcy < my) yclosest = my;- else if (wcy > bottom) yclosest = bottom;-- int dx = wcx - xclosest;- int dy = wcy - yclosest;- int dist = (dx*dx) + (dy*dy);- if (dist < closestDist)- {- index = i;- closestDist = dist;- }- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");- }- }- }-- return index;-}--// Get selected monitor position-Vector2 GetMonitorPosition(int monitor)-{- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- int x, y;- glfwGetMonitorPos(monitors[monitor], &x, &y);-- return (Vector2){ (float)x, (float)y };- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");- return (Vector2){ 0, 0 };-}--// Get selected monitor width (currently used by monitor)-int GetMonitorWidth(int monitor)-{- int width = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);-- if (mode) width = mode->width;- else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-- return width;-}--// Get selected monitor height (currently used by monitor)-int GetMonitorHeight(int monitor)-{- int height = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);-- if (mode) height = mode->height;- else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-- return height;-}--// Get selected monitor physical width in millimetres-int GetMonitorPhysicalWidth(int monitor)-{- int width = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount)) glfwGetMonitorPhysicalSize(monitors[monitor], &width, NULL);- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-- return width;-}--// Get selected monitor physical height in millimetres-int GetMonitorPhysicalHeight(int monitor)-{- int height = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount)) glfwGetMonitorPhysicalSize(monitors[monitor], NULL, &height);- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-- return height;-}--// Get selected monitor refresh rate-int GetMonitorRefreshRate(int monitor)-{- int refresh = 0;- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- const GLFWvidmode *vidmode = glfwGetVideoMode(monitors[monitor]);- refresh = vidmode->refreshRate;- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");-- return refresh;-}--// Get the human-readable, UTF-8 encoded name of the selected monitor-const char *GetMonitorName(int monitor)-{- int monitorCount = 0;- GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);-- if ((monitor >= 0) && (monitor < monitorCount))- {- return glfwGetMonitorName(monitors[monitor]);- }- else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");- return "";-}--// Get window position XY on monitor-Vector2 GetWindowPosition(void)-{- int x = 0;- int y = 0;-- glfwGetWindowPos(platform.handle, &x, &y);-- return (Vector2){ (float)x, (float)y };-}--// Get window scale DPI factor for current monitor-Vector2 GetWindowScaleDPI(void)-{- Vector2 scale = {0};- glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);- return scale;-}--// Set clipboard text content-void SetClipboardText(const char *text)-{- glfwSetClipboardString(platform.handle, text);-}--// Get clipboard text content-// NOTE: returned string is allocated and freed by GLFW-const char *GetClipboardText(void)-{- return glfwGetClipboardString(platform.handle);-}--// Show mouse cursor-void ShowCursor(void)-{- glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);- CORE.Input.Mouse.cursorHidden = false;-}--// Hides mouse cursor-void HideCursor(void)-{- glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);- CORE.Input.Mouse.cursorHidden = true;-}--// Enables cursor (unlock cursor)-void EnableCursor(void)-{- glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);-- // Set cursor position in the middle- SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);-- if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);-- CORE.Input.Mouse.cursorHidden = false;-}--// Disables cursor (lock cursor)-void DisableCursor(void)-{- glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);-- // Set cursor position in the middle- SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);-- if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);-- CORE.Input.Mouse.cursorHidden = true;-}--// Swap back buffer with front buffer (screen drawing)-void SwapScreenBuffer(void)-{- glfwSwapBuffers(platform.handle);-}--//-----------------------------------------------------------------------------------// Module Functions Definition: Misc-//------------------------------------------------------------------------------------// Get elapsed time measure in seconds since InitTimer()-double GetTime(void)-{- double time = glfwGetTime(); // Elapsed time since glfwInit()- return time;-}--// Open URL with default system browser (if available)-// NOTE: This function is only safe to use if you control the URL given.-// A user could craft a malicious string performing another action.-// Only call this function yourself not with user input or make sure to check the string yourself.-// Ref: https://github.com/raysan5/raylib/issues/686-void OpenURL(const char *url)-{- // Security check to (partially) avoid malicious code- if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");- else- {- char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));-#if defined(_WIN32)- sprintf(cmd, "explorer \"%s\"", url);-#endif-#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)- sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser-#endif-#if defined(__APPLE__)- sprintf(cmd, "open '%s'", url);-#endif- int result = system(cmd);- if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");- RL_FREE(cmd);- }-}--//-----------------------------------------------------------------------------------// Module Functions Definition: Inputs-//------------------------------------------------------------------------------------// Set internal gamepad mappings-int SetGamepadMappings(const char *mappings)-{- return glfwUpdateGamepadMappings(mappings);-}--// Set gamepad vibration-void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor)-{- TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");-}--// Set mouse position XY-void SetMousePosition(int x, int y)-{- CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;-- // NOTE: emscripten not implemented- glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);-}--// Set mouse cursor-void SetMouseCursor(int cursor)-{- CORE.Input.Mouse.cursor = cursor;- if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);- else- {- // NOTE: We are relating internal GLFW enum values to our MouseCursor enum values- glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));- }-}--// Register all input events-void PollInputEvents(void)-{-#if defined(SUPPORT_GESTURES_SYSTEM)- // NOTE: Gestures update must be called every frame to reset gestures correctly- // because ProcessGestureEvent() is just called on an event, not every frame- UpdateGestures();-#endif-- // Reset keys/chars pressed registered- CORE.Input.Keyboard.keyPressedQueueCount = 0;- CORE.Input.Keyboard.charPressedQueueCount = 0;-- // Reset last gamepad button/axis registered state- CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN- //CORE.Input.Gamepad.axisCount = 0;-- // Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)-- // Register previous keys states- for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)- {- CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];- CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;- }-- // Register previous mouse states- for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];-- // Register previous mouse wheel state- CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;- CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };-- // Register previous mouse position- CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;-- // Register previous touch states- for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];-- // Reset touch positions- //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };-- // Map touch position to mouse position for convenience- // WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!- // TODO: GLFW does not support multi-touch input just yet- // https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch- // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages- CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;-- // Check if gamepads are ready- // NOTE: We do it here in case of disconnection- for (int i = 0; i < MAX_GAMEPADS; i++)- {- if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;- else CORE.Input.Gamepad.ready[i] = false;- }-- // Register gamepads buttons events- for (int i = 0; i < MAX_GAMEPADS; i++)- {- if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available- {- // Register previous gamepad states- for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];-- // Get current gamepad state- // NOTE: There is no callback available, so we get it manually- GLFWgamepadstate state = { 0 };- glfwGetGamepadState(i, &state); // This remapps all gamepads so they have their buttons mapped like an xbox controller-- const unsigned char *buttons = state.buttons;-- for (int k = 0; (buttons != NULL) && (k < GLFW_GAMEPAD_BUTTON_DPAD_LEFT + 1) && (k < MAX_GAMEPAD_BUTTONS); k++)- {- int button = -1; // GamepadButton enum values assigned-- switch (k)- {- case GLFW_GAMEPAD_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;- case GLFW_GAMEPAD_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;- case GLFW_GAMEPAD_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;- case GLFW_GAMEPAD_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;-- case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;- case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;-- case GLFW_GAMEPAD_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;- case GLFW_GAMEPAD_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;- case GLFW_GAMEPAD_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;-- case GLFW_GAMEPAD_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;- case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;- case GLFW_GAMEPAD_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;- case GLFW_GAMEPAD_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;-- case GLFW_GAMEPAD_BUTTON_LEFT_THUMB: button = GAMEPAD_BUTTON_LEFT_THUMB; break;- case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;- default: break;- }-- if (button != -1) // Check for valid button- {- if (buttons[k] == GLFW_PRESS)- {- CORE.Input.Gamepad.currentButtonState[i][button] = 1;- CORE.Input.Gamepad.lastButtonPressed = button;- }- else CORE.Input.Gamepad.currentButtonState[i][button] = 0;- }- }-- // Get current axis state- const float *axes = state.axes;-- for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1) && (k < MAX_GAMEPAD_AXIS); k++)- {- CORE.Input.Gamepad.axisState[i][k] = axes[k];- }-- // Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)- CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);- CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);-- CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;- }- }-- CORE.Window.resizedLastFrame = false;-- if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)- else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state-- // While window minimized, stop loop execution- while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();-- CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);-- // Reset close status for next frame- glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);-}---//-----------------------------------------------------------------------------------// Module Internal Functions Definition-//------------------------------------------------------------------------------------// Initialize platform: graphics, inputs and more-int InitPlatform(void)-{- glfwSetErrorCallback(ErrorCallback);-/*- // TODO: Setup GLFW custom allocators to match raylib ones- const GLFWallocator allocator = {- .allocate = MemAlloc,- .deallocate = MemFree,- .reallocate = MemRealloc,- .user = NULL- };-- glfwInitAllocator(&allocator);-*/--#if defined(__APPLE__)- glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);-#endif- // Initialize GLFW internal global state- int result = glfwInit();- if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }-- // Initialize graphic device: display/window and graphic context- //----------------------------------------------------------------------------- glfwDefaultWindowHints(); // Set default windows hints- //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits- //glfwWindowHint(GLFW_GREEN_BITS, 8); // Framebuffer green color component bits- //glfwWindowHint(GLFW_BLUE_BITS, 8); // Framebuffer blue color component bits- //glfwWindowHint(GLFW_ALPHA_BITS, 8); // Framebuffer alpha color component bits- //glfwWindowHint(GLFW_DEPTH_BITS, 24); // Depthbuffer bits- //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window- //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API- //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers-- // Check window creation flags- if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;-- if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // Visible window- else glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); // Window initially hidden-- if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window- else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window-- if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // Resizable window- else glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // Avoid window being resizable-- // Disable FLAG_WINDOW_MINIMIZED, not supported on initialization- if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;-- // Disable FLAG_WINDOW_MAXIMIZED, not supported on initialization- if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;-- if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);- else glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);-- if ((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);- else glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);-- // NOTE: Some GLFW flags are not supported on HTML5- if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer- else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer-- if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)- {- // Resize window content area based on the monitor content scale.- // NOTE: This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11.- // On platforms like macOS the resolution of the framebuffer is changed independently of the window size.- glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on-#if defined(__APPLE__)- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);-#endif- }- else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);-- // Mouse passthrough- if ((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);- else glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);-- if (CORE.Window.flags & FLAG_MSAA_4X_HINT)- {- // NOTE: MSAA is only enabled for main framebuffer, not user-created FBOs- TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");- glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0- }-- // NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version- // with backward compatibility to older OpenGL versions.- // For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context.-- // Check selection OpenGL version- if (rlGetVersion() == RL_OPENGL_21)- {- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)- }- else if (rlGetVersion() == RL_OPENGL_33)- {- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!- // Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE-#if defined(__APPLE__)- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires forward compatibility-#else- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above!-#endif- //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context- }- else if (rlGetVersion() == RL_OPENGL_43)- {- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Choose OpenGL major version (just hint)- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE);-#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT)- glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Enable OpenGL Debug Context-#endif- }- else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context- {- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);- glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);- glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);- }- else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context- {- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);- glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);- glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);- }-- // NOTE: GLFW 3.4+ defers initialization of the Joystick subsystem on the first call to any Joystick related functions.- // Forcing this initialization here avoids doing it on PollInputEvents() called by EndDrawing() after first frame has been just drawn.- // The initialization will still happen and possible delays still occur, but before the window is shown, which is a nicer experience.- // REF: https://github.com/raysan5/raylib/issues/1554- glfwSetJoystickCallback(NULL);-- // Find monitor resolution- GLFWmonitor *monitor = glfwGetPrimaryMonitor();- if (!monitor)- {- TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");- return -1;- }-- const GLFWvidmode *mode = glfwGetVideoMode(monitor);-- CORE.Window.display.width = mode->width;- CORE.Window.display.height = mode->height;-- // Set screen width/height to the display width/height if they are 0- if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;- if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;-- if (CORE.Window.fullscreen)- {- // remember center for switchinging from fullscreen to window- if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))- {- // If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed.- // Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11.- CORE.Window.position.x = CORE.Window.display.width/4;- CORE.Window.position.y = CORE.Window.display.height/4;- }- else- {- CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;- CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;- }-- if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;- if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;-- // Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor- int count = 0;- const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);-- // Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height- for (int i = 0; i < count; i++)- {- if ((unsigned int)modes[i].width >= CORE.Window.screen.width)- {- if ((unsigned int)modes[i].height >= CORE.Window.screen.height)- {- CORE.Window.display.width = modes[i].width;- CORE.Window.display.height = modes[i].height;- break;- }- }- }-- TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);-- // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,- // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),- // framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched- // by the sides to fit all monitor space...-- // Try to setup the most appropriate fullscreen framebuffer for the requested screenWidth/screenHeight- // It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)- // Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale- // TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...- // HighDPI monitors are properly considered in a following similar function: SetupViewport()- SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);-- platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", glfwGetPrimaryMonitor(), NULL);-- // NOTE: Full-screen change, not working properly...- //glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);- }- else- {- // If we are windowed fullscreen, ensures that window does not minimize when focus is lost- if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))- {- glfwWindowHint(GLFW_AUTO_ICONIFY, 0);- }-- // No-fullscreen window creation- platform.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);-- if (platform.handle)- {- CORE.Window.render.width = CORE.Window.screen.width;- CORE.Window.render.height = CORE.Window.screen.height;- }- }-- if (!platform.handle)- {- glfwTerminate();- TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");- return -1;- }-- glfwMakeContextCurrent(platform.handle);- result = glfwGetError(NULL);-- // Check context activation- if ((result != GLFW_NO_WINDOW_CONTEXT) && (result != GLFW_PLATFORM_ERROR))- {- CORE.Window.ready = true;-- glfwSwapInterval(0); // No V-Sync by default-- // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)- // NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need- // to be activated on web platforms since VSync is enforced there.- if (CORE.Window.flags & FLAG_VSYNC_HINT)- {- // WARNING: It seems to hit a critical render path in Intel HD Graphics- glfwSwapInterval(1);- TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");- }-- int fbWidth = CORE.Window.screen.width;- int fbHeight = CORE.Window.screen.height;-- if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)- {- // NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.- // Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);- #if !defined(__APPLE__)- glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);-- // Screen scaling matrix is required in case desired screen area is different from display area- CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);-- // Mouse input scaling for the new screen size- SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);- #endif- }-- CORE.Window.render.width = fbWidth;- CORE.Window.render.height = fbHeight;- CORE.Window.currentFbo.width = fbWidth;- CORE.Window.currentFbo.height = fbHeight;-- TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");- TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);- TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);- TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);- TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);- }- else- {- TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");- return -1;- }-- if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();-- // If graphic device is no properly initialized, we end program- if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }- else - {- // Try to center window on screen but avoiding window-bar outside of screen- int posX = GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2;- int posY = GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2;- if (posX < 0) posX = 0;- if (posY < 0) posY = 0;- SetWindowPosition(posX, posY);- }-- // Load OpenGL extensions- // NOTE: GL procedures address loader is required to load extensions- rlLoadExtensions(glfwGetProcAddress);- //------------------------------------------------------------------------------ // Initialize input events callbacks- //----------------------------------------------------------------------------- // Set window callback events- glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!- glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);- glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);- glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);- glfwSetDropCallback(platform.handle, WindowDropCallback);-- if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)- {- glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);- }-- // Set input callback events- glfwSetKeyCallback(platform.handle, KeyCallback);- glfwSetCharCallback(platform.handle, CharCallback);- glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);- glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes- glfwSetScrollCallback(platform.handle, MouseScrollCallback);- glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);- glfwSetJoystickCallback(JoystickCallback);-- glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)-- // Retrieve gamepad names- for (int i = 0; i < MAX_GAMEPADS; i++)- {- if (glfwJoystickPresent(i)) strcpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i));- }- //------------------------------------------------------------------------------ // Initialize timming system- //----------------------------------------------------------------------------- InitTimer();- //------------------------------------------------------------------------------ // Initialize storage system- //----------------------------------------------------------------------------- CORE.Storage.basePath = GetWorkingDirectory();- //------------------------------------------------------------------------------ char* glfwPlatform = "";- switch (glfwGetPlatform())- {- case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;- case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;- case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;- case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;- case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;- }-- TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform);- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");-- return 0;-}--// Close platform-void ClosePlatform(void)-{- glfwDestroyWindow(platform.handle);- glfwTerminate();--#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)- timeEndPeriod(1); // Restore time period-#endif-}--// GLFW3 Error Callback, runs on GLFW3 error-static void ErrorCallback(int error, const char *description)-{- TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description);-}--// GLFW3 WindowSize Callback, runs when window is resizedLastFrame-// NOTE: Window resizing not allowed by default-static void WindowSizeCallback(GLFWwindow *window, int width, int height)-{- // Reset viewport and projection matrix for new size- SetupViewport(width, height);-- CORE.Window.currentFbo.width = width;- CORE.Window.currentFbo.height = height;- CORE.Window.resizedLastFrame = true;-- if (IsWindowFullscreen()) return;-- // Set current screen size-#if defined(__APPLE__)- CORE.Window.screen.width = width;- CORE.Window.screen.height = height;-#else- if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)- {- Vector2 windowScaleDPI = GetWindowScaleDPI();-- CORE.Window.screen.width = (unsigned int)(width/windowScaleDPI.x);- CORE.Window.screen.height = (unsigned int)(height/windowScaleDPI.y);- }- else- {- CORE.Window.screen.width = width;- CORE.Window.screen.height = height;- }-#endif-- // NOTE: Postprocessing texture is not scaled to new size-}--static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)-{- CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);-}--// GLFW3 WindowIconify Callback, runs when window is minimized/restored-static void WindowIconifyCallback(GLFWwindow *window, int iconified)-{- if (iconified) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; // The window was iconified- else CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // The window was restored-}--// GLFW3 WindowMaximize Callback, runs when window is maximized/restored-static void WindowMaximizeCallback(GLFWwindow *window, int maximized)-{- if (maximized) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // The window was maximized- else CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // The window was restored-}--// GLFW3 WindowFocus Callback, runs when window get/lose focus-static void WindowFocusCallback(GLFWwindow *window, int focused)-{- if (focused) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // The window was focused- else CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED; // The window lost focus-}--// GLFW3 Window Drop Callback, runs when drop files into window-static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)-{- if (count > 0)- {- // In case previous dropped filepaths have not been freed, we free them- if (CORE.Window.dropFileCount > 0)- {- for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);-- RL_FREE(CORE.Window.dropFilepaths);-- CORE.Window.dropFileCount = 0;- CORE.Window.dropFilepaths = NULL;- }-- // WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy- CORE.Window.dropFileCount = count;- CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));-- for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)- {- CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));- strcpy(CORE.Window.dropFilepaths[i], paths[i]);- }- }-}--// GLFW3 Keyboard Callback, runs on key pressed-static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)-{- if (key < 0) return; // Security check, macOS fn key generates -1-- // WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1- // to work properly with our implementation (IsKeyDown/IsKeyUp checks)- if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;- else if(action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;- else if(action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;-- // WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys- if (((key == KEY_CAPS_LOCK) && ((mods & GLFW_MOD_CAPS_LOCK) > 0)) ||- ((key == KEY_NUM_LOCK) && ((mods & GLFW_MOD_NUM_LOCK) > 0))) CORE.Input.Keyboard.currentKeyState[key] = 1;-- // Check if there is space available in the key queue- if ((CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) && (action == GLFW_PRESS))- {- // Add character to the queue- CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;- CORE.Input.Keyboard.keyPressedQueueCount++;- }-- // Check the exit key to set close window- if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);-}--// GLFW3 Char Callback, get unicode codepoint value-static void CharCallback(GLFWwindow *window, unsigned int codepoint)-{- //TRACELOG(LOG_DEBUG, "Char Callback: Codepoint: %i", codepoint);-- // NOTE: Registers any key down considering OS keyboard layout but- // does not detect action events, those should be managed by user...- // Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907- // Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char-- // Check if there is space available in the queue- if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)- {- // Add character to the queue- CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;- CORE.Input.Keyboard.charPressedQueueCount++;- }-}--// GLFW3 Mouse Button Callback, runs on mouse button pressed-static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)-{- // WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,- // but future releases may add more actions (i.e. GLFW_REPEAT)- CORE.Input.Mouse.currentButtonState[button] = action;- CORE.Input.Touch.currentTouchState[button] = action;--#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)- // Process mouse events as touches to be able to use mouse-gestures- GestureEvent gestureEvent = { 0 };-- // Register touch actions- if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) gestureEvent.touchAction = TOUCH_ACTION_DOWN;- else if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) gestureEvent.touchAction = TOUCH_ACTION_UP;-- // NOTE: TOUCH_ACTION_MOVE event is registered in MouseCursorPosCallback()-- // Assign a pointer ID- gestureEvent.pointId[0] = 0;-- // Register touch points count- gestureEvent.pointCount = 1;-- // Register touch points position, only one point registered- gestureEvent.position[0] = GetMousePosition();-- // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height- gestureEvent.position[0].x /= (float)GetScreenWidth();- gestureEvent.position[0].y /= (float)GetScreenHeight();-- // Gesture data is sent to gestures-system for processing- ProcessGestureEvent(gestureEvent);-#endif-}--// GLFW3 Cursor Position Callback, runs on mouse move-static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)-{- CORE.Input.Mouse.currentPosition.x = (float)x;- CORE.Input.Mouse.currentPosition.y = (float)y;- CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;--#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)- // Process mouse events as touches to be able to use mouse-gestures- GestureEvent gestureEvent = { 0 };-- gestureEvent.touchAction = TOUCH_ACTION_MOVE;-- // Assign a pointer ID- gestureEvent.pointId[0] = 0;-- // Register touch points count- gestureEvent.pointCount = 1;-- // Register touch points position, only one point registered- gestureEvent.position[0] = CORE.Input.Touch.position[0];-- // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height- gestureEvent.position[0].x /= (float)GetScreenWidth();- gestureEvent.position[0].y /= (float)GetScreenHeight();-- // Gesture data is sent to gestures-system for processing- ProcessGestureEvent(gestureEvent);-#endif-}--// GLFW3 Scrolling Callback, runs on mouse wheel-static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)-{- CORE.Input.Mouse.currentWheelMove = (Vector2){ (float)xoffset, (float)yoffset };-}--// GLFW3 CursorEnter Callback, when cursor enters the window-static void CursorEnterCallback(GLFWwindow *window, int enter)-{- if (enter) CORE.Input.Mouse.cursorOnScreen = true;- else CORE.Input.Mouse.cursorOnScreen = false;-}--// GLFW3 Joystick Connected/Disconnected Callback-static void JoystickCallback(int jid, int event)-{- if (event == GLFW_CONNECTED)- {- strcpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid));- }- else if (event == GLFW_DISCONNECTED)- {- memset(CORE.Input.Gamepad.name[jid], 0, 64);- }-}--// EOF
+ raylib/src/platforms/rcore_desktop_glfw.c view
@@ -0,0 +1,1872 @@+/**********************************************************************************************+*+* rcore_desktop - Functions to manage window, graphics device and inputs+*+* PLATFORM: DESKTOP: GLFW+* - Windows (Win32, Win64)+* - Linux (X11/Wayland desktop mode)+* - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)+* - OSX/macOS (x64, arm64)+*+* LIMITATIONS:+* - Limitation 01+* - Limitation 02+*+* POSSIBLE IMPROVEMENTS:+* - Improvement 01+* - Improvement 02+*+* ADDITIONAL NOTES:+* - TRACELOG() function is located in raylib [utils] module+*+* CONFIGURATION:+* #define RCORE_PLATFORM_CUSTOM_FLAG+* Custom flag for rcore on target platform -not used-+*+* DEPENDENCIES:+* - rglfw: Manage graphic device, OpenGL context and inputs (Windows, Linux, OSX, FreeBSD...)+* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)+*+*+* LICENSE: zlib/libpng+*+* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors+*+* This software is provided "as-is", without any express or implied warranty. In no event+* will the authors be held liable for any damages arising from the use of this software.+*+* Permission is granted to anyone to use this software for any purpose, including commercial+* applications, and to alter it and redistribute it freely, subject to the following restrictions:+*+* 1. The origin of this software must not be misrepresented; you must not claim that you+* wrote the original software. If you use this software in a product, an acknowledgment+* in the product documentation would be appreciated but is not required.+*+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented+* as being the original software.+*+* 3. This notice may not be removed or altered from any source distribution.+*+**********************************************************************************************/++#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3+ // NOTE: Already provided by rlgl implementation (on glad.h)+#include "GLFW/glfw3.h" // GLFW3 library: Windows, OpenGL context and Input management+ // NOTE: GLFW3 already includes gl.h (OpenGL) headers++// Support retrieving native window handlers+#if defined(_WIN32)+ typedef void *PVOID;+ typedef PVOID HANDLE;+ typedef HANDLE HWND;+ #define GLFW_EXPOSE_NATIVE_WIN32+ #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h+ #include "GLFW/glfw3native.h"++ #if defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)+ // NOTE: Those functions require linking with winmm library+ unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);+ unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);+ #endif+#endif+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)+ #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX++ //#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type+ //#define GLFW_EXPOSE_NATIVE_WAYLAND+ #include "GLFW/glfw3native.h" // Required for: glfwGetX11Window()+#endif+#if defined(__APPLE__)+ #include <unistd.h> // Required for: usleep()++ //#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition+ void *glfwGetCocoaWindow(GLFWwindow* handle);+ #include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()+#endif++//----------------------------------------------------------------------------------+// Types and Structures Definition+//----------------------------------------------------------------------------------+typedef struct {+ GLFWwindow *handle; // GLFW window handle (graphic device)+} PlatformData;++//----------------------------------------------------------------------------------+// Global Variables Definition+//----------------------------------------------------------------------------------+extern CoreData CORE; // Global CORE state context++static PlatformData platform = { 0 }; // Platform specific data++//----------------------------------------------------------------------------------+// Module Internal Functions Declaration+//----------------------------------------------------------------------------------+int InitPlatform(void); // Initialize platform (graphics, inputs and more)+void ClosePlatform(void); // Close platform++// Error callback event+static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error++// Window callbacks events+static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized+static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored+static void WindowMaximizeCallback(GLFWwindow* window, int maximized); // GLFW3 Window Maximize Callback, runs when window is maximized+static void WindowFocusCallback(GLFWwindow *window, int focused); // GLFW3 WindowFocus Callback, runs when window get/lose focus+static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window+static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley); // GLFW3 Window Content Scale Callback, runs when window changes scale++// Input callbacks events+static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed+static void CharCallback(GLFWwindow *window, unsigned int codepoint); // GLFW3 Char Callback, runs on key pressed (get codepoint value)+static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed+static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move+static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel+static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area+static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback++//----------------------------------------------------------------------------------+// Module Functions Declaration+//----------------------------------------------------------------------------------+// NOTE: Functions declaration is provided by raylib.h++//----------------------------------------------------------------------------------+// Module Functions Definition: Window and Graphics Device+//----------------------------------------------------------------------------------++// Check if application should close+// NOTE: By default, if KEY_ESCAPE pressed or window close icon clicked+bool WindowShouldClose(void)+{+ if (CORE.Window.ready) return CORE.Window.shouldClose;+ else return true;+}++// Toggle fullscreen mode+void ToggleFullscreen(void)+{+ if (!CORE.Window.fullscreen)+ {+ // Store previous window position (in case we exit fullscreen)+ glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y);++ int monitorCount = 0;+ int monitorIndex = GetCurrentMonitor();+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ // Use current monitor, so we correctly get the display the window is on+ GLFWmonitor *monitor = (monitorIndex < monitorCount)? monitors[monitorIndex] : NULL;++ if (monitor == NULL)+ {+ TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");++ CORE.Window.fullscreen = false;+ CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;++ glfwSetWindowMonitor(platform.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);+ }+ else+ {+ CORE.Window.fullscreen = true;+ CORE.Window.flags |= FLAG_FULLSCREEN_MODE;++ glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);+ }++ }+ else+ {+ CORE.Window.fullscreen = false;+ CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;++ glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);+ }++ // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)+ // NOTE: V-Sync can be enabled by graphic driver configuration+ if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);+}++// Toggle borderless windowed mode+void ToggleBorderlessWindowed(void)+{+ // Leave fullscreen before attempting to set borderless windowed mode and get screen position from it+ bool wasOnFullscreen = false;+ if (CORE.Window.fullscreen)+ {+ CORE.Window.previousPosition = CORE.Window.position;+ ToggleFullscreen();+ wasOnFullscreen = true;+ }++ const int monitor = GetCurrentMonitor();+ int monitorCount;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);++ if (mode)+ {+ if (!IsWindowState(FLAG_BORDERLESS_WINDOWED_MODE))+ {+ // Store screen position and size+ // NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here+ if (!wasOnFullscreen) glfwGetWindowPos(platform.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);+ CORE.Window.previousScreen = CORE.Window.screen;++ // Set undecorated and topmost modes and flags+ glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);+ CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;+ glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);+ CORE.Window.flags |= FLAG_WINDOW_TOPMOST;++ // Get monitor position and size+ int monitorPosX = 0;+ int monitorPosY = 0;+ glfwGetMonitorPos(monitors[monitor], &monitorPosX, &monitorPosY);+ const int monitorWidth = mode->width;+ const int monitorHeight = mode->height;++ // Set screen position and size+ glfwSetWindowPos(platform.handle, monitorPosX, monitorPosY);+ glfwSetWindowSize(platform.handle, monitorWidth, monitorHeight);++ // Refocus window+ glfwFocusWindow(platform.handle);++ CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;+ }+ else+ {+ // Remove topmost and undecorated modes and flags+ glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);+ CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;+ glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);+ CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;++ // Return previous screen size and position+ // NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly+ glfwSetWindowSize(platform.handle, CORE.Window.previousScreen.width, CORE.Window.previousScreen.height);+ glfwSetWindowPos(platform.handle, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y);++ // Refocus window+ glfwFocusWindow(platform.handle);++ CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;+ }+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");+}++// Set window state: maximized, if resizable+void MaximizeWindow(void)+{+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)+ {+ glfwMaximizeWindow(platform.handle);+ CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;+ }+}++// Set window state: minimized+void MinimizeWindow(void)+{+ // NOTE: Following function launches callback that sets appropriate flag!+ glfwIconifyWindow(platform.handle);+}++// Set window state: not minimized/maximized+void RestoreWindow(void)+{+ if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)+ {+ // Restores the specified window if it was previously iconified (minimized) or maximized+ glfwRestoreWindow(platform.handle);+ CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;+ CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;+ }+}++// Set window configuration state using flags+void SetWindowState(unsigned int flags)+{+ // Check previous state and requested state to apply required changes+ // NOTE: In most cases the functions already change the flags internally++ // State change: FLAG_VSYNC_HINT+ if (((CORE.Window.flags & FLAG_VSYNC_HINT) != (flags & FLAG_VSYNC_HINT)) && ((flags & FLAG_VSYNC_HINT) > 0))+ {+ glfwSwapInterval(1);+ CORE.Window.flags |= FLAG_VSYNC_HINT;+ }++ // State change: FLAG_BORDERLESS_WINDOWED_MODE+ // NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running+ if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) != (flags & FLAG_BORDERLESS_WINDOWED_MODE)) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))+ {+ ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_FULLSCREEN_MODE+ if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))+ {+ ToggleFullscreen(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_RESIZABLE+ if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != (flags & FLAG_WINDOW_RESIZABLE)) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_TRUE);+ CORE.Window.flags |= FLAG_WINDOW_RESIZABLE;+ }++ // State change: FLAG_WINDOW_UNDECORATED+ if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) != (flags & FLAG_WINDOW_UNDECORATED)) && (flags & FLAG_WINDOW_UNDECORATED))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);+ CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;+ }++ // State change: FLAG_WINDOW_HIDDEN+ if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) != (flags & FLAG_WINDOW_HIDDEN)) && ((flags & FLAG_WINDOW_HIDDEN) > 0))+ {+ glfwHideWindow(platform.handle);+ CORE.Window.flags |= FLAG_WINDOW_HIDDEN;+ }++ // State change: FLAG_WINDOW_MINIMIZED+ if (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) != (flags & FLAG_WINDOW_MINIMIZED)) && ((flags & FLAG_WINDOW_MINIMIZED) > 0))+ {+ //GLFW_ICONIFIED+ MinimizeWindow(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_MAXIMIZED+ if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) != (flags & FLAG_WINDOW_MAXIMIZED)) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))+ {+ //GLFW_MAXIMIZED+ MaximizeWindow(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_UNFOCUSED+ if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) != (flags & FLAG_WINDOW_UNFOCUSED)) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_FALSE);+ CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;+ }++ // State change: FLAG_WINDOW_TOPMOST+ if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) != (flags & FLAG_WINDOW_TOPMOST)) && ((flags & FLAG_WINDOW_TOPMOST) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);+ CORE.Window.flags |= FLAG_WINDOW_TOPMOST;+ }++ // State change: FLAG_WINDOW_ALWAYS_RUN+ if (((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) != (flags & FLAG_WINDOW_ALWAYS_RUN)) && ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0))+ {+ CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN;+ }++ // The following states can not be changed after window creation++ // State change: FLAG_WINDOW_TRANSPARENT+ if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) != (flags & FLAG_WINDOW_TRANSPARENT)) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");+ }++ // State change: FLAG_WINDOW_HIGHDPI+ if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) != (flags & FLAG_WINDOW_HIGHDPI)) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");+ }++ // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH+ if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);+ CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;+ }++ // State change: FLAG_MSAA_4X_HINT+ if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");+ }++ // State change: FLAG_INTERLACED_HINT+ if (((CORE.Window.flags & FLAG_INTERLACED_HINT) != (flags & FLAG_INTERLACED_HINT)) && ((flags & FLAG_INTERLACED_HINT) > 0))+ {+ TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");+ }+}++// Clear window configuration state flags+void ClearWindowState(unsigned int flags)+{+ // Check previous state and requested state to apply required changes+ // NOTE: In most cases the functions already change the flags internally++ // State change: FLAG_VSYNC_HINT+ if (((CORE.Window.flags & FLAG_VSYNC_HINT) > 0) && ((flags & FLAG_VSYNC_HINT) > 0))+ {+ glfwSwapInterval(0);+ CORE.Window.flags &= ~FLAG_VSYNC_HINT;+ }++ // State change: FLAG_BORDERLESS_WINDOWED_MODE+ // NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running+ if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))+ {+ ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_FULLSCREEN_MODE+ if (((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) && ((flags & FLAG_FULLSCREEN_MODE) > 0))+ {+ ToggleFullscreen(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_RESIZABLE+ if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_FALSE);+ CORE.Window.flags &= ~FLAG_WINDOW_RESIZABLE;+ }++ // State change: FLAG_WINDOW_HIDDEN+ if (((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) && ((flags & FLAG_WINDOW_HIDDEN) > 0))+ {+ glfwShowWindow(platform.handle);+ CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;+ }++ // State change: FLAG_WINDOW_MINIMIZED+ if (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) && ((flags & FLAG_WINDOW_MINIMIZED) > 0))+ {+ RestoreWindow(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_MAXIMIZED+ if (((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) && ((flags & FLAG_WINDOW_MAXIMIZED) > 0))+ {+ RestoreWindow(); // NOTE: Window state flag updated inside function+ }++ // State change: FLAG_WINDOW_UNDECORATED+ if (((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) && ((flags & FLAG_WINDOW_UNDECORATED) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);+ CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;+ }++ // State change: FLAG_WINDOW_UNFOCUSED+ if (((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) && ((flags & FLAG_WINDOW_UNFOCUSED) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_FOCUS_ON_SHOW, GLFW_TRUE);+ CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;+ }++ // State change: FLAG_WINDOW_TOPMOST+ if (((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) && ((flags & FLAG_WINDOW_TOPMOST) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);+ CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;+ }++ // State change: FLAG_WINDOW_ALWAYS_RUN+ if (((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) > 0) && ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0))+ {+ CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN;+ }++ // The following states can not be changed after window creation++ // State change: FLAG_WINDOW_TRANSPARENT+ if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");+ }++ // State change: FLAG_WINDOW_HIGHDPI+ if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");+ }++ // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH+ if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))+ {+ glfwSetWindowAttrib(platform.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);+ CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;+ }++ // State change: FLAG_MSAA_4X_HINT+ if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))+ {+ TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");+ }++ // State change: FLAG_INTERLACED_HINT+ if (((CORE.Window.flags & FLAG_INTERLACED_HINT) > 0) && ((flags & FLAG_INTERLACED_HINT) > 0))+ {+ TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");+ }+}++// Set icon for window+// NOTE 1: Image must be in RGBA format, 8bit per channel+// NOTE 2: Image is scaled by the OS for all required sizes+void SetWindowIcon(Image image)+{+ if (image.data == NULL)+ {+ // Revert to the default window icon, pass in an empty image array+ glfwSetWindowIcon(platform.handle, 0, NULL);+ }+ else+ {+ if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)+ {+ GLFWimage icon[1] = { 0 };++ icon[0].width = image.width;+ icon[0].height = image.height;+ icon[0].pixels = (unsigned char *)image.data;++ // NOTE 1: We only support one image icon+ // NOTE 2: The specified image data is copied before this function returns+ glfwSetWindowIcon(platform.handle, 1, icon);+ }+ else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");+ }+}++// Set icon for window, multiple images+// NOTE 1: Images must be in RGBA format, 8bit per channel+// NOTE 2: The multiple images are used depending on provided sizes+// Standard Windows icon sizes: 256, 128, 96, 64, 48, 32, 24, 16+void SetWindowIcons(Image *images, int count)+{+ if ((images == NULL) || (count <= 0))+ {+ // Revert to the default window icon, pass in an empty image array+ glfwSetWindowIcon(platform.handle, 0, NULL);+ }+ else+ {+ int valid = 0;+ GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));++ for (int i = 0; i < count; i++)+ {+ if (images[i].format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)+ {+ icons[valid].width = images[i].width;+ icons[valid].height = images[i].height;+ icons[valid].pixels = (unsigned char *)images[i].data;++ valid++;+ }+ else TRACELOG(LOG_WARNING, "GLFW: Window icon image must be in R8G8B8A8 pixel format");+ }+ // NOTE: Images data is copied internally before this function returns+ glfwSetWindowIcon(platform.handle, valid, icons);++ RL_FREE(icons);+ }+}++// Set title for window+void SetWindowTitle(const char *title)+{+ CORE.Window.title = title;+ glfwSetWindowTitle(platform.handle, title);+}++// Set window position on screen (windowed mode)+void SetWindowPosition(int x, int y)+{+ glfwSetWindowPos(platform.handle, x, y);+}++// Set monitor for the current window+void SetWindowMonitor(int monitor)+{+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ if (CORE.Window.fullscreen)+ {+ TRACELOG(LOG_INFO, "GLFW: Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));++ const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);+ glfwSetWindowMonitor(platform.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);+ }+ else+ {+ TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));++ const int screenWidth = CORE.Window.screen.width;+ const int screenHeight = CORE.Window.screen.height;+ int monitorWorkareaX = 0;+ int monitorWorkareaY = 0;+ int monitorWorkareaWidth = 0;+ int monitorWorkareaHeight = 0;+ glfwGetMonitorWorkarea(monitors[monitor], &monitorWorkareaX, &monitorWorkareaY, &monitorWorkareaWidth, &monitorWorkareaHeight);++ // If the screen size is larger than the monitor workarea, anchor it on the top left corner, otherwise, center it+ if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight)) glfwSetWindowPos(platform.handle, monitorWorkareaX, monitorWorkareaY);+ else+ {+ const int x = monitorWorkareaX + (monitorWorkareaWidth/2) - (screenWidth/2);+ const int y = monitorWorkareaY + (monitorWorkareaHeight/2) - (screenHeight/2);+ glfwSetWindowPos(platform.handle, x, y);+ }+ }+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");+}++// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)+void SetWindowMinSize(int width, int height)+{+ CORE.Window.screenMin.width = width;+ CORE.Window.screenMin.height = height;++ int minWidth = (CORE.Window.screenMin.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.width;+ int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.height;+ int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.width;+ int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.height;++ glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);+}++// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)+void SetWindowMaxSize(int width, int height)+{+ CORE.Window.screenMax.width = width;+ CORE.Window.screenMax.height = height;++ int minWidth = (CORE.Window.screenMin.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.width;+ int minHeight = (CORE.Window.screenMin.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMin.height;+ int maxWidth = (CORE.Window.screenMax.width == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.width;+ int maxHeight = (CORE.Window.screenMax.height == 0)? GLFW_DONT_CARE : (int)CORE.Window.screenMax.height;++ glfwSetWindowSizeLimits(platform.handle, minWidth, minHeight, maxWidth, maxHeight);+}++// Set window dimensions+void SetWindowSize(int width, int height)+{+ CORE.Window.screen.width = width;+ CORE.Window.screen.height = height;++ glfwSetWindowSize(platform.handle, width, height);+}++// Set window opacity, value opacity is between 0.0 and 1.0+void SetWindowOpacity(float opacity)+{+ if (opacity >= 1.0f) opacity = 1.0f;+ else if (opacity <= 0.0f) opacity = 0.0f;+ glfwSetWindowOpacity(platform.handle, opacity);+}++// Set window focused+void SetWindowFocused(void)+{+ glfwFocusWindow(platform.handle);+}++// Get native window handle+void *GetWindowHandle(void)+{+#if defined(_WIN32)+ // NOTE: Returned handle is: void *HWND (windows.h)+ return glfwGetWin32Window(platform.handle);+#endif+#if defined(__linux__)+ // NOTE: Returned handle is: unsigned long Window (X.h)+ // typedef unsigned long XID;+ // typedef XID Window;+ //unsigned long id = (unsigned long)glfwGetX11Window(platform.handle);+ //return NULL; // TODO: Find a way to return value... cast to void *?+ return (void *)platform.handle;+#endif+#if defined(__APPLE__)+ // NOTE: Returned handle is: (objc_object *)+ return (void *)glfwGetCocoaWindow(platform.handle);+#endif++ return NULL;+}++// Get number of monitors+int GetMonitorCount(void)+{+ int monitorCount = 0;++ glfwGetMonitors(&monitorCount);++ return monitorCount;+}++// Get number of monitors+int GetCurrentMonitor(void)+{+ int index = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);+ GLFWmonitor *monitor = NULL;++ if (monitorCount >= 1)+ {+ if (IsWindowFullscreen())+ {+ // Get the handle of the monitor that the specified window is in full screen on+ monitor = glfwGetWindowMonitor(platform.handle);++ for (int i = 0; i < monitorCount; i++)+ {+ if (monitors[i] == monitor)+ {+ index = i;+ break;+ }+ }+ }+ else+ {+ // In case the window is between two monitors, we use below logic+ // to try to detect the "current monitor" for that window, note that+ // this is probably an overengineered solution for a very side case+ // trying to match SDL behaviour++ int closestDist = 0x7FFFFFFF;++ // Window center position+ int wcx = 0;+ int wcy = 0;++ glfwGetWindowPos(platform.handle, &wcx, &wcy);+ wcx += (int)CORE.Window.screen.width/2;+ wcy += (int)CORE.Window.screen.height/2;++ for (int i = 0; i < monitorCount; i++)+ {+ // Monitor top-left position+ int mx = 0;+ int my = 0;++ monitor = monitors[i];+ glfwGetMonitorPos(monitor, &mx, &my);+ const GLFWvidmode *mode = glfwGetVideoMode(monitor);++ if (mode)+ {+ const int right = mx + mode->width - 1;+ const int bottom = my + mode->height - 1;++ if ((wcx >= mx) &&+ (wcx <= right) &&+ (wcy >= my) &&+ (wcy <= bottom))+ {+ index = i;+ break;+ }++ int xclosest = wcx;+ if (wcx < mx) xclosest = mx;+ else if (wcx > right) xclosest = right;++ int yclosest = wcy;+ if (wcy < my) yclosest = my;+ else if (wcy > bottom) yclosest = bottom;++ int dx = wcx - xclosest;+ int dy = wcy - yclosest;+ int dist = (dx*dx) + (dy*dy);+ if (dist < closestDist)+ {+ index = i;+ closestDist = dist;+ }+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");+ }+ }+ }++ return index;+}++// Get selected monitor position+Vector2 GetMonitorPosition(int monitor)+{+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ int x, y;+ glfwGetMonitorPos(monitors[monitor], &x, &y);++ return (Vector2){ (float)x, (float)y };+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");+ return (Vector2){ 0, 0 };+}++// Get selected monitor width (currently used by monitor)+int GetMonitorWidth(int monitor)+{+ int width = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);++ if (mode) width = mode->width;+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");++ return width;+}++// Get selected monitor height (currently used by monitor)+int GetMonitorHeight(int monitor)+{+ int height = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);++ if (mode) height = mode->height;+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");++ return height;+}++// Get selected monitor physical width in millimetres+int GetMonitorPhysicalWidth(int monitor)+{+ int width = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount)) glfwGetMonitorPhysicalSize(monitors[monitor], &width, NULL);+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");++ return width;+}++// Get selected monitor physical height in millimetres+int GetMonitorPhysicalHeight(int monitor)+{+ int height = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount)) glfwGetMonitorPhysicalSize(monitors[monitor], NULL, &height);+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");++ return height;+}++// Get selected monitor refresh rate+int GetMonitorRefreshRate(int monitor)+{+ int refresh = 0;+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ const GLFWvidmode *vidmode = glfwGetVideoMode(monitors[monitor]);+ refresh = vidmode->refreshRate;+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");++ return refresh;+}++// Get the human-readable, UTF-8 encoded name of the selected monitor+const char *GetMonitorName(int monitor)+{+ int monitorCount = 0;+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if ((monitor >= 0) && (monitor < monitorCount))+ {+ return glfwGetMonitorName(monitors[monitor]);+ }+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");+ return "";+}++// Get window position XY on monitor+Vector2 GetWindowPosition(void)+{+ int x = 0;+ int y = 0;++ glfwGetWindowPos(platform.handle, &x, &y);++ return (Vector2){ (float)x, (float)y };+}++// Get window scale DPI factor for current monitor+Vector2 GetWindowScaleDPI(void)+{+ Vector2 scale = {0};+ glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);+ return scale;+}++// Set clipboard text content+void SetClipboardText(const char *text)+{+ glfwSetClipboardString(platform.handle, text);+}++// Get clipboard text content+// NOTE: returned string is allocated and freed by GLFW+const char *GetClipboardText(void)+{+ return glfwGetClipboardString(platform.handle);+}++// Show mouse cursor+void ShowCursor(void)+{+ glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);+ CORE.Input.Mouse.cursorHidden = false;+}++// Hides mouse cursor+void HideCursor(void)+{+ glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);+ CORE.Input.Mouse.cursorHidden = true;+}++// Enables cursor (unlock cursor)+void EnableCursor(void)+{+ glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);++ // Set cursor position in the middle+ SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);++ if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);++ CORE.Input.Mouse.cursorHidden = false;+}++// Disables cursor (lock cursor)+void DisableCursor(void)+{+ glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);++ // Set cursor position in the middle+ SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);++ if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);++ CORE.Input.Mouse.cursorHidden = true;+}++// Swap back buffer with front buffer (screen drawing)+void SwapScreenBuffer(void)+{+ glfwSwapBuffers(platform.handle);+}++//----------------------------------------------------------------------------------+// Module Functions Definition: Misc+//----------------------------------------------------------------------------------++// Get elapsed time measure in seconds since InitTimer()+double GetTime(void)+{+ double time = glfwGetTime(); // Elapsed time since glfwInit()+ return time;+}++// Open URL with default system browser (if available)+// NOTE: This function is only safe to use if you control the URL given.+// A user could craft a malicious string performing another action.+// Only call this function yourself not with user input or make sure to check the string yourself.+// Ref: https://github.com/raysan5/raylib/issues/686+void OpenURL(const char *url)+{+ // Security check to (partially) avoid malicious code+ if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");+ else+ {+ char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));+#if defined(_WIN32)+ sprintf(cmd, "explorer \"%s\"", url);+#endif+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)+ sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser+#endif+#if defined(__APPLE__)+ sprintf(cmd, "open '%s'", url);+#endif+ int result = system(cmd);+ if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");+ RL_FREE(cmd);+ }+}++//----------------------------------------------------------------------------------+// Module Functions Definition: Inputs+//----------------------------------------------------------------------------------++// Set internal gamepad mappings+int SetGamepadMappings(const char *mappings)+{+ return glfwUpdateGamepadMappings(mappings);+}++// Set gamepad vibration+void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor)+{+ TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");+}++// Set mouse position XY+void SetMousePosition(int x, int y)+{+ CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };+ CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;++ // NOTE: emscripten not implemented+ glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);+}++// Set mouse cursor+void SetMouseCursor(int cursor)+{+ CORE.Input.Mouse.cursor = cursor;+ if (cursor == MOUSE_CURSOR_DEFAULT) glfwSetCursor(platform.handle, NULL);+ else+ {+ // NOTE: We are relating internal GLFW enum values to our MouseCursor enum values+ glfwSetCursor(platform.handle, glfwCreateStandardCursor(0x00036000 + cursor));+ }+}++// Register all input events+void PollInputEvents(void)+{+#if defined(SUPPORT_GESTURES_SYSTEM)+ // NOTE: Gestures update must be called every frame to reset gestures correctly+ // because ProcessGestureEvent() is just called on an event, not every frame+ UpdateGestures();+#endif++ // Reset keys/chars pressed registered+ CORE.Input.Keyboard.keyPressedQueueCount = 0;+ CORE.Input.Keyboard.charPressedQueueCount = 0;++ // Reset last gamepad button/axis registered state+ CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN+ //CORE.Input.Gamepad.axisCount = 0;++ // Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)++ // Register previous keys states+ for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)+ {+ CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];+ CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;+ }++ // Register previous mouse states+ for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];++ // Register previous mouse wheel state+ CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;+ CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };++ // Register previous mouse position+ CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;++ // Register previous touch states+ for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];++ // Reset touch positions+ //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };++ // Map touch position to mouse position for convenience+ // WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!+ // TODO: GLFW does not support multi-touch input just yet+ // https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch+ // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages+ CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;++ // Check if gamepads are ready+ // NOTE: We do it here in case of disconnection+ for (int i = 0; i < MAX_GAMEPADS; i++)+ {+ if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;+ else CORE.Input.Gamepad.ready[i] = false;+ }++ // Register gamepads buttons events+ for (int i = 0; i < MAX_GAMEPADS; i++)+ {+ if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available+ {+ // Register previous gamepad states+ for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];++ // Get current gamepad state+ // NOTE: There is no callback available, so we get it manually+ GLFWgamepadstate state = { 0 };+ glfwGetGamepadState(i, &state); // This remapps all gamepads so they have their buttons mapped like an xbox controller++ const unsigned char *buttons = state.buttons;++ for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++)+ {+ int button = -1; // GamepadButton enum values assigned++ switch (k)+ {+ case GLFW_GAMEPAD_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;+ case GLFW_GAMEPAD_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;+ case GLFW_GAMEPAD_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;+ case GLFW_GAMEPAD_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;++ case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;+ case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;++ case GLFW_GAMEPAD_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;+ case GLFW_GAMEPAD_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;+ case GLFW_GAMEPAD_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;++ case GLFW_GAMEPAD_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;+ case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;+ case GLFW_GAMEPAD_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;+ case GLFW_GAMEPAD_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;++ case GLFW_GAMEPAD_BUTTON_LEFT_THUMB: button = GAMEPAD_BUTTON_LEFT_THUMB; break;+ case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;+ default: break;+ }++ if (button != -1) // Check for valid button+ {+ if (buttons[k] == GLFW_PRESS)+ {+ CORE.Input.Gamepad.currentButtonState[i][button] = 1;+ CORE.Input.Gamepad.lastButtonPressed = button;+ }+ else CORE.Input.Gamepad.currentButtonState[i][button] = 0;+ }+ }++ // Get current axis state+ const float *axes = state.axes;++ for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)+ {+ CORE.Input.Gamepad.axisState[i][k] = axes[k];+ }++ // Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)+ CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);+ CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);++ CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;+ }+ }++ CORE.Window.resizedLastFrame = false;++ if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)+ else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state++ // While window minimized, stop loop execution+ while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();++ CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);++ // Reset close status for next frame+ glfwSetWindowShouldClose(platform.handle, GLFW_FALSE);+}+++//----------------------------------------------------------------------------------+// Module Internal Functions Definition+//----------------------------------------------------------------------------------++static void SetDimensionsFromMonitor(GLFWmonitor *monitor)+{+ const GLFWvidmode *mode = glfwGetVideoMode(monitor);++ // Default display resolution to that of the current mode+ CORE.Window.display.width = mode->width;+ CORE.Window.display.height = mode->height;++ // Set screen width/height to the display width/height if they are 0+ if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;+ if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;+}++// Initialize platform: graphics, inputs and more+int InitPlatform(void)+{+ glfwSetErrorCallback(ErrorCallback);+/*+ // TODO: Setup GLFW custom allocators to match raylib ones+ const GLFWallocator allocator = {+ .allocate = MemAlloc,+ .deallocate = MemFree,+ .reallocate = MemRealloc,+ .user = NULL+ };++ glfwInitAllocator(&allocator);+*/++#if defined(__APPLE__)+ glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);+#endif+ // Initialize GLFW internal global state+ int result = glfwInit();+ if (result == GLFW_FALSE) { TRACELOG(LOG_WARNING, "GLFW: Failed to initialize GLFW"); return -1; }++ // Initialize graphic device: display/window and graphic context+ //----------------------------------------------------------------------------+ glfwDefaultWindowHints(); // Set default windows hints+ //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits+ //glfwWindowHint(GLFW_GREEN_BITS, 8); // Framebuffer green color component bits+ //glfwWindowHint(GLFW_BLUE_BITS, 8); // Framebuffer blue color component bits+ //glfwWindowHint(GLFW_ALPHA_BITS, 8); // Framebuffer alpha color component bits+ //glfwWindowHint(GLFW_DEPTH_BITS, 24); // Depthbuffer bits+ //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window+ //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API+ //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers++ // Check window creation flags+ if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true;++ if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // Visible window+ else glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); // Window initially hidden++ if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window+ else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window++ if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // Resizable window+ else glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // Avoid window being resizable++ // Disable FLAG_WINDOW_MINIMIZED, not supported on initialization+ if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;++ // Disable FLAG_WINDOW_MAXIMIZED, not supported on initialization+ if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;++ if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);+ else glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);++ if ((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);+ else glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);++ // NOTE: Some GLFW flags are not supported on HTML5+ if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer+ else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer++ if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)+ {+ // Resize window content area based on the monitor content scale.+ // NOTE: This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11.+ // On platforms like macOS the resolution of the framebuffer is changed independently of the window size.+ glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on+#if defined(__APPLE__)+ glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);+#endif+ }+ else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);++ // Mouse passthrough+ if ((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);+ else glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);++ if (CORE.Window.flags & FLAG_MSAA_4X_HINT)+ {+ // NOTE: MSAA is only enabled for main framebuffer, not user-created FBOs+ TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");+ glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0+ }++ // NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version+ // with backward compatibility to older OpenGL versions.+ // For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context.++ // Check selection OpenGL version+ if (rlGetVersion() == RL_OPENGL_21)+ {+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)+ }+ else if (rlGetVersion() == RL_OPENGL_33)+ {+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!+ // Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE+#if defined(__APPLE__)+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires forward compatibility+#else+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above!+#endif+ //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context+ }+ else if (rlGetVersion() == RL_OPENGL_43)+ {+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Choose OpenGL major version (just hint)+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE);+#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT)+ glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Enable OpenGL Debug Context+#endif+ }+ else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context+ {+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);+ glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);+ }+ else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context+ {+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);+ glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);+ }++ // NOTE: GLFW 3.4+ defers initialization of the Joystick subsystem on the first call to any Joystick related functions.+ // Forcing this initialization here avoids doing it on PollInputEvents() called by EndDrawing() after first frame has been just drawn.+ // The initialization will still happen and possible delays still occur, but before the window is shown, which is a nicer experience.+ // REF: https://github.com/raysan5/raylib/issues/1554+ glfwSetJoystickCallback(NULL);++ GLFWmonitor *monitor = NULL;+ if (CORE.Window.fullscreen)+ {+ // According to glfwCreateWindow(), if the user does not have a choice, fullscreen applications+ // should default to the primary monitor.++ monitor = glfwGetPrimaryMonitor();+ if (!monitor)+ {+ TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor");+ return -1;+ }++ SetDimensionsFromMonitor(monitor);++ // Remember center for switching from fullscreen to window+ if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))+ {+ // If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed.+ // Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11.+ CORE.Window.position.x = CORE.Window.display.width/4;+ CORE.Window.position.y = CORE.Window.display.height/4;+ }+ else+ {+ CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;+ CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;+ }++ if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;+ if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;++ // Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor+ int count = 0;+ const GLFWvidmode *modes = glfwGetVideoModes(monitor, &count);++ // Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height+ for (int i = 0; i < count; i++)+ {+ if ((unsigned int)modes[i].width >= CORE.Window.screen.width)+ {+ if ((unsigned int)modes[i].height >= CORE.Window.screen.height)+ {+ CORE.Window.display.width = modes[i].width;+ CORE.Window.display.height = modes[i].height;+ break;+ }+ }+ }++ TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);++ // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,+ // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),+ // framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched+ // by the sides to fit all monitor space...++ // Try to setup the most appropriate fullscreen framebuffer for the requested screenWidth/screenHeight+ // It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)+ // Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale+ // TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...+ // HighDPI monitors are properly considered in a following similar function: SetupViewport()+ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);++ platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", monitor, NULL);++ // NOTE: Full-screen change, not working properly...+ //glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);+ }+ else+ {+ // No-fullscreen window creation+ bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);++ // If we are windowed fullscreen, ensures that window does not minimize when focus is lost.+ // This hinting code will not work if the user already specified the correct monitor dimensions;+ // at this point we don't know the monitor's dimensions. (Though, how did the user then?)+ if (requestWindowedFullscreen) glfwWindowHint(GLFW_AUTO_ICONIFY, 0);++ // Default to at least one pixel in size, as creation with a zero dimension is not allowed.+ int creationWidth = CORE.Window.screen.width != 0 ? CORE.Window.screen.width : 1;+ int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1;++ platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);++ // After the window was created, determine the monitor that the window manager assigned.+ // Derive display sizes, and, if possible, window size in case it was zero at beginning.++ int monitorCount = 0;+ int monitorIndex = GetCurrentMonitor();+ GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);++ if (monitorIndex < monitorCount)+ {+ monitor = monitors[monitorIndex];+ SetDimensionsFromMonitor(monitor);++ if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);+ }+ else+ {+ // The monitor for the window-manager-created window can not be determined, so it can not be centered.+ glfwTerminate();+ TRACELOG(LOG_WARNING, "GLFW: Failed to determine Monitor to center Window");+ return -1;+ }++ if (platform.handle)+ {+ CORE.Window.render.width = CORE.Window.screen.width;+ CORE.Window.render.height = CORE.Window.screen.height;+ }+ }++ if (!platform.handle)+ {+ glfwTerminate();+ TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");+ return -1;+ }++ glfwMakeContextCurrent(platform.handle);+ result = glfwGetError(NULL);++ // Check context activation+ if ((result != GLFW_NO_WINDOW_CONTEXT) && (result != GLFW_PLATFORM_ERROR))+ {+ CORE.Window.ready = true;++ glfwSwapInterval(0); // No V-Sync by default++ // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)+ // NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need+ // to be activated on web platforms since VSync is enforced there.+ if (CORE.Window.flags & FLAG_VSYNC_HINT)+ {+ // WARNING: It seems to hit a critical render path in Intel HD Graphics+ glfwSwapInterval(1);+ TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");+ }++ int fbWidth = CORE.Window.screen.width;+ int fbHeight = CORE.Window.screen.height;++ if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)+ {+ // NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.+ // Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);+ #if !defined(__APPLE__)+ glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);++ // Screen scaling matrix is required in case desired screen area is different from display area+ CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);++ // Mouse input scaling for the new screen size+ SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);+ #endif+ }++ CORE.Window.render.width = fbWidth;+ CORE.Window.render.height = fbHeight;+ CORE.Window.currentFbo.width = fbWidth;+ CORE.Window.currentFbo.height = fbHeight;++ TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");+ TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);+ TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);+ TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);+ TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);+ }+ else+ {+ TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");+ return -1;+ }++ if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();++ // If graphic device is no properly initialized, we end program+ if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }+ else+ {+ // Try to center window on screen but avoiding window-bar outside of screen+ int monitorX = 0;+ int monitorY = 0;+ int monitorWidth = 0;+ int monitorHeight = 0;+ glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);++ int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2;+ int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2;+ if (posX < monitorX) posX = monitorX;+ if (posY < monitorY) posY = monitorY;+ SetWindowPosition(posX, posY);+ }++ // Load OpenGL extensions+ // NOTE: GL procedures address loader is required to load extensions+ rlLoadExtensions(glfwGetProcAddress);+ //----------------------------------------------------------------------------++ // Initialize input events callbacks+ //----------------------------------------------------------------------------+ // Set window callback events+ glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!+ glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback);+ glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);+ glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);+ glfwSetDropCallback(platform.handle, WindowDropCallback);++ if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)+ {+ glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);+ }++ // Set input callback events+ glfwSetKeyCallback(platform.handle, KeyCallback);+ glfwSetCharCallback(platform.handle, CharCallback);+ glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback);+ glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); // Track mouse position changes+ glfwSetScrollCallback(platform.handle, MouseScrollCallback);+ glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback);+ glfwSetJoystickCallback(JoystickCallback);++ glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // Enable lock keys modifiers (CAPS, NUM)++ // Retrieve gamepad names+ for (int i = 0; i < MAX_GAMEPADS; i++)+ {+ if (glfwJoystickPresent(i)) strcpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i));+ }+ //----------------------------------------------------------------------------++ // Initialize timming system+ //----------------------------------------------------------------------------+ InitTimer();+ //----------------------------------------------------------------------------++ // Initialize storage system+ //----------------------------------------------------------------------------+ CORE.Storage.basePath = GetWorkingDirectory();+ //----------------------------------------------------------------------------++#if defined(__NetBSD__)+ // Workaround for NetBSD+ char *glfwPlatform = "X11";+#else+ char *glfwPlatform = "";+ switch (glfwGetPlatform())+ {+ case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break;+ case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break;+ case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break;+ case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break;+ case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break;+ }+#endif++ TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform);+ TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully");++ return 0;+}++// Close platform+void ClosePlatform(void)+{+ glfwDestroyWindow(platform.handle);+ glfwTerminate();++#if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)+ timeEndPeriod(1); // Restore time period+#endif+}++// GLFW3 Error Callback, runs on GLFW3 error+static void ErrorCallback(int error, const char *description)+{+ TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description);+}++// GLFW3 WindowSize Callback, runs when window is resizedLastFrame+// NOTE: Window resizing not allowed by default+static void WindowSizeCallback(GLFWwindow *window, int width, int height)+{+ // Reset viewport and projection matrix for new size+ SetupViewport(width, height);++ CORE.Window.currentFbo.width = width;+ CORE.Window.currentFbo.height = height;+ CORE.Window.resizedLastFrame = true;++ if (IsWindowFullscreen()) return;++ // Set current screen size++ CORE.Window.screen.width = width;+ CORE.Window.screen.height = height;++ // NOTE: Postprocessing texture is not scaled to new size+}++static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float scaley)+{+ CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);+}++// GLFW3 WindowIconify Callback, runs when window is minimized/restored+static void WindowIconifyCallback(GLFWwindow *window, int iconified)+{+ if (iconified) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; // The window was iconified+ else CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // The window was restored+}++// GLFW3 WindowMaximize Callback, runs when window is maximized/restored+static void WindowMaximizeCallback(GLFWwindow *window, int maximized)+{+ if (maximized) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // The window was maximized+ else CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // The window was restored+}++// GLFW3 WindowFocus Callback, runs when window get/lose focus+static void WindowFocusCallback(GLFWwindow *window, int focused)+{+ if (focused) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // The window was focused+ else CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED; // The window lost focus+}++// GLFW3 Window Drop Callback, runs when drop files into window+static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)+{+ if (count > 0)+ {+ // In case previous dropped filepaths have not been freed, we free them+ if (CORE.Window.dropFileCount > 0)+ {+ for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);++ RL_FREE(CORE.Window.dropFilepaths);++ CORE.Window.dropFileCount = 0;+ CORE.Window.dropFilepaths = NULL;+ }++ // WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy+ CORE.Window.dropFileCount = count;+ CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));++ for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)+ {+ CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));+ strcpy(CORE.Window.dropFilepaths[i], paths[i]);+ }+ }+}++// GLFW3 Keyboard Callback, runs on key pressed+static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)+{+ if (key < 0) return; // Security check, macOS fn key generates -1++ // WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1+ // to work properly with our implementation (IsKeyDown/IsKeyUp checks)+ if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;+ else if(action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;+ else if(action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;++ // WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys+ if (((key == KEY_CAPS_LOCK) && ((mods & GLFW_MOD_CAPS_LOCK) > 0)) ||+ ((key == KEY_NUM_LOCK) && ((mods & GLFW_MOD_NUM_LOCK) > 0))) CORE.Input.Keyboard.currentKeyState[key] = 1;++ // Check if there is space available in the key queue+ if ((CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) && (action == GLFW_PRESS))+ {+ // Add character to the queue+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;+ CORE.Input.Keyboard.keyPressedQueueCount++;+ }++ // Check the exit key to set close window+ if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(platform.handle, GLFW_TRUE);+}++// GLFW3 Char Callback, get unicode codepoint value+static void CharCallback(GLFWwindow *window, unsigned int codepoint)+{+ //TRACELOG(LOG_DEBUG, "Char Callback: Codepoint: %i", codepoint);++ // NOTE: Registers any key down considering OS keyboard layout but+ // does not detect action events, those should be managed by user...+ // Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907+ // Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char++ // Check if there is space available in the queue+ if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)+ {+ // Add character to the queue+ CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;+ CORE.Input.Keyboard.charPressedQueueCount++;+ }+}++// GLFW3 Mouse Button Callback, runs on mouse button pressed+static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)+{+ // WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,+ // but future releases may add more actions (i.e. GLFW_REPEAT)+ CORE.Input.Mouse.currentButtonState[button] = action;+ CORE.Input.Touch.currentTouchState[button] = action;++#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)+ // Process mouse events as touches to be able to use mouse-gestures+ GestureEvent gestureEvent = { 0 };++ // Register touch actions+ if ((CORE.Input.Mouse.currentButtonState[button] == 1) && (CORE.Input.Mouse.previousButtonState[button] == 0)) gestureEvent.touchAction = TOUCH_ACTION_DOWN;+ else if ((CORE.Input.Mouse.currentButtonState[button] == 0) && (CORE.Input.Mouse.previousButtonState[button] == 1)) gestureEvent.touchAction = TOUCH_ACTION_UP;++ // NOTE: TOUCH_ACTION_MOVE event is registered in MouseCursorPosCallback()++ // Assign a pointer ID+ gestureEvent.pointId[0] = 0;++ // Register touch points count+ gestureEvent.pointCount = 1;++ // Register touch points position, only one point registered+ gestureEvent.position[0] = GetMousePosition();++ // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height+ gestureEvent.position[0].x /= (float)GetScreenWidth();+ gestureEvent.position[0].y /= (float)GetScreenHeight();++ // Gesture data is sent to gestures-system for processing+ ProcessGestureEvent(gestureEvent);+#endif+}++// GLFW3 Cursor Position Callback, runs on mouse move+static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)+{+ CORE.Input.Mouse.currentPosition.x = (float)x;+ CORE.Input.Mouse.currentPosition.y = (float)y;+ CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;++#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)+ // Process mouse events as touches to be able to use mouse-gestures+ GestureEvent gestureEvent = { 0 };++ gestureEvent.touchAction = TOUCH_ACTION_MOVE;++ // Assign a pointer ID+ gestureEvent.pointId[0] = 0;++ // Register touch points count+ gestureEvent.pointCount = 1;++ // Register touch points position, only one point registered+ gestureEvent.position[0] = CORE.Input.Touch.position[0];++ // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height+ gestureEvent.position[0].x /= (float)GetScreenWidth();+ gestureEvent.position[0].y /= (float)GetScreenHeight();++ // Gesture data is sent to gestures-system for processing+ ProcessGestureEvent(gestureEvent);+#endif+}++// GLFW3 Scrolling Callback, runs on mouse wheel+static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)+{+ CORE.Input.Mouse.currentWheelMove = (Vector2){ (float)xoffset, (float)yoffset };+}++// GLFW3 CursorEnter Callback, when cursor enters the window+static void CursorEnterCallback(GLFWwindow *window, int enter)+{+ if (enter) CORE.Input.Mouse.cursorOnScreen = true;+ else CORE.Input.Mouse.cursorOnScreen = false;+}++// GLFW3 Joystick Connected/Disconnected Callback+static void JoystickCallback(int jid, int event)+{+ if (event == GLFW_CONNECTED)+ {+ strcpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid));+ }+ else if (event == GLFW_DISCONNECTED)+ {+ memset(CORE.Input.Gamepad.name[jid], 0, 64);+ }+}++// EOF
+ raylib/src/platforms/rcore_desktop_rgfw.c view
@@ -0,0 +1,1343 @@+/********************************************************************************************** +* +* rcore_desktop_rgfw template - Functions to manage window, graphics device and inputs +* +* PLATFORM: RGFW +* - Windows (Win32, Win64) +* - Linux (X11/Wayland desktop mode) +* - MacOS (Cocoa) +* +* LIMITATIONS: +* - TODO +* +* POSSIBLE IMPROVEMENTS: +* - TODO +* +* ADDITIONAL NOTES: +* - TRACELOG() function is located in raylib [utils] module +* +* CONFIGURATION: +* #define RCORE_PLATFORM_RGFW +* Custom flag for rcore on target platform RGFW +* +* DEPENDENCIES: +* - RGFW.h (main library): Windowing and inputs management +* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5), Colleague Riley and contributors +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifdef GRAPHICS_API_OPENGL_ES2 + #define RGFW_OPENGL_ES2 +#endif + +void ShowCursor(void); +void CloseWindow(void); + +#if defined(__linux__) + #define _INPUT_EVENT_CODES_H +#endif + +#if defined(__unix__) || defined(__linux__) + #define _XTYPEDEF_FONT +#endif + +#define RGFW_IMPLEMENTATION + +#if defined(__WIN32) || defined(__WIN64) + #define WIN32_LEAN_AND_MEAN + #define Rectangle rectangle_win32 + #define CloseWindow CloseWindow_win32 + #define ShowCursor __imp_ShowCursor + #define _APISETSTRING_ +#endif + +#if defined(__APPLE__) + #define Point NSPOINT + #define Size NSSIZE +#endif + +#if defined(_MSC_VER) +__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); +#endif + +#include "../external/RGFW.h" + +#if defined(__WIN32) || defined(__WIN64) + #undef DrawText + #undef ShowCursor + #undef CloseWindow + #undef Rectangle +#endif + +#if defined(__APPLE__) + #undef Point + #undef Size +#endif + +#include <stdbool.h> +#include <string.h> // Required for: strcmp() + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct { + RGFW_window *window; // Native display device (physical screen connection) +} PlatformData; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +extern CoreData CORE; // Global CORE state context + +static PlatformData platform = { NULL }; // Platform specific + +static bool RGFW_disableCursor = false; + +static const unsigned short keyMappingRGFW[] = { + [RGFW_KEY_NULL] = KEY_NULL, + [RGFW_Quote] = KEY_APOSTROPHE, + [RGFW_Comma] = KEY_COMMA, + [RGFW_Minus] = KEY_MINUS, + [RGFW_Period] = KEY_PERIOD, + [RGFW_Slash] = KEY_SLASH, + [RGFW_Escape] = KEY_ESCAPE, + [RGFW_F1] = KEY_F1, + [RGFW_F2] = KEY_F2, + [RGFW_F3] = KEY_F3, + [RGFW_F4] = KEY_F4, + [RGFW_F5] = KEY_F5, + [RGFW_F6] = KEY_F6, + [RGFW_F7] = KEY_F7, + [RGFW_F8] = KEY_F8, + [RGFW_F9] = KEY_F9, + [RGFW_F10] = KEY_F10, + [RGFW_F11] = KEY_F11, + [RGFW_F12] = KEY_F12, + [RGFW_Backtick] = KEY_GRAVE, + [RGFW_0] = KEY_ZERO, + [RGFW_1] = KEY_ONE, + [RGFW_2] = KEY_TWO, + [RGFW_3] = KEY_THREE, + [RGFW_4] = KEY_FOUR, + [RGFW_5] = KEY_FIVE, + [RGFW_6] = KEY_SIX, + [RGFW_7] = KEY_SEVEN, + [RGFW_8] = KEY_EIGHT, + [RGFW_9] = KEY_NINE, + [RGFW_Equals] = KEY_EQUAL, + [RGFW_BackSpace] = KEY_BACKSPACE, + [RGFW_Tab] = KEY_TAB, + [RGFW_CapsLock] = KEY_CAPS_LOCK, + [RGFW_ShiftL] = KEY_LEFT_SHIFT, + [RGFW_ControlL] = KEY_LEFT_CONTROL, + [RGFW_AltL] = KEY_LEFT_ALT, + [RGFW_SuperL] = KEY_LEFT_SUPER, + #ifndef RGFW_MACOS + [RGFW_ShiftR] = KEY_RIGHT_SHIFT, + + [RGFW_AltR] = KEY_RIGHT_ALT, + #endif + [RGFW_Space] = KEY_SPACE, + + [RGFW_a] = KEY_A, + [RGFW_b] = KEY_B, + [RGFW_c] = KEY_C, + [RGFW_d] = KEY_D, + [RGFW_e] = KEY_E, + [RGFW_f] = KEY_F, + [RGFW_g] = KEY_G, + [RGFW_h] = KEY_H, + [RGFW_i] = KEY_I, + [RGFW_j] = KEY_J, + [RGFW_k] = KEY_K, + [RGFW_l] = KEY_L, + [RGFW_m] = KEY_M, + [RGFW_n] = KEY_N, + [RGFW_o] = KEY_O, + [RGFW_p] = KEY_P, + [RGFW_q] = KEY_Q, + [RGFW_r] = KEY_R, + [RGFW_s] = KEY_S, + [RGFW_t] = KEY_T, + [RGFW_u] = KEY_U, + [RGFW_v] = KEY_V, + [RGFW_w] = KEY_W, + [RGFW_x] KEY_X, + [RGFW_y] = KEY_Y, + [RGFW_z] = KEY_Z, + [RGFW_Bracket] = KEY_LEFT_BRACKET, + [RGFW_BackSlash] = KEY_BACKSLASH, + [RGFW_CloseBracket] = KEY_RIGHT_BRACKET, + [RGFW_Semicolon] = KEY_SEMICOLON, + [RGFW_Insert] = KEY_INSERT, + [RGFW_Home] = KEY_HOME, + [RGFW_PageUp] = KEY_PAGE_UP, + [RGFW_Delete] = KEY_DELETE, + [RGFW_End] = KEY_END, + [RGFW_PageDown] = KEY_PAGE_DOWN, + [RGFW_Right] = KEY_RIGHT, + [RGFW_Left] = KEY_LEFT, + [RGFW_Down] = KEY_DOWN, + [RGFW_Up] = KEY_UP, + [RGFW_Numlock] = KEY_NUM_LOCK, + [RGFW_KP_Slash] = KEY_KP_DIVIDE, + [RGFW_Multiply] = KEY_KP_MULTIPLY, + [RGFW_KP_Minus] = KEY_KP_SUBTRACT, + [RGFW_KP_Return] = KEY_KP_ENTER, + [RGFW_KP_1] = KEY_KP_1, + [RGFW_KP_2] = KEY_KP_2, + [RGFW_KP_3] = KEY_KP_3, + [RGFW_KP_4] = KEY_KP_4, + [RGFW_KP_5] = KEY_KP_5, + [RGFW_KP_6] = KEY_KP_6, + [RGFW_KP_7] = KEY_KP_7, + [RGFW_KP_8] = KEY_KP_8, + [RGFW_KP_9] = KEY_KP_9, + [RGFW_KP_0] = KEY_KP_0, + [RGFW_KP_Period] = KEY_KP_DECIMAL +}; + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +int InitPlatform(void); // Initialize platform (graphics, inputs and more) +bool InitGraphicsDevice(void); // Initialize graphics device + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +// NOTE: Functions declaration is provided by raylib.h + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Window and Graphics Device +//---------------------------------------------------------------------------------- + +// Check if application should close +bool WindowShouldClose(void) +{ + if (CORE.Window.shouldClose == false) + CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window); + if (CORE.Window.ready) return CORE.Window.shouldClose; + else return true; +} + +// Toggle fullscreen mode +void ToggleFullscreen(void) +{ + RGFW_window_maximize(platform.window); + ToggleBorderlessWindowed(); +} + +// Toggle borderless windowed mode +void ToggleBorderlessWindowed(void) +{ + if (platform.window != NULL) + { + RGFW_window_setBorder(platform.window, CORE.Window.flags & FLAG_WINDOW_UNDECORATED); + } +} + +// Set window state: maximized, if resizable +void MaximizeWindow(void) +{ + RGFW_window_maximize(platform.window); +} + +// Set window state: minimized +void MinimizeWindow(void) +{ + RGFW_window_minimize(platform.window); +} + +// Set window state: not minimized/maximized +void RestoreWindow(void) +{ + RGFW_window_restore(platform.window); +} + +// Set window configuration state using flags +void SetWindowState(unsigned int flags) +{ + CORE.Window.flags |= flags; + + if (flags & FLAG_VSYNC_HINT) + { + RGFW_window_swapInterval(platform.window, 1); + } + if (flags & FLAG_FULLSCREEN_MODE) + { + RGFW_window_maximize(platform.window); + ToggleBorderlessWindowed(); + } + if (flags & FLAG_WINDOW_RESIZABLE) + { + printf("%i %i\n", platform.window->r.w, platform.window->r.h); + RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); + RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); + } + if (flags & FLAG_WINDOW_UNDECORATED) + { + ToggleBorderlessWindowed(); + } + if (flags & FLAG_WINDOW_HIDDEN) + { + RGFW_window_hide(platform.window); + } + if (flags & FLAG_WINDOW_MINIMIZED) + { + RGFW_window_minimize(platform.window); + } + if (flags & FLAG_WINDOW_MAXIMIZED) + { + RGFW_window_maximize(platform.window); + } + if (flags & FLAG_WINDOW_UNFOCUSED) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_TOPMOST) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_ALWAYS_RUN) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_TRANSPARENT) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT post window creation post window creation is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_HIGHDPI) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) + { + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); + } + if (flags & FLAG_BORDERLESS_WINDOWED_MODE) + { + ToggleBorderlessWindowed(); + } + if (flags & FLAG_MSAA_4X_HINT) + { + RGFW_setGLSamples(4); + } + if (flags & FLAG_INTERLACED_HINT) + { + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW"); + } +} + +// Clear window configuration state flags +void ClearWindowState(unsigned int flags) +{ + CORE.Window.flags &= ~flags; + + if (flags & FLAG_VSYNC_HINT) + { + RGFW_window_swapInterval(platform.window, 0); + } + if (flags & FLAG_FULLSCREEN_MODE) + { + ToggleBorderlessWindowed(); + RGFW_window_restore(platform.window); + CORE.Window.fullscreen = false; + } + if (flags & FLAG_WINDOW_RESIZABLE) + { + RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0)); + RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0)); + } + if (flags & FLAG_WINDOW_UNDECORATED) + { + ToggleBorderlessWindowed(); + } + if (flags & FLAG_WINDOW_HIDDEN) + { + RGFW_window_show(platform.window); + } + if (flags & FLAG_WINDOW_MINIMIZED) + { + RGFW_window_restore(platform.window); + } + if (flags & FLAG_WINDOW_MAXIMIZED) + { + RGFW_window_restore(platform.window); + } + if (flags & FLAG_WINDOW_UNFOCUSED) + { + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_TOPMOST) + { + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_ALWAYS_RUN) + { + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_TRANSPARENT) + { + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_HIGHDPI) + { + // NOTE: There also doesn't seem to be a feature to disable high DPI once enabled + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) + { + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW"); + } + if (flags & FLAG_BORDERLESS_WINDOWED_MODE) + { + ToggleFullscreen(); + } + if (flags & FLAG_MSAA_4X_HINT) + { + RGFW_setGLSamples(0); + } + if (flags & FLAG_INTERLACED_HINT) + { + TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW"); + } +} + +// Set icon for window +void SetWindowIcon(Image image) +{ + i32 channels = 4; + + switch (image.format) + { + case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: + case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float) + case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float) + { + channels = 1; + } break; + case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: // 8*2 bpp (2 channels) + case PIXELFORMAT_UNCOMPRESSED_R5G6B5: // 16 bpp + case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // 24 bpp + case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: // 16 bpp (1 bit alpha) + case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: // 16 bpp (4 bit alpha) + case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: // 32 bpp + { + channels = 2; + } break; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32: // 32*3 bpp (3 channels - float) + case PIXELFORMAT_UNCOMPRESSED_R16G16B16: // 16*3 bpp (3 channels - half float) + case PIXELFORMAT_COMPRESSED_DXT1_RGB: // 4 bpp (no alpha) + case PIXELFORMAT_COMPRESSED_ETC1_RGB: // 4 bpp + case PIXELFORMAT_COMPRESSED_ETC2_RGB: // 4 bpp + case PIXELFORMAT_COMPRESSED_PVRT_RGB: // 4 bpp + { + channels = 3; + } break; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: // 32*4 bpp (4 channels - float) + case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: // 16*4 bpp (4 channels - half float) + case PIXELFORMAT_COMPRESSED_DXT1_RGBA: // 4 bpp (1 bit alpha) + case PIXELFORMAT_COMPRESSED_DXT3_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_DXT5_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_PVRT_RGBA: // 4 bpp + case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 2 bpp + { + channels = 4; + } break; + default: break; + } + + RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), channels); +} + +// Set icon for window +void SetWindowIcons(Image *images, int count) +{ + TRACELOG(LOG_WARNING, "SetWindowIcons() not available on target platform"); +} + +// Set title for window +void SetWindowTitle(const char *title) +{ + RGFW_window_setName(platform.window, title); + CORE.Window.title = title; +} + +// Set window position on screen (windowed mode) +void SetWindowPosition(int x, int y) +{ + RGFW_window_move(platform.window, RGFW_VECTOR(x, y)); +} + +// Set monitor for the current window +void SetWindowMonitor(int monitor) +{ + RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]); +} + +// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) +void SetWindowMinSize(int width, int height) +{ + RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height)); + CORE.Window.screenMin.width = width; + CORE.Window.screenMin.height = height; +} + +// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) +void SetWindowMaxSize(int width, int height) +{ + RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height)); + CORE.Window.screenMax.width = width; + CORE.Window.screenMax.height = height; +} + +// Set window dimensions +void SetWindowSize(int width, int height) +{ + RGFW_window_resize(platform.window, RGFW_AREA(width, height)); +} + +// Set window opacity, value opacity is between 0.0 and 1.0 +void SetWindowOpacity(float opacity) +{ + TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform"); +} + +// Set window focused +void SetWindowFocused(void) +{ + RGFW_window_show(platform.window); +} + +// Get native window handle +void *GetWindowHandle(void) +{ +#ifndef RGFW_WINDOWS + return (void *)platform.window->src.window; +#else + return platform.window->src.hwnd; +#endif +} + +// Get number of monitors +int GetMonitorCount(void) +{ + #define MAX_MONITORS_SUPPORTED 6 + + int count = MAX_MONITORS_SUPPORTED; + RGFW_monitor *mons = RGFW_getMonitors(); + + for (int i = 0; i < 6; i++) + { + if (!mons[i].rect.x && !mons[i].rect.y && !mons[i].rect.w && mons[i].rect.h) + { + count = i; + break; + } + } + + return count; +} + +// Get number of monitors +int GetCurrentMonitor(void) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + RGFW_monitor mon = RGFW_window_getMonitor(platform.window); + + for (int i = 0; i < 6; i++) + { + if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) return i; + } + + return 0; +} + +// Get selected monitor position +Vector2 GetMonitorPosition(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return (Vector2){mons[monitor].rect.x, mons[monitor].rect.y}; +} + +// Get selected monitor width (currently used by monitor) +int GetMonitorWidth(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].rect.w; +} + +// Get selected monitor height (currently used by monitor) +int GetMonitorHeight(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].rect.h; +} + +// Get selected monitor physical width in millimetres +int GetMonitorPhysicalWidth(int monitor) +{ + RGFW_monitor* mons = RGFW_getMonitors(); + + return mons[monitor].physW; +} + +// Get selected monitor physical height in millimetres +int GetMonitorPhysicalHeight(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].physH; +} + +// Get selected monitor refresh rate +int GetMonitorRefreshRate(int monitor) +{ + TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on target platform"); + return 0; +} + +// Get the human-readable, UTF-8 encoded name of the selected monitor +const char *GetMonitorName(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].name; +} + +// Get window position XY on monitor +Vector2 GetWindowPosition(void) +{ + return (Vector2){ platform.window->r.x, platform.window->r.y }; +} + +// Get window scale DPI factor for current monitor +Vector2 GetWindowScaleDPI(void) +{ + RGFW_monitor monitor = RGFW_window_getMonitor(platform.window); + + return (Vector2){((u32)monitor.scaleX)*platform.window->r.w, ((u32) monitor.scaleX)*platform.window->r.h}; +} + +// Set clipboard text content +void SetClipboardText(const char *text) +{ + RGFW_writeClipboard(text, strlen(text)); +} + +// Get clipboard text content +// NOTE: returned string is allocated and freed by GLFW +const char *GetClipboardText(void) +{ + return RGFW_readClipboard(NULL); +} + +// Show mouse cursor +void ShowCursor(void) +{ + RGFW_window_showMouse(platform.window, true); + CORE.Input.Mouse.cursorHidden = false; +} + +// Hides mouse cursor +void HideCursor(void) +{ + RGFW_window_showMouse(platform.window, false); + CORE.Input.Mouse.cursorHidden = true; +} + +// Enables cursor (unlock cursor) +void EnableCursor(void) +{ + RGFW_disableCursor = false; + RGFW_window_mouseUnhold(platform.window); + + // Set cursor position in the middle + SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); + RGFW_window_showMouse(platform.window, true); + CORE.Input.Mouse.cursorHidden = false; +} + +// Disables cursor (lock cursor) +void DisableCursor(void) +{ + RGFW_disableCursor = true; + + // Set cursor position in the middle + SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); + + HideCursor(); +} + +// Swap back buffer with front buffer (screen drawing) +void SwapScreenBuffer(void) +{ + RGFW_window_swapBuffers(platform.window); +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Misc +//---------------------------------------------------------------------------------- + +// Get elapsed time measure in seconds since InitTimer() +double GetTime(void) +{ + double time = 0.0; + unsigned long long int nanoSeconds = RGFW_getTimeNS(); + time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() + + return time; +} + +// Open URL with default system browser (if available) +// NOTE: This function is only safe to use if you control the URL given. +// A user could craft a malicious string performing another action. +// Only call this function yourself not with user input or make sure to check the string yourself. +// Ref: https://github.com/raysan5/raylib/issues/686 +void OpenURL(const char *url) +{ + // Security check to (partially) avoid malicious code on target platform + if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + else + { + // TODO: Open URL implementation + } +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Inputs +//---------------------------------------------------------------------------------- + +// Set internal gamepad mappings +int SetGamepadMappings(const char *mappings) +{ + TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on target platform"); + return 0; +} + +// Set mouse position XY +void SetMousePosition(int x, int y) +{ + RGFW_window_moveMouse(platform.window, RGFW_VECTOR(x, y)); + CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; +} + +// Set mouse cursor +void SetMouseCursor(int cursor) +{ + RGFW_window_setMouseStandard(platform.window, cursor); +} + +static KeyboardKey ConvertScancodeToKey(u32 keycode); + +// TODO: Review function to avoid duplicate with RSGL +char RSGL_keystrToChar(const char *str) +{ + if (str[1] == 0) return str[0]; + + static const char *map[] = { + "asciitilde", "`", + "grave", "~", + "exclam", "!", + "at", "@", + "numbersign", "#", + "dollar", "$", + "percent", "%%", + "asciicircum", "^", + "ampersand", "&", + "asterisk", "*", + "parenleft", "(", + "parenright", ")", + "underscore", "_", + "minus", "-", + "plus", "+", + "equal", "=", + "braceleft", "{", + "bracketleft", "[", + "bracketright", "]", + "braceright", "}", + "colon", ":", + "semicolon", ";", + "quotedbl", "\"", + "apostrophe", "'", + "bar", "|", + "backslash", "\'", + "less", "<", + "comma", ",", + "greater", ">", + "period", ".", + "question", "?", + "slash", "/", + "space", " ", + "Return", "\n", + "Enter", "\n", + "enter", "\n", + }; + + for (unsigned char i = 0; i < (sizeof(map)/sizeof(char *)); i += 2) + { + if (strcmp(map[i], str) == 0) return *map[i + 1]; + } + + return '\0'; +} + +// Register all input events +void PollInputEvents(void) +{ +#if defined(SUPPORT_GESTURES_SYSTEM) + // NOTE: Gestures update must be called every frame to reset gestures correctly + // because ProcessGestureEvent() is just called on an event, not every frame + UpdateGestures(); +#endif + + // Reset keys/chars pressed registered + CORE.Input.Keyboard.keyPressedQueueCount = 0; + CORE.Input.Keyboard.charPressedQueueCount = 0; + + // Reset mouse wheel + CORE.Input.Mouse.currentWheelMove.x = 0; + CORE.Input.Mouse.currentWheelMove.y = 0; + + // Register previous mouse position + + // Reset last gamepad button/axis registered state + + for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) + { + // Check if gamepad is available + if (CORE.Input.Gamepad.ready[i]) + { + // Register previous gamepad button states + for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) + { + CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; + } + } + } + + // Register previous touch states + for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; + + // Map touch position to mouse position for convenience + CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; + + int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE + bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones + + // Register previous keys states + // NOTE: Android supports up to 260 keys + for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) + { + CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; + CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; + } + + // Register previous mouse states + for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; + + // Poll input events for current platform + //----------------------------------------------------------------------------- + CORE.Window.resizedLastFrame = false; + +#define RGFW_HOLD_MOUSE (1L<<2) + +#if defined(RGFW_X11) //|| defined(RGFW_MACOS) + if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) + { + CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; + CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; + } + else + { + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + } +#endif + + while (RGFW_window_checkEvent(platform.window)) + { + + if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove)) + { + if (!CORE.Input.Gamepad.ready[platform.window->event.joystick]) + { + CORE.Input.Gamepad.ready[platform.window->event.joystick] = true; + CORE.Input.Gamepad.axisCount[platform.window->event.joystick] = platform.window->event.axisesCount; + CORE.Input.Gamepad.name[platform.window->event.joystick][0] = '\0'; + CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; + CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; + } + } + + RGFW_Event *event = &platform.window->event; + + // All input events can be processed after polling + switch (event->type) + { + case RGFW_quit: CORE.Window.shouldClose = true; break; + case RGFW_dnd: // Dropped file + { + for (int i = 0; i < event->droppedFilesCount; i++) + { + if (CORE.Window.dropFileCount == 0) + { + // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files + // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed + // TODO: Pointers should probably be reallocated for any new file added... + CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); + + CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); + + CORE.Window.dropFileCount++; + } + else if (CORE.Window.dropFileCount < 1024) + { + CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); + + CORE.Window.dropFileCount++; + } + else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!"); + } + } break; + + // Window events are also polled (Minimized, maximized, close...) + case RGFW_windowResized: + { + SetupViewport(platform.window->r.w, platform.window->r.h); + CORE.Window.screen.width = platform.window->r.w; + CORE.Window.screen.height = platform.window->r.h; + CORE.Window.currentFbo.width = platform.window->r.w;; + CORE.Window.currentFbo.height = platform.window->r.h; + CORE.Window.resizedLastFrame = true; + } break; + case RGFW_windowMoved: + { + CORE.Window.position.x = platform.window->r.x; + CORE.Window.position.y = platform.window->r.x; + } break; + + // Keyboard events + case RGFW_keyPressed: + { + KeyboardKey key = ConvertScancodeToKey(event->keyCode); + + if (key != KEY_NULL) + { + // If key was up, add it to the key pressed queue + if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) + { + CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key; + CORE.Input.Keyboard.keyPressedQueueCount++; + } + + CORE.Input.Keyboard.currentKeyState[key] = 1; + } + + // TODO: Put exitKey verification outside the switch? + if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) + { + CORE.Window.shouldClose = true; + } + + // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int) + // Check if there is space available in the queue + if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) + { + // Add character (codepoint) to the queue + CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RSGL_keystrToChar(event->keyName); + CORE.Input.Keyboard.charPressedQueueCount++; + } + } break; + case RGFW_keyReleased: + { + KeyboardKey key = ConvertScancodeToKey(event->keyCode); + if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; + } break; + + // Check mouse events + case RGFW_mouseButtonPressed: + { + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { + CORE.Input.Mouse.currentWheelMove.y = event->scroll; + break; + } + + int btn = event->button; + if (btn == RGFW_mouseLeft) btn = 1; + else if (btn == RGFW_mouseRight) btn = 2; + else if (btn == RGFW_mouseMiddle) btn = 3; + + CORE.Input.Mouse.currentButtonState[btn - 1] = 1; + CORE.Input.Touch.currentTouchState[btn - 1] = 1; + + touchAction = 1; + } break; + case RGFW_mouseButtonReleased: + { + + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { + CORE.Input.Mouse.currentWheelMove.y = event->scroll; + break; + } + + int btn = event->button; + if (btn == RGFW_mouseLeft) btn = 1; + else if (btn == RGFW_mouseRight) btn = 2; + else if (btn == RGFW_mouseMiddle) btn = 3; + + CORE.Input.Mouse.currentButtonState[btn - 1] = 0; + CORE.Input.Touch.currentTouchState[btn - 1] = 0; + + touchAction = 0; + } break; + case RGFW_mousePosChanged: + { + if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) + { + CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; + + if ((event->point.x - (platform.window->r.w/2))*2) + CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x; + if ((event->point.y - (platform.window->r.h/2))*2) + CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y; + + CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w/2))*2; + CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h/2))*2; + } + else + { + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + CORE.Input.Mouse.currentPosition.x = (float)event->point.x; + CORE.Input.Mouse.currentPosition.y = (float)event->point.y; + } + + CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; + touchAction = 2; + } break; + case RGFW_jsButtonPressed: + { + int button = -1; + + switch (event->button) + { + case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break; + case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break; + case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break; + case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break; + + case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break; + case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break; + + case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break; + case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break; + + case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break; + case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break; + case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break; + + case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break; + case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break; + case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break; + case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break; + + default: break; + } + + if (button >= 0) + { + CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 1; + CORE.Input.Gamepad.lastButtonPressed = button; + } + } break; + case RGFW_jsButtonReleased: + { + int button = -1; + switch (event->button) + { + case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break; + case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break; + case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break; + case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break; + + case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break; + case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break; + + case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break; + case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break; + + case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break; + case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break; + case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break; + + case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break; + case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break; + case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break; + case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break; + default: break; + } + + if (button >= 0) + { + CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 0; + if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } + } break; + case RGFW_jsAxisMove: + { + int axis = -1; + for (int i = 0; i < event->axisesCount; i++) + { + switch(i) + { + case 0: + { + if (abs(event->axis[i].x) > abs(event->axis[i].y)) + { + axis = GAMEPAD_AXIS_LEFT_X; + break; + } + + axis = GAMEPAD_AXIS_LEFT_Y; + } break; + case 1: + { + if (abs(event->axis[i].x) > abs(event->axis[i].y)) + { + axis = GAMEPAD_AXIS_RIGHT_X; + break; + } + + axis = GAMEPAD_AXIS_RIGHT_Y; + } break; + case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break; + case 3: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break; + default: break; + } + + #ifdef __linux__ + float value = (event->axis[i].x + event->axis[i].y)/(float)32767; + #else + float value = (event->axis[i].x + -event->axis[i].y)/(float)32767; + #endif + CORE.Input.Gamepad.axisState[event->joystick][axis] = value; + + // Register button state for triggers in addition to their axes + if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER)) + { + int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; + int pressed = (value > 0.1f); + CORE.Input.Gamepad.currentButtonState[event->joystick][button] = pressed; + + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; + else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } + } + } break; + default: break; + } + +#if defined(SUPPORT_GESTURES_SYSTEM) + if (touchAction > -1) + { + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent = { 0 }; + + // Register touch actions + gestureEvent.touchAction = touchAction; + + // Assign a pointer ID + gestureEvent.pointId[0] = 0; + + // Register touch points count + gestureEvent.pointCount = 1; + + // Register touch points position, only one point registered + if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0]; + else gestureEvent.position[0] = GetMousePosition(); + + // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + // Gesture data is sent to gestures-system for processing + ProcessGestureEvent(gestureEvent); + + touchAction = -1; + } +#endif + } + + if (RGFW_disableCursor && platform.window->event.inFocus) RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); + //----------------------------------------------------------------------------- +} + + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- + +// Initialize platform: graphics, inputs and more +int InitPlatform(void) +{ + // Initialize RGFW internal global state, only required systems + unsigned int flags = RGFW_CENTER | RGFW_ALLOW_DND; + + // Check window creation flags + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) + { + CORE.Window.fullscreen = true; + flags |= RGFW_FULLSCREEN; + } + + if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER; + if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE; + + if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW; + + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN; + + // NOTE: Some OpenGL context attributes must be set before window creation + + // Check selection OpenGL version + if (rlGetVersion() == RL_OPENGL_21) + { + RGFW_setGLVersion(2, 1); + } + else if (rlGetVersion() == RL_OPENGL_33) + { + RGFW_setGLVersion(3, 3); + } + else if (rlGetVersion() == RL_OPENGL_43) + { + RGFW_setGLVersion(4, 1); + } + + if (CORE.Window.flags & FLAG_MSAA_4X_HINT) + { + RGFW_setGLSamples(4); + } + + platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); + + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); + + RGFW_window_makeCurrent(platform.window); + + // Check surface and context activation + if (platform.window != NULL) + { + CORE.Window.ready = true; + + CORE.Window.render.width = CORE.Window.screen.width; + CORE.Window.render.height = CORE.Window.screen.height; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + + TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); + TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); + TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); + } + else + { + TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device"); + return -1; + } + //---------------------------------------------------------------------------- + + // If everything work as expected, we can continue + CORE.Window.position.x = platform.window->r.x; + CORE.Window.position.y = platform.window->r.y; + CORE.Window.render.width = CORE.Window.screen.width; + CORE.Window.render.height = CORE.Window.screen.height; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + + TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); + TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); + TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); + + // Load OpenGL extensions + // NOTE: GL procedures address loader is required to load extensions + //---------------------------------------------------------------------------- + rlLoadExtensions((void*)RGFW_getProcAddress); + //---------------------------------------------------------------------------- + + // TODO: Initialize input events system + // It could imply keyboard, mouse, gamepad, touch... + // Depending on the platform libraries/SDK it could use a callback mechanism + // For system events and inputs evens polling on a per-frame basis, use PollInputEvents() + //---------------------------------------------------------------------------- + // ... + //---------------------------------------------------------------------------- + + // Initialize timing system + //---------------------------------------------------------------------------- + InitTimer(); + //---------------------------------------------------------------------------- + + // Initialize storage system + //---------------------------------------------------------------------------- + CORE.Storage.basePath = GetWorkingDirectory(); + //---------------------------------------------------------------------------- + +#ifdef RGFW_X11 + for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) + { + RGFW_registerJoystick(platform.window, i); + } +#endif + + TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully"); + + return 0; +} + +// Close platform +void ClosePlatform(void) +{ + RGFW_window_close(platform.window); +} + +// Keycode mapping +static KeyboardKey ConvertScancodeToKey(u32 keycode) +{ + if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0; + + return keyMappingRGFW[keycode]; +}
raylib/src/platforms/rcore_desktop_sdl.c view
@@ -64,7 +64,7 @@ SDL_Window *window; SDL_GLContext glContext; - SDL_Joystick *gamepad[MAX_GAMEPADS];+ SDL_GameController *gamepad[MAX_GAMEPADS]; SDL_Cursor *cursor; bool cursorRelative; } PlatformData;@@ -80,7 +80,7 @@ // Local Variables Definition //---------------------------------------------------------------------------------- #define SCANCODE_MAPPED_NUM 232-static const KeyboardKey ScancodeToKey[SCANCODE_MAPPED_NUM] = {+static const KeyboardKey mapScancodeToKey[SCANCODE_MAPPED_NUM] = { KEY_NULL, // SDL_SCANCODE_UNKNOWN 0, 0,@@ -476,9 +476,9 @@ // Set icon for window void SetWindowIcon(Image image) {- SDL_Surface* iconSurface = NULL;+ SDL_Surface *iconSurface = NULL; - Uint32 rmask, gmask, bmask, amask;+ unsigned int rmask = 0, gmask = 0, bmask = 0, amask = 0; int depth = 0; // Depth in bits int pitch = 0; // Pixel spacing (pitch) in bytes @@ -492,72 +492,67 @@ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: rmask = 0xFF, gmask = 0xFF00; bmask = 0, amask = 0;- depth = 16, pitch = image.width * 2;+ depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R5G6B5: rmask = 0xF800, gmask = 0x07E0; bmask = 0x001F, amask = 0;- depth = 16, pitch = image.width * 2;+ depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit rmask = 0x0000FF, gmask = 0x00FF00; bmask = 0xFF0000, amask = 0;- depth = 24, pitch = image.width * 3;+ depth = 24, pitch = image.width*3; break; case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: rmask = 0xF800, gmask = 0x07C0; bmask = 0x003E, amask = 0x0001;- depth = 16, pitch = image.width * 2;+ depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: rmask = 0xF000, gmask = 0x0F00; bmask = 0x00F0, amask = 0x000F;- depth = 16, pitch = image.width * 2;+ depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: rmask = 0xFF000000, gmask = 0x00FF0000; bmask = 0x0000FF00, amask = 0x000000FF;- depth = 32, pitch = image.width * 4;+ depth = 32, pitch = image.width*4; break; case PIXELFORMAT_UNCOMPRESSED_R32: rmask = 0xFFFFFFFF, gmask = 0; bmask = 0, amask = 0;- depth = 32, pitch = image.width * 4;+ depth = 32, pitch = image.width*4; break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; bmask = 0xFFFFFFFF, amask = 0;- depth = 96, pitch = image.width * 12;+ depth = 96, pitch = image.width*12; break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF; bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;- depth = 128, pitch = image.width * 16;+ depth = 128, pitch = image.width*16; break; case PIXELFORMAT_UNCOMPRESSED_R16: rmask = 0xFFFF, gmask = 0; bmask = 0, amask = 0;- depth = 16, pitch = image.width * 2;+ depth = 16, pitch = image.width*2; break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16: rmask = 0xFFFF, gmask = 0xFFFF; bmask = 0xFFFF, amask = 0;- depth = 48, pitch = image.width * 6;+ depth = 48, pitch = image.width*6; break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: rmask = 0xFFFF, gmask = 0xFFFF; bmask = 0xFFFF, amask = 0xFFFF;- depth = 64, pitch = image.width * 8;+ depth = 64, pitch = image.width*8; break;- default:- // Compressed formats are not supported- return;+ default: return; // Compressed formats are not supported } - iconSurface = SDL_CreateRGBSurfaceFrom(- image.data, image.width, image.height, depth, pitch,- rmask, gmask, bmask, amask- );+ iconSurface = SDL_CreateRGBSurfaceFrom( image.data, image.width, image.height, depth, pitch, rmask, gmask, bmask, amask ); if (iconSurface) {@@ -599,7 +594,7 @@ // 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3, // see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba // 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again.- const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false;+ const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)? true : false; const int screenWidth = CORE.Window.screen.width; const int screenHeight = CORE.Window.screen.height;@@ -941,15 +936,15 @@ // Set gamepad vibration void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) {- //Limit input values to between 0.0f and 1.0f- leftMotor = (0.0f > leftMotor) ? 0.0f : leftMotor;- rightMotor = (0.0f > rightMotor) ? 0.0f : rightMotor;- leftMotor = (1.0f < leftMotor) ? 1.0f : leftMotor;- rightMotor = (1.0f < rightMotor) ? 1.0f : rightMotor;+ // Limit input values to between 0.0f and 1.0f+ leftMotor = (0.0f > leftMotor)? 0.0f : leftMotor;+ rightMotor = (0.0f > rightMotor)? 0.0f : rightMotor;+ leftMotor = (1.0f < leftMotor)? 1.0f : leftMotor;+ rightMotor = (1.0f < rightMotor)? 1.0f : rightMotor; if (IsGamepadAvailable(gamepad)) {- SDL_JoystickRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f));+ SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); } } @@ -1131,8 +1126,19 @@ case SDL_KEYDOWN: { KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);- if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 1; + if (key != KEY_NULL)+ {+ // If key was up, add it to the key pressed queue+ if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))+ {+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;+ CORE.Input.Keyboard.keyPressedQueueCount++;+ }++ CORE.Input.Keyboard.currentKeyState[key] = 1;+ }+ if (event.key.repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1; // TODO: Put exitKey verification outside the switch?@@ -1154,14 +1160,6 @@ int codepointSize = 0; - // Check if there is space available in the key queue- if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)- {- // Add character (key) to the queue- CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = GetCodepointNext(event.text.text, &codepointSize);- CORE.Input.Keyboard.keyPressedQueueCount++;- }- // Check if there is space available in the queue if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) {@@ -1247,15 +1245,15 @@ if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) {- platform.gamepad[jid] = SDL_JoystickOpen(jid);+ platform.gamepad[jid] = SDL_GameControllerOpen(jid); if (platform.gamepad[jid]) { CORE.Input.Gamepad.ready[jid] = true;- CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]);+ CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid])); CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;- strncpy(CORE.Input.Gamepad.name[jid], SDL_JoystickName(platform.gamepad[jid]), 63);+ strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63); CORE.Input.Gamepad.name[jid][63] = '\0'; } else@@ -1268,15 +1266,15 @@ { int jid = event.jdevice.which; - if (jid == SDL_JoystickInstanceID(platform.gamepad[jid]))+ if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]))) {- SDL_JoystickClose(platform.gamepad[jid]);- platform.gamepad[jid] = SDL_JoystickOpen(0);+ SDL_GameControllerClose(platform.gamepad[jid]);+ platform.gamepad[jid] = SDL_GameControllerOpen(0); CORE.Input.Gamepad.ready[jid] = false; memset(CORE.Input.Gamepad.name[jid], 0, 64); } } break;- case SDL_JOYBUTTONDOWN:+ case SDL_CONTROLLERBUTTONDOWN: { int button = -1; @@ -1310,7 +1308,7 @@ CORE.Input.Gamepad.lastButtonPressed = button; } } break;- case SDL_JOYBUTTONUP:+ case SDL_CONTROLLERBUTTONUP: { int button = -1; @@ -1344,7 +1342,7 @@ if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } } break;- case SDL_JOYAXISMOTION:+ case SDL_CONTROLLERAXISMOTION: { int axis = -1; @@ -1362,13 +1360,13 @@ if (axis >= 0) { // SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range- float value = event.jaxis.value / (float) 32767;+ float value = event.jaxis.value/(float)32767; CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value; // Register button state for triggers in addition to their axes if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER)) {- int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;+ int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; int pressed = (value > 0.1f); CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed; if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;@@ -1497,11 +1495,6 @@ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - if (CORE.Window.flags & FLAG_VSYNC_HINT)- {- SDL_GL_SetSwapInterval(1);- }- if (CORE.Window.flags & FLAG_MSAA_4X_HINT) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);@@ -1535,6 +1528,9 @@ TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);++ if (CORE.Window.flags & FLAG_VSYNC_HINT) SDL_GL_SetSwapInterval(1);+ else SDL_GL_SetSwapInterval(0); } else {@@ -1552,14 +1548,15 @@ // Initialize gamepads for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++) {- platform.gamepad[i] = SDL_JoystickOpen(i);+ platform.gamepad[i] = SDL_GameControllerOpen(i);+ if (platform.gamepad[i]) { CORE.Input.Gamepad.ready[i] = true;- CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(platform.gamepad[i]);+ CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i])); CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;- strncpy(CORE.Input.Gamepad.name[i], SDL_JoystickName(platform.gamepad[i]), 63);+ strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63); CORE.Input.Gamepad.name[i][63] = '\0'; } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());@@ -1579,13 +1576,15 @@ CORE.Time.previous = GetTime(); // Get time as double #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP)- SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod()+ SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1"); // SDL equivalent of timeBeginPeriod() and timeEndPeriod() #endif //---------------------------------------------------------------------------- // Initialize storage system //----------------------------------------------------------------------------- CORE.Storage.basePath = GetWorkingDirectory(); // Define base path for storage+ // Define base path for storage+ CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); + CHDIR(CORE.Storage.basePath); //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");@@ -1607,8 +1606,9 @@ { if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM) {- return ScancodeToKey[sdlScancode];+ return mapScancodeToKey[sdlScancode]; }+ return KEY_NULL; // No equivalent key in Raylib } // EOF
raylib/src/platforms/rcore_drm.c view
@@ -388,29 +388,69 @@ // Get selected monitor width (currently used by monitor) int GetMonitorWidth(int monitor) {- TRACELOG(LOG_WARNING, "GetMonitorWidth() not implemented on target platform");- return 0;+ int width = 0;++ if (monitor != 0)+ {+ TRACELOG(LOG_WARNING, "GetMonitorWidth() implemented for first monitor only");+ }+ else if ((platform.connector) && (platform.modeIndex >= 0))+ {+ width = platform.connector->modes[platform.modeIndex].hdisplay;+ }++ return width; } // Get selected monitor height (currently used by monitor) int GetMonitorHeight(int monitor) {- TRACELOG(LOG_WARNING, "GetMonitorHeight() not implemented on target platform");- return 0;+ int height = 0;++ if (monitor != 0)+ {+ TRACELOG(LOG_WARNING, "GetMonitorHeight() implemented for first monitor only");+ }+ else if ((platform.connector) && (platform.modeIndex >= 0))+ {+ height = platform.connector->modes[platform.modeIndex].vdisplay;+ }++ return height; } // Get selected monitor physical width in millimetres int GetMonitorPhysicalWidth(int monitor) {- TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on target platform");- return 0;+ int physicalWidth = 0;++ if (monitor != 0)+ {+ TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() implemented for first monitor only");+ }+ else if ((platform.connector) && (platform.modeIndex >= 0))+ {+ physicalWidth = platform.connector->mmWidth;+ }++ return physicalWidth; } // Get selected monitor physical height in millimetres int GetMonitorPhysicalHeight(int monitor) {- TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on target platform");- return 0;+ int physicalHeight = 0;++ if (monitor != 0)+ {+ TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() implemented for first monitor only");+ }+ else if ((platform.connector) && (platform.modeIndex >= 0))+ {+ physicalHeight = platform.connector->mmHeight;+ }++ return physicalHeight; } // Get selected monitor refresh rate@@ -429,8 +469,18 @@ // Get the human-readable, UTF-8 encoded name of the selected monitor const char *GetMonitorName(int monitor) {- TRACELOG(LOG_WARNING, "GetMonitorName() not implemented on target platform");- return "";+ const char *name = "";++ if (monitor != 0)+ {+ TRACELOG(LOG_WARNING, "GetMonitorName() implemented for first monitor only");+ }+ else if ((platform.connector) && (platform.modeIndex >= 0))+ {+ name = platform.connector->modes[platform.modeIndex].name;+ }++ return name; } // Get window position XY on monitor@@ -978,7 +1028,7 @@ // If graphic device is no properly initialized, we end program if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }- else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor()) / 2 - CORE.Window.screen.width / 2, GetMonitorHeight(GetCurrentMonitor()) / 2 - CORE.Window.screen.height / 2);+ else SetWindowPosition(GetMonitorWidth(GetCurrentMonitor())/2 - CORE.Window.screen.width/2, GetMonitorHeight(GetCurrentMonitor())/2 - CORE.Window.screen.height/2); // Set some default window flags CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN; // false@@ -1086,7 +1136,8 @@ // Close the evdev devices - if (platform.mouseFd != -1) {+ if (platform.mouseFd != -1)+ { close(platform.mouseFd); platform.mouseFd = -1; }@@ -1563,7 +1614,7 @@ } } - TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0) ? "UP " : "DOWN", event.code, keycode);+ TRACELOG(LOG_DEBUG, "INPUT: KEY_%s Keycode(linux): %4i KeyCode(raylib): %4i", (event.value == 0)? "UP " : "DOWN", event.code, keycode); } } }@@ -1590,7 +1641,7 @@ { short keycodeRaylib = linuxToRaylibMap[event.code]; - TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0) ? "UP " : "DOWN", event.code, keycodeRaylib);+ TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: KEY_%s Keycode(linux): %4i Keycode(raylib): %4i", i, (event.value == 0)? "UP" : "DOWN", event.code, keycodeRaylib); if ((keycodeRaylib != 0) && (keycodeRaylib < MAX_GAMEPAD_BUTTONS)) {@@ -1615,7 +1666,7 @@ int range = platform.gamepadAbsAxisRange[i][event.code][1]; // NOTE: Scaling of event.value to get values between -1..1- CORE.Input.Gamepad.axisState[i][axisRaylib] = (2 * (float)(event.value - min) / range) - 1;+ CORE.Input.Gamepad.axisState[i][axisRaylib] = (2*(float)(event.value - min)/range) - 1; } } }@@ -1874,9 +1925,7 @@ const int nearestHeightDiff = abs(platform.connector->modes[nearestIndex].vdisplay - height); const int nearestFpsDiff = abs(platform.connector->modes[nearestIndex].vrefresh - fps); - if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {- nearestIndex = i;- }+ if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) nearestIndex = i; } return nearestIndex;
raylib/src/platforms/rcore_web.c view
@@ -100,6 +100,8 @@ "not-allowed" // 10 MOUSE_CURSOR_NOT_ALLOWED }; +Vector2 lockedMousePos = { 0 };+ //---------------------------------------------------------------------------------- // Module Internal Functions Declaration //----------------------------------------------------------------------------------@@ -131,6 +133,7 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData); // Emscripten input callback events+static EM_BOOL EmscriptenMouseMoveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static EM_BOOL EmscriptenPointerlockCallback(int eventType, const EmscriptenPointerlockChangeEvent *pointerlockChangeEvent, void *userData); static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);@@ -187,7 +190,8 @@ if (enterFullscreen) { // NOTE: The setTimeouts handle the browser mode change delay- EM_ASM(+ EM_ASM+ ( setTimeout(function() { Module.requestFullscreen(false, false);@@ -295,7 +299,8 @@ { // NOTE: 1. The setTimeouts handle the browser mode change delay // 2. The style unset handles the possibility of a width="value%" like on the default shell.html file- EM_ASM(+ EM_ASM+ ( setTimeout(function() { Module.requestFullscreen(false, true);@@ -862,6 +867,8 @@ CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + if (CORE.Input.Mouse.cursorHidden) lockedMousePos = CORE.Input.Mouse.currentPosition;+ // NOTE: emscripten not implemented glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y); }@@ -1270,6 +1277,9 @@ emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenPointerlockCallback); + // Following the mouse delta when the mouse is locked+ emscripten_set_mousemove_callback("#canvas", NULL, 1, EmscriptenMouseMoveCallback);+ // Support touch events emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback); emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback);@@ -1477,9 +1487,13 @@ // GLFW3 Cursor Position Callback, runs on mouse move static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) {- CORE.Input.Mouse.currentPosition.x = (float)x;- CORE.Input.Mouse.currentPosition.y = (float)y;- CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;+ // If the pointer is not locked, follow the position+ if (!CORE.Input.Mouse.cursorHidden)+ {+ CORE.Input.Mouse.currentPosition.x = (float)x;+ CORE.Input.Mouse.currentPosition.y = (float)y;+ CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;+ } #if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) // Process mouse events as touches to be able to use mouse-gestures@@ -1505,6 +1519,18 @@ #endif } +static EM_BOOL EmscriptenMouseMoveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)+{+ // To emulate the GLFW_RAW_MOUSE_MOTION property.+ if (CORE.Input.Mouse.cursorHidden)+ {+ CORE.Input.Mouse.previousPosition.x = lockedMousePos.x - mouseEvent->movementX;+ CORE.Input.Mouse.previousPosition.y = lockedMousePos.y - mouseEvent->movementY;+ }++ return 1; // The event was consumed by the callback handler+}+ // GLFW3 Scrolling Callback, runs on mouse wheel static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset) {@@ -1597,6 +1623,12 @@ static EM_BOOL EmscriptenPointerlockCallback(int eventType, const EmscriptenPointerlockChangeEvent *pointerlockChangeEvent, void *userData) { CORE.Input.Mouse.cursorHidden = EM_ASM_INT( { if (document.pointerLockElement) return 1; }, 0);++ if (CORE.Input.Mouse.cursorHidden)+ {+ lockedMousePos = CORE.Input.Mouse.currentPosition;+ CORE.Input.Mouse.previousPosition = lockedMousePos;+ } return 1; // The event was consumed by the callback handler }
raylib/src/raudio.c view
@@ -410,9 +410,18 @@ // Module specific Functions Declaration //---------------------------------------------------------------------------------- static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage);++// Reads audio data from an AudioBuffer object in internal/device formats+static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount);+static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount);+ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount); static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer); +static bool IsAudioBufferPlayingInLockedState(AudioBuffer *buffer);+static void StopAudioBufferInLockedState(AudioBuffer *buffer);+static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data, int frameCount);+ #if defined(RAUDIO_STANDALONE) static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)@@ -442,6 +451,7 @@ void TrackAudioBuffer(AudioBuffer *buffer); void UntrackAudioBuffer(AudioBuffer *buffer); + //---------------------------------------------------------------------------------- // Module Functions Definition - Audio Device initialization and Closing //----------------------------------------------------------------------------------@@ -460,12 +470,12 @@ } // Init audio device- // NOTE: Using the default device. Format is floating point because it simplifies mixing.+ // NOTE: Using the default device. Format is floating point because it simplifies mixing ma_device_config config = ma_device_config_init(ma_device_type_playback);- config.playback.pDeviceID = NULL; // NULL for the default playback AUDIO.System.device.+ config.playback.pDeviceID = NULL; // NULL for the default playback AUDIO.System.device config.playback.format = AUDIO_DEVICE_FORMAT; config.playback.channels = AUDIO_DEVICE_CHANNELS;- config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device.+ config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device config.capture.format = ma_format_s16; config.capture.channels = 1; config.sampleRate = AUDIO_DEVICE_SAMPLE_RATE;@@ -481,7 +491,7 @@ } // Mixing happens on a separate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may- // want to look at something a bit smarter later on to keep everything real-time, if that's necessary.+ // want to look at something a bit smarter later on to keep everything real-time, if that's necessary if (ma_mutex_init(&AUDIO.System.lock) != MA_SUCCESS) { TRACELOG(LOG_WARNING, "AUDIO: Failed to create mutex for mixing");@@ -491,7 +501,7 @@ } // Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running- // while there's at least one sound being played.+ // while there's at least one sound being played result = ma_device_start(&AUDIO.System.device); if (result != MA_SUCCESS) {@@ -502,7 +512,7 @@ } TRACELOG(LOG_INFO, "AUDIO: Device initialized successfully");- TRACELOG(LOG_INFO, " > Backend: miniaudio / %s", ma_get_backend_name(AUDIO.System.context.backend));+ TRACELOG(LOG_INFO, " > Backend: miniaudio | %s", ma_get_backend_name(AUDIO.System.context.backend)); TRACELOG(LOG_INFO, " > Format: %s -> %s", ma_get_format_name(AUDIO.System.device.playback.format), ma_get_format_name(AUDIO.System.device.playback.internalFormat)); TRACELOG(LOG_INFO, " > Channels: %d -> %d", AUDIO.System.device.playback.channels, AUDIO.System.device.playback.internalChannels); TRACELOG(LOG_INFO, " > Sample rate: %d -> %d", AUDIO.System.device.sampleRate, AUDIO.System.device.playback.internalSampleRate);@@ -612,69 +622,77 @@ { if (buffer != NULL) {- ma_data_converter_uninit(&buffer->converter, NULL); UntrackAudioBuffer(buffer);+ ma_data_converter_uninit(&buffer->converter, NULL); RL_FREE(buffer->data); RL_FREE(buffer); } } -// Check if an audio buffer is playing+// Check if an audio buffer is playing from a program state without lock bool IsAudioBufferPlaying(AudioBuffer *buffer) { bool result = false;-- if (buffer != NULL) result = (buffer->playing && !buffer->paused);-+ ma_mutex_lock(&AUDIO.System.lock);+ result = IsAudioBufferPlayingInLockedState(buffer);+ ma_mutex_unlock(&AUDIO.System.lock); return result; } // Play an audio buffer-// NOTE: Buffer is restarted to the start.-// Use PauseAudioBuffer() and ResumeAudioBuffer() if the playback position should be maintained.+// NOTE: Buffer is restarted to the start+// Use PauseAudioBuffer() and ResumeAudioBuffer() if the playback position should be maintained void PlayAudioBuffer(AudioBuffer *buffer) { if (buffer != NULL) {+ ma_mutex_lock(&AUDIO.System.lock); buffer->playing = true; buffer->paused = false; buffer->frameCursorPos = 0;+ ma_mutex_unlock(&AUDIO.System.lock); } } -// Stop an audio buffer+// Stop an audio buffer from a program state without lock void StopAudioBuffer(AudioBuffer *buffer) {- if (buffer != NULL)- {- if (IsAudioBufferPlaying(buffer))- {- buffer->playing = false;- buffer->paused = false;- buffer->frameCursorPos = 0;- buffer->framesProcessed = 0;- buffer->isSubBufferProcessed[0] = true;- buffer->isSubBufferProcessed[1] = true;- }- }+ ma_mutex_lock(&AUDIO.System.lock);+ StopAudioBufferInLockedState(buffer);+ ma_mutex_unlock(&AUDIO.System.lock); } // Pause an audio buffer void PauseAudioBuffer(AudioBuffer *buffer) {- if (buffer != NULL) buffer->paused = true;+ if (buffer != NULL)+ {+ ma_mutex_lock(&AUDIO.System.lock);+ buffer->paused = true;+ ma_mutex_unlock(&AUDIO.System.lock);+ } } // Resume an audio buffer void ResumeAudioBuffer(AudioBuffer *buffer) {- if (buffer != NULL) buffer->paused = false;+ if (buffer != NULL)+ {+ ma_mutex_lock(&AUDIO.System.lock);+ buffer->paused = false;+ ma_mutex_unlock(&AUDIO.System.lock);+ } } // Set volume for an audio buffer void SetAudioBufferVolume(AudioBuffer *buffer, float volume) {- if (buffer != NULL) buffer->volume = volume;+ if (buffer != NULL)+ {+ ma_mutex_lock(&AUDIO.System.lock);+ buffer->volume = volume;+ ma_mutex_unlock(&AUDIO.System.lock);+ } } // Set pitch for an audio buffer@@ -682,7 +700,8 @@ { if ((buffer != NULL) && (pitch > 0.0f)) {- // Pitching is just an adjustment of the sample rate.+ ma_mutex_lock(&AUDIO.System.lock);+ // Pitching is just an adjustment of the sample rate // Note that this changes the duration of the sound: // - higher pitches will make the sound faster // - lower pitches make it slower@@ -690,6 +709,7 @@ ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate); buffer->pitch = pitch;+ ma_mutex_unlock(&AUDIO.System.lock); } } @@ -699,7 +719,12 @@ if (pan < 0.0f) pan = 0.0f; else if (pan > 1.0f) pan = 1.0f; - if (buffer != NULL) buffer->pan = pan;+ if (buffer != NULL)+ {+ ma_mutex_lock(&AUDIO.System.lock);+ buffer->pan = pan;+ ma_mutex_unlock(&AUDIO.System.lock);+ } } // Track audio buffer to linked list next position@@ -752,7 +777,7 @@ // Loading wave from memory data if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, dataSize); - RL_FREE(fileData);+ UnloadFileData(fileData); return wave; }@@ -870,11 +895,15 @@ // Checks if wave data is ready bool IsWaveReady(Wave wave) {- return ((wave.data != NULL) && // Validate wave data available- (wave.frameCount > 0) && // Validate frame count- (wave.sampleRate > 0) && // Validate sample rate is supported- (wave.sampleSize > 0) && // Validate sample size is supported- (wave.channels > 0)); // Validate number of channels supported+ bool result = false;++ if ((wave.data != NULL) && // Validate wave data available+ (wave.frameCount > 0) && // Validate frame count+ (wave.sampleRate > 0) && // Validate sample rate is supported+ (wave.sampleSize > 0) && // Validate sample size is supported+ (wave.channels > 0)) result = true; // Validate number of channels supported++ return result; } // Load sound from file@@ -898,15 +927,15 @@ if (wave.data != NULL) {- // When using miniaudio we need to do our own mixing.+ // When using miniaudio we need to do our own mixing // To simplify this we need convert the format of each sound to be consistent with // the format used to open the playback AUDIO.System.device. We can do this two ways: //- // 1) Convert the whole sound in one go at load time (here).- // 2) Convert the audio data in chunks at mixing time.+ // 1) Convert the whole sound in one go at load time (here)+ // 2) Convert the audio data in chunks at mixing time //- // First option has been selected, format conversion is done on the loading stage.- // The downside is that it uses more memory if the original sound is u8 or s16.+ // First option has been selected, format conversion is done on the loading stage+ // The downside is that it uses more memory if the original sound is u8 or s16 ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32)); ma_uint32 frameCountIn = wave.frameCount; @@ -967,11 +996,15 @@ // Checks if a sound is ready bool IsSoundReady(Sound sound) {- return ((sound.frameCount > 0) && // Validate frame count- (sound.stream.buffer != NULL) && // Validate stream buffer- (sound.stream.sampleRate > 0) && // Validate sample rate is supported- (sound.stream.sampleSize > 0) && // Validate sample size is supported- (sound.stream.channels > 0)); // Validate number of channels supported+ bool result = false;++ if ((sound.frameCount > 0) && // Validate frame count+ (sound.stream.buffer != NULL) && // Validate stream buffer+ (sound.stream.sampleRate > 0) && // Validate sample rate is supported+ (sound.stream.sampleSize > 0) && // Validate sample size is supported+ (sound.stream.channels > 0)) result = true; // Validate number of channels supported++ return result; } // Unload wave data@@ -993,8 +1026,8 @@ // Untrack and unload just the sound buffer, not the sample data, it is shared with the source for the alias if (alias.stream.buffer != NULL) {- ma_data_converter_uninit(&alias.stream.buffer->converter, NULL); UntrackAudioBuffer(alias.stream.buffer);+ ma_data_converter_uninit(&alias.stream.buffer->converter, NULL); RL_FREE(alias.stream.buffer); } }@@ -1006,7 +1039,6 @@ { StopAudioBuffer(sound.stream.buffer); - // TODO: May want to lock/unlock this since this data buffer is read at mixing time memcpy(sound.stream.buffer->data, data, frameCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn)); } }@@ -1163,7 +1195,11 @@ // Check if a sound is playing bool IsSoundPlaying(Sound sound) {- return IsAudioBufferPlaying(sound.stream.buffer);+ bool result = false;++ if (IsAudioBufferPlaying(sound.stream.buffer)) result = true;++ return result; } // Set volume for a sound@@ -1238,20 +1274,21 @@ return newWave; } -// Crop a wave to defined samples range+// Crop a wave to defined frames range // NOTE: Security check in case of out-of-range-void WaveCrop(Wave *wave, int initSample, int finalSample)+void WaveCrop(Wave *wave, int initFrame, int finalFrame) {- if ((initSample >= 0) && (initSample < finalSample) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))+ if ((initFrame >= 0) && (initFrame < finalFrame) && ((unsigned int)finalFrame <= wave->frameCount)) {- int sampleCount = finalSample - initSample;+ int frameCount = finalFrame - initFrame; - void *data = RL_MALLOC(sampleCount*wave->sampleSize/8);+ void *data = RL_MALLOC(frameCount*wave->channels*wave->sampleSize/8); - memcpy(data, (unsigned char *)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->sampleSize/8);+ memcpy(data, (unsigned char *)wave->data + (initFrame*wave->channels*wave->sampleSize/8), frameCount*wave->channels*wave->sampleSize/8); RL_FREE(wave->data); wave->data = data;+ wave->frameCount = (unsigned int)frameCount; } else TRACELOG(LOG_WARNING, "WAVE: Crop range out of bounds"); }@@ -1267,8 +1304,8 @@ for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++) {- if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f;- else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f;+ if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 128)/128.0f;+ else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32768.0f; else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i]; } @@ -1298,11 +1335,10 @@ drwav *ctxWav = RL_CALLOC(1, sizeof(drwav)); bool success = drwav_init_file(ctxWav, fileName, NULL); - music.ctxType = MUSIC_AUDIO_WAV;- music.ctxData = ctxWav;- if (success) {+ music.ctxType = MUSIC_AUDIO_WAV;+ music.ctxData = ctxWav; int sampleSize = ctxWav->bitsPerSample; if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream() @@ -1311,17 +1347,22 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ RL_FREE(ctxWav);+ } } #endif #if defined(SUPPORT_FILEFORMAT_OGG) else if (IsFileExtension(fileName, ".ogg")) { // Open ogg audio stream- music.ctxType = MUSIC_AUDIO_OGG;- music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);+ stb_vorbis *ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL); - if (music.ctxData != NULL)+ if (ctxOgg != NULL) {+ music.ctxType = MUSIC_AUDIO_OGG;+ music.ctxData = ctxOgg; stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData); // Get Ogg file info // OGG bit rate defaults to 16 bit, it's enough for compressed format@@ -1332,6 +1373,10 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ stb_vorbis_close(ctxOgg);+ } } #endif #if defined(SUPPORT_FILEFORMAT_MP3)@@ -1340,27 +1385,30 @@ drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3)); int result = drmp3_init_file(ctxMp3, fileName, NULL); - music.ctxType = MUSIC_AUDIO_MP3;- music.ctxData = ctxMp3;- if (result > 0) {+ music.ctxType = MUSIC_AUDIO_MP3;+ music.ctxData = ctxMp3; music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels); music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3); music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ RL_FREE(ctxMp3);+ } } #endif #if defined(SUPPORT_FILEFORMAT_QOA) else if (IsFileExtension(fileName, ".qoa")) { qoaplay_desc *ctxQoa = qoaplay_open(fileName);- music.ctxType = MUSIC_AUDIO_QOA;- music.ctxData = ctxQoa; - if (ctxQoa->file != NULL)+ if (ctxQoa != NULL) {+ music.ctxType = MUSIC_AUDIO_QOA;+ music.ctxData = ctxQoa; // NOTE: We are loading samples are 32bit float normalized data, so, // we configure the output audio stream to also use float 32bit music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);@@ -1368,23 +1416,29 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else{} //No uninit required } #endif #if defined(SUPPORT_FILEFORMAT_FLAC) else if (IsFileExtension(fileName, ".flac")) {- music.ctxType = MUSIC_AUDIO_FLAC;- music.ctxData = drflac_open_file(fileName, NULL);+ drflac *ctxFlac = drflac_open_file(fileName, NULL); - if (music.ctxData != NULL)+ if (ctxFlac != NULL) {- drflac *ctxFlac = (drflac *)music.ctxData;-- music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);+ music.ctxType = MUSIC_AUDIO_FLAC;+ music.ctxData = ctxFlac;+ int sampleSize = ctxFlac->bitsPerSample;+ if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()+ music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels); music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ drflac_free(ctxFlac, NULL);+ } } #endif #if defined(SUPPORT_FILEFORMAT_XM)@@ -1393,11 +1447,10 @@ jar_xm_context_t *ctxXm = NULL; int result = jar_xm_create_context_from_file(&ctxXm, AUDIO.System.device.sampleRate, fileName); - music.ctxType = MUSIC_MODULE_XM;- music.ctxData = ctxXm;- if (result == 0) // XM AUDIO.System.context created successfully {+ music.ctxType = MUSIC_MODULE_XM;+ music.ctxData = ctxXm; jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops unsigned int bits = 32;@@ -1411,6 +1464,10 @@ jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song musicLoaded = true; }+ else+ {+ jar_xm_free_context(ctxXm);+ } } #endif #if defined(SUPPORT_FILEFORMAT_MOD)@@ -1420,48 +1477,27 @@ jar_mod_init(ctxMod); int result = jar_mod_load_file(ctxMod, fileName); - music.ctxType = MUSIC_MODULE_MOD;- music.ctxData = ctxMod;- if (result > 0) {+ music.ctxType = MUSIC_MODULE_MOD;+ music.ctxData = ctxMod; // NOTE: Only stereo is supported for MOD music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS); music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ jar_mod_unload(ctxMod);+ RL_FREE(ctxMod);+ } } #endif else TRACELOG(LOG_WARNING, "STREAM: [%s] File format not supported", fileName); if (!musicLoaded) {- if (false) { }- #if defined(SUPPORT_FILEFORMAT_WAV)- else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);- #endif- #if defined(SUPPORT_FILEFORMAT_OGG)- else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);- #endif- #if defined(SUPPORT_FILEFORMAT_MP3)- else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }- #endif- #if defined(SUPPORT_FILEFORMAT_QOA)- else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);- #endif- #if defined(SUPPORT_FILEFORMAT_FLAC)- else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);- #endif- #if defined(SUPPORT_FILEFORMAT_XM)- else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);- #endif- #if defined(SUPPORT_FILEFORMAT_MOD)- else if (music.ctxType == MUSIC_MODULE_MOD) { jar_mod_unload((jar_mod_context_t *)music.ctxData); RL_FREE(music.ctxData); }- #endif-- music.ctxData = NULL;- music.ctxType = MUSIC_AUDIO_NONE; TRACELOG(LOG_WARNING, "FILEIO: [%s] Music file could not be opened", fileName); } else@@ -1492,11 +1528,10 @@ bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL); - music.ctxType = MUSIC_AUDIO_WAV;- music.ctxData = ctxWav;- if (success) {+ music.ctxType = MUSIC_AUDIO_WAV;+ music.ctxData = ctxWav; int sampleSize = ctxWav->bitsPerSample; if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream() @@ -1505,18 +1540,22 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else {+ drwav_uninit(ctxWav);+ RL_FREE(ctxWav);+ } } #endif #if defined(SUPPORT_FILEFORMAT_OGG) else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0)) { // Open ogg audio stream- music.ctxType = MUSIC_AUDIO_OGG;- //music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);- music.ctxData = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);+ stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL); - if (music.ctxData != NULL)+ if (ctxOgg != NULL) {+ music.ctxType = MUSIC_AUDIO_OGG;+ music.ctxData = ctxOgg; stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData); // Get Ogg file info // OGG bit rate defaults to 16 bit, it's enough for compressed format@@ -1527,6 +1566,10 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ stb_vorbis_close(ctxOgg);+ } } #endif #if defined(SUPPORT_FILEFORMAT_MP3)@@ -1535,27 +1578,35 @@ drmp3 *ctxMp3 = RL_CALLOC(1, sizeof(drmp3)); int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL); - music.ctxType = MUSIC_AUDIO_MP3;- music.ctxData = ctxMp3;- if (success) {+ music.ctxType = MUSIC_AUDIO_MP3;+ music.ctxData = ctxMp3; music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels); music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3); music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ drmp3_uninit(ctxMp3);+ RL_FREE(ctxMp3);+ } } #endif #if defined(SUPPORT_FILEFORMAT_QOA) else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0)) {- qoaplay_desc *ctxQoa = qoaplay_open_memory(data, dataSize);- music.ctxType = MUSIC_AUDIO_QOA;- music.ctxData = ctxQoa;+ qoaplay_desc *ctxQoa = NULL;+ if ((data != NULL) && (dataSize > 0))+ {+ ctxQoa = qoaplay_open_memory(data, dataSize);+ } - if ((ctxQoa->file_data != NULL) && (ctxQoa->file_data_size != 0))+ if (ctxQoa != NULL) {+ music.ctxType = MUSIC_AUDIO_QOA;+ music.ctxData = ctxQoa; // NOTE: We are loading samples are 32bit float normalized data, so, // we configure the output audio stream to also use float 32bit music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);@@ -1563,23 +1614,27 @@ music.looping = true; // Looping enabled by default musicLoaded = true; }+ else{} //No uninit required } #endif #if defined(SUPPORT_FILEFORMAT_FLAC) else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0)) {- music.ctxType = MUSIC_AUDIO_FLAC;- music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);+ drflac *ctxFlac = drflac_open_memory((const void*)data, dataSize, NULL); - if (music.ctxData != NULL)+ if (ctxFlac != NULL) {- drflac *ctxFlac = (drflac *)music.ctxData;-+ music.ctxType = MUSIC_AUDIO_FLAC;+ music.ctxData = ctxFlac; music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount; music.looping = true; // Looping enabled by default musicLoaded = true; }+ else+ {+ drflac_free(ctxFlac, NULL);+ } } #endif #if defined(SUPPORT_FILEFORMAT_XM)@@ -1590,6 +1645,7 @@ if (result == 0) // XM AUDIO.System.context created successfully { music.ctxType = MUSIC_MODULE_XM;+ music.ctxData = ctxXm; jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops unsigned int bits = 32;@@ -1602,9 +1658,12 @@ music.looping = true; // Looping enabled by default jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song - music.ctxData = ctxXm; musicLoaded = true; }+ else+ {+ jar_xm_free_context(ctxXm);+ } } #endif #if defined(SUPPORT_FILEFORMAT_MOD)@@ -1631,47 +1690,25 @@ if (result > 0) { music.ctxType = MUSIC_MODULE_MOD;+ music.ctxData = ctxMod; // NOTE: Only stereo is supported for MOD music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2); music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo) music.looping = true; // Looping enabled by default musicLoaded = true;-- music.ctxData = ctxMod;- musicLoaded = true; }+ else+ {+ jar_mod_unload(ctxMod);+ RL_FREE(ctxMod);+ } } #endif else TRACELOG(LOG_WARNING, "STREAM: Data format not supported"); if (!musicLoaded) {- if (false) { }-#if defined(SUPPORT_FILEFORMAT_WAV)- else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);-#endif-#if defined(SUPPORT_FILEFORMAT_OGG)- else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);-#endif-#if defined(SUPPORT_FILEFORMAT_MP3)- else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }-#endif-#if defined(SUPPORT_FILEFORMAT_QOA)- else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);-#endif-#if defined(SUPPORT_FILEFORMAT_FLAC)- else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);-#endif-#if defined(SUPPORT_FILEFORMAT_XM)- else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);-#endif-#if defined(SUPPORT_FILEFORMAT_MOD)- else if (music.ctxType == MUSIC_MODULE_MOD) { jar_mod_unload((jar_mod_context_t *)music.ctxData); RL_FREE(music.ctxData); }-#endif-- music.ctxData = NULL;- music.ctxType = MUSIC_AUDIO_NONE; TRACELOG(LOG_WARNING, "FILEIO: Music data could not be loaded"); } else@@ -1729,19 +1766,10 @@ } } -// Start music playing (open stream)+// Start music playing (open stream) from beginning void PlayMusicStream(Music music) {- if (music.stream.buffer != NULL)- {- // For music streams, we need to make sure we maintain the frame cursor position- // This is a hack for this section of code in UpdateMusicStream()- // NOTE: In case window is minimized, music stream is stopped, just make sure to- // play again on window restore: if (IsMusicStreamPlaying(music)) PlayMusicStream(music);- ma_uint32 frameCursorPos = music.stream.buffer->frameCursorPos;- PlayAudioStream(music.stream); // WARNING: This resets the cursor position.- music.stream.buffer->frameCursorPos = frameCursorPos;- }+ PlayAudioStream(music.stream); } // Pause music playing@@ -1823,7 +1851,9 @@ default: break; } + ma_mutex_lock(&AUDIO.System.lock); music.stream.buffer->framesProcessed = positionInFrames;+ ma_mutex_unlock(&AUDIO.System.lock); } // Update (re-fill) music buffers if data already processed@@ -1831,6 +1861,8 @@ { if (music.stream.buffer == NULL) return; + ma_mutex_lock(&AUDIO.System.lock);+ unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2; // On first call of this function we lazily pre-allocated a temp buffer to read audio files/memory data in@@ -1847,7 +1879,7 @@ // Check both sub-buffers to check if they require refilling for (int i = 0; i < 2; i++) {- if ((music.stream.buffer != NULL) && !music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer+ if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed unsigned int framesToStream = 0; // Total frames to be streamed@@ -1966,7 +1998,7 @@ default: break; } - UpdateAudioStream(music.stream, AUDIO.System.pcmBuffer, framesToStream);+ UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream); music.stream.buffer->framesProcessed = music.stream.buffer->framesProcessed%music.frameCount; @@ -1974,6 +2006,7 @@ { if (!music.looping) {+ ma_mutex_unlock(&AUDIO.System.lock); // Streaming is ending, we filled latest frames from input StopMusicStream(music); return;@@ -1981,9 +2014,7 @@ } } - // NOTE: In case window is minimized, music stream is stopped,- // just make sure to play again on window restore- if (IsMusicStreamPlaying(music)) PlayMusicStream(music);+ ma_mutex_unlock(&AUDIO.System.lock); } // Check if any music is playing@@ -2037,6 +2068,7 @@ else #endif {+ ma_mutex_lock(&AUDIO.System.lock); //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; int framesProcessed = (int)music.stream.buffer->framesProcessed; int subBufferSize = (int)music.stream.buffer->sizeInFrames/2;@@ -2046,6 +2078,7 @@ int framesPlayed = (framesProcessed - framesInFirstBuffer - framesInSecondBuffer + framesSentToMix)%(int)music.frameCount; if (framesPlayed < 0) framesPlayed += music.frameCount; secondsPlayed = (float)framesPlayed/music.stream.sampleRate;+ ma_mutex_unlock(&AUDIO.System.lock); } } @@ -2106,51 +2139,9 @@ // NOTE 2: To dequeue a buffer it needs to be processed: IsAudioStreamProcessed() void UpdateAudioStream(AudioStream stream, const void *data, int frameCount) {- if (stream.buffer != NULL)- {- if (stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1])- {- ma_uint32 subBufferToUpdate = 0;-- if (stream.buffer->isSubBufferProcessed[0] && stream.buffer->isSubBufferProcessed[1])- {- // Both buffers are available for updating.- // Update the first one and make sure the cursor is moved back to the front.- subBufferToUpdate = 0;- stream.buffer->frameCursorPos = 0;- }- else- {- // Just update whichever sub-buffer is processed.- subBufferToUpdate = (stream.buffer->isSubBufferProcessed[0])? 0 : 1;- }-- ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;- unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);-- // Total frames processed in buffer is always the complete size, filled with 0 if required- stream.buffer->framesProcessed += subBufferSizeInFrames;-- // Does this API expect a whole buffer to be updated in one go?- // Assuming so, but if not will need to change this logic.- if (subBufferSizeInFrames >= (ma_uint32)frameCount)- {- ma_uint32 framesToWrite = (ma_uint32)frameCount;-- ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8);- memcpy(subBuffer, data, bytesToWrite);-- // Any leftover frames should be filled with zeros.- ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite;-- if (leftoverFrameCount > 0) memset(subBuffer + bytesToWrite, 0, leftoverFrameCount*stream.channels*(stream.sampleSize/8));-- stream.buffer->isSubBufferProcessed[subBufferToUpdate] = false;- }- else TRACELOG(LOG_WARNING, "STREAM: Attempting to write too many frames to buffer");- }- else TRACELOG(LOG_WARNING, "STREAM: Buffer not available for updating");- }+ ma_mutex_lock(&AUDIO.System.lock);+ UpdateAudioStreamInLockedState(stream, data, frameCount);+ ma_mutex_unlock(&AUDIO.System.lock); } // Check if any audio stream buffers requires refill@@ -2158,7 +2149,11 @@ { if (stream.buffer == NULL) return false; - return (stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1]);+ bool result = false;+ ma_mutex_lock(&AUDIO.System.lock);+ result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];+ ma_mutex_unlock(&AUDIO.System.lock);+ return result; } // Play audio stream@@ -2179,7 +2174,7 @@ ResumeAudioBuffer(stream.buffer); } -// Check if audio stream is playing.+// Check if audio stream is playing bool IsAudioStreamPlaying(AudioStream stream) { return IsAudioBufferPlaying(stream.buffer);@@ -2218,12 +2213,17 @@ // Audio thread callback to request new data void SetAudioStreamCallback(AudioStream stream, AudioCallback callback) {- if (stream.buffer != NULL) stream.buffer->callback = callback;+ if (stream.buffer != NULL)+ {+ ma_mutex_lock(&AUDIO.System.lock);+ stream.buffer->callback = callback;+ ma_mutex_unlock(&AUDIO.System.lock);+ } } -// Add processor to audio stream. Contrary to buffers, the order of processors is important.+// Add processor to audio stream. Contrary to buffers, the order of processors is important // The new processor must be added at the end. As there aren't supposed to be a lot of processors attached to-// a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element.+// a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element void AttachAudioStreamProcessor(AudioStream stream, AudioCallback process) { ma_mutex_lock(&AUDIO.System.lock);@@ -2338,7 +2338,7 @@ TRACELOG(LOG_WARNING, "miniaudio: %s", pMessage); // All log messages from miniaudio are errors } -// Reads audio data from an AudioBuffer object in internal format.+// Reads audio data from an AudioBuffer object in internal format static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount) { // Using audio buffer callback@@ -2412,7 +2412,7 @@ // We need to break from this loop if we're not looping if (!audioBuffer->looping) {- StopAudioBuffer(audioBuffer);+ StopAudioBufferInLockedState(audioBuffer); break; } }@@ -2426,20 +2426,20 @@ // For static buffers we can fill the remaining frames with silence for safety, but we don't want // to report those frames as "read". The reason for this is that the caller uses the return value- // to know whether a non-looping sound has finished playback.+ // to know whether a non-looping sound has finished playback if (audioBuffer->usage != AUDIO_BUFFER_USAGE_STATIC) framesRead += totalFramesRemaining; } return framesRead; } -// Reads audio data from an AudioBuffer object in device format. Returned data will be in a format appropriate for mixing.+// Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount) { // What's going on here is that we're continuously converting data from the AudioBuffer's internal format to the mixing format, which // should be defined by the output format of the data converter. We do this until frameCount frames have been output. The important // detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output- // frames. This can be achieved with ma_data_converter_get_required_input_frame_count().+ // frames. This can be achieved with ma_data_converter_get_required_input_frame_count() ma_uint8 inputBuffer[4096] = { 0 }; ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn); @@ -2548,7 +2548,7 @@ { if (!audioBuffer->looping) {- StopAudioBuffer(audioBuffer);+ StopAudioBufferInLockedState(audioBuffer); break; } else@@ -2618,6 +2618,83 @@ frameOut[c] += (frameIn[c]*localVolume); } }+ }+}++// Check if an audio buffer is playing, assuming the audio system mutex has been locked+static bool IsAudioBufferPlayingInLockedState(AudioBuffer *buffer)+{+ bool result = false;++ if (buffer != NULL) result = (buffer->playing && !buffer->paused);++ return result;+}++// Stop an audio buffer, assuming the audio system mutex has been locked+static void StopAudioBufferInLockedState(AudioBuffer *buffer)+{+ if (buffer != NULL)+ {+ if (IsAudioBufferPlayingInLockedState(buffer))+ {+ buffer->playing = false;+ buffer->paused = false;+ buffer->frameCursorPos = 0;+ buffer->framesProcessed = 0;+ buffer->isSubBufferProcessed[0] = true;+ buffer->isSubBufferProcessed[1] = true;+ }+ }+}++// Update audio stream, assuming the audio system mutex has been locked+static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data, int frameCount)+{+ if (stream.buffer != NULL)+ {+ if (stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1])+ {+ ma_uint32 subBufferToUpdate = 0;++ if (stream.buffer->isSubBufferProcessed[0] && stream.buffer->isSubBufferProcessed[1])+ {+ // Both buffers are available for updating+ // Update the first one and make sure the cursor is moved back to the front+ subBufferToUpdate = 0;+ stream.buffer->frameCursorPos = 0;+ }+ else+ {+ // Just update whichever sub-buffer is processed+ subBufferToUpdate = (stream.buffer->isSubBufferProcessed[0])? 0 : 1;+ }++ ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;+ unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);++ // Total frames processed in buffer is always the complete size, filled with 0 if required+ stream.buffer->framesProcessed += subBufferSizeInFrames;++ // Does this API expect a whole buffer to be updated in one go?+ // Assuming so, but if not will need to change this logic+ if (subBufferSizeInFrames >= (ma_uint32)frameCount)+ {+ ma_uint32 framesToWrite = (ma_uint32)frameCount;++ ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8);+ memcpy(subBuffer, data, bytesToWrite);++ // Any leftover frames should be filled with zeros+ ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite;++ if (leftoverFrameCount > 0) memset(subBuffer + bytesToWrite, 0, leftoverFrameCount*stream.channels*(stream.sampleSize/8));++ stream.buffer->isSubBufferProcessed[subBufferToUpdate] = false;+ }+ else TRACELOG(LOG_WARNING, "STREAM: Attempting to write too many frames to buffer");+ }+ else TRACELOG(LOG_WARNING, "STREAM: Buffer not available for updating"); } }
raylib/src/raylib.h view
@@ -1,6 +1,6 @@ /********************************************************************************************** *-* raylib v5.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)+* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib@@ -82,9 +82,9 @@ #include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback #define RAYLIB_VERSION_MAJOR 5-#define RAYLIB_VERSION_MINOR 1+#define RAYLIB_VERSION_MINOR 5 #define RAYLIB_VERSION_PATCH 0-#define RAYLIB_VERSION "5.1-dev"+#define RAYLIB_VERSION "5.5" // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll@@ -421,7 +421,7 @@ // Ray, ray for raycasting typedef struct Ray { Vector3 position; // Ray position (origin)- Vector3 direction; // Ray direction+ Vector3 direction; // Ray direction (normalized) } Ray; // RayCollision, ray hit information@@ -726,7 +726,7 @@ GAMEPAD_BUTTON_RIGHT_FACE_LEFT, // Gamepad right button left (i.e. PS3: Square, Xbox: X) GAMEPAD_BUTTON_LEFT_TRIGGER_1, // Gamepad top/back trigger left (first), it could be a trailing button GAMEPAD_BUTTON_LEFT_TRIGGER_2, // Gamepad top/back trigger left (second), it could be a trailing button- GAMEPAD_BUTTON_RIGHT_TRIGGER_1, // Gamepad top/back trigger right (one), it could be a trailing button+ GAMEPAD_BUTTON_RIGHT_TRIGGER_1, // Gamepad top/back trigger right (first), it could be a trailing button GAMEPAD_BUTTON_RIGHT_TRIGGER_2, // Gamepad top/back trigger right (second), it could be a trailing button GAMEPAD_BUTTON_MIDDLE_LEFT, // Gamepad center buttons, left one (i.e. PS3: Select) GAMEPAD_BUTTON_MIDDLE, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)@@ -913,11 +913,11 @@ // Camera system modes typedef enum {- CAMERA_CUSTOM = 0, // Custom camera- CAMERA_FREE, // Free camera- CAMERA_ORBITAL, // Orbital camera- CAMERA_FIRST_PERSON, // First person camera- CAMERA_THIRD_PERSON // Third person camera+ CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)+ CAMERA_FREE, // Camera free mode+ CAMERA_ORBITAL, // Camera orbital, around target, zoom supported+ CAMERA_FIRST_PERSON, // Camera first person+ CAMERA_THIRD_PERSON // Camera third person } CameraMode; // Camera projection@@ -934,7 +934,7 @@ } NPatchLayout; // Callbacks to hook some internal functions-// WARNING: These callbacks are intended for advance users+// WARNING: These callbacks are intended for advanced users typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data@@ -1066,7 +1066,7 @@ RLAPI int GetFPS(void); // Get current FPS // Custom frame control functions-// NOTE: Those functions are intended for advance users that want full control over the frame processing+// NOTE: Those functions are intended for advanced users that want full control over the frame processing // By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() // To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)@@ -1093,7 +1093,7 @@ RLAPI void MemFree(void *ptr); // Internal memory free // Set custom callbacks-// WARNING: Callbacks setup is intended for advance users+// WARNING: Callbacks setup is intended for advanced users RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver@@ -1124,6 +1124,7 @@ RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory+RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths@@ -1140,7 +1141,7 @@ // Automation events functionality RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS-RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file+RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording@@ -1232,7 +1233,7 @@ RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)-RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)+RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle@@ -1255,21 +1256,22 @@ RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges-RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline+RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges+RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)-RLAPI void DrawTriangleFan(Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)-RLAPI void DrawTriangleStrip(Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points+RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)+RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters // Splines drawing functions-RLAPI void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points-RLAPI void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points-RLAPI void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points-RLAPI void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]-RLAPI void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]+RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points+RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points+RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points+RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]+RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points@@ -1290,9 +1292,10 @@ RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle-RLAPI bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices+RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]+RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision //------------------------------------------------------------------------------------@@ -1329,6 +1332,7 @@ // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece+RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format@@ -1339,10 +1343,10 @@ RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation-RLAPI void ImageKernelConvolution(Image *image, float* kernel, int kernelSize); // Apply Custom Square image convolution kernel+RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)-RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color+RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) RLAPI void ImageFlipVertical(Image *image); // Flip image vertically@@ -1370,6 +1374,7 @@ RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version) RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)+RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version) RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image@@ -1378,6 +1383,11 @@ RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version) RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image+RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image+RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image+RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image+RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)+RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source) RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)@@ -1433,7 +1443,7 @@ // Font loading/unloading functions RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)-RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set+RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI bool IsFontReady(Font font); // Check if a font is ready@@ -1486,6 +1496,9 @@ RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string+RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string+RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string+ RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported) @@ -1498,7 +1511,7 @@ RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)-RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points+RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires@@ -1533,7 +1546,7 @@ RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)-RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture+RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation @@ -1623,7 +1636,7 @@ RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center) RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave-RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range+RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
raylib/src/raymath.h view
@@ -77,6 +77,7 @@ #endif #endif + //---------------------------------------------------------------------------------- // Defines and Macros //----------------------------------------------------------------------------------@@ -174,7 +175,7 @@ // Clamp float value RMAPI float Clamp(float value, float min, float max) {- float result = (value < min) ? min : value;+ float result = (value < min)? min : value; if (result > max) result = max; @@ -955,6 +956,22 @@ return result; } +// Calculate cubic hermite interpolation between two vectors and their tangents+// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic+RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vector3 tangent2, float amount)+{+ Vector3 result = { 0 };++ float amountPow2 = amount*amount;+ float amountPow3 = amount*amount*amount;++ result.x = (2*amountPow3 - 3*amountPow2 + 1)*v1.x + (amountPow3 - 2*amountPow2 + amount)*tangent1.x + (-2*amountPow3 + 3*amountPow2)*v2.x + (amountPow3 - amountPow2)*tangent2.x;+ result.y = (2*amountPow3 - 3*amountPow2 + 1)*v1.y + (amountPow3 - 2*amountPow2 + amount)*tangent1.y + (-2*amountPow3 + 3*amountPow2)*v2.y + (amountPow3 - amountPow2)*tangent2.y;+ result.z = (2*amountPow3 - 3*amountPow2 + 1)*v1.z + (amountPow3 - 2*amountPow2 + amount)*tangent1.z + (-2*amountPow3 + 3*amountPow2)*v2.z + (amountPow3 - amountPow2)*tangent2.z;++ return result;+}+ // Calculate reflected vector to normal RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal) {@@ -1820,32 +1837,32 @@ } // Get perspective projection matrix-RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far)+RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double nearPlane, double farPlane) { Matrix result = { 0 }; float rl = (float)(right - left); float tb = (float)(top - bottom);- float fn = (float)(far - near);+ float fn = (float)(farPlane - nearPlane); - result.m0 = ((float)near*2.0f)/rl;+ result.m0 = ((float)nearPlane*2.0f)/rl; result.m1 = 0.0f; result.m2 = 0.0f; result.m3 = 0.0f; result.m4 = 0.0f;- result.m5 = ((float)near*2.0f)/tb;+ result.m5 = ((float)nearPlane*2.0f)/tb; result.m6 = 0.0f; result.m7 = 0.0f; result.m8 = ((float)right + (float)left)/rl; result.m9 = ((float)top + (float)bottom)/tb;- result.m10 = -((float)far + (float)near)/fn;+ result.m10 = -((float)farPlane + (float)nearPlane)/fn; result.m11 = -1.0f; result.m12 = 0.0f; result.m13 = 0.0f;- result.m14 = -((float)far*(float)near*2.0f)/fn;+ result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn; result.m15 = 0.0f; return result;@@ -2197,6 +2214,32 @@ return result; } +// Calculate quaternion cubic spline interpolation using Cubic Hermite Spline algorithm+// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic+RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t)+{+ float t2 = t*t;+ float t3 = t2*t;+ float h00 = 2*t3 - 3*t2 + 1;+ float h10 = t3 - 2*t2 + t;+ float h01 = -2*t3 + 3*t2;+ float h11 = t3 - t2;++ Quaternion p0 = QuaternionScale(q1, h00);+ Quaternion m0 = QuaternionScale(outTangent1, h10);+ Quaternion p1 = QuaternionScale(q2, h01);+ Quaternion m1 = QuaternionScale(inTangent2, h11);++ Quaternion result = { 0 };++ result = QuaternionAdd(p0, m0);+ result = QuaternionAdd(result, p1);+ result = QuaternionAdd(result, m1);+ result = QuaternionNormalize(result);++ return result;+}+ // Calculate quaternion based on the rotation from one vector to another RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) {@@ -2480,6 +2523,61 @@ ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); return result;+}++// Decompose a transformation matrix into its rotational, translational and scaling components+RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale)+{+ // Extract translation.+ translation->x = mat.m12;+ translation->y = mat.m13;+ translation->z = mat.m14;++ // Extract upper-left for determinant computation+ const float a = mat.m0;+ const float b = mat.m4;+ const float c = mat.m8;+ const float d = mat.m1;+ const float e = mat.m5;+ const float f = mat.m9;+ const float g = mat.m2;+ const float h = mat.m6;+ const float i = mat.m10;+ const float A = e*i - f*h;+ const float B = f*g - d*i;+ const float C = d*h - e*g;++ // Extract scale+ const float det = a*A + b*B + c*C;+ Vector3 abc = { a, b, c };+ Vector3 def = { d, e, f };+ Vector3 ghi = { g, h, i };++ float scalex = Vector3Length(abc);+ float scaley = Vector3Length(def);+ float scalez = Vector3Length(ghi);+ Vector3 s = { scalex, scaley, scalez };++ if (det < 0) s = Vector3Negate(s);++ *scale = s;++ // Remove scale from the matrix if it is not close to zero+ Matrix clone = mat;+ if (!FloatEquals(det, 0))+ {+ clone.m0 /= s.x;+ clone.m5 /= s.y;+ clone.m10 /= s.z;++ // Extract rotation+ *rotation = QuaternionFromMatrix(clone);+ }+ else+ {+ // Set to identity if close to zero+ *rotation = QuaternionIdentity();+ } } #endif // RAYMATH_H
raylib/src/rcamera.h view
@@ -444,7 +444,8 @@ bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool rotateUp = false; - if (mode == CAMERA_ORBITAL)+ if (mode == CAMERA_CUSTOM) {}+ else if (mode == CAMERA_ORBITAL) { // Orbital can just orbit Matrix rotation = MatrixRotate(GetCameraUp(camera), CAMERA_ORBITAL_SPEED*GetFrameTime());@@ -489,8 +490,8 @@ if (IsGamepadAvailable(0)) { // Gamepad controller support- CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);- CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);+ CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);+ CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
raylib/src/rcore.c view
@@ -3,7 +3,7 @@ * rcore - Window/display management, Graphic device/context management and input management * * PLATFORMS SUPPORTED:-* > PLATFORM_DESKTOP (GLFW backend):+* > PLATFORM_DESKTOP_GLFW (GLFW backend): * - Windows (Win32, Win64) * - Linux (X11/Wayland desktop mode) * - macOS/OSX (x64, arm64)@@ -154,13 +154,15 @@ #endif // Platform specific defines to handle GetApplicationDirectory()-#if defined(_WIN32)+#if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW)) #ifndef MAX_PATH #define MAX_PATH 1025 #endif __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize); __declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize); __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);+unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);+unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); #elif defined(__linux__) #include <unistd.h> #elif defined(__APPLE__)@@ -296,7 +298,7 @@ char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state // NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially- char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.+ char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue int keyPressedQueueCount; // Input keys queue count@@ -482,7 +484,7 @@ static void RecordAutomationEvent(void); // Record frame events (to internal events array) #endif -#if defined(_WIN32)+#if defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW) // NOTE: We declare Sleep() function symbol to avoid including windows.h (kernel32.lib linkage required) void __stdcall Sleep(unsigned long msTimeout); // Required for: WaitTime() #endif@@ -491,11 +493,17 @@ const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' #endif // !SUPPORT_MODULE_RTEXT -// Include platform-specific submodules #if defined(PLATFORM_DESKTOP)- #include "platforms/rcore_desktop.c"+ #define PLATFORM_DESKTOP_GLFW+#endif++// Include platform-specific submodules+#if defined(PLATFORM_DESKTOP_GLFW)+ #include "platforms/rcore_desktop_glfw.c" #elif defined(PLATFORM_DESKTOP_SDL) #include "platforms/rcore_desktop_sdl.c"+#elif defined(PLATFORM_DESKTOP_RGFW)+ #include "platforms/rcore_desktop_rgfw.c" #elif defined(PLATFORM_WEB) #include "platforms/rcore_web.c" #elif defined(PLATFORM_DRM)@@ -560,10 +568,12 @@ { TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION); -#if defined(PLATFORM_DESKTOP)+#if defined(PLATFORM_DESKTOP_GLFW) TRACELOG(LOG_INFO, "Platform backend: DESKTOP (GLFW)"); #elif defined(PLATFORM_DESKTOP_SDL) TRACELOG(LOG_INFO, "Platform backend: DESKTOP (SDL)");+#elif defined(PLATFORM_DESKTOP_RGFW)+ TRACELOG(LOG_INFO, "Platform backend: DESKTOP (RGFW)"); #elif defined(PLATFORM_WEB) TRACELOG(LOG_INFO, "Platform backend: WEB (HTML5)"); #elif defined(PLATFORM_DRM)@@ -806,7 +816,7 @@ return CORE.Input.Mouse.cursorHidden; } -// Check if cursor is on the current screen.+// Check if cursor is on the current screen bool IsCursorOnScreen(void) { return CORE.Input.Mouse.cursorOnScreen;@@ -852,7 +862,7 @@ #ifndef GIF_RECORD_FRAMERATE #define GIF_RECORD_FRAMERATE 10 #endif- gifFrameCounter += GetFrameTime()*1000;+ gifFrameCounter += (unsigned int)(GetFrameTime()*1000); // NOTE: We record one gif frame depending on the desired gif framerate if (gifFrameCounter > 1000/GIF_RECORD_FRAMERATE)@@ -992,10 +1002,10 @@ if (camera.projection == CAMERA_PERSPECTIVE) { // Setup perspective projection- double top = RL_CULL_DISTANCE_NEAR*tan(camera.fovy*0.5*DEG2RAD);+ double top = rlGetCullDistanceNear()*tan(camera.fovy*0.5*DEG2RAD); double right = top*aspect; - rlFrustum(-right, right, -top, top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ rlFrustum(-right, right, -top, top, rlGetCullDistanceNear(), rlGetCullDistanceFar()); } else if (camera.projection == CAMERA_ORTHOGRAPHIC) {@@ -1003,7 +1013,7 @@ double top = camera.fovy/2.0; double right = top*aspect; - rlOrtho(-right, right, -top,top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ rlOrtho(-right, right, -top,top, rlGetCullDistanceNear(), rlGetCullDistanceFar()); } rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix@@ -1207,15 +1217,15 @@ // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]- Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ Matrix proj = MatrixPerspective(fovy, aspect, rlGetCullDistanceNear(), rlGetCullDistanceFar()); config.projection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); config.projection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); // Compute camera transformation matrices- // NOTE: Camera movement might seem more natural if we model the head.+ // NOTE: Camera movement might seem more natural if we model the head // Our axis of rotation is the base of our head, so we might want to add- // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.+ // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions config.viewOffset[0] = MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f); config.viewOffset[1] = MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f); @@ -1419,7 +1429,9 @@ // Get a ray trace from screen position (i.e mouse) Ray GetScreenToWorldRay(Vector2 position, Camera camera) {- return GetScreenToWorldRayEx(position, camera, GetScreenWidth(), GetScreenHeight());+ Ray ray = GetScreenToWorldRayEx(position, camera, GetScreenWidth(), GetScreenHeight());++ return ray; } // Get a ray trace from the screen position (i.e mouse) within a specific section of the screen@@ -1444,7 +1456,7 @@ if (camera.projection == CAMERA_PERSPECTIVE) { // Calculate projection matrix from perspective- matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)width/(double)height), RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)width/(double)height), rlGetCullDistanceNear(), rlGetCullDistanceFar()); } else if (camera.projection == CAMERA_ORTHOGRAPHIC) {@@ -1460,9 +1472,10 @@ Vector3 nearPoint = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); Vector3 farPoint = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); - // Unproject the mouse cursor in the near plane.- // We need this as the source position because orthographic projects, compared to perspective doesn't have a- // convergence point, meaning that the "eye" of the camera is more like a plane than a point.+ // Unproject the mouse cursor in the near plane+ // We need this as the source position because orthographic projects,+ // compared to perspective doesn't have a convergence point,+ // meaning that the "eye" of the camera is more like a plane than a point Vector3 cameraPlanePointerPos = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView); // Calculate normalized direction vector@@ -1480,7 +1493,9 @@ // Get transform matrix for camera Matrix GetCameraMatrix(Camera camera) {- return MatrixLookAt(camera.position, camera.target, camera.up);+ Matrix mat = MatrixLookAt(camera.position, camera.target, camera.up);++ return mat; } // Get camera 2d transform matrix@@ -1491,12 +1506,12 @@ // 1. Move it to target // 2. Rotate by -rotation and scale by (1/zoom) // When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller),- // not for the camera getting bigger, hence the invert. Same deal with rotation.+ // not for the camera getting bigger, hence the invert. Same deal with rotation // 3. Move it by (-offset); // Offset defines target transform relative to screen, but since we're effectively "moving" screen (camera) // we need to do it into opposite direction (inverse transform) - // Having camera transform in world-space, inverse of it gives the modelview transform.+ // Having camera transform in world-space, inverse of it gives the modelview transform // Since (A*B*C)' = C'*B'*A', the modelview is // 1. Move to offset // 2. Rotate and Scale@@ -1528,7 +1543,7 @@ if (camera.projection == CAMERA_PERSPECTIVE) { // Calculate projection matrix from perspective- matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)width/(double)height), RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)width/(double)height), rlGetCullDistanceNear(), rlGetCullDistanceFar()); } else if (camera.projection == CAMERA_ORTHOGRAPHIC) {@@ -1537,7 +1552,7 @@ double right = top*aspect; // Calculate projection matrix from orthographic- matProj = MatrixOrtho(-right, right, -top, top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR);+ matProj = MatrixOrtho(-right, right, -top, top, rlGetCullDistanceNear(), rlGetCullDistanceFar()); } // Calculate view matrix from camera look at (and transpose it)@@ -1661,7 +1676,7 @@ // Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32! void WaitTime(double seconds) {- if (seconds < 0) return;+ if (seconds < 0) return; // Security check #if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP) double destinationTime = GetTime() + seconds;@@ -1687,7 +1702,7 @@ req.tv_sec = sec; req.tv_nsec = nsec; - // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated.+ // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated while (nanosleep(&req, &req) == -1) continue; #endif #if defined(__APPLE__)@@ -1754,7 +1769,7 @@ #if defined(SUPPORT_RPRAND_GENERATOR) values = rprand_load_sequence(count, min, max); #else- if (count > ((unsigned int)abs(max - min) + 1)) return values;+ if (count > ((unsigned int)abs(max - min) + 1)) return values; // Security check values = (int *)RL_CALLOC(count, sizeof(int)); @@ -1822,7 +1837,7 @@ // Setup window configuration flags (view FLAGS) // NOTE: This function is expected to be called before window creation,-// because it sets up some flags for the window creation process.+// because it sets up some flags for the window creation process // To configure window states after creation, just use SetWindowState() void SetConfigFlags(unsigned int flags) {@@ -1946,7 +1961,9 @@ static const char *strprbrk(const char *s, const char *charset) { const char *latestMatch = NULL;+ for (; s = strpbrk(s, charset), s != NULL; latestMatch = s++) { }+ return latestMatch; } @@ -1954,9 +1971,10 @@ const char *GetFileName(const char *filePath) { const char *fileName = NULL;+ if (filePath != NULL) fileName = strprbrk(filePath, "\\/"); - if (!fileName) return filePath;+ if (fileName == NULL) return filePath; return fileName + 1; }@@ -2232,11 +2250,72 @@ return S_ISREG(result.st_mode); } +// Check if fileName is valid for the platform/OS+bool IsFileNameValid(const char *fileName)+{+ bool valid = true;++ if ((fileName != NULL) && (fileName[0] != '\0'))+ {+ int length = (int)strlen(fileName);+ bool allPeriods = true;++ for (int i = 0; i < length; i++)+ {+ // Check invalid characters+ if ((fileName[i] == '<') ||+ (fileName[i] == '>') ||+ (fileName[i] == ':') ||+ (fileName[i] == '\"') ||+ (fileName[i] == '/') ||+ (fileName[i] == '\\') ||+ (fileName[i] == '|') ||+ (fileName[i] == '?') ||+ (fileName[i] == '*')) { valid = false; break; }++ // Check non-glyph characters+ if ((unsigned char)fileName[i] < 32) { valid = false; break; }++ // TODO: Check trailing periods/spaces?++ // Check if filename is not all periods+ if (fileName[i] != '.') allPeriods = false;+ }++ if (allPeriods) valid = false;++/*+ if (valid)+ {+ // Check invalid DOS names+ if (length >= 3)+ {+ if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'N')) || // CON+ ((fileName[0] == 'P') && (fileName[1] == 'R') && (fileName[2] == 'N')) || // PRN+ ((fileName[0] == 'A') && (fileName[1] == 'U') && (fileName[2] == 'X')) || // AUX+ ((fileName[0] == 'N') && (fileName[1] == 'U') && (fileName[2] == 'L'))) valid = false; // NUL+ }++ if (length >= 4)+ {+ if (((fileName[0] == 'C') && (fileName[1] == 'O') && (fileName[2] == 'M') && ((fileName[3] >= '0') && (fileName[3] <= '9'))) || // COM0-9+ ((fileName[0] == 'L') && (fileName[1] == 'P') && (fileName[2] == 'T') && ((fileName[3] >= '0') && (fileName[3] <= '9')))) valid = false; // LPT0-9+ }+ }+*/+ }++ return valid;+}+ // Check if a file has been dropped into window bool IsFileDropped(void) {- if (CORE.Window.dropFileCount > 0) return true;- else return false;+ bool result = false;++ if (CORE.Window.dropFileCount > 0) result = true;++ return result; } // Load dropped filepaths@@ -2270,15 +2349,16 @@ long GetFileModTime(const char *fileName) { struct stat result = { 0 };+ long modTime = 0; if (stat(fileName, &result) == 0) { time_t mod = result.st_mtime; - return (long)mod;+ modTime = (long)mod; } - return 0;+ return modTime; } //----------------------------------------------------------------------------------@@ -2347,7 +2427,7 @@ char *encodedData = (char *)RL_MALLOC(*outputSize); - if (encodedData == NULL) return NULL;+ if (encodedData == NULL) return NULL; // Security check for (int i = 0, j = 0; i < dataSize;) {@@ -2949,13 +3029,15 @@ // Get mouse position X int GetMouseX(void) {- return (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);+ int mouseX = (int)((CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);+ return mouseX; } // Get mouse position Y int GetMouseY(void) {- return (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);+ int mouseY = (int)((CORE.Input.Mouse.currentPosition.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);+ return mouseY; } // Get mouse position XY@@ -3022,13 +3104,15 @@ // Get touch position X for touch point 0 (relative to screen size) int GetTouchX(void) {- return (int)CORE.Input.Touch.position[0].x;+ int touchX = (int)CORE.Input.Touch.position[0].x;+ return touchX; } // Get touch position Y for touch point 0 (relative to screen size) int GetTouchY(void) {- return (int)CORE.Input.Touch.position[0].y;+ int touchY = (int)CORE.Input.Touch.position[0].y;+ return touchY; } // Get touch position XY for a touch point index (relative to screen size)@@ -3070,10 +3154,10 @@ // Initialize hi-resolution timer void InitTimer(void) {- // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.- // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.- // High resolutions can also prevent the CPU power management system from entering power-saving modes.- // Setting a higher resolution does not improve the accuracy of the high-resolution performance counter.+ // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions+ // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often+ // High resolutions can also prevent the CPU power management system from entering power-saving modes+ // Setting a higher resolution does not improve the accuracy of the high-resolution performance counter #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) && !defined(PLATFORM_DESKTOP_SDL) timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms) #endif@@ -3557,16 +3641,6 @@ } //------------------------------------------------------------------------------------- #endif-- // Window events recording- //-------------------------------------------------------------------------------------- // TODO.- //--------------------------------------------------------------------------------------- // Custom actions events recording- //-------------------------------------------------------------------------------------- // TODO.- //------------------------------------------------------------------------------------- } #endif
raylib/src/rlgl.h view
@@ -62,12 +62,12 @@ * When loading a shader, the following vertex attributes and uniform * location names are tried to be set automatically: *-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix@@ -322,6 +322,26 @@ #define RL_READ_FRAMEBUFFER 0x8CA8 // GL_READ_FRAMEBUFFER #define RL_DRAW_FRAMEBUFFER 0x8CA9 // GL_DRAW_FRAMEBUFFER +// Default shader vertex attribute locations+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3+#endif+ #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4+#endif+#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5+#endif+ //---------------------------------------------------------------------------------- // Types and Structures Definition //----------------------------------------------------------------------------------@@ -349,6 +369,7 @@ float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)+ float *normals; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2) unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)@@ -357,7 +378,7 @@ unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) #endif unsigned int vaoId; // OpenGL Vertex Array Object id- unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data)+ unsigned int vboId[5]; // OpenGL Vertex Buffer Objects id (5 types of vertex data) } rlVertexBuffer; // Draw call type@@ -569,6 +590,9 @@ RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area+RLAPI void rlSetClipPlanes(double nearPlane, double farPlane); // Set clip planes distances+RLAPI double rlGetCullDistanceNear(void); // Get cull plane distance near+RLAPI double rlGetCullDistanceFar(void); // Get cull plane distance far //------------------------------------------------------------------------------------ // Functions Declaration - Vertex level operations@@ -696,7 +720,7 @@ RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements data on GPU buffer RLAPI void rlUnloadVertexArray(unsigned int vaoId); // Unload vertex array (vao) RLAPI void rlUnloadVertexBuffer(unsigned int vboId); // Unload vertex buffer object-RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer); // Set vertex attribute data configuration+RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset); // Set vertex attribute data configuration RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor); // Set vertex attribute data divisor RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value, when attribute to provided RLAPI void rlDrawVertexArray(int offset, int count); // Draw vertex array (currently active vao)@@ -820,9 +844,9 @@ #define GL_GLEXT_PROTOTYPES #include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library #elif defined(GRAPHICS_API_OPENGL_ES2)- // NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP,+ // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms, // in that case, functions are loaded from a custom glad for OpenGL ES 2.0- #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)+ #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) #define GLAD_GLES2_IMPLEMENTATION #include "external/glad_gles2.h" #else@@ -932,22 +956,22 @@ // Default shader vertex attribute names to set location points #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION- #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD- #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL- #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR- #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT- #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT #endif #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2- #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5+ #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 #endif #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP@@ -1062,6 +1086,9 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //----------------------------------------------------------------------------------+static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR;+static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;+ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) static rlglData RLGL = { 0 }; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2@@ -1092,8 +1119,15 @@ static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture) // Auxiliar matrix math functions+typedef struct rl_float16 {+ float v[16];+} rl_float16;+static rl_float16 rlMatrixToFloatV(Matrix mat); // Get float array of matrix data+#define rlMatrixToFloat(mat) (rlMatrixToFloatV(mat).v) // Get float vector for Matrix static Matrix rlMatrixIdentity(void); // Get identity matrix static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices+static Matrix rlMatrixTranspose(Matrix mat); // Transposes provided matrix+static Matrix rlMatrixInvert(Matrix mat); // Invert provided matrix //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations@@ -1262,7 +1296,7 @@ matf[2], matf[6], matf[10], matf[14], matf[3], matf[7], matf[11], matf[15] }; - *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, mat);+ *RLGL.State.currentMatrix = rlMatrixMultiply(mat, *RLGL.State.currentMatrix); } // Multiply the current matrix by a perspective matrix generated by parameters@@ -1336,6 +1370,25 @@ glViewport(x, y, width, height); } +// Set clip planes distances+void rlSetClipPlanes(double nearPlane, double farPlane)+{+ rlCullDistanceNear = nearPlane;+ rlCullDistanceFar = farPlane;+}++// Get cull plane distance near+double rlGetCullDistanceNear(void)+{+ return rlCullDistanceNear;+}++// Get cull plane distance far+double rlGetCullDistanceFar(void)+{+ return rlCullDistanceFar;+}+ //---------------------------------------------------------------------------------- // Module Functions Definition - Vertex level operations //----------------------------------------------------------------------------------@@ -1353,7 +1406,7 @@ } } -void rlEnd() { glEnd(); }+void rlEnd(void) { glEnd(); } void rlVertex2i(int x, int y) { glVertex2i(x, y); } void rlVertex2f(float x, float y) { glVertex2f(x, y); } void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }@@ -1456,7 +1509,10 @@ RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy; - // WARNING: By default rlVertexBuffer struct does not store normals+ // Add current normal+ RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter] = RLGL.State.normalx;+ RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 1] = RLGL.State.normaly;+ RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 2] = RLGL.State.normalz; // Add current color RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr;@@ -1492,9 +1548,26 @@ // NOTE: Normals limited to TRIANGLES only? void rlNormal3f(float x, float y, float z) {- RLGL.State.normalx = x;- RLGL.State.normaly = y;- RLGL.State.normalz = z;+ float normalx = x;+ float normaly = y;+ float normalz = z;+ if (RLGL.State.transformRequired)+ {+ normalx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z;+ normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;+ normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;+ }+ float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);+ if (length != 0.0f)+ {+ float ilength = 1.0f/length;+ normalx *= ilength;+ normaly *= ilength;+ normalz *= ilength;+ }+ RLGL.State.normalx = normalx;+ RLGL.State.normaly = normaly;+ RLGL.State.normalz = normalz; } // Define one vertex (color)@@ -1965,7 +2038,7 @@ } // Check and log OpenGL error codes-void rlCheckErrors()+void rlCheckErrors(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) int check = 1;@@ -2163,7 +2236,10 @@ RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; // Init default vertex arrays buffers+ // Simulate that the default shader has the location RL_SHADER_LOC_VERTEX_NORMAL to bind the normal buffer for the default render batch+ RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL; RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS);+ RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = -1; RLGL.currentBatch = &RLGL.defaultBatch; // Init stack matrices (emulating OpenGL 1.1)@@ -2314,7 +2390,7 @@ #elif defined(GRAPHICS_API_OPENGL_ES2) - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)+ #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) // TODO: Support GLAD loader for OpenGL ES 3.0 if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully");@@ -2608,6 +2684,7 @@ batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad+ batch.vertexBuffer[i].normals = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad #if defined(GRAPHICS_API_OPENGL_33) batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices)@@ -2618,6 +2695,7 @@ for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f; for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f;+ for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].normals[j] = 0.0f; for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0; int k = 0;@@ -2667,16 +2745,23 @@ glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); - // Vertex color buffer (shader-location = 3)+ // Vertex normal buffer (shader-location = 2) glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);+ glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].normals, GL_DYNAMIC_DRAW);+ glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]);+ glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0);++ // Vertex color buffer (shader-location = 3)+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);+ glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]); glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer- glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]);+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[4]);+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[4]); #if defined(GRAPHICS_API_OPENGL_33) glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW); #endif@@ -2731,10 +2816,10 @@ if (RLGL.ExtSupported.vao) { glBindVertexArray(batch.vertexBuffer[i].vaoId);- glDisableVertexAttribArray(0);- glDisableVertexAttribArray(1);- glDisableVertexAttribArray(2);- glDisableVertexAttribArray(3);+ glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);+ glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);+ glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);+ glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR); glBindVertexArray(0); } @@ -2743,6 +2828,7 @@ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]); glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]); glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]);+ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[4]); // Delete VAOs from GPU (VRAM) if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);@@ -2750,6 +2836,7 @@ // Free vertex arrays memory from CPU (RAM) RL_FREE(batch.vertexBuffer[i].vertices); RL_FREE(batch.vertexBuffer[i].texcoords);+ RL_FREE(batch.vertexBuffer[i].normals); RL_FREE(batch.vertexBuffer[i].colors); RL_FREE(batch.vertexBuffer[i].indices); }@@ -2784,8 +2871,13 @@ glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer - // Colors buffer+ // Normals buffer glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);+ glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].normals);+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].normals, GL_DYNAMIC_DRAW); // Update all buffer++ // Colors buffer+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer @@ -2838,14 +2930,31 @@ // Create modelview-projection matrix and upload to shader Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection);- float matMVPfloat[16] = {- matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3,- matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7,- matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11,- matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15- };- glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat);+ glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, rlMatrixToFloat(matMVP)); + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION] != -1)+ {+ glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION], 1, false, rlMatrixToFloat(RLGL.State.projection));+ }++ // WARNING: For the following setup of the view, model, and normal matrices, it is expected that+ // transformations and rendering occur between rlPushMatrix and rlPopMatrix.++ if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1)+ {+ glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW], 1, false, rlMatrixToFloat(RLGL.State.modelview));+ }++ if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL] != -1)+ {+ glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL], 1, false, rlMatrixToFloat(RLGL.State.transform));+ }++ if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL] != -1)+ {+ glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL], 1, false, rlMatrixToFloat(rlMatrixTranspose(rlMatrixInvert(RLGL.State.transform))));+ }+ if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); else {@@ -2859,12 +2968,17 @@ glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); - // Bind vertex attrib: color (shader-location = 3)+ // Bind vertex attrib: normal (shader-location = 2) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);+ glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0);+ glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]);++ // Bind vertex attrib: color (shader-location = 3)+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[4]); } // Setup some default shader values@@ -3824,14 +3938,16 @@ } // Set vertex attribute-void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer)+void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: Data type could be: GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT // Additional types (depends on OpenGL version or extensions): // - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, // - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV- glVertexAttribPointer(index, compSize, type, normalized, stride, pointer);++ size_t offsetNative = offset;+ glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offsetNative); #endif } @@ -4014,12 +4130,12 @@ glAttachShader(program, fShaderId); // NOTE: Default attribute shader locations must be Bound before linking- glBindAttribLocation(program, 0, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);- glBindAttribLocation(program, 1, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);- glBindAttribLocation(program, 2, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);- glBindAttribLocation(program, 3, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);- glBindAttribLocation(program, 4, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);- glBindAttribLocation(program, 5, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);+ glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); // NOTE: If some attrib name is no found on the shader, it locations becomes -1 @@ -4285,7 +4401,7 @@ #if defined(GRAPHICS_API_OPENGL_43) glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);- glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);+ glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); #endif return (size > 0)? (unsigned int)size : 0;@@ -4404,7 +4520,7 @@ } // Get internal projection matrix for stereo render (selected eye)-RLAPI Matrix rlGetMatrixProjectionStereo(int eye)+Matrix rlGetMatrixProjectionStereo(int eye) { Matrix mat = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)@@ -4414,7 +4530,7 @@ } // Get internal view offset matrix for stereo render (selected eye)-RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye)+Matrix rlGetMatrixViewOffsetStereo(int eye) { Matrix mat = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)@@ -4482,10 +4598,10 @@ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); // Bind vertex attributes (position, texcoords)- glEnableVertexAttribArray(0);- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions- glEnableVertexAttribArray(1);- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords+ glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);+ glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions+ glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);+ glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords // Draw quad glBindVertexArray(quadVAO);@@ -4556,12 +4672,12 @@ // Bind vertex attributes (position, normals, texcoords) glBindVertexArray(cubeVAO);- glEnableVertexAttribArray(0);- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions- glEnableVertexAttribArray(1);- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals- glEnableVertexAttribArray(2);- glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords+ glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);+ glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions+ glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);+ glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals+ glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);+ glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); @@ -4709,14 +4825,14 @@ TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShaderId); // Set default shader locations: attributes locations- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexPosition");- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexTexCoord");- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexColor");+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); // Set default shader locations: uniform locations- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, "mvp");- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "colDiffuse");- RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "texture0");+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);+ RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); } else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShaderId); }@@ -4868,6 +4984,31 @@ // Auxiliar math functions +// Get float array of matrix data+static rl_float16 rlMatrixToFloatV(Matrix mat)+{+ rl_float16 result = { 0 };++ result.v[0] = mat.m0;+ result.v[1] = mat.m1;+ result.v[2] = mat.m2;+ result.v[3] = mat.m3;+ result.v[4] = mat.m4;+ result.v[5] = mat.m5;+ result.v[6] = mat.m6;+ result.v[7] = mat.m7;+ result.v[8] = mat.m8;+ result.v[9] = mat.m9;+ result.v[10] = mat.m10;+ result.v[11] = mat.m11;+ result.v[12] = mat.m12;+ result.v[13] = mat.m13;+ result.v[14] = mat.m14;+ result.v[15] = mat.m15;++ return result;+}+ // Get identity matrix static Matrix rlMatrixIdentity(void) {@@ -4903,6 +5044,78 @@ result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;++ return result;+}++// Transposes provided matrix+static Matrix rlMatrixTranspose(Matrix mat)+{+ Matrix result = { 0 };++ result.m0 = mat.m0;+ result.m1 = mat.m4;+ result.m2 = mat.m8;+ result.m3 = mat.m12;+ result.m4 = mat.m1;+ result.m5 = mat.m5;+ result.m6 = mat.m9;+ result.m7 = mat.m13;+ result.m8 = mat.m2;+ result.m9 = mat.m6;+ result.m10 = mat.m10;+ result.m11 = mat.m14;+ result.m12 = mat.m3;+ result.m13 = mat.m7;+ result.m14 = mat.m11;+ result.m15 = mat.m15;++ return result;+}++// Invert provided matrix+static Matrix rlMatrixInvert(Matrix mat)+{+ Matrix result = { 0 };++ // Cache the matrix values (speed optimization)+ float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;+ float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;+ float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;+ float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;++ float b00 = a00*a11 - a01*a10;+ float b01 = a00*a12 - a02*a10;+ float b02 = a00*a13 - a03*a10;+ float b03 = a01*a12 - a02*a11;+ float b04 = a01*a13 - a03*a11;+ float b05 = a02*a13 - a03*a12;+ float b06 = a20*a31 - a21*a30;+ float b07 = a20*a32 - a22*a30;+ float b08 = a20*a33 - a23*a30;+ float b09 = a21*a32 - a22*a31;+ float b10 = a21*a33 - a23*a31;+ float b11 = a22*a33 - a23*a32;++ // Calculate the invert determinant (inlined to avoid double-caching)+ float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);++ result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;+ result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;+ result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;+ result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;+ result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;+ result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;+ result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;+ result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;+ result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;+ result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;+ result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;+ result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;+ result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;+ result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;+ result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;+ result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; return result; }
raylib/src/rmodels.c view
@@ -226,5851 +226,6215 @@ } // Draw a triangle strip defined by points-void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color)-{- if (pointCount < 3) return;-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 2; i < pointCount; i++)- {- if ((i%2) == 0)- {- rlVertex3f(points[i].x, points[i].y, points[i].z);- rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);- rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);- }- else- {- rlVertex3f(points[i].x, points[i].y, points[i].z);- rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);- rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);- }- }- rlEnd();-}--// Draw cube-// NOTE: Cube position is the center position-void DrawCube(Vector3 position, float width, float height, float length, Color color)-{- float x = 0.0f;- float y = 0.0f;- float z = 0.0f;-- rlPushMatrix();- // NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)- rlTranslatef(position.x, position.y, position.z);- //rlRotatef(45, 0, 1, 0);- //rlScalef(1.0f, 1.0f, 1.0f); // NOTE: Vertices are directly scaled on definition-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- // Front face- rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left-- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right-- // Back face- rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right-- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left-- // Top face- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left- rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left- rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right-- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left- rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right-- // Bottom face- rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right- rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left-- rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Right- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right- rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left-- // Right face- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left-- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left-- // Left face- rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right-- rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left- rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right- rlEnd();- rlPopMatrix();-}--// Draw cube (Vector version)-void DrawCubeV(Vector3 position, Vector3 size, Color color)-{- DrawCube(position, size.x, size.y, size.z, color);-}--// Draw cube wires-void DrawCubeWires(Vector3 position, float width, float height, float length, Color color)-{- float x = 0.0f;- float y = 0.0f;- float z = 0.0f;-- rlPushMatrix();- rlTranslatef(position.x, position.y, position.z);-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);-- // Front face- //------------------------------------------------------------------- // Bottom line- rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right-- // Left line- rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right-- // Top line- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left-- // Right line- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left- rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left-- // Back face- //------------------------------------------------------------------- // Bottom line- rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right-- // Left line- rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right-- // Top line- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left-- // Right line- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left- rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left-- // Top face- //------------------------------------------------------------------- // Left line- rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left front- rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left back-- // Right line- rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right front- rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right back-- // Bottom face- //------------------------------------------------------------------- // Left line- rlVertex3f(x - width/2, y - height/2, z + length/2); // Top left front- rlVertex3f(x - width/2, y - height/2, z - length/2); // Top left back-- // Right line- rlVertex3f(x + width/2, y - height/2, z + length/2); // Top right front- rlVertex3f(x + width/2, y - height/2, z - length/2); // Top right back- rlEnd();- rlPopMatrix();-}--// Draw cube wires (vector version)-void DrawCubeWiresV(Vector3 position, Vector3 size, Color color)-{- DrawCubeWires(position, size.x, size.y, size.z, color);-}--// Draw sphere-void DrawSphere(Vector3 centerPos, float radius, Color color)-{- DrawSphereEx(centerPos, radius, 16, 16, color);-}--// Draw sphere with extended parameters-void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)-{- rlPushMatrix();- // NOTE: Transformation is applied in inverse order (scale -> translate)- rlTranslatef(centerPos.x, centerPos.y, centerPos.z);- rlScalef(radius, radius, radius);-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 0; i < (rings + 2); i++)- {- for (int j = 0; j < slices; j++)- {- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));-- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));- }- }- rlEnd();- rlPopMatrix();-}--// Draw sphere wires-void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color)-{- rlPushMatrix();- // NOTE: Transformation is applied in inverse order (scale -> translate)- rlTranslatef(centerPos.x, centerPos.y, centerPos.z);- rlScalef(radius, radius, radius);-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 0; i < (rings + 2); i++)- {- for (int j = 0; j < slices; j++)- {- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));-- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));-- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));- rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),- sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),- cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));- }- }- rlEnd();- rlPopMatrix();-}--// Draw a cylinder-// NOTE: It could be also used for pyramid and cone-void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)-{- if (sides < 3) sides = 3;-- rlPushMatrix();- rlTranslatef(position.x, position.y, position.z);-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- if (radiusTop > 0)- {- // Draw Body -------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides)- {- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360.0f/sides))*radiusBottom); //Bottom Right- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360.0f/sides))*radiusTop); //Top Right-- rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); //Top Left- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360.0f/sides))*radiusTop); //Top Right- }-- // Draw Cap --------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides)- {- rlVertex3f(0, height, 0);- rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360.0f/sides))*radiusTop);- }- }- else- {- // Draw Cone -------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides)- {- rlVertex3f(0, height, 0);- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360.0f/sides))*radiusBottom);- }- }-- // Draw Base ------------------------------------------------------------------------------------------ for (int i = 0; i < 360; i += 360/sides)- {- rlVertex3f(0, 0, 0);- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360.0f/sides))*radiusBottom);- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);- }- rlEnd();- rlPopMatrix();-}--// Draw a cylinder with base at startPos and top at endPos-// NOTE: It could be also used for pyramid and cone-void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)-{- if (sides < 3) sides = 3;-- Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };- if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return;-- // Construct a basis of the base and the top face:- Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));- Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));-- float baseAngle = (2.0f*PI)/sides;-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 0; i < sides; i++) {- // compute the four vertices- float s1 = sinf(baseAngle*(i + 0))*startRadius;- float c1 = cosf(baseAngle*(i + 0))*startRadius;- Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };- float s2 = sinf(baseAngle*(i + 1))*startRadius;- float c2 = cosf(baseAngle*(i + 1))*startRadius;- Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };- float s3 = sinf(baseAngle*(i + 0))*endRadius;- float c3 = cosf(baseAngle*(i + 0))*endRadius;- Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };- float s4 = sinf(baseAngle*(i + 1))*endRadius;- float c4 = cosf(baseAngle*(i + 1))*endRadius;- Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };-- if (startRadius > 0) { //- rlVertex3f(startPos.x, startPos.y, startPos.z); // |- rlVertex3f(w2.x, w2.y, w2.z); // T0- rlVertex3f(w1.x, w1.y, w1.z); // |- } //- // w2 x.-----------x startPos- rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /- rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /- rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /- // | 2 \ T 'x w1- rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos- rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/- rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /- // '.\|/- if (endRadius > 0) { // 'x w3- rlVertex3f(endPos.x, endPos.y, endPos.z); // |- rlVertex3f(w3.x, w3.y, w3.z); // T3- rlVertex3f(w4.x, w4.y, w4.z); // |- } //- }- rlEnd();-}--// Draw a wired cylinder-// NOTE: It could be also used for pyramid and cone-void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)-{- if (sides < 3) sides = 3;-- rlPushMatrix();- rlTranslatef(position.x, position.y, position.z);-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 0; i < 360; i += 360/sides)- {- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360.0f/sides))*radiusBottom);-- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusBottom, 0, cosf(DEG2RAD*(i + 360.0f/sides))*radiusBottom);- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360.0f/sides))*radiusTop);-- rlVertex3f(sinf(DEG2RAD*(i + 360.0f/sides))*radiusTop, height, cosf(DEG2RAD*(i + 360.0f/sides))*radiusTop);- rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);-- rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);- rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);- }- rlEnd();- rlPopMatrix();-}---// Draw a wired cylinder with base at startPos and top at endPos-// NOTE: It could be also used for pyramid and cone-void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)-{- if (sides < 3) sides = 3;-- Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };- if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0))return;-- // Construct a basis of the base and the top face:- Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));- Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));-- float baseAngle = (2.0f*PI)/sides;-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);-- for (int i = 0; i < sides; i++) {- // compute the four vertices- float s1 = sinf(baseAngle*(i + 0))*startRadius;- float c1 = cosf(baseAngle*(i + 0))*startRadius;- Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };- float s2 = sinf(baseAngle*(i + 1))*startRadius;- float c2 = cosf(baseAngle*(i + 1))*startRadius;- Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };- float s3 = sinf(baseAngle*(i + 0))*endRadius;- float c3 = cosf(baseAngle*(i + 0))*endRadius;- Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };- float s4 = sinf(baseAngle*(i + 1))*endRadius;- float c4 = cosf(baseAngle*(i + 1))*endRadius;- Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };-- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w2.x, w2.y, w2.z);-- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w3.x, w3.y, w3.z);-- rlVertex3f(w3.x, w3.y, w3.z);- rlVertex3f(w4.x, w4.y, w4.z);- }- rlEnd();-}--// Draw a capsule with the center of its sphere caps at startPos and endPos-void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)-{- if (slices < 3) slices = 3;-- Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };-- // draw a sphere if start and end points are the same- bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);- if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};-- // Construct a basis of the base and the caps:- Vector3 b0 = Vector3Normalize(direction);- Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));- Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));- Vector3 capCenter = endPos;-- float baseSliceAngle = (2.0f*PI)/slices;- float baseRingAngle = PI * 0.5f / rings;-- rlBegin(RL_TRIANGLES);- rlColor4ub(color.r, color.g, color.b, color.a);-- // render both caps- for (int c = 0; c < 2; c++)- {- for (int i = 0; i < rings; i++)- {- for (int j = 0; j < slices; j++)- {-- // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier-- // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))- // as we iterate through the rings they must get smaller by the cos(angle(i))-- // compute the four vertices- float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));- float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));- Vector3 w1 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius- };- float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));- float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));- Vector3 w2 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius- };-- float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));- float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));- Vector3 w3 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius- };- float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));- float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));- Vector3 w4 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius- };-- // make sure cap triangle normals are facing outwards- if(c == 0)- {- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w3.x, w3.y, w3.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w4.x, w4.y, w4.z);- rlVertex3f(w3.x, w3.y, w3.z);- }- else- {- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w3.x, w3.y, w3.z);- rlVertex3f(w2.x, w2.y, w2.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w3.x, w3.y, w3.z);- rlVertex3f(w4.x, w4.y, w4.z);- }- }- }- capCenter = startPos;- b0 = Vector3Scale(b0, -1.0f);- }- // render middle- if (!sphereCase)- {- for (int j = 0; j < slices; j++)- {- // compute the four vertices- float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;- float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;- Vector3 w1 = {- startPos.x + ringSin1*b1.x + ringCos1*b2.x,- startPos.y + ringSin1*b1.y + ringCos1*b2.y,- startPos.z + ringSin1*b1.z + ringCos1*b2.z- };- float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;- float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;- Vector3 w2 = {- startPos.x + ringSin2*b1.x + ringCos2*b2.x,- startPos.y + ringSin2*b1.y + ringCos2*b2.y,- startPos.z + ringSin2*b1.z + ringCos2*b2.z- };-- float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;- float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;- Vector3 w3 = {- endPos.x + ringSin3*b1.x + ringCos3*b2.x,- endPos.y + ringSin3*b1.y + ringCos3*b2.y,- endPos.z + ringSin3*b1.z + ringCos3*b2.z- };- float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;- float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;- Vector3 w4 = {- endPos.x + ringSin4*b1.x + ringCos4*b2.x,- endPos.y + ringSin4*b1.y + ringCos4*b2.y,- endPos.z + ringSin4*b1.z + ringCos4*b2.z- };- // w2 x.-----------x startPos- rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /- rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /- rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /- // | 2 \ T 'x w1- rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos- rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/- rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /- // '.\|/- // 'x w3- }- }- rlEnd();-}--// Draw capsule wires with the center of its sphere caps at startPos and endPos-void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)-{- if (slices < 3) slices = 3;-- Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };-- // draw a sphere if start and end points are the same- bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);- if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};-- // Construct a basis of the base and the caps:- Vector3 b0 = Vector3Normalize(direction);- Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));- Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));- Vector3 capCenter = endPos;-- float baseSliceAngle = (2.0f*PI)/slices;- float baseRingAngle = PI * 0.5f / rings;-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);-- // render both caps- for (int c = 0; c < 2; c++)- {- for (int i = 0; i < rings; i++)- {- for (int j = 0; j < slices; j++)- {-- // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier-- // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))- // as we iterate through the rings they must get smaller by the cos(angle(i))-- // compute the four vertices- float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));- float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));- Vector3 w1 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius- };- float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));- float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));- Vector3 w2 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius- };-- float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));- float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));- Vector3 w3 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius- };- float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));- float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));- Vector3 w4 = (Vector3){- capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,- capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,- capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius- };-- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w2.x, w2.y, w2.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w3.x, w3.y, w3.z);-- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w3.x, w3.y, w3.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w4.x, w4.y, w4.z);-- rlVertex3f(w3.x, w3.y, w3.z);- rlVertex3f(w4.x, w4.y, w4.z);- }- }- capCenter = startPos;- b0 = Vector3Scale(b0, -1.0f);- }- // render middle- if (!sphereCase)- {- for (int j = 0; j < slices; j++)- {- // compute the four vertices- float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;- float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;- Vector3 w1 = {- startPos.x + ringSin1*b1.x + ringCos1*b2.x,- startPos.y + ringSin1*b1.y + ringCos1*b2.y,- startPos.z + ringSin1*b1.z + ringCos1*b2.z- };- float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;- float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;- Vector3 w2 = {- startPos.x + ringSin2*b1.x + ringCos2*b2.x,- startPos.y + ringSin2*b1.y + ringCos2*b2.y,- startPos.z + ringSin2*b1.z + ringCos2*b2.z- };-- float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;- float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;- Vector3 w3 = {- endPos.x + ringSin3*b1.x + ringCos3*b2.x,- endPos.y + ringSin3*b1.y + ringCos3*b2.y,- endPos.z + ringSin3*b1.z + ringCos3*b2.z- };- float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;- float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;- Vector3 w4 = {- endPos.x + ringSin4*b1.x + ringCos4*b2.x,- endPos.y + ringSin4*b1.y + ringCos4*b2.y,- endPos.z + ringSin4*b1.z + ringCos4*b2.z- };-- rlVertex3f(w1.x, w1.y, w1.z);- rlVertex3f(w3.x, w3.y, w3.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w4.x, w4.y, w4.z);-- rlVertex3f(w2.x, w2.y, w2.z);- rlVertex3f(w3.x, w3.y, w3.z);- }- }- rlEnd();-}--// Draw a plane-void DrawPlane(Vector3 centerPos, Vector2 size, Color color)-{- // NOTE: Plane is always created on XZ ground- rlPushMatrix();- rlTranslatef(centerPos.x, centerPos.y, centerPos.z);- rlScalef(size.x, 1.0f, size.y);-- rlBegin(RL_QUADS);- rlColor4ub(color.r, color.g, color.b, color.a);- rlNormal3f(0.0f, 1.0f, 0.0f);-- rlVertex3f(-0.5f, 0.0f, -0.5f);- rlVertex3f(-0.5f, 0.0f, 0.5f);- rlVertex3f(0.5f, 0.0f, 0.5f);- rlVertex3f(0.5f, 0.0f, -0.5f);- rlEnd();- rlPopMatrix();-}--// Draw a ray line-void DrawRay(Ray ray, Color color)-{- float scale = 10000;-- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);- rlColor4ub(color.r, color.g, color.b, color.a);-- rlVertex3f(ray.position.x, ray.position.y, ray.position.z);- rlVertex3f(ray.position.x + ray.direction.x*scale, ray.position.y + ray.direction.y*scale, ray.position.z + ray.direction.z*scale);- rlEnd();-}--// Draw a grid centered at (0, 0, 0)-void DrawGrid(int slices, float spacing)-{- int halfSlices = slices/2;-- rlBegin(RL_LINES);- for (int i = -halfSlices; i <= halfSlices; i++)- {- if (i == 0)- {- rlColor3f(0.5f, 0.5f, 0.5f);- rlColor3f(0.5f, 0.5f, 0.5f);- rlColor3f(0.5f, 0.5f, 0.5f);- rlColor3f(0.5f, 0.5f, 0.5f);- }- else- {- rlColor3f(0.75f, 0.75f, 0.75f);- rlColor3f(0.75f, 0.75f, 0.75f);- rlColor3f(0.75f, 0.75f, 0.75f);- rlColor3f(0.75f, 0.75f, 0.75f);- }-- rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);- rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);-- rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);- rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);- }- rlEnd();-}--// Load model from files (mesh and material)-Model LoadModel(const char *fileName)-{- Model model = { 0 };--#if defined(SUPPORT_FILEFORMAT_OBJ)- if (IsFileExtension(fileName, ".obj")) model = LoadOBJ(fileName);-#endif-#if defined(SUPPORT_FILEFORMAT_IQM)- if (IsFileExtension(fileName, ".iqm")) model = LoadIQM(fileName);-#endif-#if defined(SUPPORT_FILEFORMAT_GLTF)- if (IsFileExtension(fileName, ".gltf") || IsFileExtension(fileName, ".glb")) model = LoadGLTF(fileName);-#endif-#if defined(SUPPORT_FILEFORMAT_VOX)- if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName);-#endif-#if defined(SUPPORT_FILEFORMAT_M3D)- if (IsFileExtension(fileName, ".m3d")) model = LoadM3D(fileName);-#endif-- // Make sure model transform is set to identity matrix!- model.transform = MatrixIdentity();-- if ((model.meshCount != 0) && (model.meshes != NULL))- {- // Upload vertex data to GPU (static meshes)- for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false);- }- else TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load model mesh(es) data", fileName);-- if (model.materialCount == 0)- {- TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to load model material data, default to white material", fileName);-- model.materialCount = 1;- model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));- model.materials[0] = LoadMaterialDefault();-- if (model.meshMaterial == NULL) model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));- }-- return model;-}--// Load model from generated mesh-// WARNING: A shallow copy of mesh is generated, passed by value,-// as long as struct contains pointers to data and some values, we get a copy-// of mesh pointing to same data as original version... be careful!-Model LoadModelFromMesh(Mesh mesh)-{- Model model = { 0 };-- model.transform = MatrixIdentity();-- model.meshCount = 1;- model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));- model.meshes[0] = mesh;-- model.materialCount = 1;- model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));- model.materials[0] = LoadMaterialDefault();-- model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));- model.meshMaterial[0] = 0; // First material index-- return model;-}--// Check if a model is ready-bool IsModelReady(Model model)-{- return ((model.meshes != NULL) && // Validate model contains some mesh- (model.materials != NULL) && // Validate model contains some material (at least default one)- (model.meshMaterial != NULL) && // Validate mesh-material linkage- (model.meshCount > 0) && // Validate mesh count- (model.materialCount > 0)); // Validate material count-- // NOTE: This is a very general model validation, many elements could be validated from a model...-}--// Unload model (meshes/materials) from memory (RAM and/or VRAM)-// NOTE: This function takes care of all model elements, for a detailed control-// over them, use UnloadMesh() and UnloadMaterial()-void UnloadModel(Model model)-{- // Unload meshes- for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]);-- // Unload materials maps- // NOTE: As the user could be sharing shaders and textures between models,- // we don't unload the material but just free its maps,- // the user is responsible for freeing models shaders and textures- for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);-- // Unload arrays- RL_FREE(model.meshes);- RL_FREE(model.materials);- RL_FREE(model.meshMaterial);-- // Unload animation data- RL_FREE(model.bones);- RL_FREE(model.bindPose);-- TRACELOG(LOG_INFO, "MODEL: Unloaded model (and meshes) from RAM and VRAM");-}--// Compute model bounding box limits (considers all meshes)-BoundingBox GetModelBoundingBox(Model model)-{- BoundingBox bounds = { 0 };-- if (model.meshCount > 0)- {- Vector3 temp = { 0 };- bounds = GetMeshBoundingBox(model.meshes[0]);-- for (int i = 1; i < model.meshCount; i++)- {- BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]);-- temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x;- temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y;- temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z;- bounds.min = temp;-- temp.x = (bounds.max.x > tempBounds.max.x)? bounds.max.x : tempBounds.max.x;- temp.y = (bounds.max.y > tempBounds.max.y)? bounds.max.y : tempBounds.max.y;- temp.z = (bounds.max.z > tempBounds.max.z)? bounds.max.z : tempBounds.max.z;- bounds.max = temp;- }- }-- // Apply model.transform to bounding box- // WARNING: Current BoundingBox structure design does not support rotation transformations,- // in those cases is up to the user to calculate the proper box bounds (8 vertices transformed)- bounds.min = Vector3Transform(bounds.min, model.transform);- bounds.max = Vector3Transform(bounds.max, model.transform);-- return bounds;-}--// Upload vertex data into a VAO (if supported) and VBO-void UploadMesh(Mesh *mesh, bool dynamic)-{- if (mesh->vaoId > 0)- {- // Check if mesh has already been loaded in GPU- TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId);- return;- }-- mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));-- mesh->vaoId = 0; // Vertex Array Object- mesh->vboId[0] = 0; // Vertex buffer: positions- mesh->vboId[1] = 0; // Vertex buffer: texcoords- mesh->vboId[2] = 0; // Vertex buffer: normals- mesh->vboId[3] = 0; // Vertex buffer: colors- mesh->vboId[4] = 0; // Vertex buffer: tangents- mesh->vboId[5] = 0; // Vertex buffer: texcoords2- mesh->vboId[6] = 0; // Vertex buffer: indices--#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)- mesh->vaoId = rlLoadVertexArray();- rlEnableVertexArray(mesh->vaoId);-- // NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data-- // Enable vertex attributes: position (shader-location = 0)- void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;- mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);- rlSetVertexAttribute(0, 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(0);-- // Enable vertex attributes: texcoords (shader-location = 1)- mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);- rlSetVertexAttribute(1, 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(1);-- // WARNING: When setting default vertex attribute values, the values for each generic vertex attribute- // is part of current state, and it is maintained even if a different program object is used-- if (mesh->normals != NULL)- {- // Enable vertex attributes: normals (shader-location = 2)- void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;- mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);- rlSetVertexAttribute(2, 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(2);- }- else- {- // Default vertex attribute: normal- // WARNING: Default value provided to shader if location available- float value[3] = { 1.0f, 1.0f, 1.0f };- rlSetVertexAttributeDefault(2, value, SHADER_ATTRIB_VEC3, 3);- rlDisableVertexAttribute(2);- }-- if (mesh->colors != NULL)- {- // Enable vertex attribute: color (shader-location = 3)- mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);- rlSetVertexAttribute(3, 4, RL_UNSIGNED_BYTE, 1, 0, 0);- rlEnableVertexAttribute(3);- }- else- {- // Default vertex attribute: color- // WARNING: Default value provided to shader if location available- float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // WHITE- rlSetVertexAttributeDefault(3, value, SHADER_ATTRIB_VEC4, 4);- rlDisableVertexAttribute(3);- }-- if (mesh->tangents != NULL)- {- // Enable vertex attribute: tangent (shader-location = 4)- mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);- rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(4);- }- else- {- // Default vertex attribute: tangent- // WARNING: Default value provided to shader if location available- float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };- rlSetVertexAttributeDefault(4, value, SHADER_ATTRIB_VEC4, 4);- rlDisableVertexAttribute(4);- }-- if (mesh->texcoords2 != NULL)- {- // Enable vertex attribute: texcoord2 (shader-location = 5)- mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);- rlSetVertexAttribute(5, 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(5);- }- else- {- // Default vertex attribute: texcoord2- // WARNING: Default value provided to shader if location available- float value[2] = { 0.0f, 0.0f };- rlSetVertexAttributeDefault(5, value, SHADER_ATTRIB_VEC2, 2);- rlDisableVertexAttribute(5);- }-- if (mesh->indices != NULL)- {- mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);- }-- if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);- else TRACELOG(LOG_INFO, "VBO: Mesh uploaded successfully to VRAM (GPU)");-- rlDisableVertexArray();-#endif-}--// Update mesh vertex data in GPU for a specific buffer index-void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset)-{- rlUpdateVertexBuffer(mesh.vboId[index], data, dataSize, offset);-}--// Draw a 3d mesh with material and transform-void DrawMesh(Mesh mesh, Material material, Matrix transform)-{-#if defined(GRAPHICS_API_OPENGL_11)- #define GL_VERTEX_ARRAY 0x8074- #define GL_NORMAL_ARRAY 0x8075- #define GL_COLOR_ARRAY 0x8076- #define GL_TEXTURE_COORD_ARRAY 0x8078-- rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);-- rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);- rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);- rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);- rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);-- rlPushMatrix();- rlMultMatrixf(MatrixToFloat(transform));- rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r,- material.maps[MATERIAL_MAP_DIFFUSE].color.g,- material.maps[MATERIAL_MAP_DIFFUSE].color.b,- material.maps[MATERIAL_MAP_DIFFUSE].color.a);-- if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices);- else rlDrawVertexArray(0, mesh.vertexCount);- rlPopMatrix();-- rlDisableStatePointer(GL_VERTEX_ARRAY);- rlDisableStatePointer(GL_TEXTURE_COORD_ARRAY);- rlDisableStatePointer(GL_NORMAL_ARRAY);- rlDisableStatePointer(GL_COLOR_ARRAY);-- rlDisableTexture();-#endif--#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)- // Bind shader program- rlEnableShader(material.shader.id);-- // Send required data to shader (matrices, values)- //------------------------------------------------------ // Upload to shader material.colDiffuse- if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)- {- float values[4] = {- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f- };-- rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);- }-- // Upload to shader material.colSpecular (if location available)- if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)- {- float values[4] = {- (float)material.maps[MATERIAL_MAP_SPECULAR].color.r/255.0f,- (float)material.maps[MATERIAL_MAP_SPECULAR].color.g/255.0f,- (float)material.maps[MATERIAL_MAP_SPECULAR].color.b/255.0f,- (float)material.maps[MATERIAL_MAP_SPECULAR].color.a/255.0f- };-- rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);- }-- // Get a copy of current matrices to work with,- // just in case stereo render is required, and we need to modify them- // NOTE: At this point the modelview matrix just contains the view matrix (camera)- // That's because BeginMode3D() sets it and there is no model-drawing function- // that modifies it, all use rlPushMatrix() and rlPopMatrix()- Matrix matModel = MatrixIdentity();- Matrix matView = rlGetMatrixModelview();- Matrix matModelView = MatrixIdentity();- Matrix matProjection = rlGetMatrixProjection();-- // Upload view and projection matrices (if locations available)- if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);- if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);-- // Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL- if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform);-- // Accumulate several model transformations:- // transform: model transformation provided (includes DrawModel() params combined with model.transform)- // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack- matModel = MatrixMultiply(transform, rlGetMatrixTransform());-- // Get model-view matrix- matModelView = MatrixMultiply(matModel, matView);-- // Upload model normal matrix (if locations available)- if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));- //------------------------------------------------------- // Bind active texture maps (if available)- for (int i = 0; i < MAX_MATERIAL_MAPS; i++)- {- if (material.maps[i].texture.id > 0)- {- // Select current shader texture slot- rlActiveTextureSlot(i);-- // Enable texture for active slot- if ((i == MATERIAL_MAP_IRRADIANCE) ||- (i == MATERIAL_MAP_PREFILTER) ||- (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);- else rlEnableTexture(material.maps[i].texture.id);-- rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);- }- }-- // Try binding vertex array objects (VAO) or use VBOs if not possible- // WARNING: UploadMesh() enables all vertex attributes available in mesh and sets default attribute values- // for shader expected vertex attributes that are not provided by the mesh (i.e. colors)- // This could be a dangerous approach because different meshes with different shaders can enable/disable some attributes- if (!rlEnableVertexArray(mesh.vaoId))- {- // Bind mesh VBO data: vertex position (shader-location = 0)- rlEnableVertexBuffer(mesh.vboId[0]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);-- // Bind mesh VBO data: vertex texcoords (shader-location = 1)- rlEnableVertexBuffer(mesh.vboId[1]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);-- if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)- {- // Bind mesh VBO data: vertex normals (shader-location = 2)- rlEnableVertexBuffer(mesh.vboId[2]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);- }-- // Bind mesh VBO data: vertex colors (shader-location = 3, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)- {- if (mesh.vboId[3] != 0)- {- rlEnableVertexBuffer(mesh.vboId[3]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);- }- else- {- // Set default value for defined vertex attribute in shader but not provided by mesh- // WARNING: It could result in GPU undefined behaviour- float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };- rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);- rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);- }- }-- // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)- {- rlEnableVertexBuffer(mesh.vboId[4]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);- }-- // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)- {- rlEnableVertexBuffer(mesh.vboId[5]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);- }-- if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);- }-- int eyeCount = 1;- if (rlIsStereoRenderEnabled()) eyeCount = 2;-- for (int eye = 0; eye < eyeCount; eye++)- {- // Calculate model-view-projection matrix (MVP)- Matrix matModelViewProjection = MatrixIdentity();- if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);- else- {- // Setup current eye viewport (half screen width)- rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());- matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));- }-- // Send combined model-view-projection matrix to shader- rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);-- // Draw mesh- if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0);- else rlDrawVertexArray(0, mesh.vertexCount);- }-- // Unbind all bound texture maps- for (int i = 0; i < MAX_MATERIAL_MAPS; i++)- {- if (material.maps[i].texture.id > 0)- {- // Select current shader texture slot- rlActiveTextureSlot(i);-- // Disable texture for active slot- if ((i == MATERIAL_MAP_IRRADIANCE) ||- (i == MATERIAL_MAP_PREFILTER) ||- (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();- else rlDisableTexture();- }- }-- // Disable all possible vertex array objects (or VBOs)- rlDisableVertexArray();- rlDisableVertexBuffer();- rlDisableVertexBufferElement();-- // Disable shader program- rlDisableShader();-- // Restore rlgl internal modelview and projection matrices- rlSetMatrixModelview(matView);- rlSetMatrixProjection(matProjection);-#endif-}--// Draw multiple mesh instances with material and different transforms-void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances)-{-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)- // Instancing required variables- float16 *instanceTransforms = NULL;- unsigned int instancesVboId = 0;-- // Bind shader program- rlEnableShader(material.shader.id);-- // Send required data to shader (matrices, values)- //------------------------------------------------------ // Upload to shader material.colDiffuse- if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)- {- float values[4] = {- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,- (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f- };-- rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);- }-- // Upload to shader material.colSpecular (if location available)- if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)- {- float values[4] = {- (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f,- (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.g/255.0f,- (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.b/255.0f,- (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f- };-- rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);- }-- // Get a copy of current matrices to work with,- // just in case stereo render is required, and we need to modify them- // NOTE: At this point the modelview matrix just contains the view matrix (camera)- // That's because BeginMode3D() sets it and there is no model-drawing function- // that modifies it, all use rlPushMatrix() and rlPopMatrix()- Matrix matModel = MatrixIdentity();- Matrix matView = rlGetMatrixModelview();- Matrix matModelView = MatrixIdentity();- Matrix matProjection = rlGetMatrixProjection();-- // Upload view and projection matrices (if locations available)- if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);- if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);-- // Create instances buffer- instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));-- // Fill buffer with instances transformations as float16 arrays- for (int i = 0; i < instances; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);-- // Enable mesh VAO to attach new buffer- rlEnableVertexArray(mesh.vaoId);-- // This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData().- // It isn't clear which would be reliably faster in all cases and on all platforms,- // anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems- // no faster, since we're transferring all the transform matrices anyway- instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);-- // Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL- for (unsigned int i = 0; i < 4; i++)- {- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), (void *)(i*sizeof(Vector4)));- rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1);- }-- rlDisableVertexBuffer();- rlDisableVertexArray();-- // Accumulate internal matrix transform (push/pop) and view matrix- // NOTE: In this case, model instance transformation must be computed in the shader- matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);-- // Upload model normal matrix (if locations available)- if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));- //------------------------------------------------------- // Bind active texture maps (if available)- for (int i = 0; i < MAX_MATERIAL_MAPS; i++)- {- if (material.maps[i].texture.id > 0)- {- // Select current shader texture slot- rlActiveTextureSlot(i);-- // Enable texture for active slot- if ((i == MATERIAL_MAP_IRRADIANCE) ||- (i == MATERIAL_MAP_PREFILTER) ||- (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);- else rlEnableTexture(material.maps[i].texture.id);-- rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);- }- }-- // Try binding vertex array objects (VAO)- // or use VBOs if not possible- if (!rlEnableVertexArray(mesh.vaoId))- {- // Bind mesh VBO data: vertex position (shader-location = 0)- rlEnableVertexBuffer(mesh.vboId[0]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);-- // Bind mesh VBO data: vertex texcoords (shader-location = 1)- rlEnableVertexBuffer(mesh.vboId[1]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);-- if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)- {- // Bind mesh VBO data: vertex normals (shader-location = 2)- rlEnableVertexBuffer(mesh.vboId[2]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);- }-- // Bind mesh VBO data: vertex colors (shader-location = 3, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)- {- if (mesh.vboId[3] != 0)- {- rlEnableVertexBuffer(mesh.vboId[3]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);- }- else- {- // Set default value for unused attribute- // NOTE: Required when using default shader and no VAO support- float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };- rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);- rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);- }- }-- // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)- {- rlEnableVertexBuffer(mesh.vboId[4]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);- }-- // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)- if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)- {- rlEnableVertexBuffer(mesh.vboId[5]);- rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);- }-- if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);- }-- int eyeCount = 1;- if (rlIsStereoRenderEnabled()) eyeCount = 2;-- for (int eye = 0; eye < eyeCount; eye++)- {- // Calculate model-view-projection matrix (MVP)- Matrix matModelViewProjection = MatrixIdentity();- if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);- else- {- // Setup current eye viewport (half screen width)- rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());- matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));- }-- // Send combined model-view-projection matrix to shader- rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);-- // Draw mesh instanced- if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);- else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);- }-- // Unbind all bound texture maps- for (int i = 0; i < MAX_MATERIAL_MAPS; i++)- {- if (material.maps[i].texture.id > 0)- {- // Select current shader texture slot- rlActiveTextureSlot(i);-- // Disable texture for active slot- if ((i == MATERIAL_MAP_IRRADIANCE) ||- (i == MATERIAL_MAP_PREFILTER) ||- (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();- else rlDisableTexture();- }- }-- // Disable all possible vertex array objects (or VBOs)- rlDisableVertexArray();- rlDisableVertexBuffer();- rlDisableVertexBufferElement();-- // Disable shader program- rlDisableShader();-- // Remove instance transforms buffer- rlUnloadVertexBuffer(instancesVboId);- RL_FREE(instanceTransforms);-#endif-}--// Unload mesh from memory (RAM and VRAM)-void UnloadMesh(Mesh mesh)-{- // Unload rlgl mesh vboId data- rlUnloadVertexArray(mesh.vaoId);-- if (mesh.vboId != NULL) for (int i = 0; i < MAX_MESH_VERTEX_BUFFERS; i++) rlUnloadVertexBuffer(mesh.vboId[i]);- RL_FREE(mesh.vboId);-- RL_FREE(mesh.vertices);- RL_FREE(mesh.texcoords);- RL_FREE(mesh.normals);- RL_FREE(mesh.colors);- RL_FREE(mesh.tangents);- RL_FREE(mesh.texcoords2);- RL_FREE(mesh.indices);-- RL_FREE(mesh.animVertices);- RL_FREE(mesh.animNormals);- RL_FREE(mesh.boneWeights);- RL_FREE(mesh.boneIds);-}--// Export mesh data to file-bool ExportMesh(Mesh mesh, const char *fileName)-{- bool success = false;-- if (IsFileExtension(fileName, ".obj"))- {- // Estimated data size, it should be enough...- int dataSize = mesh.vertexCount*(int)strlen("v 0000.00f 0000.00f 0000.00f") +- mesh.vertexCount*(int)strlen("vt 0.000f 0.00f") +- mesh.vertexCount*(int)strlen("vn 0.000f 0.00f 0.00f") +- mesh.triangleCount*(int)strlen("f 00000/00000/00000 00000/00000/00000 00000/00000/00000");-- // NOTE: Text data buffer size is estimated considering mesh data size- char *txtData = (char *)RL_CALLOC(dataSize*2 + 2000, sizeof(char));-- int byteCount = 0;- byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n");- byteCount += sprintf(txtData + byteCount, "# // //\n");- byteCount += sprintf(txtData + byteCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");- byteCount += sprintf(txtData + byteCount, "# // //\n");- byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");- byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n");- byteCount += sprintf(txtData + byteCount, "# // //\n");- byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");- byteCount += sprintf(txtData + byteCount, "# // //\n");- byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");- byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount);- byteCount += sprintf(txtData + byteCount, "# Triangle Count: %i\n\n", mesh.triangleCount);-- byteCount += sprintf(txtData + byteCount, "g mesh\n");-- for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)- {- byteCount += sprintf(txtData + byteCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);- }-- for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)- {- byteCount += sprintf(txtData + byteCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);- }-- for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)- {- byteCount += sprintf(txtData + byteCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);- }-- if (mesh.indices != NULL)- {- for (int i = 0, v = 0; i < mesh.triangleCount; i++, v += 3)- {- byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n",- mesh.indices[v] + 1, mesh.indices[v] + 1, mesh.indices[v] + 1,- mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1,- mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1);- }- }- else- {- for (int i = 0, v = 1; i < mesh.triangleCount; i++, v += 3)- {- byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", v, v, v, v + 1, v + 1, v + 1, v + 2, v + 2, v + 2);- }- }-- byteCount += sprintf(txtData + byteCount, "\n");-- // NOTE: Text data length exported is determined by '\0' (NULL) character- success = SaveFileText(fileName, txtData);-- RL_FREE(txtData);- }- else if (IsFileExtension(fileName, ".raw"))- {- // TODO: Support additional file formats to export mesh vertex data- }-- return success;-}--// Export mesh as code file (.h) defining multiple arrays of vertex attributes-bool ExportMeshAsCode(Mesh mesh, const char *fileName)-{- bool success = false;--#ifndef TEXT_BYTES_PER_LINE- #define TEXT_BYTES_PER_LINE 20-#endif-- // NOTE: Text data buffer size is fixed to 64MB- char *txtData = (char *)RL_CALLOC(64*1024*1024, sizeof(char)); // 64 MB-- int byteCount = 0;- byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");- byteCount += sprintf(txtData + byteCount, "// //\n");- byteCount += sprintf(txtData + byteCount, "// MeshAsCode exporter v1.0 - Mesh vertex data exported as arrays //\n");- byteCount += sprintf(txtData + byteCount, "// //\n");- byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");- byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");- byteCount += sprintf(txtData + byteCount, "// //\n");- byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2023 Ramon Santamaria (@raysan5) //\n");- byteCount += sprintf(txtData + byteCount, "// //\n");- byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");-- // Get file name from path and convert variable name to uppercase- char varFileName[256] = { 0 };- strcpy(varFileName, GetFileNameWithoutExt(fileName));- for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }-- // Add image information- byteCount += sprintf(txtData + byteCount, "// Mesh basic information\n");- byteCount += sprintf(txtData + byteCount, "#define %s_VERTEX_COUNT %i\n", varFileName, mesh.vertexCount);- byteCount += sprintf(txtData + byteCount, "#define %s_TRIANGLE_COUNT %i\n\n", varFileName, mesh.triangleCount);-- // Define vertex attributes data as separate arrays- //------------------------------------------------------------------------------------------ if (mesh.vertices != NULL) // Vertex position (XYZ - 3 components per vertex - float)- {- byteCount += sprintf(txtData + byteCount, "static float %s_VERTEX_DATA[%i] = { ", varFileName, mesh.vertexCount*3);- for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.vertices[i]);- byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.vertices[mesh.vertexCount*3 - 1]);- }-- if (mesh.texcoords != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)- {- byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD_DATA[%i] = { ", varFileName, mesh.vertexCount*2);- for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords[i]);- byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords[mesh.vertexCount*2 - 1]);- }-- if (mesh.texcoords2 != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)- {- byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD2_DATA[%i] = { ", varFileName, mesh.vertexCount*2);- for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords2[i]);- byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords2[mesh.vertexCount*2 - 1]);- }-- if (mesh.normals != NULL) // Vertex normals (XYZ - 3 components per vertex - float)- {- byteCount += sprintf(txtData + byteCount, "static float %s_NORMAL_DATA[%i] = { ", varFileName, mesh.vertexCount*3);- for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.normals[i]);- byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.normals[mesh.vertexCount*3 - 1]);- }-- if (mesh.tangents != NULL) // Vertex tangents (XYZW - 4 components per vertex - float)- {- byteCount += sprintf(txtData + byteCount, "static float %s_TANGENT_DATA[%i] = { ", varFileName, mesh.vertexCount*4);- for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.tangents[i]);- byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.tangents[mesh.vertexCount*4 - 1]);- }-- if (mesh.colors != NULL) // Vertex colors (RGBA - 4 components per vertex - unsigned char)- {- byteCount += sprintf(txtData + byteCount, "static unsigned char %s_COLOR_DATA[%i] = { ", varFileName, mesh.vertexCount*4);- for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), mesh.colors[i]);- byteCount += sprintf(txtData + byteCount, "0x%x };\n\n", mesh.colors[mesh.vertexCount*4 - 1]);- }-- if (mesh.indices != NULL) // Vertex indices (3 index per triangle - unsigned short)- {- byteCount += sprintf(txtData + byteCount, "static unsigned short %s_INDEX_DATA[%i] = { ", varFileName, mesh.triangleCount*3);- for (int i = 0; i < mesh.triangleCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%i,\n" : "%i, "), mesh.indices[i]);- byteCount += sprintf(txtData + byteCount, "%i };\n", mesh.indices[mesh.triangleCount*3 - 1]);- }- //------------------------------------------------------------------------------------------- // NOTE: Text data size exported is determined by '\0' (NULL) character- success = SaveFileText(fileName, txtData);-- RL_FREE(txtData);-- //if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);- //else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);-- return success;-}---#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)-// Process obj materials-static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)-{- // Init model mats- for (int m = 0; m < materialCount; m++)- {- // Init material to default- // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE- materials[m] = LoadMaterialDefault();-- // Get default texture, in case no texture is defined- // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8- materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };-- if (mats[m].diffuse_texname != NULL) materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(mats[m].diffuse_texname); //char *diffuse_texname; // map_Kd- else materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(mats[m].diffuse[0]*255.0f), (unsigned char)(mats[m].diffuse[1]*255.0f), (unsigned char)(mats[m].diffuse[2] * 255.0f), 255 }; //float diffuse[3];- materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;-- if (mats[m].specular_texname != NULL) materials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(mats[m].specular_texname); //char *specular_texname; // map_Ks- materials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(mats[m].specular[0]*255.0f), (unsigned char)(mats[m].specular[1]*255.0f), (unsigned char)(mats[m].specular[2] * 255.0f), 255 }; //float specular[3];- materials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;-- if (mats[m].bump_texname != NULL) materials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(mats[m].bump_texname); //char *bump_texname; // map_bump, bump- materials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;- materials[m].maps[MATERIAL_MAP_NORMAL].value = mats[m].shininess;-- materials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(mats[m].emission[0]*255.0f), (unsigned char)(mats[m].emission[1]*255.0f), (unsigned char)(mats[m].emission[2] * 255.0f), 255 }; //float emission[3];-- if (mats[m].displacement_texname != NULL) materials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(mats[m].displacement_texname); //char *displacement_texname; // disp- }-}-#endif--// Load materials from model file-Material *LoadMaterials(const char *fileName, int *materialCount)-{- Material *materials = NULL;- unsigned int count = 0;-- // TODO: Support IQM and GLTF for materials parsing--#if defined(SUPPORT_FILEFORMAT_MTL)- if (IsFileExtension(fileName, ".mtl"))- {- tinyobj_material_t *mats = NULL;-- int result = tinyobj_parse_mtl_file(&mats, &count, fileName);- if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);-- materials = RL_MALLOC(count*sizeof(Material));- ProcessMaterialsOBJ(materials, mats, count);-- tinyobj_materials_free(mats, count);- }-#else- TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to load material file", fileName);-#endif-- *materialCount = count;- return materials;-}--// Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)-Material LoadMaterialDefault(void)-{- Material material = { 0 };- material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS, sizeof(MaterialMap));-- // Using rlgl default shader- material.shader.id = rlGetShaderIdDefault();- material.shader.locs = rlGetShaderLocsDefault();-- // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)- material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };- //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set- //material.maps[MATERIAL_MAP_SPECULAR].texture; // NOTE: By default, not set-- material.maps[MATERIAL_MAP_DIFFUSE].color = WHITE; // Diffuse color- material.maps[MATERIAL_MAP_SPECULAR].color = WHITE; // Specular color-- return material;-}--// Check if a material is ready-bool IsMaterialReady(Material material)-{- return ((material.maps != NULL) && // Validate material contain some map- (material.shader.id > 0)); // Validate material shader is valid-}--// Unload material from memory-void UnloadMaterial(Material material)-{- // Unload material shader (avoid unloading default shader, managed by raylib)- if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);-- // Unload loaded texture maps (avoid unloading default texture, managed by raylib)- if (material.maps != NULL)- {- for (int i = 0; i < MAX_MATERIAL_MAPS; i++)- {- if (material.maps[i].texture.id != rlGetTextureIdDefault()) rlUnloadTexture(material.maps[i].texture.id);- }- }-- RL_FREE(material.maps);-}--// Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)-// NOTE: Previous texture should be manually unloaded-void SetMaterialTexture(Material *material, int mapType, Texture2D texture)-{- material->maps[mapType].texture = texture;-}--// Set the material for a mesh-void SetModelMeshMaterial(Model *model, int meshId, int materialId)-{- if (meshId >= model->meshCount) TRACELOG(LOG_WARNING, "MESH: Id greater than mesh count");- else if (materialId >= model->materialCount) TRACELOG(LOG_WARNING, "MATERIAL: Id greater than material count");- else model->meshMaterial[meshId] = materialId;-}--// Load model animations from file-ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)-{- ModelAnimation *animations = NULL;--#if defined(SUPPORT_FILEFORMAT_IQM)- if (IsFileExtension(fileName, ".iqm")) animations = LoadModelAnimationsIQM(fileName, animCount);-#endif-#if defined(SUPPORT_FILEFORMAT_M3D)- if (IsFileExtension(fileName, ".m3d")) animations = LoadModelAnimationsM3D(fileName, animCount);-#endif-#if defined(SUPPORT_FILEFORMAT_GLTF)- if (IsFileExtension(fileName, ".gltf;.glb")) animations = LoadModelAnimationsGLTF(fileName, animCount);-#endif-- return animations;-}--// Update model animated vertex data (positions and normals) for a given frame-// NOTE: Updated data is uploaded to GPU-void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)-{- if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))- {- if (frame >= anim.frameCount) frame = frame%anim.frameCount;-- for (int m = 0; m < model.meshCount; m++)- {- Mesh mesh = model.meshes[m];-- if (mesh.boneIds == NULL || mesh.boneWeights == NULL)- {- TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation(): Mesh %i has no connection to bones", m);- continue;- }-- bool updated = false; // Flag to check when anim vertex information is updated- Vector3 animVertex = { 0 };- Vector3 animNormal = { 0 };-- Vector3 inTranslation = { 0 };- Quaternion inRotation = { 0 };- // Vector3 inScale = { 0 };-- Vector3 outTranslation = { 0 };- Quaternion outRotation = { 0 };- Vector3 outScale = { 0 };-- int boneId = 0;- int boneCounter = 0;- float boneWeight = 0.0;-- const int vValues = mesh.vertexCount*3;- for (int vCounter = 0; vCounter < vValues; vCounter += 3)- {- mesh.animVertices[vCounter] = 0;- mesh.animVertices[vCounter + 1] = 0;- mesh.animVertices[vCounter + 2] = 0;-- if (mesh.animNormals != NULL)- {- mesh.animNormals[vCounter] = 0;- mesh.animNormals[vCounter + 1] = 0;- mesh.animNormals[vCounter + 2] = 0;- }-- // Iterates over 4 bones per vertex- for (int j = 0; j < 4; j++, boneCounter++)- {- boneWeight = mesh.boneWeights[boneCounter];-- // Early stop when no transformation will be applied- if (boneWeight == 0.0f) continue;-- boneId = mesh.boneIds[boneCounter];- //int boneIdParent = model.bones[boneId].parent;- inTranslation = model.bindPose[boneId].translation;- inRotation = model.bindPose[boneId].rotation;- //inScale = model.bindPose[boneId].scale;- outTranslation = anim.framePoses[frame][boneId].translation;- outRotation = anim.framePoses[frame][boneId].rotation;- outScale = anim.framePoses[frame][boneId].scale;-- // Vertices processing- // NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)- animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };- animVertex = Vector3Subtract(animVertex, inTranslation);- animVertex = Vector3Multiply(animVertex, outScale);- animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));- animVertex = Vector3Add(animVertex, outTranslation);- //animVertex = Vector3Transform(animVertex, model.transform);- mesh.animVertices[vCounter] += animVertex.x*boneWeight;- mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight;- mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight;- updated = true;-- // Normals processing- // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)- if (mesh.normals != NULL)- {- animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };- animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));- mesh.animNormals[vCounter] += animNormal.x*boneWeight;- mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;- mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;- }- }- }-- // Upload new vertex data to GPU for model drawing- // NOTE: Only update data when values changed- if (updated)- {- rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position- rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals- }- }- }-}--// Unload animation array data-void UnloadModelAnimations(ModelAnimation *animations, int animCount)-{- for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);- RL_FREE(animations);-}--// Unload animation data-void UnloadModelAnimation(ModelAnimation anim)-{- for (int i = 0; i < anim.frameCount; i++) RL_FREE(anim.framePoses[i]);-- RL_FREE(anim.bones);- RL_FREE(anim.framePoses);-}--// Check model animation skeleton match-// NOTE: Only number of bones and parent connections are checked-bool IsModelAnimationValid(Model model, ModelAnimation anim)-{- int result = true;-- if (model.boneCount != anim.boneCount) result = false;- else- {- for (int i = 0; i < model.boneCount; i++)- {- if (model.bones[i].parent != anim.bones[i].parent) { result = false; break; }- }- }-- return result;-}--#if defined(SUPPORT_MESH_GENERATION)-// Generate polygonal mesh-Mesh GenMeshPoly(int sides, float radius)-{- Mesh mesh = { 0 };-- if (sides < 3) return mesh;-- int vertexCount = sides*3;-- // Vertices definition- Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));-- float d = 0.0f, dStep = 360.0f/sides;- for (int v = 0; v < vertexCount - 2; v += 3)- {- vertices[v] = (Vector3){ 0.0f, 0.0f, 0.0f };- vertices[v + 1] = (Vector3){ sinf(DEG2RAD*d)*radius, 0.0f, cosf(DEG2RAD*d)*radius };- vertices[v + 2] = (Vector3){ sinf(DEG2RAD*(d+dStep))*radius, 0.0f, cosf(DEG2RAD*(d+dStep))*radius };- d += dStep;- }-- // Normals definition- Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));- for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;-- // TexCoords definition- Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));- for (int n = 0; n < vertexCount; n++) texcoords[n] = (Vector2){ 0.0f, 0.0f };-- mesh.vertexCount = vertexCount;- mesh.triangleCount = sides;- mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));-- // Mesh vertices position array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.vertices[3*i] = vertices[i].x;- mesh.vertices[3*i + 1] = vertices[i].y;- mesh.vertices[3*i + 2] = vertices[i].z;- }-- // Mesh texcoords array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.texcoords[2*i] = texcoords[i].x;- mesh.texcoords[2*i + 1] = texcoords[i].y;- }-- // Mesh normals array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.normals[3*i] = normals[i].x;- mesh.normals[3*i + 1] = normals[i].y;- mesh.normals[3*i + 2] = normals[i].z;- }-- RL_FREE(vertices);- RL_FREE(normals);- RL_FREE(texcoords);-- // Upload vertex data to GPU (static mesh)- // NOTE: mesh.vboId array is allocated inside UploadMesh()- UploadMesh(&mesh, false);-- return mesh;-}--// Generate plane mesh (with subdivisions)-Mesh GenMeshPlane(float width, float length, int resX, int resZ)-{- Mesh mesh = { 0 };--#define CUSTOM_MESH_GEN_PLANE-#if defined(CUSTOM_MESH_GEN_PLANE)- resX++;- resZ++;-- // Vertices definition- int vertexCount = resX*resZ; // vertices get reused for the faces-- Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));- for (int z = 0; z < resZ; z++)- {- // [-length/2, length/2]- float zPos = ((float)z/(resZ - 1) - 0.5f)*length;- for (int x = 0; x < resX; x++)- {- // [-width/2, width/2]- float xPos = ((float)x/(resX - 1) - 0.5f)*width;- vertices[x + z*resX] = (Vector3){ xPos, 0.0f, zPos };- }- }-- // Normals definition- Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));- for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;-- // TexCoords definition- Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));- for (int v = 0; v < resZ; v++)- {- for (int u = 0; u < resX; u++)- {- texcoords[u + v*resX] = (Vector2){ (float)u/(resX - 1), (float)v/(resZ - 1) };- }- }-- // Triangles definition (indices)- int numFaces = (resX - 1)*(resZ - 1);- int *triangles = (int *)RL_MALLOC(numFaces*6*sizeof(int));- int t = 0;- for (int face = 0; face < numFaces; face++)- {- // Retrieve lower left corner from face ind- int i = face + face / (resX - 1);-- triangles[t++] = i + resX;- triangles[t++] = i + 1;- triangles[t++] = i;-- triangles[t++] = i + resX;- triangles[t++] = i + resX + 1;- triangles[t++] = i + 1;- }-- mesh.vertexCount = vertexCount;- mesh.triangleCount = numFaces*2;- mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.indices = (unsigned short *)RL_MALLOC(mesh.triangleCount*3*sizeof(unsigned short));-- // Mesh vertices position array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.vertices[3*i] = vertices[i].x;- mesh.vertices[3*i + 1] = vertices[i].y;- mesh.vertices[3*i + 2] = vertices[i].z;- }-- // Mesh texcoords array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.texcoords[2*i] = texcoords[i].x;- mesh.texcoords[2*i + 1] = texcoords[i].y;- }-- // Mesh normals array- for (int i = 0; i < mesh.vertexCount; i++)- {- mesh.normals[3*i] = normals[i].x;- mesh.normals[3*i + 1] = normals[i].y;- mesh.normals[3*i + 2] = normals[i].z;- }-- // Mesh indices array initialization- for (int i = 0; i < mesh.triangleCount*3; i++) mesh.indices[i] = triangles[i];-- RL_FREE(vertices);- RL_FREE(normals);- RL_FREE(texcoords);- RL_FREE(triangles);--#else // Use par_shapes library to generate plane mesh-- par_shapes_mesh *plane = par_shapes_create_plane(resX, resZ); // No normals/texcoords generated!!!- par_shapes_scale(plane, width, length, 1.0f);- par_shapes_rotate(plane, -PI/2.0f, (float[]){ 1, 0, 0 });- par_shapes_translate(plane, -width/2, 0.0f, length/2);-- mesh.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = plane->ntriangles*3;- mesh.triangleCount = plane->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = plane->points[plane->triangles[k]*3];- mesh.vertices[k*3 + 1] = plane->points[plane->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = plane->points[plane->triangles[k]*3 + 2];-- mesh.normals[k*3] = plane->normals[plane->triangles[k]*3];- mesh.normals[k*3 + 1] = plane->normals[plane->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = plane->normals[plane->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = plane->tcoords[plane->triangles[k]*2];- mesh.texcoords[k*2 + 1] = plane->tcoords[plane->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(plane);-#endif-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);-- return mesh;-}--// Generated cuboid mesh-Mesh GenMeshCube(float width, float height, float length)-{- Mesh mesh = { 0 };--#define CUSTOM_MESH_GEN_CUBE-#if defined(CUSTOM_MESH_GEN_CUBE)- float vertices[] = {- -width/2, -height/2, length/2,- width/2, -height/2, length/2,- width/2, height/2, length/2,- -width/2, height/2, length/2,- -width/2, -height/2, -length/2,- -width/2, height/2, -length/2,- width/2, height/2, -length/2,- width/2, -height/2, -length/2,- -width/2, height/2, -length/2,- -width/2, height/2, length/2,- width/2, height/2, length/2,- width/2, height/2, -length/2,- -width/2, -height/2, -length/2,- width/2, -height/2, -length/2,- width/2, -height/2, length/2,- -width/2, -height/2, length/2,- width/2, -height/2, -length/2,- width/2, height/2, -length/2,- width/2, height/2, length/2,- width/2, -height/2, length/2,- -width/2, -height/2, -length/2,- -width/2, -height/2, length/2,- -width/2, height/2, length/2,- -width/2, height/2, -length/2- };-- float texcoords[] = {- 0.0f, 0.0f,- 1.0f, 0.0f,- 1.0f, 1.0f,- 0.0f, 1.0f,- 1.0f, 0.0f,- 1.0f, 1.0f,- 0.0f, 1.0f,- 0.0f, 0.0f,- 0.0f, 1.0f,- 0.0f, 0.0f,- 1.0f, 0.0f,- 1.0f, 1.0f,- 1.0f, 1.0f,- 0.0f, 1.0f,- 0.0f, 0.0f,- 1.0f, 0.0f,- 1.0f, 0.0f,- 1.0f, 1.0f,- 0.0f, 1.0f,- 0.0f, 0.0f,- 0.0f, 0.0f,- 1.0f, 0.0f,- 1.0f, 1.0f,- 0.0f, 1.0f- };-- float normals[] = {- 0.0f, 0.0f, 1.0f,- 0.0f, 0.0f, 1.0f,- 0.0f, 0.0f, 1.0f,- 0.0f, 0.0f, 1.0f,- 0.0f, 0.0f,-1.0f,- 0.0f, 0.0f,-1.0f,- 0.0f, 0.0f,-1.0f,- 0.0f, 0.0f,-1.0f,- 0.0f, 1.0f, 0.0f,- 0.0f, 1.0f, 0.0f,- 0.0f, 1.0f, 0.0f,- 0.0f, 1.0f, 0.0f,- 0.0f,-1.0f, 0.0f,- 0.0f,-1.0f, 0.0f,- 0.0f,-1.0f, 0.0f,- 0.0f,-1.0f, 0.0f,- 1.0f, 0.0f, 0.0f,- 1.0f, 0.0f, 0.0f,- 1.0f, 0.0f, 0.0f,- 1.0f, 0.0f, 0.0f,- -1.0f, 0.0f, 0.0f,- -1.0f, 0.0f, 0.0f,- -1.0f, 0.0f, 0.0f,- -1.0f, 0.0f, 0.0f- };-- mesh.vertices = (float *)RL_MALLOC(24*3*sizeof(float));- memcpy(mesh.vertices, vertices, 24*3*sizeof(float));-- mesh.texcoords = (float *)RL_MALLOC(24*2*sizeof(float));- memcpy(mesh.texcoords, texcoords, 24*2*sizeof(float));-- mesh.normals = (float *)RL_MALLOC(24*3*sizeof(float));- memcpy(mesh.normals, normals, 24*3*sizeof(float));-- mesh.indices = (unsigned short *)RL_MALLOC(36*sizeof(unsigned short));-- int k = 0;-- // Indices can be initialized right now- for (int i = 0; i < 36; i += 6)- {- mesh.indices[i] = 4*k;- mesh.indices[i + 1] = 4*k + 1;- mesh.indices[i + 2] = 4*k + 2;- mesh.indices[i + 3] = 4*k;- mesh.indices[i + 4] = 4*k + 2;- mesh.indices[i + 5] = 4*k + 3;-- k++;- }-- mesh.vertexCount = 24;- mesh.triangleCount = 12;--#else // Use par_shapes library to generate cube mesh-/*-// Platonic solids:-par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)-par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)-par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)-par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron-par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron-*/- // Platonic solid generation: cube (6 sides)- // NOTE: No normals/texcoords generated by default- par_shapes_mesh *cube = par_shapes_create_cube();- cube->tcoords = PAR_MALLOC(float, 2*cube->npoints);- for (int i = 0; i < 2*cube->npoints; i++) cube->tcoords[i] = 0.0f;- par_shapes_scale(cube, width, height, length);- par_shapes_translate(cube, -width/2, 0.0f, -length/2);- par_shapes_compute_normals(cube);-- mesh.vertices = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(cube->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = cube->ntriangles*3;- mesh.triangleCount = cube->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = cube->points[cube->triangles[k]*3];- mesh.vertices[k*3 + 1] = cube->points[cube->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = cube->points[cube->triangles[k]*3 + 2];-- mesh.normals[k*3] = cube->normals[cube->triangles[k]*3];- mesh.normals[k*3 + 1] = cube->normals[cube->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = cube->normals[cube->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = cube->tcoords[cube->triangles[k]*2];- mesh.texcoords[k*2 + 1] = cube->tcoords[cube->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(cube);-#endif-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);-- return mesh;-}--// Generate sphere mesh (standard sphere)-Mesh GenMeshSphere(float radius, int rings, int slices)-{- Mesh mesh = { 0 };-- if ((rings >= 3) && (slices >= 3))- {- par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);- par_shapes_scale(sphere, radius, radius, radius);- // NOTE: Soft normals are computed internally-- mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = sphere->ntriangles*3;- mesh.triangleCount = sphere->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];- mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];-- mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];- mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];- mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(sphere);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: sphere");-- return mesh;-}--// Generate hemisphere mesh (half sphere, no bottom cap)-Mesh GenMeshHemiSphere(float radius, int rings, int slices)-{- Mesh mesh = { 0 };-- if ((rings >= 3) && (slices >= 3))- {- if (radius < 0.0f) radius = 0.0f;-- par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings);- par_shapes_scale(sphere, radius, radius, radius);- // NOTE: Soft normals are computed internally-- mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = sphere->ntriangles*3;- mesh.triangleCount = sphere->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];- mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];-- mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];- mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];- mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(sphere);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: hemisphere");-- return mesh;-}--// Generate cylinder mesh-Mesh GenMeshCylinder(float radius, float height, int slices)-{- Mesh mesh = { 0 };-- if (slices >= 3)- {- // Instance a cylinder that sits on the Z=0 plane using the given tessellation- // levels across the UV domain. Think of "slices" like a number of pizza- // slices, and "stacks" like a number of stacked rings.- // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale- par_shapes_mesh *cylinder = par_shapes_create_cylinder(slices, 8);- par_shapes_scale(cylinder, radius, radius, height);- par_shapes_rotate(cylinder, -PI/2.0f, (float[]){ 1, 0, 0 });-- // Generate an orientable disk shape (top cap)- par_shapes_mesh *capTop = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, 1 });- capTop->tcoords = PAR_MALLOC(float, 2*capTop->npoints);- for (int i = 0; i < 2*capTop->npoints; i++) capTop->tcoords[i] = 0.0f;- par_shapes_rotate(capTop, -PI/2.0f, (float[]){ 1, 0, 0 });- par_shapes_rotate(capTop, 90*DEG2RAD, (float[]){ 0, 1, 0 });- par_shapes_translate(capTop, 0, height, 0);-- // Generate an orientable disk shape (bottom cap)- par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });- capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);- for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;- par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });- par_shapes_rotate(capBottom, -90*DEG2RAD, (float[]){ 0, 1, 0 });-- par_shapes_merge_and_free(cylinder, capTop);- par_shapes_merge_and_free(cylinder, capBottom);-- mesh.vertices = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(cylinder->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = cylinder->ntriangles*3;- mesh.triangleCount = cylinder->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = cylinder->points[cylinder->triangles[k]*3];- mesh.vertices[k*3 + 1] = cylinder->points[cylinder->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = cylinder->points[cylinder->triangles[k]*3 + 2];-- mesh.normals[k*3] = cylinder->normals[cylinder->triangles[k]*3];- mesh.normals[k*3 + 1] = cylinder->normals[cylinder->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = cylinder->normals[cylinder->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = cylinder->tcoords[cylinder->triangles[k]*2];- mesh.texcoords[k*2 + 1] = cylinder->tcoords[cylinder->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(cylinder);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cylinder");-- return mesh;-}--// Generate cone/pyramid mesh-Mesh GenMeshCone(float radius, float height, int slices)-{- Mesh mesh = { 0 };-- if (slices >= 3)- {- // Instance a cone that sits on the Z=0 plane using the given tessellation- // levels across the UV domain. Think of "slices" like a number of pizza- // slices, and "stacks" like a number of stacked rings.- // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale- par_shapes_mesh *cone = par_shapes_create_cone(slices, 8);- par_shapes_scale(cone, radius, radius, height);- par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 });- par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 });-- // Generate an orientable disk shape (bottom cap)- par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });- capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);- for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;- par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });-- par_shapes_merge_and_free(cone, capBottom);-- mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = cone->ntriangles*3;- mesh.triangleCount = cone->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = cone->points[cone->triangles[k]*3];- mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2];-- mesh.normals[k*3] = cone->normals[cone->triangles[k]*3];- mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2];- mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(cone);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone");-- return mesh;-}--// Generate torus mesh-Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)-{- Mesh mesh = { 0 };-- if ((sides >= 3) && (radSeg >= 3))- {- if (radius > 1.0f) radius = 1.0f;- else if (radius < 0.1f) radius = 0.1f;-- // Create a donut that sits on the Z=0 plane with the specified inner radius- // The outer radius can be controlled with par_shapes_scale- par_shapes_mesh *torus = par_shapes_create_torus(radSeg, sides, radius);- par_shapes_scale(torus, size/2, size/2, size/2);-- mesh.vertices = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(torus->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = torus->ntriangles*3;- mesh.triangleCount = torus->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = torus->points[torus->triangles[k]*3];- mesh.vertices[k*3 + 1] = torus->points[torus->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = torus->points[torus->triangles[k]*3 + 2];-- mesh.normals[k*3] = torus->normals[torus->triangles[k]*3];- mesh.normals[k*3 + 1] = torus->normals[torus->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = torus->normals[torus->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = torus->tcoords[torus->triangles[k]*2];- mesh.texcoords[k*2 + 1] = torus->tcoords[torus->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(torus);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: torus");-- return mesh;-}--// Generate trefoil knot mesh-Mesh GenMeshKnot(float radius, float size, int radSeg, int sides)-{- Mesh mesh = { 0 };-- if ((sides >= 3) && (radSeg >= 3))- {- if (radius > 3.0f) radius = 3.0f;- else if (radius < 0.5f) radius = 0.5f;-- par_shapes_mesh *knot = par_shapes_create_trefoil_knot(radSeg, sides, radius);- par_shapes_scale(knot, size, size, size);-- mesh.vertices = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(knot->ntriangles*3*2*sizeof(float));- mesh.normals = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));-- mesh.vertexCount = knot->ntriangles*3;- mesh.triangleCount = knot->ntriangles;-- for (int k = 0; k < mesh.vertexCount; k++)- {- mesh.vertices[k*3] = knot->points[knot->triangles[k]*3];- mesh.vertices[k*3 + 1] = knot->points[knot->triangles[k]*3 + 1];- mesh.vertices[k*3 + 2] = knot->points[knot->triangles[k]*3 + 2];-- mesh.normals[k*3] = knot->normals[knot->triangles[k]*3];- mesh.normals[k*3 + 1] = knot->normals[knot->triangles[k]*3 + 1];- mesh.normals[k*3 + 2] = knot->normals[knot->triangles[k]*3 + 2];-- mesh.texcoords[k*2] = knot->tcoords[knot->triangles[k]*2];- mesh.texcoords[k*2 + 1] = knot->tcoords[knot->triangles[k]*2 + 1];- }-- par_shapes_free_mesh(knot);-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);- }- else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: knot");-- return mesh;-}--// Generate a mesh from heightmap-// NOTE: Vertex data is uploaded to GPU-Mesh GenMeshHeightmap(Image heightmap, Vector3 size)-{- #define GRAY_VALUE(c) ((float)(c.r + c.g + c.b)/3.0f)-- Mesh mesh = { 0 };-- int mapX = heightmap.width;- int mapZ = heightmap.height;-- Color *pixels = LoadImageColors(heightmap);-- // NOTE: One vertex per pixel- mesh.triangleCount = (mapX - 1)*(mapZ - 1)*2; // One quad every four pixels-- mesh.vertexCount = mesh.triangleCount*3;-- mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));- mesh.colors = NULL;-- int vCounter = 0; // Used to count vertices float by float- int tcCounter = 0; // Used to count texcoords float by float- int nCounter = 0; // Used to count normals float by float-- Vector3 scaleFactor = { size.x/(mapX - 1), size.y/255.0f, size.z/(mapZ - 1) };-- Vector3 vA = { 0 };- Vector3 vB = { 0 };- Vector3 vC = { 0 };- Vector3 vN = { 0 };-- for (int z = 0; z < mapZ-1; z++)- {- for (int x = 0; x < mapX-1; x++)- {- // Fill vertices array with data- //------------------------------------------------------------ // one triangle - 3 vertex- mesh.vertices[vCounter] = (float)x*scaleFactor.x;- mesh.vertices[vCounter + 1] = GRAY_VALUE(pixels[x + z*mapX])*scaleFactor.y;- mesh.vertices[vCounter + 2] = (float)z*scaleFactor.z;-- mesh.vertices[vCounter + 3] = (float)x*scaleFactor.x;- mesh.vertices[vCounter + 4] = GRAY_VALUE(pixels[x + (z + 1)*mapX])*scaleFactor.y;- mesh.vertices[vCounter + 5] = (float)(z + 1)*scaleFactor.z;-- mesh.vertices[vCounter + 6] = (float)(x + 1)*scaleFactor.x;- mesh.vertices[vCounter + 7] = GRAY_VALUE(pixels[(x + 1) + z*mapX])*scaleFactor.y;- mesh.vertices[vCounter + 8] = (float)z*scaleFactor.z;-- // Another triangle - 3 vertex- mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6];- mesh.vertices[vCounter + 10] = mesh.vertices[vCounter + 7];- mesh.vertices[vCounter + 11] = mesh.vertices[vCounter + 8];-- mesh.vertices[vCounter + 12] = mesh.vertices[vCounter + 3];- mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4];- mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5];-- mesh.vertices[vCounter + 15] = (float)(x + 1)*scaleFactor.x;- mesh.vertices[vCounter + 16] = GRAY_VALUE(pixels[(x + 1) + (z + 1)*mapX])*scaleFactor.y;- mesh.vertices[vCounter + 17] = (float)(z + 1)*scaleFactor.z;- vCounter += 18; // 6 vertex, 18 floats-- // Fill texcoords array with data- //--------------------------------------------------------------- mesh.texcoords[tcCounter] = (float)x/(mapX - 1);- mesh.texcoords[tcCounter + 1] = (float)z/(mapZ - 1);-- mesh.texcoords[tcCounter + 2] = (float)x/(mapX - 1);- mesh.texcoords[tcCounter + 3] = (float)(z + 1)/(mapZ - 1);-- mesh.texcoords[tcCounter + 4] = (float)(x + 1)/(mapX - 1);- mesh.texcoords[tcCounter + 5] = (float)z/(mapZ - 1);-- mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4];- mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5];-- mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2];- mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3];-- mesh.texcoords[tcCounter + 10] = (float)(x + 1)/(mapX - 1);- mesh.texcoords[tcCounter + 11] = (float)(z + 1)/(mapZ - 1);- tcCounter += 12; // 6 texcoords, 12 floats-- // Fill normals array with data- //--------------------------------------------------------------- for (int i = 0; i < 18; i += 9)- {- vA.x = mesh.vertices[nCounter + i];- vA.y = mesh.vertices[nCounter + i + 1];- vA.z = mesh.vertices[nCounter + i + 2];-- vB.x = mesh.vertices[nCounter + i + 3];- vB.y = mesh.vertices[nCounter + i + 4];- vB.z = mesh.vertices[nCounter + i + 5];-- vC.x = mesh.vertices[nCounter + i + 6];- vC.y = mesh.vertices[nCounter + i + 7];- vC.z = mesh.vertices[nCounter + i + 8];-- vN = Vector3Normalize(Vector3CrossProduct(Vector3Subtract(vB, vA), Vector3Subtract(vC, vA)));-- mesh.normals[nCounter + i] = vN.x;- mesh.normals[nCounter + i + 1] = vN.y;- mesh.normals[nCounter + i + 2] = vN.z;-- mesh.normals[nCounter + i + 3] = vN.x;- mesh.normals[nCounter + i + 4] = vN.y;- mesh.normals[nCounter + i + 5] = vN.z;-- mesh.normals[nCounter + i + 6] = vN.x;- mesh.normals[nCounter + i + 7] = vN.y;- mesh.normals[nCounter + i + 8] = vN.z;- }-- nCounter += 18; // 6 vertex, 18 floats- }- }-- UnloadImageColors(pixels); // Unload pixels color data-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);-- return mesh;-}--// Generate a cubes mesh from pixel data-// NOTE: Vertex data is uploaded to GPU-Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)-{- #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))-- Mesh mesh = { 0 };-- Color *pixels = LoadImageColors(cubicmap);-- // NOTE: Max possible number of triangles numCubes*(12 triangles by cube)- int maxTriangles = cubicmap.width * cubicmap.height * 12;-- int vCounter = 0; // Used to count vertices- int tcCounter = 0; // Used to count texcoords- int nCounter = 0; // Used to count normals-- float w = cubeSize.x;- float h = cubeSize.z;- float h2 = cubeSize.y;-- Vector3 *mapVertices = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));- Vector2 *mapTexcoords = (Vector2 *)RL_MALLOC(maxTriangles*3*sizeof(Vector2));- Vector3 *mapNormals = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));-- // Define the 6 normals of the cube, we will combine them accordingly later...- Vector3 n1 = { 1.0f, 0.0f, 0.0f };- Vector3 n2 = { -1.0f, 0.0f, 0.0f };- Vector3 n3 = { 0.0f, 1.0f, 0.0f };- Vector3 n4 = { 0.0f, -1.0f, 0.0f };- Vector3 n5 = { 0.0f, 0.0f, -1.0f };- Vector3 n6 = { 0.0f, 0.0f, 1.0f };-- // NOTE: We use texture rectangles to define different textures for top-bottom-front-back-right-left (6)- typedef struct RectangleF {- float x;- float y;- float width;- float height;- } RectangleF;-- RectangleF rightTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };- RectangleF leftTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };- RectangleF frontTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };- RectangleF backTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };- RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };- RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };-- for (int z = 0; z < cubicmap.height; ++z)- {- for (int x = 0; x < cubicmap.width; ++x)- {- // Define the 8 vertex of the cube, we will combine them accordingly later...- Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };- Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) };- Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) };- Vector3 v4 = { w*(x + 0.5f), h2, h*(z - 0.5f) };- Vector3 v5 = { w*(x + 0.5f), 0, h*(z - 0.5f) };- Vector3 v6 = { w*(x - 0.5f), 0, h*(z - 0.5f) };- Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) };- Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) };-- // We check pixel color to be WHITE -> draw full cube- if (COLOR_EQUAL(pixels[z*cubicmap.width + x], WHITE))- {- // Define triangles and checking collateral cubes- //-------------------------------------------------- // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)- // WARNING: Not required for a WHITE cubes, created to allow seeing the map from outside- mapVertices[vCounter] = v1;- mapVertices[vCounter + 1] = v2;- mapVertices[vCounter + 2] = v3;- mapVertices[vCounter + 3] = v1;- mapVertices[vCounter + 4] = v3;- mapVertices[vCounter + 5] = v4;- vCounter += 6;-- mapNormals[nCounter] = n3;- mapNormals[nCounter + 1] = n3;- mapNormals[nCounter + 2] = n3;- mapNormals[nCounter + 3] = n3;- mapNormals[nCounter + 4] = n3;- mapNormals[nCounter + 5] = n3;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };- mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };- mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };- tcCounter += 6;-- // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)- mapVertices[vCounter] = v6;- mapVertices[vCounter + 1] = v8;- mapVertices[vCounter + 2] = v7;- mapVertices[vCounter + 3] = v6;- mapVertices[vCounter + 4] = v5;- mapVertices[vCounter + 5] = v8;- vCounter += 6;-- mapNormals[nCounter] = n4;- mapNormals[nCounter + 1] = n4;- mapNormals[nCounter + 2] = n4;- mapNormals[nCounter + 3] = n4;- mapNormals[nCounter + 4] = n4;- mapNormals[nCounter + 5] = n4;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };- mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y };- mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };- tcCounter += 6;-- // Checking cube on bottom of current cube- if (((z < cubicmap.height - 1) && COLOR_EQUAL(pixels[(z + 1)*cubicmap.width + x], BLACK)) || (z == cubicmap.height - 1))- {- // Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8- // NOTE: Collateral occluded faces are not generated- mapVertices[vCounter] = v2;- mapVertices[vCounter + 1] = v7;- mapVertices[vCounter + 2] = v3;- mapVertices[vCounter + 3] = v3;- mapVertices[vCounter + 4] = v7;- mapVertices[vCounter + 5] = v8;- vCounter += 6;-- mapNormals[nCounter] = n6;- mapNormals[nCounter + 1] = n6;- mapNormals[nCounter + 2] = n6;- mapNormals[nCounter + 3] = n6;- mapNormals[nCounter + 4] = n6;- mapNormals[nCounter + 5] = n6;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ frontTexUV.x, frontTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };- mapTexcoords[tcCounter + 3] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };- mapTexcoords[tcCounter + 5] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y + frontTexUV.height };- tcCounter += 6;- }-- // Checking cube on top of current cube- if (((z > 0) && COLOR_EQUAL(pixels[(z - 1)*cubicmap.width + x], BLACK)) || (z == 0))- {- // Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5- // NOTE: Collateral occluded faces are not generated- mapVertices[vCounter] = v1;- mapVertices[vCounter + 1] = v5;- mapVertices[vCounter + 2] = v6;- mapVertices[vCounter + 3] = v1;- mapVertices[vCounter + 4] = v4;- mapVertices[vCounter + 5] = v5;- vCounter += 6;-- mapNormals[nCounter] = n5;- mapNormals[nCounter + 1] = n5;- mapNormals[nCounter + 2] = n5;- mapNormals[nCounter + 3] = n5;- mapNormals[nCounter + 4] = n5;- mapNormals[nCounter + 5] = n5;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y + backTexUV.height };- mapTexcoords[tcCounter + 3] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ backTexUV.x, backTexUV.y };- mapTexcoords[tcCounter + 5] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };- tcCounter += 6;- }-- // Checking cube on right of current cube- if (((x < cubicmap.width - 1) && COLOR_EQUAL(pixels[z*cubicmap.width + (x + 1)], BLACK)) || (x == cubicmap.width - 1))- {- // Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5- // NOTE: Collateral occluded faces are not generated- mapVertices[vCounter] = v3;- mapVertices[vCounter + 1] = v8;- mapVertices[vCounter + 2] = v4;- mapVertices[vCounter + 3] = v4;- mapVertices[vCounter + 4] = v8;- mapVertices[vCounter + 5] = v5;- vCounter += 6;-- mapNormals[nCounter] = n1;- mapNormals[nCounter + 1] = n1;- mapNormals[nCounter + 2] = n1;- mapNormals[nCounter + 3] = n1;- mapNormals[nCounter + 4] = n1;- mapNormals[nCounter + 5] = n1;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ rightTexUV.x, rightTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };- mapTexcoords[tcCounter + 3] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };- mapTexcoords[tcCounter + 5] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y + rightTexUV.height };- tcCounter += 6;- }-- // Checking cube on left of current cube- if (((x > 0) && COLOR_EQUAL(pixels[z*cubicmap.width + (x - 1)], BLACK)) || (x == 0))- {- // Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7- // NOTE: Collateral occluded faces are not generated- mapVertices[vCounter] = v1;- mapVertices[vCounter + 1] = v7;- mapVertices[vCounter + 2] = v2;- mapVertices[vCounter + 3] = v1;- mapVertices[vCounter + 4] = v6;- mapVertices[vCounter + 5] = v7;- vCounter += 6;-- mapNormals[nCounter] = n2;- mapNormals[nCounter + 1] = n2;- mapNormals[nCounter + 2] = n2;- mapNormals[nCounter + 3] = n2;- mapNormals[nCounter + 4] = n2;- mapNormals[nCounter + 5] = n2;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ leftTexUV.x, leftTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y };- mapTexcoords[tcCounter + 3] = (Vector2){ leftTexUV.x, leftTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ leftTexUV.x, leftTexUV.y + leftTexUV.height };- mapTexcoords[tcCounter + 5] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };- tcCounter += 6;- }- }- // We check pixel color to be BLACK, we will only draw floor and roof- else if (COLOR_EQUAL(pixels[z*cubicmap.width + x], BLACK))- {- // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)- mapVertices[vCounter] = v1;- mapVertices[vCounter + 1] = v3;- mapVertices[vCounter + 2] = v2;- mapVertices[vCounter + 3] = v1;- mapVertices[vCounter + 4] = v4;- mapVertices[vCounter + 5] = v3;- vCounter += 6;-- mapNormals[nCounter] = n4;- mapNormals[nCounter + 1] = n4;- mapNormals[nCounter + 2] = n4;- mapNormals[nCounter + 3] = n4;- mapNormals[nCounter + 4] = n4;- mapNormals[nCounter + 5] = n4;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };- mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };- mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };- tcCounter += 6;-- // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)- mapVertices[vCounter] = v6;- mapVertices[vCounter + 1] = v7;- mapVertices[vCounter + 2] = v8;- mapVertices[vCounter + 3] = v6;- mapVertices[vCounter + 4] = v8;- mapVertices[vCounter + 5] = v5;- vCounter += 6;-- mapNormals[nCounter] = n3;- mapNormals[nCounter + 1] = n3;- mapNormals[nCounter + 2] = n3;- mapNormals[nCounter + 3] = n3;- mapNormals[nCounter + 4] = n3;- mapNormals[nCounter + 5] = n3;- nCounter += 6;-- mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };- mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };- mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };- mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };- mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };- mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y };- tcCounter += 6;- }- }- }-- // Move data from mapVertices temp arrays to vertices float array- mesh.vertexCount = vCounter;- mesh.triangleCount = vCounter/3;-- mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));- mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));- mesh.colors = NULL;-- int fCounter = 0;-- // Move vertices data- for (int i = 0; i < vCounter; i++)- {- mesh.vertices[fCounter] = mapVertices[i].x;- mesh.vertices[fCounter + 1] = mapVertices[i].y;- mesh.vertices[fCounter + 2] = mapVertices[i].z;- fCounter += 3;- }-- fCounter = 0;-- // Move normals data- for (int i = 0; i < nCounter; i++)- {- mesh.normals[fCounter] = mapNormals[i].x;- mesh.normals[fCounter + 1] = mapNormals[i].y;- mesh.normals[fCounter + 2] = mapNormals[i].z;- fCounter += 3;- }-- fCounter = 0;-- // Move texcoords data- for (int i = 0; i < tcCounter; i++)- {- mesh.texcoords[fCounter] = mapTexcoords[i].x;- mesh.texcoords[fCounter + 1] = mapTexcoords[i].y;- fCounter += 2;- }-- RL_FREE(mapVertices);- RL_FREE(mapNormals);- RL_FREE(mapTexcoords);-- UnloadImageColors(pixels); // Unload pixels color data-- // Upload vertex data to GPU (static mesh)- UploadMesh(&mesh, false);-- return mesh;-}-#endif // SUPPORT_MESH_GENERATION--// Compute mesh bounding box limits-// NOTE: minVertex and maxVertex should be transformed by model transform matrix-BoundingBox GetMeshBoundingBox(Mesh mesh)-{- // Get min and max vertex to construct bounds (AABB)- Vector3 minVertex = { 0 };- Vector3 maxVertex = { 0 };-- if (mesh.vertices != NULL)- {- minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };- maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };-- for (int i = 1; i < mesh.vertexCount; i++)- {- minVertex = Vector3Min(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });- maxVertex = Vector3Max(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });- }- }-- // Create the bounding box- BoundingBox box = { 0 };- box.min = minVertex;- box.max = maxVertex;-- return box;-}--// Compute mesh tangents-// NOTE: To calculate mesh tangents and binormals we need mesh vertex positions and texture coordinates-// Implementation based on: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html-void GenMeshTangents(Mesh *mesh)-{- if ((mesh->vertices == NULL) || (mesh->texcoords == NULL))- {- TRACELOG(LOG_WARNING, "MESH: Tangents generation requires texcoord vertex attribute data");- return;- }-- if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));- else- {- RL_FREE(mesh->tangents);- mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));- }-- Vector3 *tan1 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));- Vector3 *tan2 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));-- for (int i = 0; i < mesh->vertexCount; i += 3)- {- // Get triangle vertices- Vector3 v1 = { mesh->vertices[(i + 0)*3 + 0], mesh->vertices[(i + 0)*3 + 1], mesh->vertices[(i + 0)*3 + 2] };- Vector3 v2 = { mesh->vertices[(i + 1)*3 + 0], mesh->vertices[(i + 1)*3 + 1], mesh->vertices[(i + 1)*3 + 2] };- Vector3 v3 = { mesh->vertices[(i + 2)*3 + 0], mesh->vertices[(i + 2)*3 + 1], mesh->vertices[(i + 2)*3 + 2] };-- // Get triangle texcoords- Vector2 uv1 = { mesh->texcoords[(i + 0)*2 + 0], mesh->texcoords[(i + 0)*2 + 1] };- Vector2 uv2 = { mesh->texcoords[(i + 1)*2 + 0], mesh->texcoords[(i + 1)*2 + 1] };- Vector2 uv3 = { mesh->texcoords[(i + 2)*2 + 0], mesh->texcoords[(i + 2)*2 + 1] };-- float x1 = v2.x - v1.x;- float y1 = v2.y - v1.y;- float z1 = v2.z - v1.z;- float x2 = v3.x - v1.x;- float y2 = v3.y - v1.y;- float z2 = v3.z - v1.z;-- float s1 = uv2.x - uv1.x;- float t1 = uv2.y - uv1.y;- float s2 = uv3.x - uv1.x;- float t2 = uv3.y - uv1.y;-- float div = s1*t2 - s2*t1;- float r = (div == 0.0f)? 0.0f : 1.0f/div;-- Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };- Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };-- tan1[i + 0] = sdir;- tan1[i + 1] = sdir;- tan1[i + 2] = sdir;-- tan2[i + 0] = tdir;- tan2[i + 1] = tdir;- tan2[i + 2] = tdir;- }-- // Compute tangents considering normals- for (int i = 0; i < mesh->vertexCount; i++)- {- Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };- Vector3 tangent = tan1[i];-- // TODO: Review, not sure if tangent computation is right, just used reference proposed maths...-#if defined(COMPUTE_TANGENTS_METHOD_01)- Vector3 tmp = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));- tmp = Vector3Normalize(tmp);- mesh->tangents[i*4 + 0] = tmp.x;- mesh->tangents[i*4 + 1] = tmp.y;- mesh->tangents[i*4 + 2] = tmp.z;- mesh->tangents[i*4 + 3] = 1.0f;-#else- Vector3OrthoNormalize(&normal, &tangent);- mesh->tangents[i*4 + 0] = tangent.x;- mesh->tangents[i*4 + 1] = tangent.y;- mesh->tangents[i*4 + 2] = tangent.z;- mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f)? -1.0f : 1.0f;-#endif- }-- RL_FREE(tan1);- RL_FREE(tan2);-- if (mesh->vboId != NULL)- {- if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)- {- // Update existing vertex buffer- rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);- }- else- {- // Load a new tangent attributes buffer- mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);- }-- rlEnableVertexArray(mesh->vaoId);- rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0);- rlEnableVertexAttribute(4);- rlDisableVertexArray();- }-- TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh");-}--// Draw a model (with texture if set)-void DrawModel(Model model, Vector3 position, float scale, Color tint)-{- Vector3 vScale = { scale, scale, scale };- Vector3 rotationAxis = { 0.0f, 1.0f, 0.0f };-- DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint);-}--// Draw a model with extended parameters-void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)-{- // Calculate transformation matrix from function parameters- // Get transform matrix (rotation -> scale -> translation)- Matrix matScale = MatrixScale(scale.x, scale.y, scale.z);- Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD);- Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z);-- Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);-- // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform)- model.transform = MatrixMultiply(model.transform, matTransform);-- for (int i = 0; i < model.meshCount; i++)- {- Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color;-- Color colorTint = WHITE;- colorTint.r = (unsigned char)((((float)color.r/255.0f)*((float)tint.r/255.0f))*255.0f);- colorTint.g = (unsigned char)((((float)color.g/255.0f)*((float)tint.g/255.0f))*255.0f);- colorTint.b = (unsigned char)((((float)color.b/255.0f)*((float)tint.b/255.0f))*255.0f);- colorTint.a = (unsigned char)((((float)color.a/255.0f)*((float)tint.a/255.0f))*255.0f);-- model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;- DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform);- model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color;- }-}--// Draw a model wires (with texture if set)-void DrawModelWires(Model model, Vector3 position, float scale, Color tint)-{- rlEnableWireMode();-- DrawModel(model, position, scale, tint);-- rlDisableWireMode();-}--// Draw a model wires (with texture if set) with extended parameters-void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)-{- rlEnableWireMode();-- DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);-- rlDisableWireMode();-}--// Draw a billboard-void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint)-{- Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };-- DrawBillboardRec(camera, texture, source, position, (Vector2){ size, size }, tint);-}--// Draw a billboard (part of a texture defined by a rectangle)-void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint)-{- // NOTE: Billboard locked on axis-Y- Vector3 up = { 0.0f, 1.0f, 0.0f };-- DrawBillboardPro(camera, texture, source, position, up, size, Vector2Zero(), 0.0f, tint);-}--void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)-{- // NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width- Vector2 sizeRatio = { size.x*fabsf((float)source.width/source.height), size.y };-- Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);-- Vector3 right = { matView.m0, matView.m4, matView.m8 };- //Vector3 up = { matView.m1, matView.m5, matView.m9 };-- Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2);- Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2);-- Vector3 p1 = Vector3Add(rightScaled, upScaled);- Vector3 p2 = Vector3Subtract(rightScaled, upScaled);-- Vector3 topLeft = Vector3Scale(p2, -1);- Vector3 topRight = p1;- Vector3 bottomRight = p2;- Vector3 bottomLeft = Vector3Scale(p1, -1);-- if (rotation != 0.0f)- {- float sinRotation = sinf(rotation*DEG2RAD);- float cosRotation = cosf(rotation*DEG2RAD);-- // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture- float rotateAboutX = sizeRatio.x*origin.x/2;- float rotateAboutY = sizeRatio.y*origin.y/2;-- float xtvalue, ytvalue;- float rotatedX, rotatedY;-- xtvalue = Vector3DotProduct(right, topLeft) - rotateAboutX; // Project points to x and y coordinates on the billboard plane- ytvalue = Vector3DotProduct(up, topLeft) - rotateAboutY;- rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; // Rotate about the point origin- rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY;- topLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); // Translate back to cartesian coordinates-- xtvalue = Vector3DotProduct(right, topRight) - rotateAboutX;- ytvalue = Vector3DotProduct(up, topRight) - rotateAboutY;- rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX;- rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY;- topRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX));-- xtvalue = Vector3DotProduct(right, bottomRight) - rotateAboutX;- ytvalue = Vector3DotProduct(up, bottomRight) - rotateAboutY;- rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX;- rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY;- bottomRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX));-- xtvalue = Vector3DotProduct(right, bottomLeft)-rotateAboutX;- ytvalue = Vector3DotProduct(up, bottomLeft)-rotateAboutY;- rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX;- rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY;- bottomLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX));- }-- // Translate points to the draw center (position)- topLeft = Vector3Add(topLeft, position);- topRight = Vector3Add(topRight, position);- bottomRight = Vector3Add(bottomRight, position);- bottomLeft = Vector3Add(bottomLeft, position);-- rlSetTexture(texture.id);-- rlBegin(RL_QUADS);- rlColor4ub(tint.r, tint.g, tint.b, tint.a);-- if (sizeRatio.x * sizeRatio.y >= 0.0f)- {- // Bottom-left corner for texture and quad- rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);- rlVertex3f(topLeft.x, topLeft.y, topLeft.z);-- // Top-left corner for texture and quad- rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height);- rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z);-- // Top-right corner for texture and quad- rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height);- rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z);-- // Bottom-right corner for texture and quad- rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height);- rlVertex3f(topRight.x, topRight.y, topRight.z);- }- else- {- // Reverse vertex order if the size has only one negative dimension- rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height);- rlVertex3f(topRight.x, topRight.y, topRight.z);-- rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height);- rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z);-- rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height);- rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z);-- rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);- rlVertex3f(topLeft.x, topLeft.y, topLeft.z);- }-- rlEnd();-- rlSetTexture(0);-}--// Draw a bounding box with wires-void DrawBoundingBox(BoundingBox box, Color color)-{- Vector3 size = { 0 };-- size.x = fabsf(box.max.x - box.min.x);- size.y = fabsf(box.max.y - box.min.y);- size.z = fabsf(box.max.z - box.min.z);-- Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };-- DrawCubeWires(center, size.x, size.y, size.z, color);-}--// Check collision between two spheres-bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2)-{- bool collision = false;-- // Simple way to check for collision, just checking distance between two points- // Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution- /*- float dx = center1.x - center2.x; // X distance between centers- float dy = center1.y - center2.y; // Y distance between centers- float dz = center1.z - center2.z; // Z distance between centers-- float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers-- if (distance <= (radius1 + radius2)) collision = true;- */-- // Check for distances squared to avoid sqrtf()- if (Vector3DotProduct(Vector3Subtract(center2, center1), Vector3Subtract(center2, center1)) <= (radius1 + radius2)*(radius1 + radius2)) collision = true;-- return collision;-}--// Check collision between two boxes-// NOTE: Boxes are defined by two points minimum and maximum-bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2)-{- bool collision = true;-- if ((box1.max.x >= box2.min.x) && (box1.min.x <= box2.max.x))- {- if ((box1.max.y < box2.min.y) || (box1.min.y > box2.max.y)) collision = false;- if ((box1.max.z < box2.min.z) || (box1.min.z > box2.max.z)) collision = false;- }- else collision = false;-- return collision;-}--// Check collision between box and sphere-bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)-{- bool collision = false;-- float dmin = 0;-- if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2);- else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);-- if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);- else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);-- if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);- else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);-- if (dmin <= (radius*radius)) collision = true;-- return collision;-}--// Get collision info between ray and sphere-RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius)-{- RayCollision collision = { 0 };-- Vector3 raySpherePos = Vector3Subtract(center, ray.position);- float vector = Vector3DotProduct(raySpherePos, ray.direction);- float distance = Vector3Length(raySpherePos);- float d = radius*radius - (distance*distance - vector*vector);-- collision.hit = d >= 0.0f;-- // Check if ray origin is inside the sphere to calculate the correct collision point- if (distance < radius)- {- collision.distance = vector + sqrtf(d);-- // Calculate collision point- collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));-- // Calculate collision normal (pointing outwards)- collision.normal = Vector3Negate(Vector3Normalize(Vector3Subtract(collision.point, center)));- }- else- {- collision.distance = vector - sqrtf(d);-- // Calculate collision point- collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));-- // Calculate collision normal (pointing inwards)- collision.normal = Vector3Normalize(Vector3Subtract(collision.point, center));- }-- return collision;-}--// Get collision info between ray and box-RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)-{- RayCollision collision = { 0 };-- // Note: If ray.position is inside the box, the distance is negative (as if the ray was reversed)- // Reversing ray.direction will give use the correct result.- bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&- (ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&- (ray.position.z > box.min.z) && (ray.position.z < box.max.z);-- if (insideBox) ray.direction = Vector3Negate(ray.direction);-- float t[11] = { 0 };-- t[8] = 1.0f/ray.direction.x;- t[9] = 1.0f/ray.direction.y;- t[10] = 1.0f/ray.direction.z;-- t[0] = (box.min.x - ray.position.x)*t[8];- t[1] = (box.max.x - ray.position.x)*t[8];- t[2] = (box.min.y - ray.position.y)*t[9];- t[3] = (box.max.y - ray.position.y)*t[9];- t[4] = (box.min.z - ray.position.z)*t[10];- t[5] = (box.max.z - ray.position.z)*t[10];- t[6] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));- t[7] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));-- collision.hit = !((t[7] < 0) || (t[6] > t[7]));- collision.distance = t[6];- collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));-- // Get box center point- collision.normal = Vector3Lerp(box.min, box.max, 0.5f);- // Get vector center point->hit point- collision.normal = Vector3Subtract(collision.point, collision.normal);- // Scale vector to unit cube- // NOTE: We use an additional .01 to fix numerical errors- collision.normal = Vector3Scale(collision.normal, 2.01f);- collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));- // The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f)- // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal!- collision.normal.x = (float)((int)collision.normal.x);- collision.normal.y = (float)((int)collision.normal.y);- collision.normal.z = (float)((int)collision.normal.z);-- collision.normal = Vector3Normalize(collision.normal);-- if (insideBox)- {- // Reset ray.direction- ray.direction = Vector3Negate(ray.direction);- // Fix result- collision.distance *= -1.0f;- collision.normal = Vector3Negate(collision.normal);- }-- return collision;-}--// Get collision info between ray and mesh-RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)-{- RayCollision collision = { 0 };-- // Check if mesh vertex data on CPU for testing- if (mesh.vertices != NULL)- {- int triangleCount = mesh.triangleCount;-- // Test against all triangles in mesh- for (int i = 0; i < triangleCount; i++)- {- Vector3 a, b, c;- Vector3* vertdata = (Vector3*)mesh.vertices;-- if (mesh.indices)- {- a = vertdata[mesh.indices[i*3 + 0]];- b = vertdata[mesh.indices[i*3 + 1]];- c = vertdata[mesh.indices[i*3 + 2]];- }- else- {- a = vertdata[i*3 + 0];- b = vertdata[i*3 + 1];- c = vertdata[i*3 + 2];- }-- a = Vector3Transform(a, transform);- b = Vector3Transform(b, transform);- c = Vector3Transform(c, transform);-- RayCollision triHitInfo = GetRayCollisionTriangle(ray, a, b, c);-- if (triHitInfo.hit)- {- // Save the closest hit triangle- if ((!collision.hit) || (collision.distance > triHitInfo.distance)) collision = triHitInfo;- }- }- }-- return collision;-}--// Get collision info between ray and triangle-// NOTE: The points are expected to be in counter-clockwise winding-// NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm-RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3)-{- #define EPSILON 0.000001f // A small number-- RayCollision collision = { 0 };- Vector3 edge1 = { 0 };- Vector3 edge2 = { 0 };- Vector3 p, q, tv;- float det, invDet, u, v, t;-- // Find vectors for two edges sharing V1- edge1 = Vector3Subtract(p2, p1);- edge2 = Vector3Subtract(p3, p1);-- // Begin calculating determinant - also used to calculate u parameter- p = Vector3CrossProduct(ray.direction, edge2);-- // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle- det = Vector3DotProduct(edge1, p);-- // Avoid culling!- if ((det > -EPSILON) && (det < EPSILON)) return collision;-- invDet = 1.0f/det;-- // Calculate distance from V1 to ray origin- tv = Vector3Subtract(ray.position, p1);-- // Calculate u parameter and test bound- u = Vector3DotProduct(tv, p)*invDet;-- // The intersection lies outside the triangle- if ((u < 0.0f) || (u > 1.0f)) return collision;-- // Prepare to test v parameter- q = Vector3CrossProduct(tv, edge1);-- // Calculate V parameter and test bound- v = Vector3DotProduct(ray.direction, q)*invDet;-- // The intersection lies outside the triangle- if ((v < 0.0f) || ((u + v) > 1.0f)) return collision;-- t = Vector3DotProduct(edge2, q)*invDet;-- if (t > EPSILON)- {- // Ray hit, get hit point and normal- collision.hit = true;- collision.distance = t;- collision.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2));- collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, t));- }-- return collision;-}--// Get collision info between ray and quad-// NOTE: The points are expected to be in counter-clockwise winding-RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)-{- RayCollision collision = { 0 };-- collision = GetRayCollisionTriangle(ray, p1, p2, p4);-- if (!collision.hit) collision = GetRayCollisionTriangle(ray, p2, p3, p4);-- return collision;-}--//-----------------------------------------------------------------------------------// Module specific Functions Definition-//-----------------------------------------------------------------------------------#if defined(SUPPORT_FILEFORMAT_IQM) || defined(SUPPORT_FILEFORMAT_GLTF)-// Build pose from parent joints-// NOTE: Required for animations loading (required by IQM and GLTF)-static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform *transforms)-{- for (int i = 0; i < boneCount; i++)- {- if (bones[i].parent >= 0)- {- if (bones[i].parent > i)- {- TRACELOG(LOG_WARNING, "Assumes bones are toplogically sorted, but bone %d has parent %d. Skipping.", i, bones[i].parent);- continue;- }- transforms[i].rotation = QuaternionMultiply(transforms[bones[i].parent].rotation, transforms[i].rotation);- transforms[i].translation = Vector3RotateByQuaternion(transforms[i].translation, transforms[bones[i].parent].rotation);- transforms[i].translation = Vector3Add(transforms[i].translation, transforms[bones[i].parent].translation);- transforms[i].scale = Vector3Multiply(transforms[i].scale, transforms[bones[i].parent].scale);- }- }-}-#endif--#if defined(SUPPORT_FILEFORMAT_OBJ)-// Load OBJ mesh data-//-// Keep the following information in mind when reading this-// - A mesh is created for every material present in the obj file-// - the model.meshCount is therefore the materialCount returned from tinyobj-// - the mesh is automatically triangulated by tinyobj-static Model LoadOBJ(const char *fileName)-{- Model model = { 0 };-- tinyobj_attrib_t attrib = { 0 };- tinyobj_shape_t *meshes = NULL;- unsigned int meshCount = 0;-- tinyobj_material_t *materials = NULL;- unsigned int materialCount = 0;-- char *fileText = LoadFileText(fileName);-- if (fileText != NULL)- {- unsigned int dataSize = (unsigned int)strlen(fileText);-- char currentDir[1024] = { 0 };- strcpy(currentDir, GetWorkingDirectory()); // Save current working directory- const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness- if (CHDIR(workingDir) != 0)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);- }-- unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;- int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileText, dataSize, flags);-- if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);- else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);-- // WARNING: We are not splitting meshes by materials (previous implementation)- // Depending on the provided OBJ that was not the best option and it just crashed- // so, implementation was simplified to prioritize parsed meshes- model.meshCount = meshCount;-- // Set number of materials available- // NOTE: There could be more materials available than meshes but it will be resolved at- // model.meshMaterial, just assigning the right material to corresponding mesh- model.materialCount = materialCount;- if (model.materialCount == 0)- {- model.materialCount = 1;- TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes");- }-- // Init model meshes and materials- model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));- model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh- model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));-- // Process each provided mesh- for (int i = 0; i < model.meshCount; i++)- {- // WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset- // because in case of triangulated quads, meshes[i].length actually report quads,- // despite the triangulation that is efectively considered on attrib.num_faces- unsigned int tris = 0;- if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;- else tris = meshes[i + 1].face_offset;-- model.meshes[i].vertexCount = tris*3;- model.meshes[i].triangleCount = tris; // Face count (triangulated)- model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));- model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float));- model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));- model.meshMaterial[i] = 0; // By default, assign material 0 to each mesh-- // Process all mesh faces- for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3)- {- // Get indices for the face- tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0];- tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1];- tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2];-- // Fill vertices buffer (float) using vertex index of the face- for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; }- for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; }- for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; }-- if (attrib.num_texcoords > 0)- {- // Fill texcoords buffer (float) using vertex index of the face- // NOTE: Y-coordinate must be flipped upside-down- model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];- model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1];-- model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];- model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1];-- model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];- model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1];- }-- if (attrib.num_normals > 0)- {- // Fill normals buffer (float) using vertex index of the face- for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; }- for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; }- for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; }- }- }- }-- // Init model materials- if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount);- else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh-- tinyobj_attrib_free(&attrib);- tinyobj_shapes_free(meshes, model.meshCount);- tinyobj_materials_free(materials, materialCount);-- UnloadFileText(fileText);-- // Restore current working directory- if (CHDIR(currentDir) != 0)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);- }- }-- return model;-}-#endif--#if defined(SUPPORT_FILEFORMAT_IQM)-// Load IQM mesh data-static Model LoadIQM(const char *fileName)-{- #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number- #define IQM_VERSION 2 // only IQM version 2 supported-- #define BONE_NAME_LENGTH 32 // BoneInfo name string length- #define MESH_NAME_LENGTH 32 // Mesh name string length- #define MATERIAL_NAME_LENGTH 32 // Material name string length-- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);- unsigned char *fileDataPtr = fileData;-- // IQM file structs- //------------------------------------------------------------------------------------ typedef struct IQMHeader {- char magic[16];- unsigned int version;- unsigned int dataSize;- unsigned int flags;- unsigned int num_text, ofs_text;- unsigned int num_meshes, ofs_meshes;- unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;- unsigned int num_triangles, ofs_triangles, ofs_adjacency;- unsigned int num_joints, ofs_joints;- unsigned int num_poses, ofs_poses;- unsigned int num_anims, ofs_anims;- unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;- unsigned int num_comment, ofs_comment;- unsigned int num_extensions, ofs_extensions;- } IQMHeader;-- typedef struct IQMMesh {- unsigned int name;- unsigned int material;- unsigned int first_vertex, num_vertexes;- unsigned int first_triangle, num_triangles;- } IQMMesh;-- typedef struct IQMTriangle {- unsigned int vertex[3];- } IQMTriangle;-- typedef struct IQMJoint {- unsigned int name;- int parent;- float translate[3], rotate[4], scale[3];- } IQMJoint;-- typedef struct IQMVertexArray {- unsigned int type;- unsigned int flags;- unsigned int format;- unsigned int size;- unsigned int offset;- } IQMVertexArray;-- // NOTE: Below IQM structures are not used but listed for reference- /*- typedef struct IQMAdjacency {- unsigned int triangle[3];- } IQMAdjacency;-- typedef struct IQMPose {- int parent;- unsigned int mask;- float channeloffset[10];- float channelscale[10];- } IQMPose;-- typedef struct IQMAnim {- unsigned int name;- unsigned int first_frame, num_frames;- float framerate;- unsigned int flags;- } IQMAnim;-- typedef struct IQMBounds {- float bbmin[3], bbmax[3];- float xyradius, radius;- } IQMBounds;- */- //------------------------------------------------------------------------------------- // IQM vertex data types- enum {- IQM_POSITION = 0,- IQM_TEXCOORD = 1,- IQM_NORMAL = 2,- IQM_TANGENT = 3, // NOTE: Tangents unused by default- IQM_BLENDINDEXES = 4,- IQM_BLENDWEIGHTS = 5,- IQM_COLOR = 6,- IQM_CUSTOM = 0x10 // NOTE: Custom vertex values unused by default- };-- Model model = { 0 };-- IQMMesh *imesh = NULL;- IQMTriangle *tri = NULL;- IQMVertexArray *va = NULL;- IQMJoint *ijoint = NULL;-- float *vertex = NULL;- float *normal = NULL;- float *text = NULL;- char *blendi = NULL;- unsigned char *blendw = NULL;- unsigned char *color = NULL;-- // In case file can not be read, return an empty model- if (fileDataPtr == NULL) return model;-- // Read IQM header- IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;-- if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);- return model;- }-- if (iqmHeader->version != IQM_VERSION)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);- return model;- }-- //fileDataPtr += sizeof(IQMHeader); // Move file data pointer-- // Meshes data processing- imesh = RL_MALLOC(iqmHeader->num_meshes*sizeof(IQMMesh));- //fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET);- //fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile);- memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh));-- model.meshCount = iqmHeader->num_meshes;- model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));-- model.materialCount = model.meshCount;- model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));- model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));-- char name[MESH_NAME_LENGTH] = { 0 };- char material[MATERIAL_NAME_LENGTH] = { 0 };-- for (int i = 0; i < model.meshCount; i++)- {- //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].name, SEEK_SET);- //fread(name, sizeof(char), MESH_NAME_LENGTH, iqmFile);- memcpy(name, fileDataPtr + iqmHeader->ofs_text + imesh[i].name, MESH_NAME_LENGTH*sizeof(char));-- //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].material, SEEK_SET);- //fread(material, sizeof(char), MATERIAL_NAME_LENGTH, iqmFile);- memcpy(material, fileDataPtr + iqmHeader->ofs_text + imesh[i].material, MATERIAL_NAME_LENGTH*sizeof(char));-- model.materials[i] = LoadMaterialDefault();-- TRACELOG(LOG_DEBUG, "MODEL: [%s] mesh name (%s), material (%s)", fileName, name, material);-- model.meshes[i].vertexCount = imesh[i].num_vertexes;-- model.meshes[i].vertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions- model.meshes[i].normals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals- model.meshes[i].texcoords = RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords-- model.meshes[i].boneIds = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(unsigned char)); // Up-to 4 bones supported!- model.meshes[i].boneWeights = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!-- model.meshes[i].triangleCount = imesh[i].num_triangles;- model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));-- // Animated vertex data, what we actually process for rendering- // NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)- model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));- model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));- }-- // Triangles data processing- tri = RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle));- //fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET);- //fread(tri, sizeof(IQMTriangle), iqmHeader->num_triangles, iqmFile);- memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle));-- for (int m = 0; m < model.meshCount; m++)- {- int tcounter = 0;-- for (unsigned int i = imesh[m].first_triangle; i < (imesh[m].first_triangle + imesh[m].num_triangles); i++)- {- // IQM triangles indexes are stored in counter-clockwise, but raylib processes the index in linear order,- // expecting they point to the counter-clockwise vertex triangle, so we need to reverse triangle indexes- // NOTE: raylib renders vertex data in counter-clockwise order (standard convention) by default- model.meshes[m].indices[tcounter + 2] = tri[i].vertex[0] - imesh[m].first_vertex;- model.meshes[m].indices[tcounter + 1] = tri[i].vertex[1] - imesh[m].first_vertex;- model.meshes[m].indices[tcounter] = tri[i].vertex[2] - imesh[m].first_vertex;- tcounter += 3;- }- }-- // Vertex arrays data processing- va = RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));- //fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET);- //fread(va, sizeof(IQMVertexArray), iqmHeader->num_vertexarrays, iqmFile);- memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));-- for (unsigned int i = 0; i < iqmHeader->num_vertexarrays; i++)- {- switch (va[i].type)- {- case IQM_POSITION:- {- vertex = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);- memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- int vCounter = 0;- for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)- {- model.meshes[m].vertices[vCounter] = vertex[i];- model.meshes[m].animVertices[vCounter] = vertex[i];- vCounter++;- }- }- } break;- case IQM_NORMAL:- {- normal = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);- memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- int vCounter = 0;- for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)- {- model.meshes[m].normals[vCounter] = normal[i];- model.meshes[m].animNormals[vCounter] = normal[i];- vCounter++;- }- }- } break;- case IQM_TEXCOORD:- {- text = RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile);- memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- int vCounter = 0;- for (unsigned int i = imesh[m].first_vertex*2; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*2; i++)- {- model.meshes[m].texcoords[vCounter] = text[i];- vCounter++;- }- }- } break;- case IQM_BLENDINDEXES:- {- blendi = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile);- memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- int boneCounter = 0;- for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)- {- model.meshes[m].boneIds[boneCounter] = blendi[i];- boneCounter++;- }- }- } break;- case IQM_BLENDWEIGHTS:- {- blendw = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);- memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- int boneCounter = 0;- for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)- {- model.meshes[m].boneWeights[boneCounter] = blendw[i]/255.0f;- boneCounter++;- }- }- } break;- case IQM_COLOR:- {- color = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));- //fseek(iqmFile, va[i].offset, SEEK_SET);- //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);- memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));-- for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)- {- model.meshes[m].colors = RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char));-- int vCounter = 0;- for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)- {- model.meshes[m].colors[vCounter] = color[i];- vCounter++;- }- }- } break;- }- }-- // Bones (joints) data processing- ijoint = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));- //fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET);- //fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);- memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));-- model.boneCount = iqmHeader->num_joints;- model.bones = RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo));- model.bindPose = RL_MALLOC(iqmHeader->num_joints*sizeof(Transform));-- for (unsigned int i = 0; i < iqmHeader->num_joints; i++)- {- // Bones- model.bones[i].parent = ijoint[i].parent;- //fseek(iqmFile, iqmHeader->ofs_text + ijoint[i].name, SEEK_SET);- //fread(model.bones[i].name, sizeof(char), BONE_NAME_LENGTH, iqmFile);- memcpy(model.bones[i].name, fileDataPtr + iqmHeader->ofs_text + ijoint[i].name, BONE_NAME_LENGTH*sizeof(char));-- // Bind pose (base pose)- model.bindPose[i].translation.x = ijoint[i].translate[0];- model.bindPose[i].translation.y = ijoint[i].translate[1];- model.bindPose[i].translation.z = ijoint[i].translate[2];-- model.bindPose[i].rotation.x = ijoint[i].rotate[0];- model.bindPose[i].rotation.y = ijoint[i].rotate[1];- model.bindPose[i].rotation.z = ijoint[i].rotate[2];- model.bindPose[i].rotation.w = ijoint[i].rotate[3];-- model.bindPose[i].scale.x = ijoint[i].scale[0];- model.bindPose[i].scale.y = ijoint[i].scale[1];- model.bindPose[i].scale.z = ijoint[i].scale[2];- }-- BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);-- RL_FREE(fileData);-- RL_FREE(imesh);- RL_FREE(tri);- RL_FREE(va);- RL_FREE(vertex);- RL_FREE(normal);- RL_FREE(text);- RL_FREE(blendi);- RL_FREE(blendw);- RL_FREE(ijoint);- RL_FREE(color);-- return model;-}--// Load IQM animation data-static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount)-{- #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number- #define IQM_VERSION 2 // only IQM version 2 supported-- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);- unsigned char *fileDataPtr = fileData;-- typedef struct IQMHeader {- char magic[16];- unsigned int version;- unsigned int dataSize;- unsigned int flags;- unsigned int num_text, ofs_text;- unsigned int num_meshes, ofs_meshes;- unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;- unsigned int num_triangles, ofs_triangles, ofs_adjacency;- unsigned int num_joints, ofs_joints;- unsigned int num_poses, ofs_poses;- unsigned int num_anims, ofs_anims;- unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;- unsigned int num_comment, ofs_comment;- unsigned int num_extensions, ofs_extensions;- } IQMHeader;-- typedef struct IQMJoint {- unsigned int name;- int parent;- float translate[3], rotate[4], scale[3];- } IQMJoint;-- typedef struct IQMPose {- int parent;- unsigned int mask;- float channeloffset[10];- float channelscale[10];- } IQMPose;-- typedef struct IQMAnim {- unsigned int name;- unsigned int first_frame, num_frames;- float framerate;- unsigned int flags;- } IQMAnim;-- // In case file can not be read, return an empty model- if (fileDataPtr == NULL) return NULL;-- // Read IQM header- IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;-- if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);- return NULL;- }-- if (iqmHeader->version != IQM_VERSION)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);- return NULL;- }-- // Get bones data- IQMPose *poses = RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose));- //fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET);- //fread(poses, sizeof(IQMPose), iqmHeader->num_poses, iqmFile);- memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose));-- // Get animations data- *animCount = iqmHeader->num_anims;- IQMAnim *anim = RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim));- //fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET);- //fread(anim, sizeof(IQMAnim), iqmHeader->num_anims, iqmFile);- memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim));-- ModelAnimation *animations = RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation));-- // frameposes- unsigned short *framedata = RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));- //fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET);- //fread(framedata, sizeof(unsigned short), iqmHeader->num_frames*iqmHeader->num_framechannels, iqmFile);- memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));-- // joints- IQMJoint *joints = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));- memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));-- for (unsigned int a = 0; a < iqmHeader->num_anims; a++)- {- animations[a].frameCount = anim[a].num_frames;- animations[a].boneCount = iqmHeader->num_poses;- animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));- animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));- // animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?-- for (unsigned int j = 0; j < iqmHeader->num_poses; j++)- {- // If animations and skeleton are in the same file, copy bone names to anim- if (iqmHeader->num_joints > 0)- memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char));- else- strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // default bone name otherwise- animations[a].bones[j].parent = poses[j].parent;- }-- for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqmHeader->num_poses*sizeof(Transform));-- int dcounter = anim[a].first_frame*iqmHeader->num_framechannels;-- for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)- {- for (unsigned int i = 0; i < iqmHeader->num_poses; i++)- {- animations[a].framePoses[frame][i].translation.x = poses[i].channeloffset[0];-- if (poses[i].mask & 0x01)- {- animations[a].framePoses[frame][i].translation.x += framedata[dcounter]*poses[i].channelscale[0];- dcounter++;- }-- animations[a].framePoses[frame][i].translation.y = poses[i].channeloffset[1];-- if (poses[i].mask & 0x02)- {- animations[a].framePoses[frame][i].translation.y += framedata[dcounter]*poses[i].channelscale[1];- dcounter++;- }-- animations[a].framePoses[frame][i].translation.z = poses[i].channeloffset[2];-- if (poses[i].mask & 0x04)- {- animations[a].framePoses[frame][i].translation.z += framedata[dcounter]*poses[i].channelscale[2];- dcounter++;- }-- animations[a].framePoses[frame][i].rotation.x = poses[i].channeloffset[3];-- if (poses[i].mask & 0x08)- {- animations[a].framePoses[frame][i].rotation.x += framedata[dcounter]*poses[i].channelscale[3];- dcounter++;- }-- animations[a].framePoses[frame][i].rotation.y = poses[i].channeloffset[4];-- if (poses[i].mask & 0x10)- {- animations[a].framePoses[frame][i].rotation.y += framedata[dcounter]*poses[i].channelscale[4];- dcounter++;- }-- animations[a].framePoses[frame][i].rotation.z = poses[i].channeloffset[5];-- if (poses[i].mask & 0x20)- {- animations[a].framePoses[frame][i].rotation.z += framedata[dcounter]*poses[i].channelscale[5];- dcounter++;- }-- animations[a].framePoses[frame][i].rotation.w = poses[i].channeloffset[6];-- if (poses[i].mask & 0x40)- {- animations[a].framePoses[frame][i].rotation.w += framedata[dcounter]*poses[i].channelscale[6];- dcounter++;- }-- animations[a].framePoses[frame][i].scale.x = poses[i].channeloffset[7];-- if (poses[i].mask & 0x80)- {- animations[a].framePoses[frame][i].scale.x += framedata[dcounter]*poses[i].channelscale[7];- dcounter++;- }-- animations[a].framePoses[frame][i].scale.y = poses[i].channeloffset[8];-- if (poses[i].mask & 0x100)- {- animations[a].framePoses[frame][i].scale.y += framedata[dcounter]*poses[i].channelscale[8];- dcounter++;- }-- animations[a].framePoses[frame][i].scale.z = poses[i].channeloffset[9];-- if (poses[i].mask & 0x200)- {- animations[a].framePoses[frame][i].scale.z += framedata[dcounter]*poses[i].channelscale[9];- dcounter++;- }-- animations[a].framePoses[frame][i].rotation = QuaternionNormalize(animations[a].framePoses[frame][i].rotation);- }- }-- // Build frameposes- for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)- {- for (int i = 0; i < animations[a].boneCount; i++)- {- if (animations[a].bones[i].parent >= 0)- {- animations[a].framePoses[frame][i].rotation = QuaternionMultiply(animations[a].framePoses[frame][animations[a].bones[i].parent].rotation, animations[a].framePoses[frame][i].rotation);- animations[a].framePoses[frame][i].translation = Vector3RotateByQuaternion(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].rotation);- animations[a].framePoses[frame][i].translation = Vector3Add(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].translation);- animations[a].framePoses[frame][i].scale = Vector3Multiply(animations[a].framePoses[frame][i].scale, animations[a].framePoses[frame][animations[a].bones[i].parent].scale);- }- }- }- }-- RL_FREE(fileData);-- RL_FREE(joints);- RL_FREE(framedata);- RL_FREE(poses);- RL_FREE(anim);-- return animations;-}--#endif--#if defined(SUPPORT_FILEFORMAT_GLTF)-// Load file data callback for cgltf-static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, const char *path, cgltf_size *size, void **data)-{- int filesize;- unsigned char *filedata = LoadFileData(path, &filesize);-- if (filedata == NULL) return cgltf_result_io_error;-- *size = filesize;- *data = filedata;-- return cgltf_result_success;-}--// Release file data callback for cgltf-static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data) {- UnloadFileData(data);-}--// Load image from different glTF provided methods (uri, path, buffer_view)-static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPath)-{- Image image = { 0 };-- if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path)- {- if ((strlen(cgltfImage->uri) > 5) &&- (cgltfImage->uri[0] == 'd') &&- (cgltfImage->uri[1] == 'a') &&- (cgltfImage->uri[2] == 't') &&- (cgltfImage->uri[3] == 'a') &&- (cgltfImage->uri[4] == ':')) // Check if image is provided as base64 text data- {- // Data URI Format: data:<mediatype>;base64,<data>-- // Find the comma- int i = 0;- while ((cgltfImage->uri[i] != ',') && (cgltfImage->uri[i] != 0)) i++;-- if (cgltfImage->uri[i] == 0) TRACELOG(LOG_WARNING, "IMAGE: glTF data URI is not a valid image");- else- {- int base64Size = (int)strlen(cgltfImage->uri + i + 1);- int outSize = 3*(base64Size/4); // TODO: Consider padding (-numberOfPaddingCharacters)- void *data = NULL;-- cgltf_options options = { 0 };- options.file.read = LoadFileGLTFCallback;- options.file.release = ReleaseFileGLTFCallback;- cgltf_result result = cgltf_load_buffer_base64(&options, outSize, cgltfImage->uri + i + 1, &data);-- if (result == cgltf_result_success)- {- image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);- RL_FREE(data);- }- }- }- else // Check if image is provided as image path- {- image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));- }- }- else if (cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer- {- unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size);- int offset = (int)cgltfImage->buffer_view->offset;- int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1;-- // Copy buffer data to memory for loading- for (unsigned int i = 0; i < cgltfImage->buffer_view->size; i++)- {- data[i] = ((unsigned char *)cgltfImage->buffer_view->buffer->data)[offset];- offset += stride;- }-- // Check mime_type for image: (cgltfImage->mime_type == "image/png")- // NOTE: Detected that some models define mime_type as "image\\/png"- if ((strcmp(cgltfImage->mime_type, "image\\/png") == 0) ||- (strcmp(cgltfImage->mime_type, "image/png") == 0)) image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size);- else if ((strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) ||- (strcmp(cgltfImage->mime_type, "image/jpeg") == 0)) image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size);- else TRACELOG(LOG_WARNING, "MODEL: glTF image data MIME type not recognized", TextFormat("%s/%s", texPath, cgltfImage->uri));-- RL_FREE(data);- }-- return image;-}--// Load bone info from GLTF skin data-static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)-{- *boneCount = (int)skin.joints_count;- BoneInfo *bones = RL_MALLOC(skin.joints_count*sizeof(BoneInfo));-- for (unsigned int i = 0; i < skin.joints_count; i++)- {- cgltf_node node = *skin.joints[i];- strncpy(bones[i].name, node.name, sizeof(bones[i].name));-- // Find parent bone index- unsigned int parentIndex = -1;-- for (unsigned int j = 0; j < skin.joints_count; j++)- {- if (skin.joints[j] == node.parent)- {- parentIndex = j;- break;- }- }-- bones[i].parent = parentIndex;- }-- return bones;-}--// Load glTF file into model struct, .gltf and .glb supported-static Model LoadGLTF(const char *fileName)-{- /*********************************************************************************************-- Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend)- Reviewed by Ramon Santamaria (@raysan5)-- FEATURES:- - Supports .gltf and .glb files- - Supports embedded (base64) or external textures- - Supports PBR metallic/roughness flow, loads material textures, values and colors- PBR specular/glossiness flow and extended texture flows not supported- - Supports multiple meshes per model (every primitives is loaded as a separate mesh)- - Supports basic animations-- RESTRICTIONS:- - Only triangle meshes supported- - Vertex attribute types and formats supported:- > Vertices (position): vec3: float- > Normals: vec3: float- > Texcoords: vec2: float- > Colors: vec4: u8, u16, f32 (normalized)- > Indices: u16, u32 (truncated to u16)- - Node hierarchies or transforms not supported-- ***********************************************************************************************/-- // Macro to simplify attributes loading code- #define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \- { \- int n = 0; \- dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \- for (unsigned int k = 0; k < accesor->count; k++) \- {\- for (int l = 0; l < numComp; l++) \- {\- dstPtr[numComp*k + l] = buffer[n + l];\- }\- n += (int)(accesor->stride/sizeof(dataType));\- }\- }-- Model model = { 0 };-- // glTF file loading- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);-- if (fileData == NULL) return model;-- // glTF data loading- cgltf_options options = { 0 };- options.file.read = LoadFileGLTFCallback;- options.file.release = ReleaseFileGLTFCallback;- cgltf_data *data = NULL;- cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);-- if (result == cgltf_result_success)- {- if (data->file_type == cgltf_file_type_glb) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glb) loaded successfully", fileName);- else if (data->file_type == cgltf_file_type_gltf) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glTF) loaded successfully", fileName);- else TRACELOG(LOG_WARNING, "MODEL: [%s] Model format not recognized", fileName);-- TRACELOG(LOG_INFO, " > Meshes count: %i", data->meshes_count);- TRACELOG(LOG_INFO, " > Materials count: %i (+1 default)", data->materials_count);- TRACELOG(LOG_DEBUG, " > Buffers count: %i", data->buffers_count);- TRACELOG(LOG_DEBUG, " > Images count: %i", data->images_count);- TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count);-- // Force reading data buffers (fills buffer_view->buffer->data)- // NOTE: If an uri is defined to base64 data or external path, it's automatically loaded- result = cgltf_load_buffers(&options, data, fileName);- if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName);-- int primitivesCount = 0;- // NOTE: We will load every primitive in the glTF as a separate raylib mesh- for (unsigned int i = 0; i < data->meshes_count; i++) primitivesCount += (int)data->meshes[i].primitives_count;-- // Load our model data: meshes and materials- model.meshCount = primitivesCount;- model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));-- // NOTE: We keep an extra slot for default material, in case some mesh requires it- model.materialCount = (int)data->materials_count + 1;- model.materials = RL_CALLOC(model.materialCount, sizeof(Material));- model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)-- // Load mesh-material indices, by default all meshes are mapped to material index: 0- model.meshMaterial = RL_CALLOC(model.meshCount, sizeof(int));-- // Load materials data- //----------------------------------------------------------------------------------------------------- for (unsigned int i = 0, j = 1; i < data->materials_count; i++, j++)- {- model.materials[j] = LoadMaterialDefault();- const char *texPath = GetDirectoryPath(fileName);-- // Check glTF material flow: PBR metallic/roughness flow- // NOTE: Alternatively, materials can follow PBR specular/glossiness flow- if (data->materials[i].has_pbr_metallic_roughness)- {- // Load base color texture (albedo)- if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture)- {- Image imAlbedo = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath);- if (imAlbedo.data != NULL)- {- model.materials[j].maps[MATERIAL_MAP_ALBEDO].texture = LoadTextureFromImage(imAlbedo);- UnloadImage(imAlbedo);- }- }- // Load base color factor (tint)- model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255);- model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255);- model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255);- model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255);-- // Load metallic/roughness texture- if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture)- {- Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath);- if (imMetallicRoughness.data != NULL)- {- model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imMetallicRoughness);- UnloadImage(imMetallicRoughness);- }-- // Load metallic/roughness material properties- float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor;- model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].value = roughness;-- float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor;- model.materials[j].maps[MATERIAL_MAP_METALNESS].value = metallic;- }-- // Load normal texture- if (data->materials[i].normal_texture.texture)- {- Image imNormal = LoadImageFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath);- if (imNormal.data != NULL)- {- model.materials[j].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(imNormal);- UnloadImage(imNormal);- }- }-- // Load ambient occlusion texture- if (data->materials[i].occlusion_texture.texture)- {- Image imOcclusion = LoadImageFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath);- if (imOcclusion.data != NULL)- {- model.materials[j].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(imOcclusion);- UnloadImage(imOcclusion);- }- }-- // Load emissive texture- if (data->materials[i].emissive_texture.texture)- {- Image imEmissive = LoadImageFromCgltfImage(data->materials[i].emissive_texture.texture->image, texPath);- if (imEmissive.data != NULL)- {- model.materials[j].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(imEmissive);- UnloadImage(imEmissive);- }-- // Load emissive color factor- model.materials[j].maps[MATERIAL_MAP_EMISSION].color.r = (unsigned char)(data->materials[i].emissive_factor[0]*255);- model.materials[j].maps[MATERIAL_MAP_EMISSION].color.g = (unsigned char)(data->materials[i].emissive_factor[1]*255);- model.materials[j].maps[MATERIAL_MAP_EMISSION].color.b = (unsigned char)(data->materials[i].emissive_factor[2]*255);- model.materials[j].maps[MATERIAL_MAP_EMISSION].color.a = 255;- }- }-- // Other possible materials not supported by raylib pipeline:- // has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen- }-- // Load meshes data- //----------------------------------------------------------------------------------------------------- for (unsigned int i = 0, meshIndex = 0; i < data->meshes_count; i++)- {- // NOTE: meshIndex accumulates primitives-- for (unsigned int p = 0; p < data->meshes[i].primitives_count; p++)- {- // NOTE: We only support primitives defined by triangles- // Other alternatives: points, lines, line_strip, triangle_strip- if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue;-- // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...),- // Only some formats for each attribute type are supported, read info at the top of this function!-- for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++)- {- // Check the different attributes for every primitive- if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position) // POSITION- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined.-- if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec3))- {- // Init raylib mesh vertices to copy glTF attribute data- model.meshes[meshIndex].vertexCount = (int)attribute->count;- model.meshes[meshIndex].vertices = RL_MALLOC(attribute->count*3*sizeof(float));-- // Load 3 components of float data type into mesh.vertices- LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName);- }- else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec3))- {- // Init raylib mesh normals to copy glTF attribute data- model.meshes[meshIndex].normals = RL_MALLOC(attribute->count*3*sizeof(float));-- // Load 3 components of float data type into mesh.normals- LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName);- }- else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec4))- {- // Init raylib mesh tangent to copy glTF attribute data- model.meshes[meshIndex].tangents = RL_MALLOC(attribute->count*4*sizeof(float));-- // Load 4 components of float data type into mesh.tangents- LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName);- }- else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_0- {- // TODO: Support additional texture coordinates: TEXCOORD_1 -> mesh.texcoords2-- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec2))- {- // Init raylib mesh texcoords to copy glTF attribute data- model.meshes[meshIndex].texcoords = RL_MALLOC(attribute->count*2*sizeof(float));-- // Load 3 components of float data type into mesh.texcoords- LOAD_ATTRIBUTE(attribute, 2, float, model.meshes[meshIndex].texcoords)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported, use vec2 float", fileName);- }- else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_0- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- // WARNING: SPECS: All components of each COLOR_n accessor element MUST be clamped to [0.0, 1.0] range.-- if ((attribute->component_type == cgltf_component_type_r_8u) && (attribute->type == cgltf_type_vec4))- {- // Init raylib mesh color to copy glTF attribute data- model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));-- // Load 4 components of unsigned char data type into mesh.colors- LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)- }- else if ((attribute->component_type == cgltf_component_type_r_16u) && (attribute->type == cgltf_type_vec4))- {- // Init raylib mesh color to copy glTF attribute data- model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));-- // Load data into a temp buffer to be converted to raylib data type- unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short));- LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);-- // Convert data to raylib color data type (4 bytes)- for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f);-- RL_FREE(temp);- }- else if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec4))- {- // Init raylib mesh color to copy glTF attribute data- model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));-- // Load data into a temp buffer to be converted to raylib data type- float *temp = RL_MALLOC(attribute->count*4*sizeof(float));- LOAD_ATTRIBUTE(attribute, 4, float, temp);-- // Convert data to raylib color data type (4 bytes), we expect the color data normalized- for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);-- RL_FREE(temp);- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);- }-- // NOTE: Attributes related to animations are processed separately- }-- // Load primitive indices data (if provided)- if (data->meshes[i].primitives[p].indices != NULL)- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].indices;-- model.meshes[meshIndex].triangleCount = (int)attribute->count/3;-- if (attribute->component_type == cgltf_component_type_r_16u)- {- // Init raylib mesh indices to copy glTF attribute data- model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));-- // Load unsigned short data type into mesh.indices- LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)- }- else if (attribute->component_type == cgltf_component_type_r_32u)- {- // Init raylib mesh indices to copy glTF attribute data- model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));-- // Load data into a temp buffer to be converted to raylib data type- unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int));- LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp);-- // Convert data to raylib indices data type (unsigned short)- for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d];-- TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);-- RL_FREE(temp);- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);- }- else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh-- // Assign to the primitive mesh the corresponding material index- // NOTE: If no material defined, mesh uses the already assigned default material (index: 0)- for (unsigned int m = 0; m < data->materials_count; m++)- {- // The primitive actually keeps the pointer to the corresponding material,- // raylib instead assigns to the mesh the by its index, as loaded in model.materials array- // To get the index, we check if material pointers match, and we assign the corresponding index,- // skipping index 0, the default material- if (&data->materials[m] == data->meshes[i].primitives[p].material)- {- model.meshMaterial[meshIndex] = m + 1;- break;- }- }-- meshIndex++; // Move to next mesh- }- }-- // Load glTF meshes animation data- // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins- // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes- //- // LIMITATIONS:- // - Only supports 1 armature per file, and skips loading it if there are multiple armatures- // - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file)- // - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets)- //----------------------------------------------------------------------------------------------------- if (data->skins_count == 1)- {- cgltf_skin skin = data->skins[0];- model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);- model.bindPose = RL_MALLOC(model.boneCount*sizeof(Transform));-- for (int i = 0; i < model.boneCount; i++)- {- cgltf_node node = *skin.joints[i];- model.bindPose[i].translation.x = node.translation[0];- model.bindPose[i].translation.y = node.translation[1];- model.bindPose[i].translation.z = node.translation[2];-- model.bindPose[i].rotation.x = node.rotation[0];- model.bindPose[i].rotation.y = node.rotation[1];- model.bindPose[i].rotation.z = node.rotation[2];- model.bindPose[i].rotation.w = node.rotation[3];-- model.bindPose[i].scale.x = node.scale[0];- model.bindPose[i].scale.y = node.scale[1];- model.bindPose[i].scale.z = node.scale[2];- }-- BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);- }- else if (data->skins_count > 1)- {- TRACELOG(LOG_ERROR, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);- }-- for (unsigned int i = 0, meshIndex = 0; i < data->meshes_count; i++)- {- for (unsigned int p = 0; p < data->meshes[i].primitives_count; p++)- {- // NOTE: We only support primitives defined by triangles- if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue;-- for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++)- {- // NOTE: JOINTS_1 + WEIGHT_1 will be used for +4 joints influencing a vertex -> Not supported by raylib-- if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_joints) // JOINTS_n (vec4: 4 bones max per vertex / u8, u16)- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- if ((attribute->component_type == cgltf_component_type_r_8u) && (attribute->type == cgltf_type_vec4))- {- // Handle 8-bit unsigned byte, vec4 format- model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));- LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)- }- else if ((attribute->component_type == cgltf_component_type_r_16u) && (attribute->type == cgltf_type_vec2))- {- // TODO: WARNING: model.meshes[].boneIds is an (unsigned char *) --> Conversion required!-- // Handle 16-bit unsigned short, vec2 format- model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*2, sizeof(unsigned short));- unsigned short *ptr = (unsigned short *)model.meshes[meshIndex].boneIds;- LOAD_ATTRIBUTE(attribute, 2, unsigned short, ptr)- }- else if ((attribute->component_type == cgltf_component_type_r_16u) && (attribute->type == cgltf_type_vec4))- {- // TODO: WARNING: model.meshes[].boneIds is an (unsigned char *) --> Conversion required!-- // Handle 16-bit unsigned short, vec4 format- model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned short));- unsigned short *ptr = (unsigned short *)model.meshes[meshIndex].boneIds;- LOAD_ATTRIBUTE(attribute, 4, unsigned short, ptr)- }- else if ((attribute->component_type == cgltf_component_type_r_32u) && (attribute->type == cgltf_type_vec4))- {- // TODO: WARNING: model.meshes[].boneIds is an (unsigned char *) --> Conversion required!-- // Handle 32-bit unsigned int, vec4 format- model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned int));- unsigned int *ptr = (unsigned int *)model.meshes[meshIndex].boneIds;- LOAD_ATTRIBUTE(attribute, 4, unsigned int, ptr)- }- else if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec2))- {- // TODO: WARNING: model.meshes[].boneIds is an (unsigned char *) --> Conversion required!-- // Handle 32-bit float, vec2 format- model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*2, sizeof(float));- float *ptr = (float *)model.meshes[meshIndex].boneIds;- LOAD_ATTRIBUTE(attribute, 2, float, ptr)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);- }- else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4 / u8, u16, f32)- {- cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;-- if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec4))- {- // Init raylib mesh bone weight to copy glTF attribute data- model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));-- // Load 4 components of float data type into mesh.boneWeights- // for cgltf_attribute_type_weights we have:- // - data.meshes[0] (256 vertices)- // - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)- LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint weight attribute data format not supported, use vec4 float", fileName);- }- }-- // Animated vertex data- model.meshes[meshIndex].animVertices = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));- memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));- model.meshes[meshIndex].animNormals = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));- if (model.meshes[meshIndex].normals != NULL) {- memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));- }-- meshIndex++; // Move to next mesh- }-- }-- // Free all cgltf loaded data- cgltf_free(data);- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);-- // WARNING: cgltf requires the file pointer available while reading data- UnloadFileData(fileData);-- return model;-}--// Get interpolated pose for bone sampler at a specific time. Returns true on success.-static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, float time, void *data)-{- // Input and output should have the same count- float tstart = 0.0f;- float tend = 0.0f;- int keyframe = 0; // Defaults to first pose-- for (int i = 0; i < (int)input->count - 1; i++)- {- cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);- if (!r1) return false;-- cgltf_bool r2 = cgltf_accessor_read_float(input, i + 1, &tend, 1);- if (!r2) return false;-- if ((tstart <= time) && (time < tend))- {- keyframe = i;- break;- }- }-- float t = (time - tstart)/fmax((tend - tstart), EPSILON);- t = (t < 0.0f)? 0.0f : t;- t = (t > 1.0f)? 1.0f : t;-- if (output->component_type != cgltf_component_type_r_32f) return false;-- if (output->type == cgltf_type_vec3)- {- float tmp[3] = { 0.0f };- cgltf_accessor_read_float(output, keyframe, tmp, 3);- Vector3 v1 = {tmp[0], tmp[1], tmp[2]};- cgltf_accessor_read_float(output, keyframe+1, tmp, 3);- Vector3 v2 = {tmp[0], tmp[1], tmp[2]};- Vector3 *r = data;- *r = Vector3Lerp(v1, v2, t);- }- else if (output->type == cgltf_type_vec4)- {- float tmp[4] = { 0.0f };- cgltf_accessor_read_float(output, keyframe, tmp, 4);- Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};- cgltf_accessor_read_float(output, keyframe+1, tmp, 4);- Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};- Vector4 *r = data;-- // Only v4 is for rotations, so we know it's a quaternion- *r = QuaternionSlerp(v1, v2, t);- }-- return true;-}--#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)--static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)-{- // glTF file loading- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);-- ModelAnimation *animations = NULL;-- // glTF data loading- cgltf_options options = { 0 };- options.file.read = LoadFileGLTFCallback;- options.file.release = ReleaseFileGLTFCallback;- cgltf_data *data = NULL;- cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);-- if (result != cgltf_result_success)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);- *animCount = 0;- return NULL;- }-- result = cgltf_load_buffers(&options, data, fileName);- if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load animation buffers", fileName);-- if (result == cgltf_result_success)- {- if (data->skins_count == 1)- {- cgltf_skin skin = data->skins[0];- *animCount = (int)data->animations_count;- animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));-- for (unsigned int i = 0; i < data->animations_count; i++)- {- animations[i].bones = LoadBoneInfoGLTF(skin, &animations[i].boneCount);-- cgltf_animation animData = data->animations[i];-- struct Channels {- cgltf_animation_channel *translate;- cgltf_animation_channel *rotate;- cgltf_animation_channel *scale;- };-- struct Channels *boneChannels = RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));- float animDuration = 0.0f;-- for (unsigned int j = 0; j < animData.channels_count; j++)- {- cgltf_animation_channel channel = animData.channels[j];- int boneIndex = -1;-- for (unsigned int k = 0; k < skin.joints_count; k++)- {- if (animData.channels[j].target_node == skin.joints[k])- {- boneIndex = k;- break;- }- }-- if (boneIndex == -1)- {- // Animation channel for a node not in the armature- continue;- }-- if (animData.channels[j].sampler->interpolation == cgltf_interpolation_type_linear)- {- if (channel.target_path == cgltf_animation_path_type_translation)- {- boneChannels[boneIndex].translate = &animData.channels[j];- }- else if (channel.target_path == cgltf_animation_path_type_rotation)- {- boneChannels[boneIndex].rotate = &animData.channels[j];- }- else if (channel.target_path == cgltf_animation_path_type_scale)- {- boneChannels[boneIndex].scale = &animData.channels[j];- }- else- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Unsupported target_path on channel %d's sampler for animation %d. Skipping.", fileName, j, i);- }- }- else TRACELOG(LOG_WARNING, "MODEL: [%s] Only linear interpolation curves are supported for GLTF animation.", fileName);-- float t = 0.0f;- cgltf_bool r = cgltf_accessor_read_float(channel.sampler->input, channel.sampler->input->count - 1, &t, 1);-- if (!r)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load input time", fileName);- continue;- }-- animDuration = (t > animDuration)? t : animDuration;- }-- strncpy(animations[i].name, animData.name, sizeof(animations[i].name));- animations[i].name[sizeof(animations[i].name) - 1] = '\0';-- animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY) + 1;- animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));-- for (int j = 0; j < animations[i].frameCount; j++)- {- animations[i].framePoses[j] = RL_MALLOC(animations[i].boneCount*sizeof(Transform));- float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;-- for (int k = 0; k < animations[i].boneCount; k++)- {- Vector3 translation = {0, 0, 0};- Quaternion rotation = {0, 0, 0, 1};- Vector3 scale = {1, 1, 1};-- if (boneChannels[k].translate)- {- if (!GetPoseAtTimeGLTF(boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))- {- TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load translate pose data for bone %s", fileName, animations[i].bones[k].name);- }- }-- if (boneChannels[k].rotate)- {- if (!GetPoseAtTimeGLTF(boneChannels[k].rotate->sampler->input, boneChannels[k].rotate->sampler->output, time, &rotation))- {- TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load rotate pose data for bone %s", fileName, animations[i].bones[k].name);- }- }-- if (boneChannels[k].scale)- {- if (!GetPoseAtTimeGLTF(boneChannels[k].scale->sampler->input, boneChannels[k].scale->sampler->output, time, &scale))- {- TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load scale pose data for bone %s", fileName, animations[i].bones[k].name);- }- }-- animations[i].framePoses[j][k] = (Transform){- .translation = translation,- .rotation = rotation,- .scale = scale- };- }-- BuildPoseFromParentJoints(animations[i].bones, animations[i].boneCount, animations[i].framePoses[j]);- }-- TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s (%d frames, %fs)", fileName, animData.name, animations[i].frameCount, animDuration);- RL_FREE(boneChannels);- }- }- else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);-- cgltf_free(data);- }- UnloadFileData(fileData);- return animations;-}-#endif--#if defined(SUPPORT_FILEFORMAT_VOX)-// Load VOX (MagicaVoxel) mesh data-static Model LoadVOX(const char *fileName)-{- Model model = { 0 };-- int nbvertices = 0;- int meshescount = 0;-- // Read vox file into buffer- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);-- if (fileData == 0)- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);- return model;- }-- // Read and build voxarray description- VoxArray3D voxarray = { 0 };- int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);-- if (ret != VOX_SUCCESS)- {- // Error- UnloadFileData(fileData);-- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName);- return model;- }- else- {- // Success: Compute meshes count- nbvertices = voxarray.vertices.used;- meshescount = 1 + (nbvertices/65536);-- TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount);- }-- // Build models from meshes- model.transform = MatrixIdentity();-- model.meshCount = meshescount;- model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));-- model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));-- model.materialCount = 1;- model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));- model.materials[0] = LoadMaterialDefault();-- // Init model meshes- int verticesRemain = voxarray.vertices.used;- int verticesMax = 65532; // 5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536)-- // 6*4 = 12 vertices per voxel- Vector3 *pvertices = (Vector3 *)voxarray.vertices.array;- Vector3 *pnormals = (Vector3 *)voxarray.normals.array;- Color *pcolors = (Color *)voxarray.colors.array;-- unsigned short *pindices = voxarray.indices.array; // 5461*6*6 = 196596 indices max per mesh-- int size = 0;-- for (int i = 0; i < meshescount; i++)- {- Mesh *pmesh = &model.meshes[i];- memset(pmesh, 0, sizeof(Mesh));-- // Copy vertices- pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain);-- size = pmesh->vertexCount*sizeof(float)*3;- pmesh->vertices = (float *)RL_MALLOC(size);- memcpy(pmesh->vertices, pvertices, size);-- // Copy normals- pmesh->normals = (float *)RL_MALLOC(size);- memcpy(pmesh->normals, pnormals, size);-- // Copy indices- size = voxarray.indices.used*sizeof(unsigned short);- pmesh->indices = (unsigned short *)RL_MALLOC(size);- memcpy(pmesh->indices, pindices, size);-- pmesh->triangleCount = (pmesh->vertexCount/4)*2;-- // Copy colors- size = pmesh->vertexCount*sizeof(Color);- pmesh->colors = RL_MALLOC(size);- memcpy(pmesh->colors, pcolors, size);-- // First material index- model.meshMaterial[i] = 0;-- verticesRemain -= verticesMax;- pvertices += verticesMax;- pnormals += verticesMax;- pcolors += verticesMax;- }-- // Free buffers- Vox_FreeArrays(&voxarray);- UnloadFileData(fileData);-- return model;-}-#endif--#if defined(SUPPORT_FILEFORMAT_M3D)-// Hook LoadFileData()/UnloadFileData() calls to M3D loaders-unsigned char *m3d_loaderhook(char *fn, unsigned int *len) { return LoadFileData((const char *)fn, (int *)len); }-void m3d_freehook(void *data) { UnloadFileData((unsigned char *)data); }--// Load M3D mesh data-static Model LoadM3D(const char *fileName)-{- Model model = { 0 };-- m3d_t *m3d = NULL;- m3dp_t *prop = NULL;- int i, j, k, l, n, mi = -2, vcolor = 0;-- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);-- if (fileData != NULL)- {- m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);-- if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);- if (m3d) m3d_free(m3d);- UnloadFileData(fileData);- return model;- }- else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i faces/%i materials", fileName, m3d->numface, m3d->nummaterial);-- // no face? this is probably just a material library- if (!m3d->numface)- {- m3d_free(m3d);- UnloadFileData(fileData);- return model;- }-- if (m3d->nummaterial > 0)- {- model.meshCount = model.materialCount = m3d->nummaterial;- TRACELOG(LOG_INFO, "MODEL: model has %i material meshes", model.materialCount);- }- else- {- model.meshCount = 1; model.materialCount = 0;- TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");- }-- // We always need a default material, so we add +1- model.materialCount++;-- // Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise.- // WARNING: Sorting is not needed, valid M3D model files should already be sorted- // Just keeping the sorting function for reference (Check PR #3363 #3385)- /*- for (i = 1; i < m3d->numface; i++)- {- if (m3d->face[i-1].materialid <= m3d->face[i].materialid) continue;-- // face[i-1] > face[i]. slide face[i] lower.- m3df_t slider = m3d->face[i];- j = i-1;-- do- { // face[j] > slider, face[j+1] is svailable vacant gap.- m3d->face[j+1] = m3d->face[j];- j = j-1;- }- while (j >= 0 && m3d->face[j].materialid > slider.materialid);-- m3d->face[j+1] = slider;- }- */-- model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));- model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));- model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));-- // Map no material to index 0 with default shader, everything else materialid + 1- model.materials[0] = LoadMaterialDefault();-- for (i = l = 0, k = -1; i < (int)m3d->numface; i++, l++)- {- // Materials are grouped together- if (mi != m3d->face[i].materialid)- {- // there should be only one material switch per material kind, but be bulletproof for non-optimal model files- if (k + 1 >= model.meshCount)- {- model.meshCount++;- model.meshes = (Mesh *)RL_REALLOC(model.meshes, model.meshCount*sizeof(Mesh));- memset(&model.meshes[model.meshCount - 1], 0, sizeof(Mesh));- model.meshMaterial = (int *)RL_REALLOC(model.meshMaterial, model.meshCount*sizeof(int));- }-- k++;- mi = m3d->face[i].materialid;-- // Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch- // if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors- for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)- {- if (!m3d->vertex[m3d->face[j].vertex[0]].color ||- !m3d->vertex[m3d->face[j].vertex[1]].color ||- !m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;- }-- model.meshes[k].vertexCount = l*3;- model.meshes[k].triangleCount = l;- model.meshes[k].vertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));- model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));- model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));-- // If no map is provided, or we have colors defined, we allocate storage for vertex colors- // M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors- if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));-- // If no map is provided and we allocated vertex colors, set them to white- if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))- {- for (int c = 0; c < model.meshes[k].vertexCount*4; c++) model.meshes[k].colors[c] = 255;- }-- if (m3d->numbone && m3d->numskin)- {- model.meshes[k].boneIds = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));- model.meshes[k].boneWeights = (float *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(float));- model.meshes[k].animVertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));- model.meshes[k].animNormals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));- }-- model.meshMaterial[k] = mi + 1;- l = 0;- }-- // Process meshes per material, add triangles- model.meshes[k].vertices[l*9 + 0] = m3d->vertex[m3d->face[i].vertex[0]].x*m3d->scale;- model.meshes[k].vertices[l*9 + 1] = m3d->vertex[m3d->face[i].vertex[0]].y*m3d->scale;- model.meshes[k].vertices[l*9 + 2] = m3d->vertex[m3d->face[i].vertex[0]].z*m3d->scale;- model.meshes[k].vertices[l*9 + 3] = m3d->vertex[m3d->face[i].vertex[1]].x*m3d->scale;- model.meshes[k].vertices[l*9 + 4] = m3d->vertex[m3d->face[i].vertex[1]].y*m3d->scale;- model.meshes[k].vertices[l*9 + 5] = m3d->vertex[m3d->face[i].vertex[1]].z*m3d->scale;- model.meshes[k].vertices[l*9 + 6] = m3d->vertex[m3d->face[i].vertex[2]].x*m3d->scale;- model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;- model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;-- // Without vertex color (full transparency), we use the default color- if (model.meshes[k].colors != NULL)- {- if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)- memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);- if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xFF000000)- memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);- if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xFF000000)- memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);- }-- if (m3d->face[i].texcoord[0] != M3D_UNDEF)- {- model.meshes[k].texcoords[l*6 + 0] = m3d->tmap[m3d->face[i].texcoord[0]].u;- model.meshes[k].texcoords[l*6 + 1] = 1.0f - m3d->tmap[m3d->face[i].texcoord[0]].v;- model.meshes[k].texcoords[l*6 + 2] = m3d->tmap[m3d->face[i].texcoord[1]].u;- model.meshes[k].texcoords[l*6 + 3] = 1.0f - m3d->tmap[m3d->face[i].texcoord[1]].v;- model.meshes[k].texcoords[l*6 + 4] = m3d->tmap[m3d->face[i].texcoord[2]].u;- model.meshes[k].texcoords[l*6 + 5] = 1.0f - m3d->tmap[m3d->face[i].texcoord[2]].v;- }-- if (m3d->face[i].normal[0] != M3D_UNDEF)- {- model.meshes[k].normals[l*9 + 0] = m3d->vertex[m3d->face[i].normal[0]].x;- model.meshes[k].normals[l*9 + 1] = m3d->vertex[m3d->face[i].normal[0]].y;- model.meshes[k].normals[l*9 + 2] = m3d->vertex[m3d->face[i].normal[0]].z;- model.meshes[k].normals[l*9 + 3] = m3d->vertex[m3d->face[i].normal[1]].x;- model.meshes[k].normals[l*9 + 4] = m3d->vertex[m3d->face[i].normal[1]].y;- model.meshes[k].normals[l*9 + 5] = m3d->vertex[m3d->face[i].normal[1]].z;- model.meshes[k].normals[l*9 + 6] = m3d->vertex[m3d->face[i].normal[2]].x;- model.meshes[k].normals[l*9 + 7] = m3d->vertex[m3d->face[i].normal[2]].y;- model.meshes[k].normals[l*9 + 8] = m3d->vertex[m3d->face[i].normal[2]].z;- }-- // Add skin (vertex / bone weight pairs)- if (m3d->numbone && m3d->numskin)- {- for (n = 0; n < 3; n++)- {- int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;-- // Check if there is a skin for this mesh, should be, just failsafe- if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin))- {- for (j = 0; j < 4; j++)- {- model.meshes[k].boneIds[l*12 + n*4 + j] = m3d->skin[skinid].boneid[j];- model.meshes[k].boneWeights[l*12 + n*4 + j] = m3d->skin[skinid].weight[j];- }- }- else- {- // raylib does not handle boneless meshes with skeletal animations, so- // we put all vertices without a bone into a special "no bone" bone- model.meshes[k].boneIds[l*12 + n*4] = m3d->numbone;- model.meshes[k].boneWeights[l*12 + n*4] = 1.0f;- }- }- }- }-- // Load materials- for (i = 0; i < (int)m3d->nummaterial; i++)- {- model.materials[i + 1] = LoadMaterialDefault();-- for (j = 0; j < m3d->material[i].numprop; j++)- {- prop = &m3d->material[i].prop[j];-- switch (prop->type)- {- case m3dp_Kd:- {- memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].color, &prop->value.color, 4);- model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;- } break;- case m3dp_Ks:- {- memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].color, &prop->value.color, 4);- } break;- case m3dp_Ns:- {- model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].value = prop->value.fnum;- } break;- case m3dp_Ke:- {- memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].color, &prop->value.color, 4);- model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].value = 0.0f;- } break;- case m3dp_Pm:- {- model.materials[i + 1].maps[MATERIAL_MAP_METALNESS].value = prop->value.fnum;- } break;- case m3dp_Pr:- {- model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].value = prop->value.fnum;- } break;- case m3dp_Ps:- {- model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].color = WHITE;- model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].value = prop->value.fnum;- } break;- default:- {- if (prop->type >= 128)- {- Image image = { 0 };- image.data = m3d->texture[prop->value.textureid].d;- image.width = m3d->texture[prop->value.textureid].w;- image.height = m3d->texture[prop->value.textureid].h;- image.mipmaps = 1;- image.format = (m3d->texture[prop->value.textureid].f == 4)? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 :- ((m3d->texture[prop->value.textureid].f == 3)? PIXELFORMAT_UNCOMPRESSED_R8G8B8 :- ((m3d->texture[prop->value.textureid].f == 2)? PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA : PIXELFORMAT_UNCOMPRESSED_GRAYSCALE));-- switch (prop->type)- {- case m3dp_map_Kd: model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTextureFromImage(image); break;- case m3dp_map_Ks: model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].texture = LoadTextureFromImage(image); break;- case m3dp_map_Ke: model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(image); break;- case m3dp_map_Km: model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(image); break;- case m3dp_map_Ka: model.materials[i + 1].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(image); break;- case m3dp_map_Pm: model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(image); break;- default: break;- }- }- } break;- }- }- }-- // Load bones- if (m3d->numbone)- {- model.boneCount = m3d->numbone + 1;- model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));- model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));-- for (i = 0; i < (int)m3d->numbone; i++)- {- model.bones[i].parent = m3d->bone[i].parent;- strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name));- model.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;- model.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;- model.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;- model.bindPose[i].rotation.x = m3d->vertex[m3d->bone[i].ori].x;- model.bindPose[i].rotation.y = m3d->vertex[m3d->bone[i].ori].y;- model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;- model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;-- // TODO: If the orientation quaternion is not normalized, then that's encoding scaling- model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);- model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;-- // Child bones are stored in parent bone relative space, convert that into model space- if (model.bones[i].parent >= 0)- {- model.bindPose[i].rotation = QuaternionMultiply(model.bindPose[model.bones[i].parent].rotation, model.bindPose[i].rotation);- model.bindPose[i].translation = Vector3RotateByQuaternion(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].rotation);- model.bindPose[i].translation = Vector3Add(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].translation);- model.bindPose[i].scale = Vector3Multiply(model.bindPose[i].scale, model.bindPose[model.bones[i].parent].scale);- }- }-- // Add a special "no bone" bone- model.bones[i].parent = -1;- strcpy(model.bones[i].name, "NO BONE");- model.bindPose[i].translation.x = 0.0f;- model.bindPose[i].translation.y = 0.0f;- model.bindPose[i].translation.z = 0.0f;- model.bindPose[i].rotation.x = 0.0f;- model.bindPose[i].rotation.y = 0.0f;- model.bindPose[i].rotation.z = 0.0f;- model.bindPose[i].rotation.w = 1.0f;- model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;- }-- // Load bone-pose default mesh into animation vertices. These will be updated when UpdateModelAnimation gets- // called, but not before, however DrawMesh uses these if they exist (so not good if they are left empty).- if (m3d->numbone && m3d->numskin)- {- for(i = 0; i < model.meshCount; i++)- {- memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float));- memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));- }- }-- m3d_free(m3d);- UnloadFileData(fileData);- }-- return model;-}--#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)--// Load M3D animation data-static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)-{- ModelAnimation *animations = NULL;-- m3d_t *m3d = NULL;- int i = 0, j = 0;- *animCount = 0;-- int dataSize = 0;- unsigned char *fileData = LoadFileData(fileName, &dataSize);-- if (fileData != NULL)- {- m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);-- if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))- {- TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);- UnloadFileData(fileData);- return NULL;- }- else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i animations, %i bones, %i skins", fileName,- m3d->numaction, m3d->numbone, m3d->numskin);-- // No animation or bone+skin?- if (!m3d->numaction || !m3d->numbone || !m3d->numskin)- {- m3d_free(m3d);- UnloadFileData(fileData);- return NULL;- }-- animations = RL_MALLOC(m3d->numaction*sizeof(ModelAnimation));- *animCount = m3d->numaction;-- for (unsigned int a = 0; a < m3d->numaction; a++)- {- animations[a].frameCount = m3d->action[a].durationmsec / M3D_ANIMDELAY;+void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color)+{+ if (pointCount < 3) return; // Security check++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 2; i < pointCount; i++)+ {+ if ((i%2) == 0)+ {+ rlVertex3f(points[i].x, points[i].y, points[i].z);+ rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);+ rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);+ }+ else+ {+ rlVertex3f(points[i].x, points[i].y, points[i].z);+ rlVertex3f(points[i - 1].x, points[i - 1].y, points[i - 1].z);+ rlVertex3f(points[i - 2].x, points[i - 2].y, points[i - 2].z);+ }+ }+ rlEnd();+}++// Draw cube+// NOTE: Cube position is the center position+void DrawCube(Vector3 position, float width, float height, float length, Color color)+{+ float x = 0.0f;+ float y = 0.0f;+ float z = 0.0f;++ rlPushMatrix();+ // NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)+ rlTranslatef(position.x, position.y, position.z);+ //rlRotatef(45, 0, 1, 0);+ //rlScalef(1.0f, 1.0f, 1.0f); // NOTE: Vertices are directly scaled on definition++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ // Front face+ rlNormal3f(0.0f, 0.0f, 1.0f);+ rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left++ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right++ // Back face+ rlNormal3f(0.0f, 0.0f, -1.0f);+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right++ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left++ // Top face+ rlNormal3f(0.0f, 1.0f, 0.0f);+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right++ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right++ // Bottom face+ rlNormal3f(0.0f, -1.0f, 0.0f);+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right+ rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left++ rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Right+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Left++ // Right face+ rlNormal3f(1.0f, 0.0f, 0.0f);+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right+ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left++ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left++ // Left face+ rlNormal3f(-1.0f, 0.0f, 0.0f);+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right++ rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right+ rlEnd();+ rlPopMatrix();+}++// Draw cube (Vector version)+void DrawCubeV(Vector3 position, Vector3 size, Color color)+{+ DrawCube(position, size.x, size.y, size.z, color);+}++// Draw cube wires+void DrawCubeWires(Vector3 position, float width, float height, float length, Color color)+{+ float x = 0.0f;+ float y = 0.0f;+ float z = 0.0f;++ rlPushMatrix();+ rlTranslatef(position.x, position.y, position.z);++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ // Front face+ //------------------------------------------------------------------+ // Bottom line+ rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right++ // Left line+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom right+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right++ // Top line+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left++ // Right line+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left+ rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom left++ // Back face+ //------------------------------------------------------------------+ // Bottom line+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right++ // Left line+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom right+ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right++ // Top line+ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left++ // Right line+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom left++ // Top face+ //------------------------------------------------------------------+ // Left line+ rlVertex3f(x - width/2, y + height/2, z + length/2); // Top left front+ rlVertex3f(x - width/2, y + height/2, z - length/2); // Top left back++ // Right line+ rlVertex3f(x + width/2, y + height/2, z + length/2); // Top right front+ rlVertex3f(x + width/2, y + height/2, z - length/2); // Top right back++ // Bottom face+ //------------------------------------------------------------------+ // Left line+ rlVertex3f(x - width/2, y - height/2, z + length/2); // Top left front+ rlVertex3f(x - width/2, y - height/2, z - length/2); // Top left back++ // Right line+ rlVertex3f(x + width/2, y - height/2, z + length/2); // Top right front+ rlVertex3f(x + width/2, y - height/2, z - length/2); // Top right back+ rlEnd();+ rlPopMatrix();+}++// Draw cube wires (vector version)+void DrawCubeWiresV(Vector3 position, Vector3 size, Color color)+{+ DrawCubeWires(position, size.x, size.y, size.z, color);+}++// Draw sphere+void DrawSphere(Vector3 centerPos, float radius, Color color)+{+ DrawSphereEx(centerPos, radius, 16, 16, color);+}++// Draw sphere with extended parameters+void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)+{+#if 0+ // Basic implementation, do not use it!+ // For a sphere with 16 rings and 16 slices it requires 8640 cos()/sin() function calls! + // New optimized version below only requires 4 cos()/sin() calls+ + rlPushMatrix();+ // NOTE: Transformation is applied in inverse order (scale -> translate)+ rlTranslatef(centerPos.x, centerPos.y, centerPos.z);+ rlScalef(radius, radius, radius);+ + rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < (rings + 2); i++)+ {+ for (int j = 0; j < slices; j++)+ {+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));++ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));+ }+ }+ rlEnd();+ rlPopMatrix();+#endif++ rlPushMatrix();+ // NOTE: Transformation is applied in inverse order (scale -> translate)+ rlTranslatef(centerPos.x, centerPos.y, centerPos.z);+ rlScalef(radius, radius, radius);++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ float ringangle = DEG2RAD*(180.0f/(rings + 1)); // Angle between latitudinal parallels+ float sliceangle = DEG2RAD*(360.0f/slices); // Angle between longitudinal meridians++ float cosring = cosf(ringangle);+ float sinring = sinf(ringangle);+ float cosslice = cosf(sliceangle);+ float sinslice = sinf(sliceangle);++ Vector3 vertices[4] = { 0 }; // Required to store face vertices+ vertices[2] = (Vector3){ 0, 1, 0 };+ vertices[3] = (Vector3){ sinring, cosring, 0 };++ for (int i = 0; i < rings + 1; i++)+ {+ for (int j = 0; j < slices; j++) + {+ vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face+ vertices[1] = vertices[3];+ vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis+ vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z };++ rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);+ rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);+ rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z);++ rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);+ rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z);+ rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);+ }++ vertices[2] = vertices[3]; // Rotate around z axis to set up starting vertices for next ring+ vertices[3] = (Vector3){ cosring*vertices[3].x + sinring*vertices[3].y, -sinring*vertices[3].x + cosring*vertices[3].y, vertices[3].z }; // Rotation matrix around z axis+ }+ rlEnd();+ rlPopMatrix();+}++// Draw sphere wires+void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color)+{+ rlPushMatrix();+ // NOTE: Transformation is applied in inverse order (scale -> translate)+ rlTranslatef(centerPos.x, centerPos.y, centerPos.z);+ rlScalef(radius, radius, radius);++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < (rings + 2); i++)+ {+ for (int j = 0; j < slices; j++)+ {+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));++ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));++ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));+ rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),+ sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),+ cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));+ }+ }+ rlEnd();+ rlPopMatrix();+}++// Draw a cylinder+// NOTE: It could be also used for pyramid and cone+void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)+{+ if (sides < 3) sides = 3;++ const float angleStep = 360.0f/sides;++ rlPushMatrix();+ rlTranslatef(position.x, position.y, position.z);++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ if (radiusTop > 0)+ {+ // Draw Body -------------------------------------------------------------------------------------+ for (int i = 0; i < sides; i++)+ {+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom); //Bottom Left+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom); //Bottom Right+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop); //Top Right++ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop); //Top Left+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom); //Bottom Left+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop); //Top Right+ }++ // Draw Cap --------------------------------------------------------------------------------------+ for (int i = 0; i < sides; i++)+ {+ rlVertex3f(0, height, 0);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);+ }+ }+ else+ {+ // Draw Cone -------------------------------------------------------------------------------------+ for (int i = 0; i < sides; i++)+ {+ rlVertex3f(0, height, 0);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);+ }+ }++ // Draw Base -----------------------------------------------------------------------------------------+ for (int i = 0; i < sides; i++)+ {+ rlVertex3f(0, 0, 0);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);+ }++ rlEnd();+ rlPopMatrix();+}++// Draw a cylinder with base at startPos and top at endPos+// NOTE: It could be also used for pyramid and cone+void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)+{+ if (sides < 3) sides = 3;++ Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };+ if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check++ // Construct a basis of the base and the top face:+ Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));+ Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));++ float baseAngle = (2.0f*PI)/sides;++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < sides; i++)+ {+ // Compute the four vertices+ float s1 = sinf(baseAngle*(i + 0))*startRadius;+ float c1 = cosf(baseAngle*(i + 0))*startRadius;+ Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };+ float s2 = sinf(baseAngle*(i + 1))*startRadius;+ float c2 = cosf(baseAngle*(i + 1))*startRadius;+ Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };+ float s3 = sinf(baseAngle*(i + 0))*endRadius;+ float c3 = cosf(baseAngle*(i + 0))*endRadius;+ Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };+ float s4 = sinf(baseAngle*(i + 1))*endRadius;+ float c4 = cosf(baseAngle*(i + 1))*endRadius;+ Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };++ if (startRadius > 0)+ {+ rlVertex3f(startPos.x, startPos.y, startPos.z); // |+ rlVertex3f(w2.x, w2.y, w2.z); // T0+ rlVertex3f(w1.x, w1.y, w1.z); // |+ }+ // w2 x.-----------x startPos+ rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /+ rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /+ rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /+ // | 2 \ T 'x w1+ rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos+ rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/+ rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /+ // '.\|/+ if (endRadius > 0) // 'x w3+ {+ rlVertex3f(endPos.x, endPos.y, endPos.z); // |+ rlVertex3f(w3.x, w3.y, w3.z); // T3+ rlVertex3f(w4.x, w4.y, w4.z); // |+ } //+ }+ rlEnd();+}++// Draw a wired cylinder+// NOTE: It could be also used for pyramid and cone+void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)+{+ if (sides < 3) sides = 3;++ const float angleStep = 360.0f/sides;++ rlPushMatrix();+ rlTranslatef(position.x, position.y, position.z);++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < sides; i++)+ {+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);++ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusBottom, 0, cosf(DEG2RAD*(i+1)*angleStep)*radiusBottom);+ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);++ rlVertex3f(sinf(DEG2RAD*(i+1)*angleStep)*radiusTop, height, cosf(DEG2RAD*(i+1)*angleStep)*radiusTop);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);++ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusTop, height, cosf(DEG2RAD*i*angleStep)*radiusTop);+ rlVertex3f(sinf(DEG2RAD*i*angleStep)*radiusBottom, 0, cosf(DEG2RAD*i*angleStep)*radiusBottom);+ }+ rlEnd();+ rlPopMatrix();+}+++// Draw a wired cylinder with base at startPos and top at endPos+// NOTE: It could be also used for pyramid and cone+void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color)+{+ if (sides < 3) sides = 3;++ Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };+ if ((direction.x == 0) && (direction.y == 0) && (direction.z == 0)) return; // Security check++ // Construct a basis of the base and the top face:+ Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));+ Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));++ float baseAngle = (2.0f*PI)/sides;++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < sides; i++)+ {+ // Compute the four vertices+ float s1 = sinf(baseAngle*(i + 0))*startRadius;+ float c1 = cosf(baseAngle*(i + 0))*startRadius;+ Vector3 w1 = { startPos.x + s1*b1.x + c1*b2.x, startPos.y + s1*b1.y + c1*b2.y, startPos.z + s1*b1.z + c1*b2.z };+ float s2 = sinf(baseAngle*(i + 1))*startRadius;+ float c2 = cosf(baseAngle*(i + 1))*startRadius;+ Vector3 w2 = { startPos.x + s2*b1.x + c2*b2.x, startPos.y + s2*b1.y + c2*b2.y, startPos.z + s2*b1.z + c2*b2.z };+ float s3 = sinf(baseAngle*(i + 0))*endRadius;+ float c3 = cosf(baseAngle*(i + 0))*endRadius;+ Vector3 w3 = { endPos.x + s3*b1.x + c3*b2.x, endPos.y + s3*b1.y + c3*b2.y, endPos.z + s3*b1.z + c3*b2.z };+ float s4 = sinf(baseAngle*(i + 1))*endRadius;+ float c4 = cosf(baseAngle*(i + 1))*endRadius;+ Vector3 w4 = { endPos.x + s4*b1.x + c4*b2.x, endPos.y + s4*b1.y + c4*b2.y, endPos.z + s4*b1.z + c4*b2.z };++ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w2.x, w2.y, w2.z);++ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w3.x, w3.y, w3.z);++ rlVertex3f(w3.x, w3.y, w3.z);+ rlVertex3f(w4.x, w4.y, w4.z);+ }+ rlEnd();+}++// Draw a capsule with the center of its sphere caps at startPos and endPos+void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)+{+ if (slices < 3) slices = 3;++ Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };++ // draw a sphere if start and end points are the same+ bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);+ if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};++ // Construct a basis of the base and the caps:+ Vector3 b0 = Vector3Normalize(direction);+ Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));+ Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));+ Vector3 capCenter = endPos;++ float baseSliceAngle = (2.0f*PI)/slices;+ float baseRingAngle = PI*0.5f/rings;++ rlBegin(RL_TRIANGLES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ // render both caps+ for (int c = 0; c < 2; c++)+ {+ for (int i = 0; i < rings; i++)+ {+ for (int j = 0; j < slices; j++)+ {++ // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier++ // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))+ // as we iterate through the rings they must get smaller by the cos(angle(i))++ // compute the four vertices+ float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));+ float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));+ Vector3 w1 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z)*radius+ };+ float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));+ float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));+ Vector3 w2 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z)*radius+ };++ float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));+ float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));+ Vector3 w3 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z)*radius+ };+ float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));+ float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));+ Vector3 w4 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z)*radius+ };++ // Make sure cap triangle normals are facing outwards+ if (c == 0)+ {+ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w3.x, w3.y, w3.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w4.x, w4.y, w4.z);+ rlVertex3f(w3.x, w3.y, w3.z);+ }+ else+ {+ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w3.x, w3.y, w3.z);+ rlVertex3f(w2.x, w2.y, w2.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w3.x, w3.y, w3.z);+ rlVertex3f(w4.x, w4.y, w4.z);+ }+ }+ }+ capCenter = startPos;+ b0 = Vector3Scale(b0, -1.0f);+ }+ // render middle+ if (!sphereCase)+ {+ for (int j = 0; j < slices; j++)+ {+ // compute the four vertices+ float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;+ float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;+ Vector3 w1 = {+ startPos.x + ringSin1*b1.x + ringCos1*b2.x,+ startPos.y + ringSin1*b1.y + ringCos1*b2.y,+ startPos.z + ringSin1*b1.z + ringCos1*b2.z+ };+ float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;+ float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;+ Vector3 w2 = {+ startPos.x + ringSin2*b1.x + ringCos2*b2.x,+ startPos.y + ringSin2*b1.y + ringCos2*b2.y,+ startPos.z + ringSin2*b1.z + ringCos2*b2.z+ };++ float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;+ float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;+ Vector3 w3 = {+ endPos.x + ringSin3*b1.x + ringCos3*b2.x,+ endPos.y + ringSin3*b1.y + ringCos3*b2.y,+ endPos.z + ringSin3*b1.z + ringCos3*b2.z+ };+ float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;+ float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;+ Vector3 w4 = {+ endPos.x + ringSin4*b1.x + ringCos4*b2.x,+ endPos.y + ringSin4*b1.y + ringCos4*b2.y,+ endPos.z + ringSin4*b1.z + ringCos4*b2.z+ };+ // w2 x.-----------x startPos+ rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 /+ rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. /+ rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. /+ // | 2 \ T 'x w1+ rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos+ rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/+ rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | /+ // '.\|/+ // 'x w3+ }+ }+ rlEnd();+}++// Draw capsule wires with the center of its sphere caps at startPos and endPos+void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)+{+ if (slices < 3) slices = 3;++ Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };++ // draw a sphere if start and end points are the same+ bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);+ if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};++ // Construct a basis of the base and the caps:+ Vector3 b0 = Vector3Normalize(direction);+ Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction));+ Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction));+ Vector3 capCenter = endPos;++ float baseSliceAngle = (2.0f*PI)/slices;+ float baseRingAngle = PI*0.5f/rings;++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ // render both caps+ for (int c = 0; c < 2; c++)+ {+ for (int i = 0; i < rings; i++)+ {+ for (int j = 0; j < slices; j++)+ {++ // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier++ // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))+ // as we iterate through the rings they must get smaller by the cos(angle(i))++ // compute the four vertices+ float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));+ float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));+ Vector3 w1 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z)*radius+ };+ float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));+ float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 0 ));+ Vector3 w2 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z)*radius+ };++ float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));+ float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 1 ));+ Vector3 w3 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z)*radius+ };+ float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));+ float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle*( i + 1 ));+ Vector3 w4 = (Vector3){+ capCenter.x + (sinf(baseRingAngle*( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x)*radius,+ capCenter.y + (sinf(baseRingAngle*( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y)*radius,+ capCenter.z + (sinf(baseRingAngle*( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z)*radius+ };++ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w2.x, w2.y, w2.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w3.x, w3.y, w3.z);++ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w3.x, w3.y, w3.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w4.x, w4.y, w4.z);++ rlVertex3f(w3.x, w3.y, w3.z);+ rlVertex3f(w4.x, w4.y, w4.z);+ }+ }+ capCenter = startPos;+ b0 = Vector3Scale(b0, -1.0f);+ }+ // render middle+ if (!sphereCase)+ {+ for (int j = 0; j < slices; j++)+ {+ // compute the four vertices+ float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;+ float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;+ Vector3 w1 = {+ startPos.x + ringSin1*b1.x + ringCos1*b2.x,+ startPos.y + ringSin1*b1.y + ringCos1*b2.y,+ startPos.z + ringSin1*b1.z + ringCos1*b2.z+ };+ float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;+ float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;+ Vector3 w2 = {+ startPos.x + ringSin2*b1.x + ringCos2*b2.x,+ startPos.y + ringSin2*b1.y + ringCos2*b2.y,+ startPos.z + ringSin2*b1.z + ringCos2*b2.z+ };++ float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;+ float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;+ Vector3 w3 = {+ endPos.x + ringSin3*b1.x + ringCos3*b2.x,+ endPos.y + ringSin3*b1.y + ringCos3*b2.y,+ endPos.z + ringSin3*b1.z + ringCos3*b2.z+ };+ float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;+ float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;+ Vector3 w4 = {+ endPos.x + ringSin4*b1.x + ringCos4*b2.x,+ endPos.y + ringSin4*b1.y + ringCos4*b2.y,+ endPos.z + ringSin4*b1.z + ringCos4*b2.z+ };++ rlVertex3f(w1.x, w1.y, w1.z);+ rlVertex3f(w3.x, w3.y, w3.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w4.x, w4.y, w4.z);++ rlVertex3f(w2.x, w2.y, w2.z);+ rlVertex3f(w3.x, w3.y, w3.z);+ }+ }+ rlEnd();+}++// Draw a plane+void DrawPlane(Vector3 centerPos, Vector2 size, Color color)+{+ // NOTE: Plane is always created on XZ ground+ rlPushMatrix();+ rlTranslatef(centerPos.x, centerPos.y, centerPos.z);+ rlScalef(size.x, 1.0f, size.y);++ rlBegin(RL_QUADS);+ rlColor4ub(color.r, color.g, color.b, color.a);+ rlNormal3f(0.0f, 1.0f, 0.0f);++ rlVertex3f(-0.5f, 0.0f, -0.5f);+ rlVertex3f(-0.5f, 0.0f, 0.5f);+ rlVertex3f(0.5f, 0.0f, 0.5f);+ rlVertex3f(0.5f, 0.0f, -0.5f);+ rlEnd();+ rlPopMatrix();+}++// Draw a ray line+void DrawRay(Ray ray, Color color)+{+ float scale = 10000;++ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);+ rlColor4ub(color.r, color.g, color.b, color.a);++ rlVertex3f(ray.position.x, ray.position.y, ray.position.z);+ rlVertex3f(ray.position.x + ray.direction.x*scale, ray.position.y + ray.direction.y*scale, ray.position.z + ray.direction.z*scale);+ rlEnd();+}++// Draw a grid centered at (0, 0, 0)+void DrawGrid(int slices, float spacing)+{+ int halfSlices = slices/2;++ rlBegin(RL_LINES);+ for (int i = -halfSlices; i <= halfSlices; i++)+ {+ if (i == 0)+ {+ rlColor3f(0.5f, 0.5f, 0.5f);+ }+ else+ {+ rlColor3f(0.75f, 0.75f, 0.75f);+ }++ rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);+ rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);++ rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);+ rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);+ }+ rlEnd();+}++// Load model from files (mesh and material)+Model LoadModel(const char *fileName)+{+ Model model = { 0 };++#if defined(SUPPORT_FILEFORMAT_OBJ)+ if (IsFileExtension(fileName, ".obj")) model = LoadOBJ(fileName);+#endif+#if defined(SUPPORT_FILEFORMAT_IQM)+ if (IsFileExtension(fileName, ".iqm")) model = LoadIQM(fileName);+#endif+#if defined(SUPPORT_FILEFORMAT_GLTF)+ if (IsFileExtension(fileName, ".gltf") || IsFileExtension(fileName, ".glb")) model = LoadGLTF(fileName);+#endif+#if defined(SUPPORT_FILEFORMAT_VOX)+ if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName);+#endif+#if defined(SUPPORT_FILEFORMAT_M3D)+ if (IsFileExtension(fileName, ".m3d")) model = LoadM3D(fileName);+#endif++ // Make sure model transform is set to identity matrix!+ model.transform = MatrixIdentity();++ if ((model.meshCount != 0) && (model.meshes != NULL))+ {+ // Upload vertex data to GPU (static meshes)+ for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false);+ }+ else TRACELOG(LOG_WARNING, "MESH: [%s] Failed to load model mesh(es) data", fileName);++ if (model.materialCount == 0)+ {+ TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to load model material data, default to white material", fileName);++ model.materialCount = 1;+ model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));+ model.materials[0] = LoadMaterialDefault();++ if (model.meshMaterial == NULL) model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));+ }++ return model;+}++// Load model from generated mesh+// WARNING: A shallow copy of mesh is generated, passed by value,+// as long as struct contains pointers to data and some values, we get a copy+// of mesh pointing to same data as original version... be careful!+Model LoadModelFromMesh(Mesh mesh)+{+ Model model = { 0 };++ model.transform = MatrixIdentity();++ model.meshCount = 1;+ model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));+ model.meshes[0] = mesh;++ model.materialCount = 1;+ model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));+ model.materials[0] = LoadMaterialDefault();++ model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));+ model.meshMaterial[0] = 0; // First material index++ return model;+}++// Check if a model is ready+bool IsModelReady(Model model)+{+ bool result = false;++ if ((model.meshes != NULL) && // Validate model contains some mesh+ (model.materials != NULL) && // Validate model contains some material (at least default one)+ (model.meshMaterial != NULL) && // Validate mesh-material linkage+ (model.meshCount > 0) && // Validate mesh count+ (model.materialCount > 0)) result = true; // Validate material count++ // NOTE: This is a very general model validation, many elements could be validated from a model...++ return result;+}++// Unload model (meshes/materials) from memory (RAM and/or VRAM)+// NOTE: This function takes care of all model elements, for a detailed control+// over them, use UnloadMesh() and UnloadMaterial()+void UnloadModel(Model model)+{+ // Unload meshes+ for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]);++ // Unload materials maps+ // NOTE: As the user could be sharing shaders and textures between models,+ // we don't unload the material but just free its maps,+ // the user is responsible for freeing models shaders and textures+ for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);++ // Unload arrays+ RL_FREE(model.meshes);+ RL_FREE(model.materials);+ RL_FREE(model.meshMaterial);++ // Unload animation data+ RL_FREE(model.bones);+ RL_FREE(model.bindPose);++ TRACELOG(LOG_INFO, "MODEL: Unloaded model (and meshes) from RAM and VRAM");+}++// Compute model bounding box limits (considers all meshes)+BoundingBox GetModelBoundingBox(Model model)+{+ BoundingBox bounds = { 0 };++ if (model.meshCount > 0)+ {+ Vector3 temp = { 0 };+ bounds = GetMeshBoundingBox(model.meshes[0]);++ for (int i = 1; i < model.meshCount; i++)+ {+ BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]);++ temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x;+ temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y;+ temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z;+ bounds.min = temp;++ temp.x = (bounds.max.x > tempBounds.max.x)? bounds.max.x : tempBounds.max.x;+ temp.y = (bounds.max.y > tempBounds.max.y)? bounds.max.y : tempBounds.max.y;+ temp.z = (bounds.max.z > tempBounds.max.z)? bounds.max.z : tempBounds.max.z;+ bounds.max = temp;+ }+ }++ // Apply model.transform to bounding box+ // WARNING: Current BoundingBox structure design does not support rotation transformations,+ // in those cases is up to the user to calculate the proper box bounds (8 vertices transformed)+ bounds.min = Vector3Transform(bounds.min, model.transform);+ bounds.max = Vector3Transform(bounds.max, model.transform);++ return bounds;+}++// Upload vertex data into a VAO (if supported) and VBO+void UploadMesh(Mesh *mesh, bool dynamic)+{+ if (mesh->vaoId > 0)+ {+ // Check if mesh has already been loaded in GPU+ TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId);+ return;+ }++ mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));++ mesh->vaoId = 0; // Vertex Array Object+ mesh->vboId[0] = 0; // Vertex buffer: positions+ mesh->vboId[1] = 0; // Vertex buffer: texcoords+ mesh->vboId[2] = 0; // Vertex buffer: normals+ mesh->vboId[3] = 0; // Vertex buffer: colors+ mesh->vboId[4] = 0; // Vertex buffer: tangents+ mesh->vboId[5] = 0; // Vertex buffer: texcoords2+ mesh->vboId[6] = 0; // Vertex buffer: indices++#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)+ mesh->vaoId = rlLoadVertexArray();+ rlEnableVertexArray(mesh->vaoId);++ // NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data++ // Enable vertex attributes: position (shader-location = 0)+ void *vertices = (mesh->animVertices != NULL)? mesh->animVertices : mesh->vertices;+ mesh->vboId[0] = rlLoadVertexBuffer(vertices, mesh->vertexCount*3*sizeof(float), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);++ // Enable vertex attributes: texcoords (shader-location = 1)+ mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);++ // WARNING: When setting default vertex attribute values, the values for each generic vertex attribute+ // is part of current state, and it is maintained even if a different program object is used++ if (mesh->normals != NULL)+ {+ // Enable vertex attributes: normals (shader-location = 2)+ void *normals = (mesh->animNormals != NULL)? mesh->animNormals : mesh->normals;+ mesh->vboId[2] = rlLoadVertexBuffer(normals, mesh->vertexCount*3*sizeof(float), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);+ }+ else+ {+ // Default vertex attribute: normal+ // WARNING: Default value provided to shader if location available+ float value[3] = { 1.0f, 1.0f, 1.0f };+ rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, value, SHADER_ATTRIB_VEC3, 3);+ rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);+ }++ if (mesh->colors != NULL)+ {+ // Enable vertex attribute: color (shader-location = 3)+ mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, 4, RL_UNSIGNED_BYTE, 1, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);+ }+ else+ {+ // Default vertex attribute: color+ // WARNING: Default value provided to shader if location available+ float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // WHITE+ rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, value, SHADER_ATTRIB_VEC4, 4);+ rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);+ }++ if (mesh->tangents != NULL)+ {+ // Enable vertex attribute: tangent (shader-location = 4)+ mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);+ }+ else+ {+ // Default vertex attribute: tangent+ // WARNING: Default value provided to shader if location available+ float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f };+ rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, value, SHADER_ATTRIB_VEC4, 4);+ rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);+ }++ if (mesh->texcoords2 != NULL)+ {+ // Enable vertex attribute: texcoord2 (shader-location = 5)+ mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);+ }+ else+ {+ // Default vertex attribute: texcoord2+ // WARNING: Default value provided to shader if location available+ float value[2] = { 0.0f, 0.0f };+ rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, value, SHADER_ATTRIB_VEC2, 2);+ rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2);+ }++ if (mesh->indices != NULL)+ {+ mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic);+ }++ if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);+ else TRACELOG(LOG_INFO, "VBO: Mesh uploaded successfully to VRAM (GPU)");++ rlDisableVertexArray();+#endif+}++// Update mesh vertex data in GPU for a specific buffer index+void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset)+{+ rlUpdateVertexBuffer(mesh.vboId[index], data, dataSize, offset);+}++// Draw a 3d mesh with material and transform+void DrawMesh(Mesh mesh, Material material, Matrix transform)+{+#if defined(GRAPHICS_API_OPENGL_11)+ #define GL_VERTEX_ARRAY 0x8074+ #define GL_NORMAL_ARRAY 0x8075+ #define GL_COLOR_ARRAY 0x8076+ #define GL_TEXTURE_COORD_ARRAY 0x8078++ rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);++ rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);+ rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);+ rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);+ rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);++ rlPushMatrix();+ rlMultMatrixf(MatrixToFloat(transform));+ rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r,+ material.maps[MATERIAL_MAP_DIFFUSE].color.g,+ material.maps[MATERIAL_MAP_DIFFUSE].color.b,+ material.maps[MATERIAL_MAP_DIFFUSE].color.a);++ if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices);+ else rlDrawVertexArray(0, mesh.vertexCount);+ rlPopMatrix();++ rlDisableStatePointer(GL_VERTEX_ARRAY);+ rlDisableStatePointer(GL_TEXTURE_COORD_ARRAY);+ rlDisableStatePointer(GL_NORMAL_ARRAY);+ rlDisableStatePointer(GL_COLOR_ARRAY);++ rlDisableTexture();+#endif++#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)+ // Bind shader program+ rlEnableShader(material.shader.id);++ // Send required data to shader (matrices, values)+ //-----------------------------------------------------+ // Upload to shader material.colDiffuse+ if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)+ {+ float values[4] = {+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f+ };++ rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);+ }++ // Upload to shader material.colSpecular (if location available)+ if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)+ {+ float values[4] = {+ (float)material.maps[MATERIAL_MAP_SPECULAR].color.r/255.0f,+ (float)material.maps[MATERIAL_MAP_SPECULAR].color.g/255.0f,+ (float)material.maps[MATERIAL_MAP_SPECULAR].color.b/255.0f,+ (float)material.maps[MATERIAL_MAP_SPECULAR].color.a/255.0f+ };++ rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);+ }++ // Get a copy of current matrices to work with,+ // just in case stereo render is required, and we need to modify them+ // NOTE: At this point the modelview matrix just contains the view matrix (camera)+ // That's because BeginMode3D() sets it and there is no model-drawing function+ // that modifies it, all use rlPushMatrix() and rlPopMatrix()+ Matrix matModel = MatrixIdentity();+ Matrix matView = rlGetMatrixModelview();+ Matrix matModelView = MatrixIdentity();+ Matrix matProjection = rlGetMatrixProjection();++ // Upload view and projection matrices (if locations available)+ if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);+ if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);++ // Accumulate several model transformations:+ // transform: model transformation provided (includes DrawModel() params combined with model.transform)+ // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack+ matModel = MatrixMultiply(transform, rlGetMatrixTransform());++ // Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL+ if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], matModel);++ // Get model-view matrix+ matModelView = MatrixMultiply(matModel, matView);++ // Upload model normal matrix (if locations available)+ if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));+ //-----------------------------------------------------++ // Bind active texture maps (if available)+ for (int i = 0; i < MAX_MATERIAL_MAPS; i++)+ {+ if (material.maps[i].texture.id > 0)+ {+ // Select current shader texture slot+ rlActiveTextureSlot(i);++ // Enable texture for active slot+ if ((i == MATERIAL_MAP_IRRADIANCE) ||+ (i == MATERIAL_MAP_PREFILTER) ||+ (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);+ else rlEnableTexture(material.maps[i].texture.id);++ rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);+ }+ }++ // Try binding vertex array objects (VAO) or use VBOs if not possible+ // WARNING: UploadMesh() enables all vertex attributes available in mesh and sets default attribute values+ // for shader expected vertex attributes that are not provided by the mesh (i.e. colors)+ // This could be a dangerous approach because different meshes with different shaders can enable/disable some attributes+ if (!rlEnableVertexArray(mesh.vaoId))+ {+ // Bind mesh VBO data: vertex position (shader-location = 0)+ rlEnableVertexBuffer(mesh.vboId[0]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);++ // Bind mesh VBO data: vertex texcoords (shader-location = 1)+ rlEnableVertexBuffer(mesh.vboId[1]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);++ if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)+ {+ // Bind mesh VBO data: vertex normals (shader-location = 2)+ rlEnableVertexBuffer(mesh.vboId[2]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);+ }++ // Bind mesh VBO data: vertex colors (shader-location = 3, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)+ {+ if (mesh.vboId[3] != 0)+ {+ rlEnableVertexBuffer(mesh.vboId[3]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);+ }+ else+ {+ // Set default value for defined vertex attribute in shader but not provided by mesh+ // WARNING: It could result in GPU undefined behaviour+ float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };+ rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);+ rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);+ }+ }++ // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)+ {+ rlEnableVertexBuffer(mesh.vboId[4]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);+ }++ // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)+ {+ rlEnableVertexBuffer(mesh.vboId[5]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);+ }++ if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);+ }++ int eyeCount = 1;+ if (rlIsStereoRenderEnabled()) eyeCount = 2;++ for (int eye = 0; eye < eyeCount; eye++)+ {+ // Calculate model-view-projection matrix (MVP)+ Matrix matModelViewProjection = MatrixIdentity();+ if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);+ else+ {+ // Setup current eye viewport (half screen width)+ rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());+ matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));+ }++ // Send combined model-view-projection matrix to shader+ rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);++ // Draw mesh+ if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0);+ else rlDrawVertexArray(0, mesh.vertexCount);+ }++ // Unbind all bound texture maps+ for (int i = 0; i < MAX_MATERIAL_MAPS; i++)+ {+ if (material.maps[i].texture.id > 0)+ {+ // Select current shader texture slot+ rlActiveTextureSlot(i);++ // Disable texture for active slot+ if ((i == MATERIAL_MAP_IRRADIANCE) ||+ (i == MATERIAL_MAP_PREFILTER) ||+ (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();+ else rlDisableTexture();+ }+ }++ // Disable all possible vertex array objects (or VBOs)+ rlDisableVertexArray();+ rlDisableVertexBuffer();+ rlDisableVertexBufferElement();++ // Disable shader program+ rlDisableShader();++ // Restore rlgl internal modelview and projection matrices+ rlSetMatrixModelview(matView);+ rlSetMatrixProjection(matProjection);+#endif+}++// Draw multiple mesh instances with material and different transforms+void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances)+{+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)+ // Instancing required variables+ float16 *instanceTransforms = NULL;+ unsigned int instancesVboId = 0;++ // Bind shader program+ rlEnableShader(material.shader.id);++ // Send required data to shader (matrices, values)+ //-----------------------------------------------------+ // Upload to shader material.colDiffuse+ if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)+ {+ float values[4] = {+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,+ (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f+ };++ rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);+ }++ // Upload to shader material.colSpecular (if location available)+ if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)+ {+ float values[4] = {+ (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f,+ (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.g/255.0f,+ (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.b/255.0f,+ (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f+ };++ rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);+ }++ // Get a copy of current matrices to work with,+ // just in case stereo render is required, and we need to modify them+ // NOTE: At this point the modelview matrix just contains the view matrix (camera)+ // That's because BeginMode3D() sets it and there is no model-drawing function+ // that modifies it, all use rlPushMatrix() and rlPopMatrix()+ Matrix matModel = MatrixIdentity();+ Matrix matView = rlGetMatrixModelview();+ Matrix matModelView = MatrixIdentity();+ Matrix matProjection = rlGetMatrixProjection();++ // Upload view and projection matrices (if locations available)+ if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);+ if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);++ // Create instances buffer+ instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));++ // Fill buffer with instances transformations as float16 arrays+ for (int i = 0; i < instances; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);++ // Enable mesh VAO to attach new buffer+ rlEnableVertexArray(mesh.vaoId);++ // This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()+ // It isn't clear which would be reliably faster in all cases and on all platforms,+ // anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems+ // no faster, since we're transferring all the transform matrices anyway+ instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);++ // Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL+ for (unsigned int i = 0; i < 4; i++)+ {+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4));+ rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1);+ }++ rlDisableVertexBuffer();+ rlDisableVertexArray();++ // Accumulate internal matrix transform (push/pop) and view matrix+ // NOTE: In this case, model instance transformation must be computed in the shader+ matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);++ // Upload model normal matrix (if locations available)+ if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));+ //-----------------------------------------------------++ // Bind active texture maps (if available)+ for (int i = 0; i < MAX_MATERIAL_MAPS; i++)+ {+ if (material.maps[i].texture.id > 0)+ {+ // Select current shader texture slot+ rlActiveTextureSlot(i);++ // Enable texture for active slot+ if ((i == MATERIAL_MAP_IRRADIANCE) ||+ (i == MATERIAL_MAP_PREFILTER) ||+ (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);+ else rlEnableTexture(material.maps[i].texture.id);++ rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);+ }+ }++ // Try binding vertex array objects (VAO)+ // or use VBOs if not possible+ if (!rlEnableVertexArray(mesh.vaoId))+ {+ // Bind mesh VBO data: vertex position (shader-location = 0)+ rlEnableVertexBuffer(mesh.vboId[0]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);++ // Bind mesh VBO data: vertex texcoords (shader-location = 1)+ rlEnableVertexBuffer(mesh.vboId[1]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);++ if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)+ {+ // Bind mesh VBO data: vertex normals (shader-location = 2)+ rlEnableVertexBuffer(mesh.vboId[2]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);+ }++ // Bind mesh VBO data: vertex colors (shader-location = 3, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)+ {+ if (mesh.vboId[3] != 0)+ {+ rlEnableVertexBuffer(mesh.vboId[3]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);+ }+ else+ {+ // Set default value for unused attribute+ // NOTE: Required when using default shader and no VAO support+ float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };+ rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);+ rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);+ }+ }++ // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)+ {+ rlEnableVertexBuffer(mesh.vboId[4]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);+ }++ // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)+ if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)+ {+ rlEnableVertexBuffer(mesh.vboId[5]);+ rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);+ }++ if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);+ }++ int eyeCount = 1;+ if (rlIsStereoRenderEnabled()) eyeCount = 2;++ for (int eye = 0; eye < eyeCount; eye++)+ {+ // Calculate model-view-projection matrix (MVP)+ Matrix matModelViewProjection = MatrixIdentity();+ if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);+ else+ {+ // Setup current eye viewport (half screen width)+ rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());+ matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));+ }++ // Send combined model-view-projection matrix to shader+ rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);++ // Draw mesh instanced+ if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);+ else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);+ }++ // Unbind all bound texture maps+ for (int i = 0; i < MAX_MATERIAL_MAPS; i++)+ {+ if (material.maps[i].texture.id > 0)+ {+ // Select current shader texture slot+ rlActiveTextureSlot(i);++ // Disable texture for active slot+ if ((i == MATERIAL_MAP_IRRADIANCE) ||+ (i == MATERIAL_MAP_PREFILTER) ||+ (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();+ else rlDisableTexture();+ }+ }++ // Disable all possible vertex array objects (or VBOs)+ rlDisableVertexArray();+ rlDisableVertexBuffer();+ rlDisableVertexBufferElement();++ // Disable shader program+ rlDisableShader();++ // Remove instance transforms buffer+ rlUnloadVertexBuffer(instancesVboId);+ RL_FREE(instanceTransforms);+#endif+}++// Unload mesh from memory (RAM and VRAM)+void UnloadMesh(Mesh mesh)+{+ // Unload rlgl mesh vboId data+ rlUnloadVertexArray(mesh.vaoId);++ if (mesh.vboId != NULL) for (int i = 0; i < MAX_MESH_VERTEX_BUFFERS; i++) rlUnloadVertexBuffer(mesh.vboId[i]);+ RL_FREE(mesh.vboId);++ RL_FREE(mesh.vertices);+ RL_FREE(mesh.texcoords);+ RL_FREE(mesh.normals);+ RL_FREE(mesh.colors);+ RL_FREE(mesh.tangents);+ RL_FREE(mesh.texcoords2);+ RL_FREE(mesh.indices);++ RL_FREE(mesh.animVertices);+ RL_FREE(mesh.animNormals);+ RL_FREE(mesh.boneWeights);+ RL_FREE(mesh.boneIds);+}++// Export mesh data to file+bool ExportMesh(Mesh mesh, const char *fileName)+{+ bool success = false;++ if (IsFileExtension(fileName, ".obj"))+ {+ // Estimated data size, it should be enough...+ int dataSize = mesh.vertexCount*(int)strlen("v 0000.00f 0000.00f 0000.00f") ++ mesh.vertexCount*(int)strlen("vt 0.000f 0.00f") ++ mesh.vertexCount*(int)strlen("vn 0.000f 0.00f 0.00f") ++ mesh.triangleCount*(int)strlen("f 00000/00000/00000 00000/00000/00000 00000/00000/00000");++ // NOTE: Text data buffer size is estimated considering mesh data size+ char *txtData = (char *)RL_CALLOC(dataSize*2 + 2000, sizeof(char));++ int byteCount = 0;+ byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n");+ byteCount += sprintf(txtData + byteCount, "# // //\n");+ byteCount += sprintf(txtData + byteCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");+ byteCount += sprintf(txtData + byteCount, "# // //\n");+ byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");+ byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n");+ byteCount += sprintf(txtData + byteCount, "# // //\n");+ byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");+ byteCount += sprintf(txtData + byteCount, "# // //\n");+ byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");+ byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount);+ byteCount += sprintf(txtData + byteCount, "# Triangle Count: %i\n\n", mesh.triangleCount);++ byteCount += sprintf(txtData + byteCount, "g mesh\n");++ for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)+ {+ byteCount += sprintf(txtData + byteCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);+ }++ for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)+ {+ byteCount += sprintf(txtData + byteCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);+ }++ for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)+ {+ byteCount += sprintf(txtData + byteCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);+ }++ if (mesh.indices != NULL)+ {+ for (int i = 0, v = 0; i < mesh.triangleCount; i++, v += 3)+ {+ byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n",+ mesh.indices[v] + 1, mesh.indices[v] + 1, mesh.indices[v] + 1,+ mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1, mesh.indices[v + 1] + 1,+ mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1, mesh.indices[v + 2] + 1);+ }+ }+ else+ {+ for (int i = 0, v = 1; i < mesh.triangleCount; i++, v += 3)+ {+ byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", v, v, v, v + 1, v + 1, v + 1, v + 2, v + 2, v + 2);+ }+ }++ byteCount += sprintf(txtData + byteCount, "\n");++ // NOTE: Text data length exported is determined by '\0' (NULL) character+ success = SaveFileText(fileName, txtData);++ RL_FREE(txtData);+ }+ else if (IsFileExtension(fileName, ".raw"))+ {+ // TODO: Support additional file formats to export mesh vertex data+ }++ return success;+}++// Export mesh as code file (.h) defining multiple arrays of vertex attributes+bool ExportMeshAsCode(Mesh mesh, const char *fileName)+{+ bool success = false;++#ifndef TEXT_BYTES_PER_LINE+ #define TEXT_BYTES_PER_LINE 20+#endif++ // NOTE: Text data buffer size is fixed to 64MB+ char *txtData = (char *)RL_CALLOC(64*1024*1024, sizeof(char)); // 64 MB++ int byteCount = 0;+ byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");+ byteCount += sprintf(txtData + byteCount, "// //\n");+ byteCount += sprintf(txtData + byteCount, "// MeshAsCode exporter v1.0 - Mesh vertex data exported as arrays //\n");+ byteCount += sprintf(txtData + byteCount, "// //\n");+ byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");+ byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");+ byteCount += sprintf(txtData + byteCount, "// //\n");+ byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2023 Ramon Santamaria (@raysan5) //\n");+ byteCount += sprintf(txtData + byteCount, "// //\n");+ byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");++ // Get file name from path and convert variable name to uppercase+ char varFileName[256] = { 0 };+ strcpy(varFileName, GetFileNameWithoutExt(fileName));+ for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }++ // Add image information+ byteCount += sprintf(txtData + byteCount, "// Mesh basic information\n");+ byteCount += sprintf(txtData + byteCount, "#define %s_VERTEX_COUNT %i\n", varFileName, mesh.vertexCount);+ byteCount += sprintf(txtData + byteCount, "#define %s_TRIANGLE_COUNT %i\n\n", varFileName, mesh.triangleCount);++ // Define vertex attributes data as separate arrays+ //-----------------------------------------------------------------------------------------+ if (mesh.vertices != NULL) // Vertex position (XYZ - 3 components per vertex - float)+ {+ byteCount += sprintf(txtData + byteCount, "static float %s_VERTEX_DATA[%i] = { ", varFileName, mesh.vertexCount*3);+ for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.vertices[i]);+ byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.vertices[mesh.vertexCount*3 - 1]);+ }++ if (mesh.texcoords != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)+ {+ byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD_DATA[%i] = { ", varFileName, mesh.vertexCount*2);+ for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords[i]);+ byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords[mesh.vertexCount*2 - 1]);+ }++ if (mesh.texcoords2 != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)+ {+ byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD2_DATA[%i] = { ", varFileName, mesh.vertexCount*2);+ for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords2[i]);+ byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords2[mesh.vertexCount*2 - 1]);+ }++ if (mesh.normals != NULL) // Vertex normals (XYZ - 3 components per vertex - float)+ {+ byteCount += sprintf(txtData + byteCount, "static float %s_NORMAL_DATA[%i] = { ", varFileName, mesh.vertexCount*3);+ for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.normals[i]);+ byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.normals[mesh.vertexCount*3 - 1]);+ }++ if (mesh.tangents != NULL) // Vertex tangents (XYZW - 4 components per vertex - float)+ {+ byteCount += sprintf(txtData + byteCount, "static float %s_TANGENT_DATA[%i] = { ", varFileName, mesh.vertexCount*4);+ for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.tangents[i]);+ byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.tangents[mesh.vertexCount*4 - 1]);+ }++ if (mesh.colors != NULL) // Vertex colors (RGBA - 4 components per vertex - unsigned char)+ {+ byteCount += sprintf(txtData + byteCount, "static unsigned char %s_COLOR_DATA[%i] = { ", varFileName, mesh.vertexCount*4);+ for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), mesh.colors[i]);+ byteCount += sprintf(txtData + byteCount, "0x%x };\n\n", mesh.colors[mesh.vertexCount*4 - 1]);+ }++ if (mesh.indices != NULL) // Vertex indices (3 index per triangle - unsigned short)+ {+ byteCount += sprintf(txtData + byteCount, "static unsigned short %s_INDEX_DATA[%i] = { ", varFileName, mesh.triangleCount*3);+ for (int i = 0; i < mesh.triangleCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%i,\n" : "%i, "), mesh.indices[i]);+ byteCount += sprintf(txtData + byteCount, "%i };\n", mesh.indices[mesh.triangleCount*3 - 1]);+ }+ //-----------------------------------------------------------------------------------------++ // NOTE: Text data size exported is determined by '\0' (NULL) character+ success = SaveFileText(fileName, txtData);++ RL_FREE(txtData);++ //if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);+ //else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);++ return success;+}+++#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)+// Process obj materials+static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)+{+ // Init model mats+ for (int m = 0; m < materialCount; m++)+ {+ // Init material to default+ // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE+ materials[m] = LoadMaterialDefault();++ // Get default texture, in case no texture is defined+ // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8+ materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };++ if (mats[m].diffuse_texname != NULL) materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(mats[m].diffuse_texname); //char *diffuse_texname; // map_Kd+ else materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(mats[m].diffuse[0]*255.0f), (unsigned char)(mats[m].diffuse[1]*255.0f), (unsigned char)(mats[m].diffuse[2]*255.0f), 255 }; //float diffuse[3];+ materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;++ if (mats[m].specular_texname != NULL) materials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(mats[m].specular_texname); //char *specular_texname; // map_Ks+ materials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(mats[m].specular[0]*255.0f), (unsigned char)(mats[m].specular[1]*255.0f), (unsigned char)(mats[m].specular[2]*255.0f), 255 }; //float specular[3];+ materials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;++ if (mats[m].bump_texname != NULL) materials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(mats[m].bump_texname); //char *bump_texname; // map_bump, bump+ materials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;+ materials[m].maps[MATERIAL_MAP_NORMAL].value = mats[m].shininess;++ materials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(mats[m].emission[0]*255.0f), (unsigned char)(mats[m].emission[1]*255.0f), (unsigned char)(mats[m].emission[2]*255.0f), 255 }; //float emission[3];++ if (mats[m].displacement_texname != NULL) materials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(mats[m].displacement_texname); //char *displacement_texname; // disp+ }+}+#endif++// Load materials from model file+Material *LoadMaterials(const char *fileName, int *materialCount)+{+ Material *materials = NULL;+ unsigned int count = 0;++ // TODO: Support IQM and GLTF for materials parsing++#if defined(SUPPORT_FILEFORMAT_MTL)+ if (IsFileExtension(fileName, ".mtl"))+ {+ tinyobj_material_t *mats = NULL;++ int result = tinyobj_parse_mtl_file(&mats, &count, fileName);+ if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);++ materials = RL_MALLOC(count*sizeof(Material));+ ProcessMaterialsOBJ(materials, mats, count);++ tinyobj_materials_free(mats, count);+ }+#else+ TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to load material file", fileName);+#endif++ *materialCount = count;+ return materials;+}++// Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)+Material LoadMaterialDefault(void)+{+ Material material = { 0 };+ material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS, sizeof(MaterialMap));++ // Using rlgl default shader+ material.shader.id = rlGetShaderIdDefault();+ material.shader.locs = rlGetShaderLocsDefault();++ // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)+ material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };+ //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set+ //material.maps[MATERIAL_MAP_SPECULAR].texture; // NOTE: By default, not set++ material.maps[MATERIAL_MAP_DIFFUSE].color = WHITE; // Diffuse color+ material.maps[MATERIAL_MAP_SPECULAR].color = WHITE; // Specular color++ return material;+}++// Check if a material is ready+bool IsMaterialReady(Material material)+{+ bool result = false;++ if ((material.maps != NULL) && // Validate material contain some map+ (material.shader.id > 0)) result = true; // Validate material shader is valid++ return result;+}++// Unload material from memory+void UnloadMaterial(Material material)+{+ // Unload material shader (avoid unloading default shader, managed by raylib)+ if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);++ // Unload loaded texture maps (avoid unloading default texture, managed by raylib)+ if (material.maps != NULL)+ {+ for (int i = 0; i < MAX_MATERIAL_MAPS; i++)+ {+ if (material.maps[i].texture.id != rlGetTextureIdDefault()) rlUnloadTexture(material.maps[i].texture.id);+ }+ }++ RL_FREE(material.maps);+}++// Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)+// NOTE: Previous texture should be manually unloaded+void SetMaterialTexture(Material *material, int mapType, Texture2D texture)+{+ material->maps[mapType].texture = texture;+}++// Set the material for a mesh+void SetModelMeshMaterial(Model *model, int meshId, int materialId)+{+ if (meshId >= model->meshCount) TRACELOG(LOG_WARNING, "MESH: Id greater than mesh count");+ else if (materialId >= model->materialCount) TRACELOG(LOG_WARNING, "MATERIAL: Id greater than material count");+ else model->meshMaterial[meshId] = materialId;+}++// Load model animations from file+ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)+{+ ModelAnimation *animations = NULL;++#if defined(SUPPORT_FILEFORMAT_IQM)+ if (IsFileExtension(fileName, ".iqm")) animations = LoadModelAnimationsIQM(fileName, animCount);+#endif+#if defined(SUPPORT_FILEFORMAT_M3D)+ if (IsFileExtension(fileName, ".m3d")) animations = LoadModelAnimationsM3D(fileName, animCount);+#endif+#if defined(SUPPORT_FILEFORMAT_GLTF)+ if (IsFileExtension(fileName, ".gltf;.glb")) animations = LoadModelAnimationsGLTF(fileName, animCount);+#endif++ return animations;+}++// Update model animated vertex data (positions and normals) for a given frame+// NOTE: Updated data is uploaded to GPU+void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)+{+ if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))+ {+ if (frame >= anim.frameCount) frame = frame%anim.frameCount;++ for (int m = 0; m < model.meshCount; m++)+ {+ Mesh mesh = model.meshes[m];++ if (mesh.boneIds == NULL || mesh.boneWeights == NULL)+ {+ TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation(): Mesh %i has no connection to bones", m);+ continue;+ }++ bool updated = false; // Flag to check when anim vertex information is updated+ Vector3 animVertex = { 0 };+ Vector3 animNormal = { 0 };++ Vector3 inTranslation = { 0 };+ Quaternion inRotation = { 0 };+ // Vector3 inScale = { 0 };++ Vector3 outTranslation = { 0 };+ Quaternion outRotation = { 0 };+ Vector3 outScale = { 0 };++ int boneId = 0;+ int boneCounter = 0;+ float boneWeight = 0.0;++ const int vValues = mesh.vertexCount*3;+ for (int vCounter = 0; vCounter < vValues; vCounter += 3)+ {+ mesh.animVertices[vCounter] = 0;+ mesh.animVertices[vCounter + 1] = 0;+ mesh.animVertices[vCounter + 2] = 0;++ if (mesh.animNormals != NULL)+ {+ mesh.animNormals[vCounter] = 0;+ mesh.animNormals[vCounter + 1] = 0;+ mesh.animNormals[vCounter + 2] = 0;+ }++ // Iterates over 4 bones per vertex+ for (int j = 0; j < 4; j++, boneCounter++)+ {+ boneWeight = mesh.boneWeights[boneCounter];++ // Early stop when no transformation will be applied+ if (boneWeight == 0.0f) continue;++ boneId = mesh.boneIds[boneCounter];+ //int boneIdParent = model.bones[boneId].parent;+ inTranslation = model.bindPose[boneId].translation;+ inRotation = model.bindPose[boneId].rotation;+ //inScale = model.bindPose[boneId].scale;+ outTranslation = anim.framePoses[frame][boneId].translation;+ outRotation = anim.framePoses[frame][boneId].rotation;+ outScale = anim.framePoses[frame][boneId].scale;++ // Vertices processing+ // NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)+ animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };+ animVertex = Vector3Subtract(animVertex, inTranslation);+ animVertex = Vector3Multiply(animVertex, outScale);+ animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));+ animVertex = Vector3Add(animVertex, outTranslation);+ //animVertex = Vector3Transform(animVertex, model.transform);+ mesh.animVertices[vCounter] += animVertex.x*boneWeight;+ mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight;+ mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight;+ updated = true;++ // Normals processing+ // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)+ if (mesh.normals != NULL)+ {+ animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };+ animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));+ mesh.animNormals[vCounter] += animNormal.x*boneWeight;+ mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;+ mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;+ }+ }+ }++ // Upload new vertex data to GPU for model drawing+ // NOTE: Only update data when values changed+ if (updated)+ {+ rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position+ rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals+ }+ }+ }+}++// Unload animation array data+void UnloadModelAnimations(ModelAnimation *animations, int animCount)+{+ for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);+ RL_FREE(animations);+}++// Unload animation data+void UnloadModelAnimation(ModelAnimation anim)+{+ for (int i = 0; i < anim.frameCount; i++) RL_FREE(anim.framePoses[i]);++ RL_FREE(anim.bones);+ RL_FREE(anim.framePoses);+}++// Check model animation skeleton match+// NOTE: Only number of bones and parent connections are checked+bool IsModelAnimationValid(Model model, ModelAnimation anim)+{+ int result = true;++ if (model.boneCount != anim.boneCount) result = false;+ else+ {+ for (int i = 0; i < model.boneCount; i++)+ {+ if (model.bones[i].parent != anim.bones[i].parent) { result = false; break; }+ }+ }++ return result;+}++#if defined(SUPPORT_MESH_GENERATION)+// Generate polygonal mesh+Mesh GenMeshPoly(int sides, float radius)+{+ Mesh mesh = { 0 };++ if (sides < 3) return mesh; // Security check++ int vertexCount = sides*3;++ // Vertices definition+ Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));++ float d = 0.0f, dStep = 360.0f/sides;+ for (int v = 0; v < vertexCount - 2; v += 3)+ {+ vertices[v] = (Vector3){ 0.0f, 0.0f, 0.0f };+ vertices[v + 1] = (Vector3){ sinf(DEG2RAD*d)*radius, 0.0f, cosf(DEG2RAD*d)*radius };+ vertices[v + 2] = (Vector3){ sinf(DEG2RAD*(d+dStep))*radius, 0.0f, cosf(DEG2RAD*(d+dStep))*radius };+ d += dStep;+ }++ // Normals definition+ Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));+ for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;++ // TexCoords definition+ Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));+ for (int n = 0; n < vertexCount; n++) texcoords[n] = (Vector2){ 0.0f, 0.0f };++ mesh.vertexCount = vertexCount;+ mesh.triangleCount = sides;+ mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));++ // Mesh vertices position array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.vertices[3*i] = vertices[i].x;+ mesh.vertices[3*i + 1] = vertices[i].y;+ mesh.vertices[3*i + 2] = vertices[i].z;+ }++ // Mesh texcoords array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.texcoords[2*i] = texcoords[i].x;+ mesh.texcoords[2*i + 1] = texcoords[i].y;+ }++ // Mesh normals array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.normals[3*i] = normals[i].x;+ mesh.normals[3*i + 1] = normals[i].y;+ mesh.normals[3*i + 2] = normals[i].z;+ }++ RL_FREE(vertices);+ RL_FREE(normals);+ RL_FREE(texcoords);++ // Upload vertex data to GPU (static mesh)+ // NOTE: mesh.vboId array is allocated inside UploadMesh()+ UploadMesh(&mesh, false);++ return mesh;+}++// Generate plane mesh (with subdivisions)+Mesh GenMeshPlane(float width, float length, int resX, int resZ)+{+ Mesh mesh = { 0 };++#define CUSTOM_MESH_GEN_PLANE+#if defined(CUSTOM_MESH_GEN_PLANE)+ resX++;+ resZ++;++ // Vertices definition+ int vertexCount = resX*resZ; // vertices get reused for the faces++ Vector3 *vertices = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));+ for (int z = 0; z < resZ; z++)+ {+ // [-length/2, length/2]+ float zPos = ((float)z/(resZ - 1) - 0.5f)*length;+ for (int x = 0; x < resX; x++)+ {+ // [-width/2, width/2]+ float xPos = ((float)x/(resX - 1) - 0.5f)*width;+ vertices[x + z*resX] = (Vector3){ xPos, 0.0f, zPos };+ }+ }++ // Normals definition+ Vector3 *normals = (Vector3 *)RL_MALLOC(vertexCount*sizeof(Vector3));+ for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;++ // TexCoords definition+ Vector2 *texcoords = (Vector2 *)RL_MALLOC(vertexCount*sizeof(Vector2));+ for (int v = 0; v < resZ; v++)+ {+ for (int u = 0; u < resX; u++)+ {+ texcoords[u + v*resX] = (Vector2){ (float)u/(resX - 1), (float)v/(resZ - 1) };+ }+ }++ // Triangles definition (indices)+ int numFaces = (resX - 1)*(resZ - 1);+ int *triangles = (int *)RL_MALLOC(numFaces*6*sizeof(int));+ int t = 0;+ for (int face = 0; face < numFaces; face++)+ {+ // Retrieve lower left corner from face ind+ int i = face + face/(resX - 1);++ triangles[t++] = i + resX;+ triangles[t++] = i + 1;+ triangles[t++] = i;++ triangles[t++] = i + resX;+ triangles[t++] = i + resX + 1;+ triangles[t++] = i + 1;+ }++ mesh.vertexCount = vertexCount;+ mesh.triangleCount = numFaces*2;+ mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.indices = (unsigned short *)RL_MALLOC(mesh.triangleCount*3*sizeof(unsigned short));++ // Mesh vertices position array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.vertices[3*i] = vertices[i].x;+ mesh.vertices[3*i + 1] = vertices[i].y;+ mesh.vertices[3*i + 2] = vertices[i].z;+ }++ // Mesh texcoords array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.texcoords[2*i] = texcoords[i].x;+ mesh.texcoords[2*i + 1] = texcoords[i].y;+ }++ // Mesh normals array+ for (int i = 0; i < mesh.vertexCount; i++)+ {+ mesh.normals[3*i] = normals[i].x;+ mesh.normals[3*i + 1] = normals[i].y;+ mesh.normals[3*i + 2] = normals[i].z;+ }++ // Mesh indices array initialization+ for (int i = 0; i < mesh.triangleCount*3; i++) mesh.indices[i] = triangles[i];++ RL_FREE(vertices);+ RL_FREE(normals);+ RL_FREE(texcoords);+ RL_FREE(triangles);++#else // Use par_shapes library to generate plane mesh++ par_shapes_mesh *plane = par_shapes_create_plane(resX, resZ); // No normals/texcoords generated!!!+ par_shapes_scale(plane, width, length, 1.0f);+ par_shapes_rotate(plane, -PI/2.0f, (float[]){ 1, 0, 0 });+ par_shapes_translate(plane, -width/2, 0.0f, length/2);++ mesh.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = plane->ntriangles*3;+ mesh.triangleCount = plane->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = plane->points[plane->triangles[k]*3];+ mesh.vertices[k*3 + 1] = plane->points[plane->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = plane->points[plane->triangles[k]*3 + 2];++ mesh.normals[k*3] = plane->normals[plane->triangles[k]*3];+ mesh.normals[k*3 + 1] = plane->normals[plane->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = plane->normals[plane->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = plane->tcoords[plane->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = plane->tcoords[plane->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(plane);+#endif++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);++ return mesh;+}++// Generated cuboid mesh+Mesh GenMeshCube(float width, float height, float length)+{+ Mesh mesh = { 0 };++#define CUSTOM_MESH_GEN_CUBE+#if defined(CUSTOM_MESH_GEN_CUBE)+ float vertices[] = {+ -width/2, -height/2, length/2,+ width/2, -height/2, length/2,+ width/2, height/2, length/2,+ -width/2, height/2, length/2,+ -width/2, -height/2, -length/2,+ -width/2, height/2, -length/2,+ width/2, height/2, -length/2,+ width/2, -height/2, -length/2,+ -width/2, height/2, -length/2,+ -width/2, height/2, length/2,+ width/2, height/2, length/2,+ width/2, height/2, -length/2,+ -width/2, -height/2, -length/2,+ width/2, -height/2, -length/2,+ width/2, -height/2, length/2,+ -width/2, -height/2, length/2,+ width/2, -height/2, -length/2,+ width/2, height/2, -length/2,+ width/2, height/2, length/2,+ width/2, -height/2, length/2,+ -width/2, -height/2, -length/2,+ -width/2, -height/2, length/2,+ -width/2, height/2, length/2,+ -width/2, height/2, -length/2+ };++ float texcoords[] = {+ 0.0f, 0.0f,+ 1.0f, 0.0f,+ 1.0f, 1.0f,+ 0.0f, 1.0f,+ 1.0f, 0.0f,+ 1.0f, 1.0f,+ 0.0f, 1.0f,+ 0.0f, 0.0f,+ 0.0f, 1.0f,+ 0.0f, 0.0f,+ 1.0f, 0.0f,+ 1.0f, 1.0f,+ 1.0f, 1.0f,+ 0.0f, 1.0f,+ 0.0f, 0.0f,+ 1.0f, 0.0f,+ 1.0f, 0.0f,+ 1.0f, 1.0f,+ 0.0f, 1.0f,+ 0.0f, 0.0f,+ 0.0f, 0.0f,+ 1.0f, 0.0f,+ 1.0f, 1.0f,+ 0.0f, 1.0f+ };++ float normals[] = {+ 0.0f, 0.0f, 1.0f,+ 0.0f, 0.0f, 1.0f,+ 0.0f, 0.0f, 1.0f,+ 0.0f, 0.0f, 1.0f,+ 0.0f, 0.0f,-1.0f,+ 0.0f, 0.0f,-1.0f,+ 0.0f, 0.0f,-1.0f,+ 0.0f, 0.0f,-1.0f,+ 0.0f, 1.0f, 0.0f,+ 0.0f, 1.0f, 0.0f,+ 0.0f, 1.0f, 0.0f,+ 0.0f, 1.0f, 0.0f,+ 0.0f,-1.0f, 0.0f,+ 0.0f,-1.0f, 0.0f,+ 0.0f,-1.0f, 0.0f,+ 0.0f,-1.0f, 0.0f,+ 1.0f, 0.0f, 0.0f,+ 1.0f, 0.0f, 0.0f,+ 1.0f, 0.0f, 0.0f,+ 1.0f, 0.0f, 0.0f,+ -1.0f, 0.0f, 0.0f,+ -1.0f, 0.0f, 0.0f,+ -1.0f, 0.0f, 0.0f,+ -1.0f, 0.0f, 0.0f+ };++ mesh.vertices = (float *)RL_MALLOC(24*3*sizeof(float));+ memcpy(mesh.vertices, vertices, 24*3*sizeof(float));++ mesh.texcoords = (float *)RL_MALLOC(24*2*sizeof(float));+ memcpy(mesh.texcoords, texcoords, 24*2*sizeof(float));++ mesh.normals = (float *)RL_MALLOC(24*3*sizeof(float));+ memcpy(mesh.normals, normals, 24*3*sizeof(float));++ mesh.indices = (unsigned short *)RL_MALLOC(36*sizeof(unsigned short));++ int k = 0;++ // Indices can be initialized right now+ for (int i = 0; i < 36; i += 6)+ {+ mesh.indices[i] = 4*k;+ mesh.indices[i + 1] = 4*k + 1;+ mesh.indices[i + 2] = 4*k + 2;+ mesh.indices[i + 3] = 4*k;+ mesh.indices[i + 4] = 4*k + 2;+ mesh.indices[i + 5] = 4*k + 3;++ k++;+ }++ mesh.vertexCount = 24;+ mesh.triangleCount = 12;++#else // Use par_shapes library to generate cube mesh+/*+// Platonic solids:+par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)+par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)+par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)+par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron+par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron+*/+ // Platonic solid generation: cube (6 sides)+ // NOTE: No normals/texcoords generated by default+ par_shapes_mesh *cube = par_shapes_create_cube();+ cube->tcoords = PAR_MALLOC(float, 2*cube->npoints);+ for (int i = 0; i < 2*cube->npoints; i++) cube->tcoords[i] = 0.0f;+ par_shapes_scale(cube, width, height, length);+ par_shapes_translate(cube, -width/2, 0.0f, -length/2);+ par_shapes_compute_normals(cube);++ mesh.vertices = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(cube->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(cube->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = cube->ntriangles*3;+ mesh.triangleCount = cube->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = cube->points[cube->triangles[k]*3];+ mesh.vertices[k*3 + 1] = cube->points[cube->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = cube->points[cube->triangles[k]*3 + 2];++ mesh.normals[k*3] = cube->normals[cube->triangles[k]*3];+ mesh.normals[k*3 + 1] = cube->normals[cube->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = cube->normals[cube->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = cube->tcoords[cube->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = cube->tcoords[cube->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(cube);+#endif++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);++ return mesh;+}++// Generate sphere mesh (standard sphere)+Mesh GenMeshSphere(float radius, int rings, int slices)+{+ Mesh mesh = { 0 };++ if ((rings >= 3) && (slices >= 3))+ {+ par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);+ par_shapes_scale(sphere, radius, radius, radius);+ // NOTE: Soft normals are computed internally++ mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = sphere->ntriangles*3;+ mesh.triangleCount = sphere->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];+ mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];++ mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];+ mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(sphere);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: sphere");++ return mesh;+}++// Generate hemisphere mesh (half sphere, no bottom cap)+Mesh GenMeshHemiSphere(float radius, int rings, int slices)+{+ Mesh mesh = { 0 };++ if ((rings >= 3) && (slices >= 3))+ {+ if (radius < 0.0f) radius = 0.0f;++ par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings);+ par_shapes_scale(sphere, radius, radius, radius);+ // NOTE: Soft normals are computed internally++ mesh.vertices = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(sphere->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(sphere->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = sphere->ntriangles*3;+ mesh.triangleCount = sphere->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = sphere->points[sphere->triangles[k]*3];+ mesh.vertices[k*3 + 1] = sphere->points[sphere->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = sphere->points[sphere->triangles[k]*3 + 2];++ mesh.normals[k*3] = sphere->normals[sphere->triangles[k]*3];+ mesh.normals[k*3 + 1] = sphere->normals[sphere->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = sphere->normals[sphere->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = sphere->tcoords[sphere->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = sphere->tcoords[sphere->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(sphere);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: hemisphere");++ return mesh;+}++// Generate cylinder mesh+Mesh GenMeshCylinder(float radius, float height, int slices)+{+ Mesh mesh = { 0 };++ if (slices >= 3)+ {+ // Instance a cylinder that sits on the Z=0 plane using the given tessellation+ // levels across the UV domain. Think of "slices" like a number of pizza+ // slices, and "stacks" like a number of stacked rings+ // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale+ par_shapes_mesh *cylinder = par_shapes_create_cylinder(slices, 8);+ par_shapes_scale(cylinder, radius, radius, height);+ par_shapes_rotate(cylinder, -PI/2.0f, (float[]){ 1, 0, 0 });++ // Generate an orientable disk shape (top cap)+ par_shapes_mesh *capTop = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, 1 });+ capTop->tcoords = PAR_MALLOC(float, 2*capTop->npoints);+ for (int i = 0; i < 2*capTop->npoints; i++) capTop->tcoords[i] = 0.0f;+ par_shapes_rotate(capTop, -PI/2.0f, (float[]){ 1, 0, 0 });+ par_shapes_rotate(capTop, 90*DEG2RAD, (float[]){ 0, 1, 0 });+ par_shapes_translate(capTop, 0, height, 0);++ // Generate an orientable disk shape (bottom cap)+ par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });+ capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);+ for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;+ par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });+ par_shapes_rotate(capBottom, -90*DEG2RAD, (float[]){ 0, 1, 0 });++ par_shapes_merge_and_free(cylinder, capTop);+ par_shapes_merge_and_free(cylinder, capBottom);++ mesh.vertices = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(cylinder->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(cylinder->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = cylinder->ntriangles*3;+ mesh.triangleCount = cylinder->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = cylinder->points[cylinder->triangles[k]*3];+ mesh.vertices[k*3 + 1] = cylinder->points[cylinder->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = cylinder->points[cylinder->triangles[k]*3 + 2];++ mesh.normals[k*3] = cylinder->normals[cylinder->triangles[k]*3];+ mesh.normals[k*3 + 1] = cylinder->normals[cylinder->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = cylinder->normals[cylinder->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = cylinder->tcoords[cylinder->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = cylinder->tcoords[cylinder->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(cylinder);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cylinder");++ return mesh;+}++// Generate cone/pyramid mesh+Mesh GenMeshCone(float radius, float height, int slices)+{+ Mesh mesh = { 0 };++ if (slices >= 3)+ {+ // Instance a cone that sits on the Z=0 plane using the given tessellation+ // levels across the UV domain. Think of "slices" like a number of pizza+ // slices, and "stacks" like a number of stacked rings+ // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale+ par_shapes_mesh *cone = par_shapes_create_cone(slices, 8);+ par_shapes_scale(cone, radius, radius, height);+ par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 });+ par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 });++ // Generate an orientable disk shape (bottom cap)+ par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });+ capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);+ for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;+ par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });++ par_shapes_merge_and_free(cone, capBottom);++ mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = cone->ntriangles*3;+ mesh.triangleCount = cone->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = cone->points[cone->triangles[k]*3];+ mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2];++ mesh.normals[k*3] = cone->normals[cone->triangles[k]*3];+ mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(cone);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone");++ return mesh;+}++// Generate torus mesh+Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)+{+ Mesh mesh = { 0 };++ if ((sides >= 3) && (radSeg >= 3))+ {+ if (radius > 1.0f) radius = 1.0f;+ else if (radius < 0.1f) radius = 0.1f;++ // Create a donut that sits on the Z=0 plane with the specified inner radius+ // The outer radius can be controlled with par_shapes_scale+ par_shapes_mesh *torus = par_shapes_create_torus(radSeg, sides, radius);+ par_shapes_scale(torus, size/2, size/2, size/2);++ mesh.vertices = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(torus->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(torus->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = torus->ntriangles*3;+ mesh.triangleCount = torus->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = torus->points[torus->triangles[k]*3];+ mesh.vertices[k*3 + 1] = torus->points[torus->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = torus->points[torus->triangles[k]*3 + 2];++ mesh.normals[k*3] = torus->normals[torus->triangles[k]*3];+ mesh.normals[k*3 + 1] = torus->normals[torus->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = torus->normals[torus->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = torus->tcoords[torus->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = torus->tcoords[torus->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(torus);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: torus");++ return mesh;+}++// Generate trefoil knot mesh+Mesh GenMeshKnot(float radius, float size, int radSeg, int sides)+{+ Mesh mesh = { 0 };++ if ((sides >= 3) && (radSeg >= 3))+ {+ if (radius > 3.0f) radius = 3.0f;+ else if (radius < 0.5f) radius = 0.5f;++ par_shapes_mesh *knot = par_shapes_create_trefoil_knot(radSeg, sides, radius);+ par_shapes_scale(knot, size, size, size);++ mesh.vertices = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(knot->ntriangles*3*2*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(knot->ntriangles*3*3*sizeof(float));++ mesh.vertexCount = knot->ntriangles*3;+ mesh.triangleCount = knot->ntriangles;++ for (int k = 0; k < mesh.vertexCount; k++)+ {+ mesh.vertices[k*3] = knot->points[knot->triangles[k]*3];+ mesh.vertices[k*3 + 1] = knot->points[knot->triangles[k]*3 + 1];+ mesh.vertices[k*3 + 2] = knot->points[knot->triangles[k]*3 + 2];++ mesh.normals[k*3] = knot->normals[knot->triangles[k]*3];+ mesh.normals[k*3 + 1] = knot->normals[knot->triangles[k]*3 + 1];+ mesh.normals[k*3 + 2] = knot->normals[knot->triangles[k]*3 + 2];++ mesh.texcoords[k*2] = knot->tcoords[knot->triangles[k]*2];+ mesh.texcoords[k*2 + 1] = knot->tcoords[knot->triangles[k]*2 + 1];+ }++ par_shapes_free_mesh(knot);++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);+ }+ else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: knot");++ return mesh;+}++// Generate a mesh from heightmap+// NOTE: Vertex data is uploaded to GPU+Mesh GenMeshHeightmap(Image heightmap, Vector3 size)+{+ #define GRAY_VALUE(c) ((float)(c.r + c.g + c.b)/3.0f)++ Mesh mesh = { 0 };++ int mapX = heightmap.width;+ int mapZ = heightmap.height;++ Color *pixels = LoadImageColors(heightmap);++ // NOTE: One vertex per pixel+ mesh.triangleCount = (mapX - 1)*(mapZ - 1)*2; // One quad every four pixels++ mesh.vertexCount = mesh.triangleCount*3;++ mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));+ mesh.colors = NULL;++ int vCounter = 0; // Used to count vertices float by float+ int tcCounter = 0; // Used to count texcoords float by float+ int nCounter = 0; // Used to count normals float by float++ Vector3 scaleFactor = { size.x/(mapX - 1), size.y/255.0f, size.z/(mapZ - 1) };++ Vector3 vA = { 0 };+ Vector3 vB = { 0 };+ Vector3 vC = { 0 };+ Vector3 vN = { 0 };++ for (int z = 0; z < mapZ-1; z++)+ {+ for (int x = 0; x < mapX-1; x++)+ {+ // Fill vertices array with data+ //----------------------------------------------------------++ // one triangle - 3 vertex+ mesh.vertices[vCounter] = (float)x*scaleFactor.x;+ mesh.vertices[vCounter + 1] = GRAY_VALUE(pixels[x + z*mapX])*scaleFactor.y;+ mesh.vertices[vCounter + 2] = (float)z*scaleFactor.z;++ mesh.vertices[vCounter + 3] = (float)x*scaleFactor.x;+ mesh.vertices[vCounter + 4] = GRAY_VALUE(pixels[x + (z + 1)*mapX])*scaleFactor.y;+ mesh.vertices[vCounter + 5] = (float)(z + 1)*scaleFactor.z;++ mesh.vertices[vCounter + 6] = (float)(x + 1)*scaleFactor.x;+ mesh.vertices[vCounter + 7] = GRAY_VALUE(pixels[(x + 1) + z*mapX])*scaleFactor.y;+ mesh.vertices[vCounter + 8] = (float)z*scaleFactor.z;++ // Another triangle - 3 vertex+ mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6];+ mesh.vertices[vCounter + 10] = mesh.vertices[vCounter + 7];+ mesh.vertices[vCounter + 11] = mesh.vertices[vCounter + 8];++ mesh.vertices[vCounter + 12] = mesh.vertices[vCounter + 3];+ mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4];+ mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5];++ mesh.vertices[vCounter + 15] = (float)(x + 1)*scaleFactor.x;+ mesh.vertices[vCounter + 16] = GRAY_VALUE(pixels[(x + 1) + (z + 1)*mapX])*scaleFactor.y;+ mesh.vertices[vCounter + 17] = (float)(z + 1)*scaleFactor.z;+ vCounter += 18; // 6 vertex, 18 floats++ // Fill texcoords array with data+ //--------------------------------------------------------------+ mesh.texcoords[tcCounter] = (float)x/(mapX - 1);+ mesh.texcoords[tcCounter + 1] = (float)z/(mapZ - 1);++ mesh.texcoords[tcCounter + 2] = (float)x/(mapX - 1);+ mesh.texcoords[tcCounter + 3] = (float)(z + 1)/(mapZ - 1);++ mesh.texcoords[tcCounter + 4] = (float)(x + 1)/(mapX - 1);+ mesh.texcoords[tcCounter + 5] = (float)z/(mapZ - 1);++ mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4];+ mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5];++ mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2];+ mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3];++ mesh.texcoords[tcCounter + 10] = (float)(x + 1)/(mapX - 1);+ mesh.texcoords[tcCounter + 11] = (float)(z + 1)/(mapZ - 1);+ tcCounter += 12; // 6 texcoords, 12 floats++ // Fill normals array with data+ //--------------------------------------------------------------+ for (int i = 0; i < 18; i += 9)+ {+ vA.x = mesh.vertices[nCounter + i];+ vA.y = mesh.vertices[nCounter + i + 1];+ vA.z = mesh.vertices[nCounter + i + 2];++ vB.x = mesh.vertices[nCounter + i + 3];+ vB.y = mesh.vertices[nCounter + i + 4];+ vB.z = mesh.vertices[nCounter + i + 5];++ vC.x = mesh.vertices[nCounter + i + 6];+ vC.y = mesh.vertices[nCounter + i + 7];+ vC.z = mesh.vertices[nCounter + i + 8];++ vN = Vector3Normalize(Vector3CrossProduct(Vector3Subtract(vB, vA), Vector3Subtract(vC, vA)));++ mesh.normals[nCounter + i] = vN.x;+ mesh.normals[nCounter + i + 1] = vN.y;+ mesh.normals[nCounter + i + 2] = vN.z;++ mesh.normals[nCounter + i + 3] = vN.x;+ mesh.normals[nCounter + i + 4] = vN.y;+ mesh.normals[nCounter + i + 5] = vN.z;++ mesh.normals[nCounter + i + 6] = vN.x;+ mesh.normals[nCounter + i + 7] = vN.y;+ mesh.normals[nCounter + i + 8] = vN.z;+ }++ nCounter += 18; // 6 vertex, 18 floats+ }+ }++ UnloadImageColors(pixels); // Unload pixels color data++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);++ return mesh;+}++// Generate a cubes mesh from pixel data+// NOTE: Vertex data is uploaded to GPU+Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)+{+ #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))++ Mesh mesh = { 0 };++ Color *pixels = LoadImageColors(cubicmap);++ // NOTE: Max possible number of triangles numCubes*(12 triangles by cube)+ int maxTriangles = cubicmap.width*cubicmap.height*12;++ int vCounter = 0; // Used to count vertices+ int tcCounter = 0; // Used to count texcoords+ int nCounter = 0; // Used to count normals++ float w = cubeSize.x;+ float h = cubeSize.z;+ float h2 = cubeSize.y;++ Vector3 *mapVertices = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));+ Vector2 *mapTexcoords = (Vector2 *)RL_MALLOC(maxTriangles*3*sizeof(Vector2));+ Vector3 *mapNormals = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));++ // Define the 6 normals of the cube, we will combine them accordingly later...+ Vector3 n1 = { 1.0f, 0.0f, 0.0f };+ Vector3 n2 = { -1.0f, 0.0f, 0.0f };+ Vector3 n3 = { 0.0f, 1.0f, 0.0f };+ Vector3 n4 = { 0.0f, -1.0f, 0.0f };+ Vector3 n5 = { 0.0f, 0.0f, -1.0f };+ Vector3 n6 = { 0.0f, 0.0f, 1.0f };++ // NOTE: We use texture rectangles to define different textures for top-bottom-front-back-right-left (6)+ typedef struct RectangleF {+ float x;+ float y;+ float width;+ float height;+ } RectangleF;++ RectangleF rightTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };+ RectangleF leftTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };+ RectangleF frontTexUV = { 0.0f, 0.0f, 0.5f, 0.5f };+ RectangleF backTexUV = { 0.5f, 0.0f, 0.5f, 0.5f };+ RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };+ RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };++ for (int z = 0; z < cubicmap.height; ++z)+ {+ for (int x = 0; x < cubicmap.width; ++x)+ {+ // Define the 8 vertex of the cube, we will combine them accordingly later...+ Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };+ Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) };+ Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) };+ Vector3 v4 = { w*(x + 0.5f), h2, h*(z - 0.5f) };+ Vector3 v5 = { w*(x + 0.5f), 0, h*(z - 0.5f) };+ Vector3 v6 = { w*(x - 0.5f), 0, h*(z - 0.5f) };+ Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) };+ Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) };++ // We check pixel color to be WHITE -> draw full cube+ if (COLOR_EQUAL(pixels[z*cubicmap.width + x], WHITE))+ {+ // Define triangles and checking collateral cubes+ //------------------------------------------------++ // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)+ // WARNING: Not required for a WHITE cubes, created to allow seeing the map from outside+ mapVertices[vCounter] = v1;+ mapVertices[vCounter + 1] = v2;+ mapVertices[vCounter + 2] = v3;+ mapVertices[vCounter + 3] = v1;+ mapVertices[vCounter + 4] = v3;+ mapVertices[vCounter + 5] = v4;+ vCounter += 6;++ mapNormals[nCounter] = n3;+ mapNormals[nCounter + 1] = n3;+ mapNormals[nCounter + 2] = n3;+ mapNormals[nCounter + 3] = n3;+ mapNormals[nCounter + 4] = n3;+ mapNormals[nCounter + 5] = n3;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };+ mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };+ mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };+ tcCounter += 6;++ // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)+ mapVertices[vCounter] = v6;+ mapVertices[vCounter + 1] = v8;+ mapVertices[vCounter + 2] = v7;+ mapVertices[vCounter + 3] = v6;+ mapVertices[vCounter + 4] = v5;+ mapVertices[vCounter + 5] = v8;+ vCounter += 6;++ mapNormals[nCounter] = n4;+ mapNormals[nCounter + 1] = n4;+ mapNormals[nCounter + 2] = n4;+ mapNormals[nCounter + 3] = n4;+ mapNormals[nCounter + 4] = n4;+ mapNormals[nCounter + 5] = n4;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };+ mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y };+ mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };+ tcCounter += 6;++ // Checking cube on bottom of current cube+ if (((z < cubicmap.height - 1) && COLOR_EQUAL(pixels[(z + 1)*cubicmap.width + x], BLACK)) || (z == cubicmap.height - 1))+ {+ // Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8+ // NOTE: Collateral occluded faces are not generated+ mapVertices[vCounter] = v2;+ mapVertices[vCounter + 1] = v7;+ mapVertices[vCounter + 2] = v3;+ mapVertices[vCounter + 3] = v3;+ mapVertices[vCounter + 4] = v7;+ mapVertices[vCounter + 5] = v8;+ vCounter += 6;++ mapNormals[nCounter] = n6;+ mapNormals[nCounter + 1] = n6;+ mapNormals[nCounter + 2] = n6;+ mapNormals[nCounter + 3] = n6;+ mapNormals[nCounter + 4] = n6;+ mapNormals[nCounter + 5] = n6;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ frontTexUV.x, frontTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };+ mapTexcoords[tcCounter + 3] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ frontTexUV.x, frontTexUV.y + frontTexUV.height };+ mapTexcoords[tcCounter + 5] = (Vector2){ frontTexUV.x + frontTexUV.width, frontTexUV.y + frontTexUV.height };+ tcCounter += 6;+ }++ // Checking cube on top of current cube+ if (((z > 0) && COLOR_EQUAL(pixels[(z - 1)*cubicmap.width + x], BLACK)) || (z == 0))+ {+ // Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5+ // NOTE: Collateral occluded faces are not generated+ mapVertices[vCounter] = v1;+ mapVertices[vCounter + 1] = v5;+ mapVertices[vCounter + 2] = v6;+ mapVertices[vCounter + 3] = v1;+ mapVertices[vCounter + 4] = v4;+ mapVertices[vCounter + 5] = v5;+ vCounter += 6;++ mapNormals[nCounter] = n5;+ mapNormals[nCounter + 1] = n5;+ mapNormals[nCounter + 2] = n5;+ mapNormals[nCounter + 3] = n5;+ mapNormals[nCounter + 4] = n5;+ mapNormals[nCounter + 5] = n5;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y + backTexUV.height };+ mapTexcoords[tcCounter + 3] = (Vector2){ backTexUV.x + backTexUV.width, backTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ backTexUV.x, backTexUV.y };+ mapTexcoords[tcCounter + 5] = (Vector2){ backTexUV.x, backTexUV.y + backTexUV.height };+ tcCounter += 6;+ }++ // Checking cube on right of current cube+ if (((x < cubicmap.width - 1) && COLOR_EQUAL(pixels[z*cubicmap.width + (x + 1)], BLACK)) || (x == cubicmap.width - 1))+ {+ // Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5+ // NOTE: Collateral occluded faces are not generated+ mapVertices[vCounter] = v3;+ mapVertices[vCounter + 1] = v8;+ mapVertices[vCounter + 2] = v4;+ mapVertices[vCounter + 3] = v4;+ mapVertices[vCounter + 4] = v8;+ mapVertices[vCounter + 5] = v5;+ vCounter += 6;++ mapNormals[nCounter] = n1;+ mapNormals[nCounter + 1] = n1;+ mapNormals[nCounter + 2] = n1;+ mapNormals[nCounter + 3] = n1;+ mapNormals[nCounter + 4] = n1;+ mapNormals[nCounter + 5] = n1;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ rightTexUV.x, rightTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };+ mapTexcoords[tcCounter + 3] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ rightTexUV.x, rightTexUV.y + rightTexUV.height };+ mapTexcoords[tcCounter + 5] = (Vector2){ rightTexUV.x + rightTexUV.width, rightTexUV.y + rightTexUV.height };+ tcCounter += 6;+ }++ // Checking cube on left of current cube+ if (((x > 0) && COLOR_EQUAL(pixels[z*cubicmap.width + (x - 1)], BLACK)) || (x == 0))+ {+ // Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7+ // NOTE: Collateral occluded faces are not generated+ mapVertices[vCounter] = v1;+ mapVertices[vCounter + 1] = v7;+ mapVertices[vCounter + 2] = v2;+ mapVertices[vCounter + 3] = v1;+ mapVertices[vCounter + 4] = v6;+ mapVertices[vCounter + 5] = v7;+ vCounter += 6;++ mapNormals[nCounter] = n2;+ mapNormals[nCounter + 1] = n2;+ mapNormals[nCounter + 2] = n2;+ mapNormals[nCounter + 3] = n2;+ mapNormals[nCounter + 4] = n2;+ mapNormals[nCounter + 5] = n2;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ leftTexUV.x, leftTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y };+ mapTexcoords[tcCounter + 3] = (Vector2){ leftTexUV.x, leftTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ leftTexUV.x, leftTexUV.y + leftTexUV.height };+ mapTexcoords[tcCounter + 5] = (Vector2){ leftTexUV.x + leftTexUV.width, leftTexUV.y + leftTexUV.height };+ tcCounter += 6;+ }+ }+ // We check pixel color to be BLACK, we will only draw floor and roof+ else if (COLOR_EQUAL(pixels[z*cubicmap.width + x], BLACK))+ {+ // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)+ mapVertices[vCounter] = v1;+ mapVertices[vCounter + 1] = v3;+ mapVertices[vCounter + 2] = v2;+ mapVertices[vCounter + 3] = v1;+ mapVertices[vCounter + 4] = v4;+ mapVertices[vCounter + 5] = v3;+ vCounter += 6;++ mapNormals[nCounter] = n4;+ mapNormals[nCounter + 1] = n4;+ mapNormals[nCounter + 2] = n4;+ mapNormals[nCounter + 3] = n4;+ mapNormals[nCounter + 4] = n4;+ mapNormals[nCounter + 5] = n4;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ topTexUV.x, topTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ topTexUV.x, topTexUV.y + topTexUV.height };+ mapTexcoords[tcCounter + 3] = (Vector2){ topTexUV.x, topTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y };+ mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height };+ tcCounter += 6;++ // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)+ mapVertices[vCounter] = v6;+ mapVertices[vCounter + 1] = v7;+ mapVertices[vCounter + 2] = v8;+ mapVertices[vCounter + 3] = v6;+ mapVertices[vCounter + 4] = v8;+ mapVertices[vCounter + 5] = v5;+ vCounter += 6;++ mapNormals[nCounter] = n3;+ mapNormals[nCounter + 1] = n3;+ mapNormals[nCounter + 2] = n3;+ mapNormals[nCounter + 3] = n3;+ mapNormals[nCounter + 4] = n3;+ mapNormals[nCounter + 5] = n3;+ nCounter += 6;++ mapTexcoords[tcCounter] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };+ mapTexcoords[tcCounter + 1] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y + bottomTexUV.height };+ mapTexcoords[tcCounter + 2] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };+ mapTexcoords[tcCounter + 3] = (Vector2){ bottomTexUV.x + bottomTexUV.width, bottomTexUV.y };+ mapTexcoords[tcCounter + 4] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };+ mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y };+ tcCounter += 6;+ }+ }+ }++ // Move data from mapVertices temp arrays to vertices float array+ mesh.vertexCount = vCounter;+ mesh.triangleCount = vCounter/3;++ mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));+ mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));+ mesh.colors = NULL;++ int fCounter = 0;++ // Move vertices data+ for (int i = 0; i < vCounter; i++)+ {+ mesh.vertices[fCounter] = mapVertices[i].x;+ mesh.vertices[fCounter + 1] = mapVertices[i].y;+ mesh.vertices[fCounter + 2] = mapVertices[i].z;+ fCounter += 3;+ }++ fCounter = 0;++ // Move normals data+ for (int i = 0; i < nCounter; i++)+ {+ mesh.normals[fCounter] = mapNormals[i].x;+ mesh.normals[fCounter + 1] = mapNormals[i].y;+ mesh.normals[fCounter + 2] = mapNormals[i].z;+ fCounter += 3;+ }++ fCounter = 0;++ // Move texcoords data+ for (int i = 0; i < tcCounter; i++)+ {+ mesh.texcoords[fCounter] = mapTexcoords[i].x;+ mesh.texcoords[fCounter + 1] = mapTexcoords[i].y;+ fCounter += 2;+ }++ RL_FREE(mapVertices);+ RL_FREE(mapNormals);+ RL_FREE(mapTexcoords);++ UnloadImageColors(pixels); // Unload pixels color data++ // Upload vertex data to GPU (static mesh)+ UploadMesh(&mesh, false);++ return mesh;+}+#endif // SUPPORT_MESH_GENERATION++// Compute mesh bounding box limits+// NOTE: minVertex and maxVertex should be transformed by model transform matrix+BoundingBox GetMeshBoundingBox(Mesh mesh)+{+ // Get min and max vertex to construct bounds (AABB)+ Vector3 minVertex = { 0 };+ Vector3 maxVertex = { 0 };++ if (mesh.vertices != NULL)+ {+ minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };+ maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };++ for (int i = 1; i < mesh.vertexCount; i++)+ {+ minVertex = Vector3Min(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });+ maxVertex = Vector3Max(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] });+ }+ }++ // Create the bounding box+ BoundingBox box = { 0 };+ box.min = minVertex;+ box.max = maxVertex;++ return box;+}++// Compute mesh tangents+// NOTE: To calculate mesh tangents and binormals we need mesh vertex positions and texture coordinates+// Implementation based on: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html+void GenMeshTangents(Mesh *mesh)+{+ if ((mesh->vertices == NULL) || (mesh->texcoords == NULL))+ {+ TRACELOG(LOG_WARNING, "MESH: Tangents generation requires texcoord vertex attribute data");+ return;+ }++ if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));+ else+ {+ RL_FREE(mesh->tangents);+ mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));+ }++ Vector3 *tan1 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));+ Vector3 *tan2 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));++ if (mesh->vertexCount % 3 != 0)+ {+ TRACELOG(LOG_WARNING, "MESH: vertexCount expected to be a multiple of 3. Expect uninitialized values.");+ }++ for (int i = 0; i <= mesh->vertexCount - 3; i += 3)+ {+ // Get triangle vertices+ Vector3 v1 = { mesh->vertices[(i + 0)*3 + 0], mesh->vertices[(i + 0)*3 + 1], mesh->vertices[(i + 0)*3 + 2] };+ Vector3 v2 = { mesh->vertices[(i + 1)*3 + 0], mesh->vertices[(i + 1)*3 + 1], mesh->vertices[(i + 1)*3 + 2] };+ Vector3 v3 = { mesh->vertices[(i + 2)*3 + 0], mesh->vertices[(i + 2)*3 + 1], mesh->vertices[(i + 2)*3 + 2] };++ // Get triangle texcoords+ Vector2 uv1 = { mesh->texcoords[(i + 0)*2 + 0], mesh->texcoords[(i + 0)*2 + 1] };+ Vector2 uv2 = { mesh->texcoords[(i + 1)*2 + 0], mesh->texcoords[(i + 1)*2 + 1] };+ Vector2 uv3 = { mesh->texcoords[(i + 2)*2 + 0], mesh->texcoords[(i + 2)*2 + 1] };++ float x1 = v2.x - v1.x;+ float y1 = v2.y - v1.y;+ float z1 = v2.z - v1.z;+ float x2 = v3.x - v1.x;+ float y2 = v3.y - v1.y;+ float z2 = v3.z - v1.z;++ float s1 = uv2.x - uv1.x;+ float t1 = uv2.y - uv1.y;+ float s2 = uv3.x - uv1.x;+ float t2 = uv3.y - uv1.y;++ float div = s1*t2 - s2*t1;+ float r = (div == 0.0f)? 0.0f : 1.0f/div;++ Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };+ Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };++ tan1[i + 0] = sdir;+ tan1[i + 1] = sdir;+ tan1[i + 2] = sdir;++ tan2[i + 0] = tdir;+ tan2[i + 1] = tdir;+ tan2[i + 2] = tdir;+ }++ // Compute tangents considering normals+ for (int i = 0; i < mesh->vertexCount; i++)+ {+ Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };+ Vector3 tangent = tan1[i];++ // TODO: Review, not sure if tangent computation is right, just used reference proposed maths...+#if defined(COMPUTE_TANGENTS_METHOD_01)+ Vector3 tmp = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));+ tmp = Vector3Normalize(tmp);+ mesh->tangents[i*4 + 0] = tmp.x;+ mesh->tangents[i*4 + 1] = tmp.y;+ mesh->tangents[i*4 + 2] = tmp.z;+ mesh->tangents[i*4 + 3] = 1.0f;+#else+ Vector3OrthoNormalize(&normal, &tangent);+ mesh->tangents[i*4 + 0] = tangent.x;+ mesh->tangents[i*4 + 1] = tangent.y;+ mesh->tangents[i*4 + 2] = tangent.z;+ mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f)? -1.0f : 1.0f;+#endif+ }++ RL_FREE(tan1);+ RL_FREE(tan2);++ if (mesh->vboId != NULL)+ {+ if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)+ {+ // Update existing vertex buffer+ rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);+ }+ else+ {+ // Load a new tangent attributes buffer+ mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);+ }++ rlEnableVertexArray(mesh->vaoId);+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);+ rlDisableVertexArray();+ }++ TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh");+}++// Draw a model (with texture if set)+void DrawModel(Model model, Vector3 position, float scale, Color tint)+{+ Vector3 vScale = { scale, scale, scale };+ Vector3 rotationAxis = { 0.0f, 1.0f, 0.0f };++ DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint);+}++// Draw a model with extended parameters+void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)+{+ // Calculate transformation matrix from function parameters+ // Get transform matrix (rotation -> scale -> translation)+ Matrix matScale = MatrixScale(scale.x, scale.y, scale.z);+ Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD);+ Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z);++ Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);++ // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform)+ model.transform = MatrixMultiply(model.transform, matTransform);++ for (int i = 0; i < model.meshCount; i++)+ {+ Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color;++ Color colorTint = WHITE;+ colorTint.r = (unsigned char)(((int)color.r*(int)tint.r)/255);+ colorTint.g = (unsigned char)(((int)color.g*(int)tint.g)/255);+ colorTint.b = (unsigned char)(((int)color.b*(int)tint.b)/255);+ colorTint.a = (unsigned char)(((int)color.a*(int)tint.a)/255);++ model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;+ DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform);+ model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color;+ }+}++// Draw a model wires (with texture if set)+void DrawModelWires(Model model, Vector3 position, float scale, Color tint)+{+ rlEnableWireMode();++ DrawModel(model, position, scale, tint);++ rlDisableWireMode();+}++// Draw a model wires (with texture if set) with extended parameters+void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)+{+ rlEnableWireMode();++ DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);++ rlDisableWireMode();+}++// Draw a billboard+void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)+{+ Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };++ DrawBillboardRec(camera, texture, source, position, (Vector2) { scale*fabsf((float)source.width/source.height), scale }, tint);+}++// Draw a billboard (part of a texture defined by a rectangle)+void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint)+{+ // NOTE: Billboard locked on axis-Y+ Vector3 up = { 0.0f, 1.0f, 0.0f };++ DrawBillboardPro(camera, texture, source, position, up, size, Vector2Scale(size, 0.5), 0.0f, tint);+}++// Draw a billboard with additional parameters+void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint)+{+ // Compute the up vector and the right vector+ Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);+ Vector3 right = { matView.m0, matView.m4, matView.m8 };+ right = Vector3Scale(right, size.x);+ up = Vector3Scale(up, size.y);++ // Flip the content of the billboard while maintaining the counterclockwise edge rendering order+ if (size.x < 0.0f)+ {+ source.x += size.x;+ source.width *= -1.0;+ right = Vector3Negate(right);+ origin.x *= -1.0f;+ }+ if (size.y < 0.0f)+ {+ source.y += size.y;+ source.height *= -1.0;+ up = Vector3Negate(up);+ origin.y *= -1.0f;+ }++ // Draw the texture region described by source on the following rectangle in 3D space:+ //+ // size.x <--.+ // 3 ^---------------------------+ 2 \ rotation+ // | | /+ // | |+ // | origin.x position |+ // up |.............. | size.y+ // | . |+ // | . origin.y |+ // | . |+ // 0 +---------------------------> 1+ // right+ Vector3 forward;+ if (rotation != 0.0) forward = Vector3CrossProduct(right, up);++ Vector3 origin3D = Vector3Add(Vector3Scale(Vector3Normalize(right), origin.x), Vector3Scale(Vector3Normalize(up), origin.y));++ Vector3 points[4];+ points[0] = Vector3Zero();+ points[1] = right;+ points[2] = Vector3Add(up, right);+ points[3] = up;++ for (int i = 0; i < 4; i++)+ {+ points[i] = Vector3Subtract(points[i], origin3D);+ if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD);+ points[i] = Vector3Add(points[i], position);+ }++ Vector2 texcoords[4];+ texcoords[0] = (Vector2) { (float)source.x/texture.width, (float)(source.y + source.height)/texture.height };+ texcoords[1] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height };+ texcoords[2] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)source.y/texture.height };+ texcoords[3] = (Vector2) { (float)source.x/texture.width, (float)source.y/texture.height };++ rlSetTexture(texture.id);+ rlBegin(RL_QUADS);++ rlColor4ub(tint.r, tint.g, tint.b, tint.a);+ for (int i = 0; i < 4; i++)+ {+ rlTexCoord2f(texcoords[i].x, texcoords[i].y);+ rlVertex3f(points[i].x, points[i].y, points[i].z);+ }++ rlEnd();+ rlSetTexture(0);+}++// Draw a bounding box with wires+void DrawBoundingBox(BoundingBox box, Color color)+{+ Vector3 size = { 0 };++ size.x = fabsf(box.max.x - box.min.x);+ size.y = fabsf(box.max.y - box.min.y);+ size.z = fabsf(box.max.z - box.min.z);++ Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };++ DrawCubeWires(center, size.x, size.y, size.z, color);+}++// Check collision between two spheres+bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2)+{+ bool collision = false;++ // Simple way to check for collision, just checking distance between two points+ // Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution+ /*+ float dx = center1.x - center2.x; // X distance between centers+ float dy = center1.y - center2.y; // Y distance between centers+ float dz = center1.z - center2.z; // Z distance between centers++ float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers++ if (distance <= (radius1 + radius2)) collision = true;+ */++ // Check for distances squared to avoid sqrtf()+ if (Vector3DotProduct(Vector3Subtract(center2, center1), Vector3Subtract(center2, center1)) <= (radius1 + radius2)*(radius1 + radius2)) collision = true;++ return collision;+}++// Check collision between two boxes+// NOTE: Boxes are defined by two points minimum and maximum+bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2)+{+ bool collision = true;++ if ((box1.max.x >= box2.min.x) && (box1.min.x <= box2.max.x))+ {+ if ((box1.max.y < box2.min.y) || (box1.min.y > box2.max.y)) collision = false;+ if ((box1.max.z < box2.min.z) || (box1.min.z > box2.max.z)) collision = false;+ }+ else collision = false;++ return collision;+}++// Check collision between box and sphere+bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius)+{+ bool collision = false;++ float dmin = 0;++ if (center.x < box.min.x) dmin += powf(center.x - box.min.x, 2);+ else if (center.x > box.max.x) dmin += powf(center.x - box.max.x, 2);++ if (center.y < box.min.y) dmin += powf(center.y - box.min.y, 2);+ else if (center.y > box.max.y) dmin += powf(center.y - box.max.y, 2);++ if (center.z < box.min.z) dmin += powf(center.z - box.min.z, 2);+ else if (center.z > box.max.z) dmin += powf(center.z - box.max.z, 2);++ if (dmin <= (radius*radius)) collision = true;++ return collision;+}++// Get collision info between ray and sphere+RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius)+{+ RayCollision collision = { 0 };++ Vector3 raySpherePos = Vector3Subtract(center, ray.position);+ float vector = Vector3DotProduct(raySpherePos, ray.direction);+ float distance = Vector3Length(raySpherePos);+ float d = radius*radius - (distance*distance - vector*vector);++ collision.hit = d >= 0.0f;++ // Check if ray origin is inside the sphere to calculate the correct collision point+ if (distance < radius)+ {+ collision.distance = vector + sqrtf(d);++ // Calculate collision point+ collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));++ // Calculate collision normal (pointing outwards)+ collision.normal = Vector3Negate(Vector3Normalize(Vector3Subtract(collision.point, center)));+ }+ else+ {+ collision.distance = vector - sqrtf(d);++ // Calculate collision point+ collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));++ // Calculate collision normal (pointing inwards)+ collision.normal = Vector3Normalize(Vector3Subtract(collision.point, center));+ }++ return collision;+}++// Get collision info between ray and box+RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)+{+ RayCollision collision = { 0 };++ // Note: If ray.position is inside the box, the distance is negative (as if the ray was reversed)+ // Reversing ray.direction will give use the correct result+ bool insideBox = (ray.position.x > box.min.x) && (ray.position.x < box.max.x) &&+ (ray.position.y > box.min.y) && (ray.position.y < box.max.y) &&+ (ray.position.z > box.min.z) && (ray.position.z < box.max.z);++ if (insideBox) ray.direction = Vector3Negate(ray.direction);++ float t[11] = { 0 };++ t[8] = 1.0f/ray.direction.x;+ t[9] = 1.0f/ray.direction.y;+ t[10] = 1.0f/ray.direction.z;++ t[0] = (box.min.x - ray.position.x)*t[8];+ t[1] = (box.max.x - ray.position.x)*t[8];+ t[2] = (box.min.y - ray.position.y)*t[9];+ t[3] = (box.max.y - ray.position.y)*t[9];+ t[4] = (box.min.z - ray.position.z)*t[10];+ t[5] = (box.max.z - ray.position.z)*t[10];+ t[6] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));+ t[7] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));++ collision.hit = !((t[7] < 0) || (t[6] > t[7]));+ collision.distance = t[6];+ collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, collision.distance));++ // Get box center point+ collision.normal = Vector3Lerp(box.min, box.max, 0.5f);+ // Get vector center point->hit point+ collision.normal = Vector3Subtract(collision.point, collision.normal);+ // Scale vector to unit cube+ // NOTE: We use an additional .01 to fix numerical errors+ collision.normal = Vector3Scale(collision.normal, 2.01f);+ collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));+ // The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f)+ // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal!+ collision.normal.x = (float)((int)collision.normal.x);+ collision.normal.y = (float)((int)collision.normal.y);+ collision.normal.z = (float)((int)collision.normal.z);++ collision.normal = Vector3Normalize(collision.normal);++ if (insideBox)+ {+ // Reset ray.direction+ ray.direction = Vector3Negate(ray.direction);+ // Fix result+ collision.distance *= -1.0f;+ collision.normal = Vector3Negate(collision.normal);+ }++ return collision;+}++// Get collision info between ray and mesh+RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)+{+ RayCollision collision = { 0 };++ // Check if mesh vertex data on CPU for testing+ if (mesh.vertices != NULL)+ {+ int triangleCount = mesh.triangleCount;++ // Test against all triangles in mesh+ for (int i = 0; i < triangleCount; i++)+ {+ Vector3 a, b, c;+ Vector3* vertdata = (Vector3*)mesh.vertices;++ if (mesh.indices)+ {+ a = vertdata[mesh.indices[i*3 + 0]];+ b = vertdata[mesh.indices[i*3 + 1]];+ c = vertdata[mesh.indices[i*3 + 2]];+ }+ else+ {+ a = vertdata[i*3 + 0];+ b = vertdata[i*3 + 1];+ c = vertdata[i*3 + 2];+ }++ a = Vector3Transform(a, transform);+ b = Vector3Transform(b, transform);+ c = Vector3Transform(c, transform);++ RayCollision triHitInfo = GetRayCollisionTriangle(ray, a, b, c);++ if (triHitInfo.hit)+ {+ // Save the closest hit triangle+ if ((!collision.hit) || (collision.distance > triHitInfo.distance)) collision = triHitInfo;+ }+ }+ }++ return collision;+}++// Get collision info between ray and triangle+// NOTE: The points are expected to be in counter-clockwise winding+// NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm+RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3)+{+ #define EPSILON 0.000001f // A small number++ RayCollision collision = { 0 };+ Vector3 edge1 = { 0 };+ Vector3 edge2 = { 0 };+ Vector3 p, q, tv;+ float det, invDet, u, v, t;++ // Find vectors for two edges sharing V1+ edge1 = Vector3Subtract(p2, p1);+ edge2 = Vector3Subtract(p3, p1);++ // Begin calculating determinant - also used to calculate u parameter+ p = Vector3CrossProduct(ray.direction, edge2);++ // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle+ det = Vector3DotProduct(edge1, p);++ // Avoid culling!+ if ((det > -EPSILON) && (det < EPSILON)) return collision;++ invDet = 1.0f/det;++ // Calculate distance from V1 to ray origin+ tv = Vector3Subtract(ray.position, p1);++ // Calculate u parameter and test bound+ u = Vector3DotProduct(tv, p)*invDet;++ // The intersection lies outside the triangle+ if ((u < 0.0f) || (u > 1.0f)) return collision;++ // Prepare to test v parameter+ q = Vector3CrossProduct(tv, edge1);++ // Calculate V parameter and test bound+ v = Vector3DotProduct(ray.direction, q)*invDet;++ // The intersection lies outside the triangle+ if ((v < 0.0f) || ((u + v) > 1.0f)) return collision;++ t = Vector3DotProduct(edge2, q)*invDet;++ if (t > EPSILON)+ {+ // Ray hit, get hit point and normal+ collision.hit = true;+ collision.distance = t;+ collision.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2));+ collision.point = Vector3Add(ray.position, Vector3Scale(ray.direction, t));+ }++ return collision;+}++// Get collision info between ray and quad+// NOTE: The points are expected to be in counter-clockwise winding+RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)+{+ RayCollision collision = { 0 };++ collision = GetRayCollisionTriangle(ray, p1, p2, p4);++ if (!collision.hit) collision = GetRayCollisionTriangle(ray, p2, p3, p4);++ return collision;+}++//----------------------------------------------------------------------------------+// Module specific Functions Definition+//----------------------------------------------------------------------------------+#if defined(SUPPORT_FILEFORMAT_IQM) || defined(SUPPORT_FILEFORMAT_GLTF)+// Build pose from parent joints+// NOTE: Required for animations loading (required by IQM and GLTF)+static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform *transforms)+{+ for (int i = 0; i < boneCount; i++)+ {+ if (bones[i].parent >= 0)+ {+ if (bones[i].parent > i)+ {+ TRACELOG(LOG_WARNING, "Assumes bones are toplogically sorted, but bone %d has parent %d. Skipping.", i, bones[i].parent);+ continue;+ }+ transforms[i].rotation = QuaternionMultiply(transforms[bones[i].parent].rotation, transforms[i].rotation);+ transforms[i].translation = Vector3RotateByQuaternion(transforms[i].translation, transforms[bones[i].parent].rotation);+ transforms[i].translation = Vector3Add(transforms[i].translation, transforms[bones[i].parent].translation);+ transforms[i].scale = Vector3Multiply(transforms[i].scale, transforms[bones[i].parent].scale);+ }+ }+}+#endif++#if defined(SUPPORT_FILEFORMAT_OBJ)+// Load OBJ mesh data+//+// Keep the following information in mind when reading this+// - A mesh is created for every material present in the obj file+// - the model.meshCount is therefore the materialCount returned from tinyobj+// - the mesh is automatically triangulated by tinyobj+static Model LoadOBJ(const char *fileName)+{+ Model model = { 0 };++ tinyobj_attrib_t attrib = { 0 };+ tinyobj_shape_t *meshes = NULL;+ unsigned int meshCount = 0;++ tinyobj_material_t *materials = NULL;+ unsigned int materialCount = 0;++ char *fileText = LoadFileText(fileName);++ if (fileText != NULL)+ {+ unsigned int dataSize = (unsigned int)strlen(fileText);++ char currentDir[1024] = { 0 };+ strcpy(currentDir, GetWorkingDirectory()); // Save current working directory+ const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness+ if (CHDIR(workingDir) != 0)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);+ }++ unsigned int flags = TINYOBJ_FLAG_TRIANGULATE;+ int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileText, dataSize, flags);++ if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);+ else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);++ // WARNING: We are not splitting meshes by materials (previous implementation)+ // Depending on the provided OBJ that was not the best option and it just crashed+ // so, implementation was simplified to prioritize parsed meshes+ model.meshCount = meshCount;++ // Set number of materials available+ // NOTE: There could be more materials available than meshes but it will be resolved at+ // model.meshMaterial, just assigning the right material to corresponding mesh+ model.materialCount = materialCount;+ if (model.materialCount == 0)+ {+ model.materialCount = 1;+ TRACELOG(LOG_INFO, "MODEL: No materials provided, setting one default material for all meshes");+ }++ // Init model meshes and materials+ model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));+ model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int)); // Material index assigned to each mesh+ model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));++ // Process each provided mesh+ for (int i = 0; i < model.meshCount; i++)+ {+ // WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset+ // because in case of triangulated quads, meshes[i].length actually report quads,+ // despite the triangulation that is efectively considered on attrib.num_faces+ unsigned int tris = 0;+ if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;+ else tris = meshes[i + 1].face_offset;++ model.meshes[i].vertexCount = tris*3;+ model.meshes[i].triangleCount = tris; // Face count (triangulated)+ model.meshes[i].vertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));+ model.meshes[i].texcoords = (float *)RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float));+ model.meshes[i].normals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));+ model.meshMaterial[i] = 0; // By default, assign material 0 to each mesh++ // Process all mesh faces+ for (unsigned int face = 0, f = meshes[i].face_offset, v = 0, vt = 0, vn = 0; face < tris; face++, f++, v += 3, vt += 3, vn += 3)+ {+ // Get indices for the face+ tinyobj_vertex_index_t idx0 = attrib.faces[f*3 + 0];+ tinyobj_vertex_index_t idx1 = attrib.faces[f*3 + 1];+ tinyobj_vertex_index_t idx2 = attrib.faces[f*3 + 2];++ // Fill vertices buffer (float) using vertex index of the face+ for (int n = 0; n < 3; n++) { model.meshes[i].vertices[v*3 + n] = attrib.vertices[idx0.v_idx*3 + n]; }+ for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 1)*3 + n] = attrib.vertices[idx1.v_idx*3 + n]; }+ for (int n = 0; n < 3; n++) { model.meshes[i].vertices[(v + 2)*3 + n] = attrib.vertices[idx2.v_idx*3 + n]; }++ if (attrib.num_texcoords > 0)+ {+ // Fill texcoords buffer (float) using vertex index of the face+ // NOTE: Y-coordinate must be flipped upside-down+ model.meshes[i].texcoords[vt*2 + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];+ model.meshes[i].texcoords[vt*2 + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1];++ model.meshes[i].texcoords[(vt + 1)*2 + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];+ model.meshes[i].texcoords[(vt + 1)*2 + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1];++ model.meshes[i].texcoords[(vt + 2)*2 + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];+ model.meshes[i].texcoords[(vt + 2)*2 + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1];+ }++ if (attrib.num_normals > 0)+ {+ // Fill normals buffer (float) using vertex index of the face+ for (int n = 0; n < 3; n++) { model.meshes[i].normals[vn*3 + n] = attrib.normals[idx0.vn_idx*3 + n]; }+ for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 1)*3 + n] = attrib.normals[idx1.vn_idx*3 + n]; }+ for (int n = 0; n < 3; n++) { model.meshes[i].normals[(vn + 2)*3 + n] = attrib.normals[idx2.vn_idx*3 + n]; }+ }+ }+ }++ // Init model materials+ if (materialCount > 0) ProcessMaterialsOBJ(model.materials, materials, materialCount);+ else model.materials[0] = LoadMaterialDefault(); // Set default material for the mesh++ tinyobj_attrib_free(&attrib);+ tinyobj_shapes_free(meshes, model.meshCount);+ tinyobj_materials_free(materials, materialCount);++ UnloadFileText(fileText);++ // Restore current working directory+ if (CHDIR(currentDir) != 0)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", currentDir);+ }+ }++ return model;+}+#endif++#if defined(SUPPORT_FILEFORMAT_IQM)+// Load IQM mesh data+static Model LoadIQM(const char *fileName)+{+ #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number+ #define IQM_VERSION 2 // only IQM version 2 supported++ #define BONE_NAME_LENGTH 32 // BoneInfo name string length+ #define MESH_NAME_LENGTH 32 // Mesh name string length+ #define MATERIAL_NAME_LENGTH 32 // Material name string length++ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);+ unsigned char *fileDataPtr = fileData;++ // IQM file structs+ //-----------------------------------------------------------------------------------+ typedef struct IQMHeader {+ char magic[16];+ unsigned int version;+ unsigned int dataSize;+ unsigned int flags;+ unsigned int num_text, ofs_text;+ unsigned int num_meshes, ofs_meshes;+ unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;+ unsigned int num_triangles, ofs_triangles, ofs_adjacency;+ unsigned int num_joints, ofs_joints;+ unsigned int num_poses, ofs_poses;+ unsigned int num_anims, ofs_anims;+ unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;+ unsigned int num_comment, ofs_comment;+ unsigned int num_extensions, ofs_extensions;+ } IQMHeader;++ typedef struct IQMMesh {+ unsigned int name;+ unsigned int material;+ unsigned int first_vertex, num_vertexes;+ unsigned int first_triangle, num_triangles;+ } IQMMesh;++ typedef struct IQMTriangle {+ unsigned int vertex[3];+ } IQMTriangle;++ typedef struct IQMJoint {+ unsigned int name;+ int parent;+ float translate[3], rotate[4], scale[3];+ } IQMJoint;++ typedef struct IQMVertexArray {+ unsigned int type;+ unsigned int flags;+ unsigned int format;+ unsigned int size;+ unsigned int offset;+ } IQMVertexArray;++ // NOTE: Below IQM structures are not used but listed for reference+ /*+ typedef struct IQMAdjacency {+ unsigned int triangle[3];+ } IQMAdjacency;++ typedef struct IQMPose {+ int parent;+ unsigned int mask;+ float channeloffset[10];+ float channelscale[10];+ } IQMPose;++ typedef struct IQMAnim {+ unsigned int name;+ unsigned int first_frame, num_frames;+ float framerate;+ unsigned int flags;+ } IQMAnim;++ typedef struct IQMBounds {+ float bbmin[3], bbmax[3];+ float xyradius, radius;+ } IQMBounds;+ */+ //-----------------------------------------------------------------------------------++ // IQM vertex data types+ enum {+ IQM_POSITION = 0,+ IQM_TEXCOORD = 1,+ IQM_NORMAL = 2,+ IQM_TANGENT = 3, // NOTE: Tangents unused by default+ IQM_BLENDINDEXES = 4,+ IQM_BLENDWEIGHTS = 5,+ IQM_COLOR = 6,+ IQM_CUSTOM = 0x10 // NOTE: Custom vertex values unused by default+ };++ Model model = { 0 };++ IQMMesh *imesh = NULL;+ IQMTriangle *tri = NULL;+ IQMVertexArray *va = NULL;+ IQMJoint *ijoint = NULL;++ float *vertex = NULL;+ float *normal = NULL;+ float *text = NULL;+ char *blendi = NULL;+ unsigned char *blendw = NULL;+ unsigned char *color = NULL;++ // In case file can not be read, return an empty model+ if (fileDataPtr == NULL) return model;++ const char *basePath = GetDirectoryPath(fileName);++ // Read IQM header+ IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;++ if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);+ return model;+ }++ if (iqmHeader->version != IQM_VERSION)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);+ return model;+ }++ //fileDataPtr += sizeof(IQMHeader); // Move file data pointer++ // Meshes data processing+ imesh = RL_MALLOC(iqmHeader->num_meshes*sizeof(IQMMesh));+ //fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET);+ //fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile);+ memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh));++ model.meshCount = iqmHeader->num_meshes;+ model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));++ model.materialCount = model.meshCount;+ model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));+ model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));++ char name[MESH_NAME_LENGTH] = { 0 };+ char material[MATERIAL_NAME_LENGTH] = { 0 };++ for (int i = 0; i < model.meshCount; i++)+ {+ //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].name, SEEK_SET);+ //fread(name, sizeof(char), MESH_NAME_LENGTH, iqmFile);+ memcpy(name, fileDataPtr + iqmHeader->ofs_text + imesh[i].name, MESH_NAME_LENGTH*sizeof(char));++ //fseek(iqmFile, iqmHeader->ofs_text + imesh[i].material, SEEK_SET);+ //fread(material, sizeof(char), MATERIAL_NAME_LENGTH, iqmFile);+ memcpy(material, fileDataPtr + iqmHeader->ofs_text + imesh[i].material, MATERIAL_NAME_LENGTH*sizeof(char));++ model.materials[i] = LoadMaterialDefault();+ model.materials[i].maps[MATERIAL_MAP_ALBEDO].texture = LoadTexture(TextFormat("%s/%s", basePath, material));++ model.meshMaterial[i] = i;++ TRACELOG(LOG_DEBUG, "MODEL: [%s] mesh name (%s), material (%s)", fileName, name, material);++ model.meshes[i].vertexCount = imesh[i].num_vertexes;++ model.meshes[i].vertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions+ model.meshes[i].normals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals+ model.meshes[i].texcoords = RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords++ model.meshes[i].boneIds = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(unsigned char)); // Up-to 4 bones supported!+ model.meshes[i].boneWeights = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!++ model.meshes[i].triangleCount = imesh[i].num_triangles;+ model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));++ // Animated vertex data, what we actually process for rendering+ // NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)+ model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));+ model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));+ }++ // Triangles data processing+ tri = RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle));+ //fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET);+ //fread(tri, sizeof(IQMTriangle), iqmHeader->num_triangles, iqmFile);+ memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle));++ for (int m = 0; m < model.meshCount; m++)+ {+ int tcounter = 0;++ for (unsigned int i = imesh[m].first_triangle; i < (imesh[m].first_triangle + imesh[m].num_triangles); i++)+ {+ // IQM triangles indexes are stored in counter-clockwise, but raylib processes the index in linear order,+ // expecting they point to the counter-clockwise vertex triangle, so we need to reverse triangle indexes+ // NOTE: raylib renders vertex data in counter-clockwise order (standard convention) by default+ model.meshes[m].indices[tcounter + 2] = tri[i].vertex[0] - imesh[m].first_vertex;+ model.meshes[m].indices[tcounter + 1] = tri[i].vertex[1] - imesh[m].first_vertex;+ model.meshes[m].indices[tcounter] = tri[i].vertex[2] - imesh[m].first_vertex;+ tcounter += 3;+ }+ }++ // Vertex arrays data processing+ va = RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));+ //fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET);+ //fread(va, sizeof(IQMVertexArray), iqmHeader->num_vertexarrays, iqmFile);+ memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray));++ for (unsigned int i = 0; i < iqmHeader->num_vertexarrays; i++)+ {+ switch (va[i].type)+ {+ case IQM_POSITION:+ {+ vertex = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);+ memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ int vCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)+ {+ model.meshes[m].vertices[vCounter] = vertex[i];+ model.meshes[m].animVertices[vCounter] = vertex[i];+ vCounter++;+ }+ }+ } break;+ case IQM_NORMAL:+ {+ normal = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile);+ memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ int vCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)+ {+ model.meshes[m].normals[vCounter] = normal[i];+ model.meshes[m].animNormals[vCounter] = normal[i];+ vCounter++;+ }+ }+ } break;+ case IQM_TEXCOORD:+ {+ text = RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile);+ memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ int vCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*2; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*2; i++)+ {+ model.meshes[m].texcoords[vCounter] = text[i];+ vCounter++;+ }+ }+ } break;+ case IQM_BLENDINDEXES:+ {+ blendi = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile);+ memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ int boneCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)+ {+ model.meshes[m].boneIds[boneCounter] = blendi[i];+ boneCounter++;+ }+ }+ } break;+ case IQM_BLENDWEIGHTS:+ {+ blendw = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);+ memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ int boneCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)+ {+ model.meshes[m].boneWeights[boneCounter] = blendw[i]/255.0f;+ boneCounter++;+ }+ }+ } break;+ case IQM_COLOR:+ {+ color = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char));+ //fseek(iqmFile, va[i].offset, SEEK_SET);+ //fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile);+ memcpy(color, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char));++ for (unsigned int m = 0; m < iqmHeader->num_meshes; m++)+ {+ model.meshes[m].colors = RL_CALLOC(model.meshes[m].vertexCount*4, sizeof(unsigned char));++ int vCounter = 0;+ for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)+ {+ model.meshes[m].colors[vCounter] = color[i];+ vCounter++;+ }+ }+ } break;+ }+ }++ // Bones (joints) data processing+ ijoint = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));+ //fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET);+ //fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);+ memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));++ model.boneCount = iqmHeader->num_joints;+ model.bones = RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo));+ model.bindPose = RL_MALLOC(iqmHeader->num_joints*sizeof(Transform));++ for (unsigned int i = 0; i < iqmHeader->num_joints; i++)+ {+ // Bones+ model.bones[i].parent = ijoint[i].parent;+ //fseek(iqmFile, iqmHeader->ofs_text + ijoint[i].name, SEEK_SET);+ //fread(model.bones[i].name, sizeof(char), BONE_NAME_LENGTH, iqmFile);+ memcpy(model.bones[i].name, fileDataPtr + iqmHeader->ofs_text + ijoint[i].name, BONE_NAME_LENGTH*sizeof(char));++ // Bind pose (base pose)+ model.bindPose[i].translation.x = ijoint[i].translate[0];+ model.bindPose[i].translation.y = ijoint[i].translate[1];+ model.bindPose[i].translation.z = ijoint[i].translate[2];++ model.bindPose[i].rotation.x = ijoint[i].rotate[0];+ model.bindPose[i].rotation.y = ijoint[i].rotate[1];+ model.bindPose[i].rotation.z = ijoint[i].rotate[2];+ model.bindPose[i].rotation.w = ijoint[i].rotate[3];++ model.bindPose[i].scale.x = ijoint[i].scale[0];+ model.bindPose[i].scale.y = ijoint[i].scale[1];+ model.bindPose[i].scale.z = ijoint[i].scale[2];+ }++ BuildPoseFromParentJoints(model.bones, model.boneCount, model.bindPose);++ UnloadFileData(fileData);++ RL_FREE(imesh);+ RL_FREE(tri);+ RL_FREE(va);+ RL_FREE(vertex);+ RL_FREE(normal);+ RL_FREE(text);+ RL_FREE(blendi);+ RL_FREE(blendw);+ RL_FREE(ijoint);+ RL_FREE(color);++ return model;+}++// Load IQM animation data+static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount)+{+ #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number+ #define IQM_VERSION 2 // only IQM version 2 supported++ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);+ unsigned char *fileDataPtr = fileData;++ typedef struct IQMHeader {+ char magic[16];+ unsigned int version;+ unsigned int dataSize;+ unsigned int flags;+ unsigned int num_text, ofs_text;+ unsigned int num_meshes, ofs_meshes;+ unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;+ unsigned int num_triangles, ofs_triangles, ofs_adjacency;+ unsigned int num_joints, ofs_joints;+ unsigned int num_poses, ofs_poses;+ unsigned int num_anims, ofs_anims;+ unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;+ unsigned int num_comment, ofs_comment;+ unsigned int num_extensions, ofs_extensions;+ } IQMHeader;++ typedef struct IQMJoint {+ unsigned int name;+ int parent;+ float translate[3], rotate[4], scale[3];+ } IQMJoint;++ typedef struct IQMPose {+ int parent;+ unsigned int mask;+ float channeloffset[10];+ float channelscale[10];+ } IQMPose;++ typedef struct IQMAnim {+ unsigned int name;+ unsigned int first_frame, num_frames;+ float framerate;+ unsigned int flags;+ } IQMAnim;++ // In case file can not be read, return an empty model+ if (fileDataPtr == NULL) return NULL;++ // Read IQM header+ IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr;++ if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName);+ return NULL;+ }++ if (iqmHeader->version != IQM_VERSION)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version);+ return NULL;+ }++ // Get bones data+ IQMPose *poses = RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose));+ //fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET);+ //fread(poses, sizeof(IQMPose), iqmHeader->num_poses, iqmFile);+ memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose));++ // Get animations data+ *animCount = iqmHeader->num_anims;+ IQMAnim *anim = RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim));+ //fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET);+ //fread(anim, sizeof(IQMAnim), iqmHeader->num_anims, iqmFile);+ memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim));++ ModelAnimation *animations = RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation));++ // frameposes+ unsigned short *framedata = RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));+ //fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET);+ //fread(framedata, sizeof(unsigned short), iqmHeader->num_frames*iqmHeader->num_framechannels, iqmFile);+ memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));++ // joints+ IQMJoint *joints = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));+ memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));++ for (unsigned int a = 0; a < iqmHeader->num_anims; a++)+ {+ animations[a].frameCount = anim[a].num_frames;+ animations[a].boneCount = iqmHeader->num_poses;+ animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));+ animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));+ memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here+ TraceLog(LOG_INFO, "IQM Anim %s", animations[a].name);+ // animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?++ for (unsigned int j = 0; j < iqmHeader->num_poses; j++)+ {+ // If animations and skeleton are in the same file, copy bone names to anim+ if (iqmHeader->num_joints > 0)+ memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char));+ else+ strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // default bone name otherwise+ animations[a].bones[j].parent = poses[j].parent;+ }++ for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqmHeader->num_poses*sizeof(Transform));++ int dcounter = anim[a].first_frame*iqmHeader->num_framechannels;++ for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)+ {+ for (unsigned int i = 0; i < iqmHeader->num_poses; i++)+ {+ animations[a].framePoses[frame][i].translation.x = poses[i].channeloffset[0];++ if (poses[i].mask & 0x01)+ {+ animations[a].framePoses[frame][i].translation.x += framedata[dcounter]*poses[i].channelscale[0];+ dcounter++;+ }++ animations[a].framePoses[frame][i].translation.y = poses[i].channeloffset[1];++ if (poses[i].mask & 0x02)+ {+ animations[a].framePoses[frame][i].translation.y += framedata[dcounter]*poses[i].channelscale[1];+ dcounter++;+ }++ animations[a].framePoses[frame][i].translation.z = poses[i].channeloffset[2];++ if (poses[i].mask & 0x04)+ {+ animations[a].framePoses[frame][i].translation.z += framedata[dcounter]*poses[i].channelscale[2];+ dcounter++;+ }++ animations[a].framePoses[frame][i].rotation.x = poses[i].channeloffset[3];++ if (poses[i].mask & 0x08)+ {+ animations[a].framePoses[frame][i].rotation.x += framedata[dcounter]*poses[i].channelscale[3];+ dcounter++;+ }++ animations[a].framePoses[frame][i].rotation.y = poses[i].channeloffset[4];++ if (poses[i].mask & 0x10)+ {+ animations[a].framePoses[frame][i].rotation.y += framedata[dcounter]*poses[i].channelscale[4];+ dcounter++;+ }++ animations[a].framePoses[frame][i].rotation.z = poses[i].channeloffset[5];++ if (poses[i].mask & 0x20)+ {+ animations[a].framePoses[frame][i].rotation.z += framedata[dcounter]*poses[i].channelscale[5];+ dcounter++;+ }++ animations[a].framePoses[frame][i].rotation.w = poses[i].channeloffset[6];++ if (poses[i].mask & 0x40)+ {+ animations[a].framePoses[frame][i].rotation.w += framedata[dcounter]*poses[i].channelscale[6];+ dcounter++;+ }++ animations[a].framePoses[frame][i].scale.x = poses[i].channeloffset[7];++ if (poses[i].mask & 0x80)+ {+ animations[a].framePoses[frame][i].scale.x += framedata[dcounter]*poses[i].channelscale[7];+ dcounter++;+ }++ animations[a].framePoses[frame][i].scale.y = poses[i].channeloffset[8];++ if (poses[i].mask & 0x100)+ {+ animations[a].framePoses[frame][i].scale.y += framedata[dcounter]*poses[i].channelscale[8];+ dcounter++;+ }++ animations[a].framePoses[frame][i].scale.z = poses[i].channeloffset[9];++ if (poses[i].mask & 0x200)+ {+ animations[a].framePoses[frame][i].scale.z += framedata[dcounter]*poses[i].channelscale[9];+ dcounter++;+ }++ animations[a].framePoses[frame][i].rotation = QuaternionNormalize(animations[a].framePoses[frame][i].rotation);+ }+ }++ // Build frameposes+ for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)+ {+ for (int i = 0; i < animations[a].boneCount; i++)+ {+ if (animations[a].bones[i].parent >= 0)+ {+ animations[a].framePoses[frame][i].rotation = QuaternionMultiply(animations[a].framePoses[frame][animations[a].bones[i].parent].rotation, animations[a].framePoses[frame][i].rotation);+ animations[a].framePoses[frame][i].translation = Vector3RotateByQuaternion(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].rotation);+ animations[a].framePoses[frame][i].translation = Vector3Add(animations[a].framePoses[frame][i].translation, animations[a].framePoses[frame][animations[a].bones[i].parent].translation);+ animations[a].framePoses[frame][i].scale = Vector3Multiply(animations[a].framePoses[frame][i].scale, animations[a].framePoses[frame][animations[a].bones[i].parent].scale);+ }+ }+ }+ }++ UnloadFileData(fileData);++ RL_FREE(joints);+ RL_FREE(framedata);+ RL_FREE(poses);+ RL_FREE(anim);++ return animations;+}++#endif++#if defined(SUPPORT_FILEFORMAT_GLTF)+// Load file data callback for cgltf+static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, const char *path, cgltf_size *size, void **data)+{+ int filesize;+ unsigned char *filedata = LoadFileData(path, &filesize);++ if (filedata == NULL) return cgltf_result_io_error;++ *size = filesize;+ *data = filedata;++ return cgltf_result_success;+}++// Release file data callback for cgltf+static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)+{+ UnloadFileData(data);+}++// Load image from different glTF provided methods (uri, path, buffer_view)+static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPath)+{+ Image image = { 0 };++ if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path)+ {+ if ((strlen(cgltfImage->uri) > 5) &&+ (cgltfImage->uri[0] == 'd') &&+ (cgltfImage->uri[1] == 'a') &&+ (cgltfImage->uri[2] == 't') &&+ (cgltfImage->uri[3] == 'a') &&+ (cgltfImage->uri[4] == ':')) // Check if image is provided as base64 text data+ {+ // Data URI Format: data:<mediatype>;base64,<data>++ // Find the comma+ int i = 0;+ while ((cgltfImage->uri[i] != ',') && (cgltfImage->uri[i] != 0)) i++;++ if (cgltfImage->uri[i] == 0) TRACELOG(LOG_WARNING, "IMAGE: glTF data URI is not a valid image");+ else+ {+ int base64Size = (int)strlen(cgltfImage->uri + i + 1);+ while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings+ int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits+ int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes+ void *data = NULL;++ cgltf_options options = { 0 };+ options.file.read = LoadFileGLTFCallback;+ options.file.release = ReleaseFileGLTFCallback;+ cgltf_result result = cgltf_load_buffer_base64(&options, outSize, cgltfImage->uri + i + 1, &data);++ if (result == cgltf_result_success)+ {+ image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);+ RL_FREE(data);+ }+ }+ }+ else // Check if image is provided as image path+ {+ image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));+ }+ }+ else if (cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer+ {+ unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size);+ int offset = (int)cgltfImage->buffer_view->offset;+ int stride = (int)cgltfImage->buffer_view->stride? (int)cgltfImage->buffer_view->stride : 1;++ // Copy buffer data to memory for loading+ for (unsigned int i = 0; i < cgltfImage->buffer_view->size; i++)+ {+ data[i] = ((unsigned char *)cgltfImage->buffer_view->buffer->data)[offset];+ offset += stride;+ }++ // Check mime_type for image: (cgltfImage->mime_type == "image/png")+ // NOTE: Detected that some models define mime_type as "image\\/png"+ if ((strcmp(cgltfImage->mime_type, "image\\/png") == 0) ||+ (strcmp(cgltfImage->mime_type, "image/png") == 0)) image = LoadImageFromMemory(".png", data, (int)cgltfImage->buffer_view->size);+ else if ((strcmp(cgltfImage->mime_type, "image\\/jpeg") == 0) ||+ (strcmp(cgltfImage->mime_type, "image/jpeg") == 0)) image = LoadImageFromMemory(".jpg", data, (int)cgltfImage->buffer_view->size);+ else TRACELOG(LOG_WARNING, "MODEL: glTF image data MIME type not recognized", TextFormat("%s/%s", texPath, cgltfImage->uri));++ RL_FREE(data);+ }++ return image;+}++// Load bone info from GLTF skin data+static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)+{+ *boneCount = (int)skin.joints_count;+ BoneInfo *bones = RL_MALLOC(skin.joints_count*sizeof(BoneInfo));++ for (unsigned int i = 0; i < skin.joints_count; i++)+ {+ cgltf_node node = *skin.joints[i];+ if (node.name != NULL)+ {+ strncpy(bones[i].name, node.name, sizeof(bones[i].name));+ bones[i].name[sizeof(bones[i].name) - 1] = '\0';+ }++ // Find parent bone index+ int parentIndex = -1;++ for (unsigned int j = 0; j < skin.joints_count; j++)+ {+ if (skin.joints[j] == node.parent)+ {+ parentIndex = (int)j;+ break;+ }+ }++ bones[i].parent = parentIndex;+ }++ return bones;+}++// Load glTF file into model struct, .gltf and .glb supported+static Model LoadGLTF(const char *fileName)+{+ /*********************************************************************************************++ Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend)+ Transform handling implemented by Paul Melis (@paulmelis).+ Reviewed by Ramon Santamaria (@raysan5)++ FEATURES:+ - Supports .gltf and .glb files+ - Supports embedded (base64) or external textures+ - Supports PBR metallic/roughness flow, loads material textures, values and colors+ PBR specular/glossiness flow and extended texture flows not supported+ - Supports multiple meshes per model (every primitives is loaded as a separate mesh)+ - Supports basic animations+ - Transforms, including parent-child relations, are applied on the mesh data, but the+ hierarchy is not kept (as it can't be represented).+ - Mesh instances in the glTF file (i.e. same mesh linked from multiple nodes)+ are turned into separate raylib Meshes.++ RESTRICTIONS:+ - Only triangle meshes supported+ - Vertex attribute types and formats supported:+ > Vertices (position): vec3: float+ > Normals: vec3: float+ > Texcoords: vec2: float+ > Colors: vec4: u8, u16, f32 (normalized)+ > Indices: u16, u32 (truncated to u16)+ - Scenes defined in the glTF file are ignored. All nodes in the file+ are used.++ ***********************************************************************************************/++ // Macro to simplify attributes loading code+ #define LOAD_ATTRIBUTE(accesor, numComp, dataType, dstPtr) \+ { \+ int n = 0; \+ dataType *buffer = (dataType *)accesor->buffer_view->buffer->data + accesor->buffer_view->offset/sizeof(dataType) + accesor->offset/sizeof(dataType); \+ for (unsigned int k = 0; k < accesor->count; k++) \+ {\+ for (int l = 0; l < numComp; l++) \+ {\+ dstPtr[numComp*k + l] = buffer[n + l];\+ }\+ n += (int)(accesor->stride/sizeof(dataType));\+ }\+ }++ Model model = { 0 };++ // glTF file loading+ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);++ if (fileData == NULL) return model;++ // glTF data loading+ cgltf_options options = { 0 };+ options.file.read = LoadFileGLTFCallback;+ options.file.release = ReleaseFileGLTFCallback;+ cgltf_data *data = NULL;+ cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);++ if (result == cgltf_result_success)+ {+ if (data->file_type == cgltf_file_type_glb) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glb) loaded successfully", fileName);+ else if (data->file_type == cgltf_file_type_gltf) TRACELOG(LOG_INFO, "MODEL: [%s] Model basic data (glTF) loaded successfully", fileName);+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Model format not recognized", fileName);++ TRACELOG(LOG_INFO, " > Meshes count: %i", data->meshes_count);+ TRACELOG(LOG_INFO, " > Materials count: %i (+1 default)", data->materials_count);+ TRACELOG(LOG_DEBUG, " > Buffers count: %i", data->buffers_count);+ TRACELOG(LOG_DEBUG, " > Images count: %i", data->images_count);+ TRACELOG(LOG_DEBUG, " > Textures count: %i", data->textures_count);++ // Force reading data buffers (fills buffer_view->buffer->data)+ // NOTE: If an uri is defined to base64 data or external path, it's automatically loaded+ result = cgltf_load_buffers(&options, data, fileName);+ if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load mesh/material buffers", fileName);++ int primitivesCount = 0;+ // NOTE: We will load every primitive in the glTF as a separate raylib Mesh.+ // Determine total number of meshes needed from the node hierarchy.+ for (unsigned int i = 0; i < data->nodes_count; i++)+ {+ cgltf_node *node = &(data->nodes[i]);+ cgltf_mesh *mesh = node->mesh;+ if (!mesh)+ continue;++ for (unsigned int p = 0; p < mesh->primitives_count; p++)+ {+ if (mesh->primitives[p].type == cgltf_primitive_type_triangles)+ primitivesCount++;+ }+ }+ TRACELOG(LOG_DEBUG, " > Primitives (triangles only) count based on hierarchy : %i", primitivesCount);++ // Load our model data: meshes and materials+ model.meshCount = primitivesCount;+ model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));++ // NOTE: We keep an extra slot for default material, in case some mesh requires it+ model.materialCount = (int)data->materials_count + 1;+ model.materials = RL_CALLOC(model.materialCount, sizeof(Material));+ model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)++ // Load mesh-material indices, by default all meshes are mapped to material index: 0+ model.meshMaterial = RL_CALLOC(model.meshCount, sizeof(int));++ // Load materials data+ //----------------------------------------------------------------------------------------------------+ for (unsigned int i = 0, j = 1; i < data->materials_count; i++, j++)+ {+ model.materials[j] = LoadMaterialDefault();+ const char *texPath = GetDirectoryPath(fileName);++ // Check glTF material flow: PBR metallic/roughness flow+ // NOTE: Alternatively, materials can follow PBR specular/glossiness flow+ if (data->materials[i].has_pbr_metallic_roughness)+ {+ // Load base color texture (albedo)+ if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture)+ {+ Image imAlbedo = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath);+ if (imAlbedo.data != NULL)+ {+ model.materials[j].maps[MATERIAL_MAP_ALBEDO].texture = LoadTextureFromImage(imAlbedo);+ UnloadImage(imAlbedo);+ }+ }+ // Load base color factor (tint)+ model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255);+ model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255);+ model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255);+ model.materials[j].maps[MATERIAL_MAP_ALBEDO].color.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255);++ // Load metallic/roughness texture+ if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture)+ {+ Image imMetallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath);+ if (imMetallicRoughness.data != NULL)+ {+ model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(imMetallicRoughness);+ UnloadImage(imMetallicRoughness);+ }++ // Load metallic/roughness material properties+ float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor;+ model.materials[j].maps[MATERIAL_MAP_ROUGHNESS].value = roughness;++ float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor;+ model.materials[j].maps[MATERIAL_MAP_METALNESS].value = metallic;+ }++ // Load normal texture+ if (data->materials[i].normal_texture.texture)+ {+ Image imNormal = LoadImageFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath);+ if (imNormal.data != NULL)+ {+ model.materials[j].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(imNormal);+ UnloadImage(imNormal);+ }+ }++ // Load ambient occlusion texture+ if (data->materials[i].occlusion_texture.texture)+ {+ Image imOcclusion = LoadImageFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath);+ if (imOcclusion.data != NULL)+ {+ model.materials[j].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(imOcclusion);+ UnloadImage(imOcclusion);+ }+ }++ // Load emissive texture+ if (data->materials[i].emissive_texture.texture)+ {+ Image imEmissive = LoadImageFromCgltfImage(data->materials[i].emissive_texture.texture->image, texPath);+ if (imEmissive.data != NULL)+ {+ model.materials[j].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(imEmissive);+ UnloadImage(imEmissive);+ }++ // Load emissive color factor+ model.materials[j].maps[MATERIAL_MAP_EMISSION].color.r = (unsigned char)(data->materials[i].emissive_factor[0]*255);+ model.materials[j].maps[MATERIAL_MAP_EMISSION].color.g = (unsigned char)(data->materials[i].emissive_factor[1]*255);+ model.materials[j].maps[MATERIAL_MAP_EMISSION].color.b = (unsigned char)(data->materials[i].emissive_factor[2]*255);+ model.materials[j].maps[MATERIAL_MAP_EMISSION].color.a = 255;+ }+ }++ // Other possible materials not supported by raylib pipeline:+ // has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen+ }++ // Visit each node in the hierarchy and process any mesh linked from it.+ // Each primitive within a glTF node becomes a Raylib Mesh.+ // The local-to-world transform of each node is used to transform the+ // points/normals/tangents of the created Mesh(es).+ // Any glTF mesh linked from more than one Node (i.e. instancing)+ // is turned into multiple Mesh's, as each Node will have its own+ // transform applied.+ // Note: the code below disregards the scenes defined in the file, all nodes are used.+ //----------------------------------------------------------------------------------------------------+ int meshIndex = 0;+ for (unsigned int i = 0; i < data->nodes_count; i++)+ {+ cgltf_node *node = &(data->nodes[i]);++ cgltf_mesh *mesh = node->mesh;+ if (!mesh)+ continue;++ cgltf_float worldTransform[16];+ cgltf_node_transform_world(node, worldTransform);++ Matrix worldMatrix = {+ worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],+ worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],+ worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],+ worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]+ };++ Matrix worldMatrixNormals = MatrixTranspose(MatrixInvert(worldMatrix));++ for (unsigned int p = 0; p < mesh->primitives_count; p++)+ {+ // NOTE: We only support primitives defined by triangles+ // Other alternatives: points, lines, line_strip, triangle_strip+ if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;++ // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...),+ // Only some formats for each attribute type are supported, read info at the top of this function!++ for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)+ {+ // Check the different attributes for every primitive+ if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_position) // POSITION, vec3, float+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined++ if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))+ {+ // Init raylib mesh vertices to copy glTF attribute data+ model.meshes[meshIndex].vertexCount = (int)attribute->count;+ model.meshes[meshIndex].vertices = RL_MALLOC(attribute->count*3*sizeof(float));++ // Load 3 components of float data type into mesh.vertices+ LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)++ // Transform the vertices+ float *vertices = model.meshes[meshIndex].vertices;+ for (unsigned int k = 0; k < attribute->count; k++)+ {+ Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix);+ vertices[3*k] = vt.x;+ vertices[3*k+1] = vt.y;+ vertices[3*k+2] = vt.z;+ }+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName);+ }+ else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))+ {+ // Init raylib mesh normals to copy glTF attribute data+ model.meshes[meshIndex].normals = RL_MALLOC(attribute->count*3*sizeof(float));++ // Load 3 components of float data type into mesh.normals+ LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)++ // Transform the normals+ float *normals = model.meshes[meshIndex].normals;+ for (unsigned int k = 0; k < attribute->count; k++)+ {+ Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals);+ normals[3*k] = nt.x;+ normals[3*k+1] = nt.y;+ normals[3*k+2] = nt.z;+ }+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName);+ }+ else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec3, float+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))+ {+ // Init raylib mesh tangent to copy glTF attribute data+ model.meshes[meshIndex].tangents = RL_MALLOC(attribute->count*4*sizeof(float));++ // Load 4 components of float data type into mesh.tangents+ LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)++ // Transform the tangents+ float *tangents = model.meshes[meshIndex].tangents;+ for (unsigned int k = 0; k < attribute->count; k++)+ {+ Vector3 tt = Vector3Transform((Vector3){ tangents[3*k], tangents[3*k+1], tangents[3*k+2] }, worldMatrix);+ tangents[3*k] = tt.x;+ tangents[3*k+1] = tt.y;+ tangents[3*k+2] = tt.z;+ }+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName);+ }+ else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_n, vec2, float/u8n/u16n+ {+ // Support up to 2 texture coordinates attributes+ float *texcoordPtr = NULL;++ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ if (attribute->type == cgltf_type_vec2)+ {+ if (attribute->component_type == cgltf_component_type_r_32f) // vec2, float+ {+ // Init raylib mesh texcoords to copy glTF attribute data+ texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));++ // Load 3 components of float data type into mesh.texcoords+ LOAD_ATTRIBUTE(attribute, 2, float, texcoordPtr)+ }+ else if (attribute->component_type == cgltf_component_type_r_8u) // vec2, u8n+ {+ // Init raylib mesh texcoords to copy glTF attribute data+ texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*2*sizeof(unsigned char));+ LOAD_ATTRIBUTE(attribute, 2, unsigned char, temp);++ // Convert data to raylib texcoord data type (float)+ for (unsigned int t = 0; t < attribute->count*2; t++) texcoordPtr[t] = (float)temp[t]/255.0f;++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_16u) // vec2, u16n+ {+ // Init raylib mesh texcoords to copy glTF attribute data+ texcoordPtr = (float *)RL_MALLOC(attribute->count*2*sizeof(float));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*2*sizeof(unsigned short));+ LOAD_ATTRIBUTE(attribute, 2, unsigned short, temp);++ // Convert data to raylib texcoord data type (float)+ for (unsigned int t = 0; t < attribute->count*2; t++) texcoordPtr[t] = (float)temp[t]/65535.0f;++ RL_FREE(temp);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported", fileName);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Texcoords attribute data format not supported, use vec2 float", fileName);++ int index = mesh->primitives[p].attributes[j].index;+ if (index == 0) model.meshes[meshIndex].texcoords = texcoordPtr;+ else if (index == 1) model.meshes[meshIndex].texcoords2 = texcoordPtr;+ else+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] No more than 2 texture coordinates attributes supported", fileName);+ if (texcoordPtr != NULL) RL_FREE(texcoordPtr);+ }+ }+ else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color) // COLOR_n, vec3/vec4, float/u8n/u16n+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ // WARNING: SPECS: All components of each COLOR_n accessor element MUST be clamped to [0.0, 1.0] range++ if (attribute->type == cgltf_type_vec3) // RGB+ {+ if (attribute->component_type == cgltf_component_type_r_8u)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned char *temp = RL_MALLOC(attribute->count*3*sizeof(unsigned char));+ LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);++ // Convert data to raylib color data type (4 bytes)+ for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)+ {+ model.meshes[meshIndex].colors[c] = temp[k];+ model.meshes[meshIndex].colors[c + 1] = temp[k + 1];+ model.meshes[meshIndex].colors[c + 2] = temp[k + 2];+ model.meshes[meshIndex].colors[c + 3] = 255;+ }++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_16u)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned short *temp = RL_MALLOC(attribute->count*3*sizeof(unsigned short));+ LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);++ // Convert data to raylib color data type (4 bytes)+ for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)+ {+ model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[k]/65535.0f)*255.0f);+ model.meshes[meshIndex].colors[c + 1] = (unsigned char)(((float)temp[k + 1]/65535.0f)*255.0f);+ model.meshes[meshIndex].colors[c + 2] = (unsigned char)(((float)temp[k + 2]/65535.0f)*255.0f);+ model.meshes[meshIndex].colors[c + 3] = 255;+ }++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_32f)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ float *temp = RL_MALLOC(attribute->count*3*sizeof(float));+ LOAD_ATTRIBUTE(attribute, 3, float, temp);++ // Convert data to raylib color data type (4 bytes)+ for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)+ {+ model.meshes[meshIndex].colors[c] = (unsigned char)(temp[k]*255.0f);+ model.meshes[meshIndex].colors[c + 1] = (unsigned char)(temp[k + 1]*255.0f);+ model.meshes[meshIndex].colors[c + 2] = (unsigned char)(temp[k + 2]*255.0f);+ model.meshes[meshIndex].colors[c + 3] = 255;+ }++ RL_FREE(temp);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);+ }+ else if (attribute->type == cgltf_type_vec4) // RGBA+ {+ if (attribute->component_type == cgltf_component_type_r_8u)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load 4 components of unsigned char data type into mesh.colors+ LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)+ }+ else if (attribute->component_type == cgltf_component_type_r_16u)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short));+ LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);++ // Convert data to raylib color data type (4 bytes)+ for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f);++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_32f)+ {+ // Init raylib mesh color to copy glTF attribute data+ model.meshes[meshIndex].colors = RL_MALLOC(attribute->count*4*sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ float *temp = RL_MALLOC(attribute->count*4*sizeof(float));+ LOAD_ATTRIBUTE(attribute, 4, float, temp);++ // Convert data to raylib color data type (4 bytes), we expect the color data normalized+ for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);++ RL_FREE(temp);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);+++ }++ // NOTE: Attributes related to animations are processed separately+ }++ // Load primitive indices data (if provided)+ if (mesh->primitives[p].indices != NULL)+ {+ cgltf_accessor *attribute = mesh->primitives[p].indices;++ model.meshes[meshIndex].triangleCount = (int)attribute->count/3;++ if (attribute->component_type == cgltf_component_type_r_16u)+ {+ // Init raylib mesh indices to copy glTF attribute data+ model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));++ // Load unsigned short data type into mesh.indices+ LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)+ }+ else if (attribute->component_type == cgltf_component_type_r_32u)+ {+ // Init raylib mesh indices to copy glTF attribute data+ model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned int *temp = RL_MALLOC(attribute->count*sizeof(unsigned int));+ LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp);++ // Convert data to raylib indices data type (unsigned short)+ for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d];++ TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);++ RL_FREE(temp);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);+ }+ else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh++ // Assign to the primitive mesh the corresponding material index+ // NOTE: If no material defined, mesh uses the already assigned default material (index: 0)+ for (unsigned int m = 0; m < data->materials_count; m++)+ {+ // The primitive actually keeps the pointer to the corresponding material,+ // raylib instead assigns to the mesh the by its index, as loaded in model.materials array+ // To get the index, we check if material pointers match, and we assign the corresponding index,+ // skipping index 0, the default material+ if (&data->materials[m] == mesh->primitives[p].material)+ {+ model.meshMaterial[meshIndex] = m + 1;+ break;+ }+ }++ meshIndex++; // Move to next mesh+ }+ }++ // Load glTF meshes animation data+ // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins+ // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes+ //+ // LIMITATIONS:+ // - Only supports 1 armature per file, and skips loading it if there are multiple armatures+ // - Only supports linear interpolation (default method in Blender when checked "Always Sample Animations" when exporting a GLTF file)+ // - Only supports translation/rotation/scale animation channel.path, weights not considered (i.e. morph targets)+ //----------------------------------------------------------------------------------------------------+ if (data->skins_count == 1)+ {+ cgltf_skin skin = data->skins[0];+ model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);+ model.bindPose = RL_MALLOC(model.boneCount*sizeof(Transform));++ for (int i = 0; i < model.boneCount; i++)+ {+ cgltf_node* node = skin.joints[i];+ cgltf_float worldTransform[16];+ cgltf_node_transform_world(node, worldTransform);+ Matrix worldMatrix = {+ worldTransform[0], worldTransform[4], worldTransform[8], worldTransform[12],+ worldTransform[1], worldTransform[5], worldTransform[9], worldTransform[13],+ worldTransform[2], worldTransform[6], worldTransform[10], worldTransform[14],+ worldTransform[3], worldTransform[7], worldTransform[11], worldTransform[15]+ };+ MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));+ }+ }+ else if (data->skins_count > 1)+ {+ TRACELOG(LOG_ERROR, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);+ }++ meshIndex = 0;+ for (unsigned int i = 0; i < data->nodes_count; i++)+ {+ cgltf_node *node = &(data->nodes[i]);++ cgltf_mesh *mesh = node->mesh;+ if (!mesh)+ continue;++ for (unsigned int p = 0; p < mesh->primitives_count; p++)+ {+ // NOTE: We only support primitives defined by triangles+ if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;++ for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)+ {+ // NOTE: JOINTS_1 + WEIGHT_1 will be used for +4 joints influencing a vertex -> Not supported by raylib++ if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints) // JOINTS_n (vec4: 4 bones max per vertex / u8, u16)+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ // NOTE: JOINTS_n can only be vec4 and u8/u16+ // SPECS: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview++ // WARNING: raylib only supports model.meshes[].boneIds as u8 (unsigned char),+ // if data is provided in any other format, it is converted to supported format but+ // it could imply data loss (a warning message is issued in that case)++ if (attribute->type == cgltf_type_vec4)+ {+ if (attribute->component_type == cgltf_component_type_r_8u)+ {+ // Init raylib mesh boneIds to copy glTF attribute data+ model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));++ // Load attribute: vec4, u8 (unsigned char)+ LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)+ }+ else if (attribute->component_type == cgltf_component_type_r_16u)+ {+ // Init raylib mesh boneIds to copy glTF attribute data+ model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned short *temp = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned short));+ LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);++ // Convert data to raylib color data type (4 bytes)+ bool boneIdOverflowWarning = false;+ for (int b = 0; b < model.meshes[meshIndex].vertexCount*4; b++)+ {+ if ((temp[b] > 255) && !boneIdOverflowWarning)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format (u16) overflow", fileName);+ boneIdOverflowWarning = true;+ }++ // Despite the possible overflow, we convert data to unsigned char+ model.meshes[meshIndex].boneIds[b] = (unsigned char)temp[b];+ }++ RL_FREE(temp);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);+ }+ else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4, u8n/u16n/f32)+ {+ cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;++ if (attribute->type == cgltf_type_vec4)+ {+ // TODO: Support component types: u8, u16?+ if (attribute->component_type == cgltf_component_type_r_8u)+ {+ // Init raylib mesh bone weight to copy glTF attribute data+ model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned char *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned char));+ LOAD_ATTRIBUTE(attribute, 4, unsigned char, temp);++ // Convert data to raylib bone weight data type (4 bytes)+ for (unsigned int b = 0; b < attribute->count*4; b++) model.meshes[meshIndex].boneWeights[b] = (float)temp[b]/255.0f;++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_16u)+ {+ // Init raylib mesh bone weight to copy glTF attribute data+ model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));++ // Load data into a temp buffer to be converted to raylib data type+ unsigned short *temp = RL_MALLOC(attribute->count*4*sizeof(unsigned short));+ LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);++ // Convert data to raylib bone weight data type+ for (unsigned int b = 0; b < attribute->count*4; b++) model.meshes[meshIndex].boneWeights[b] = (float)temp[b]/65535.0f;++ RL_FREE(temp);+ }+ else if (attribute->component_type == cgltf_component_type_r_32f)+ {+ // Init raylib mesh bone weight to copy glTF attribute data+ model.meshes[meshIndex].boneWeights = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));++ // Load 4 components of float data type into mesh.boneWeights+ // for cgltf_attribute_type_weights we have:+ // - data.meshes[0] (256 vertices)+ // - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)+ LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint weight attribute data format not supported, use vec4 float", fileName);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint weight attribute data format not supported, use vec4 float", fileName);+ }+ }++ // Animated vertex data+ model.meshes[meshIndex].animVertices = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));+ memcpy(model.meshes[meshIndex].animVertices, model.meshes[meshIndex].vertices, model.meshes[meshIndex].vertexCount*3*sizeof(float));+ model.meshes[meshIndex].animNormals = RL_CALLOC(model.meshes[meshIndex].vertexCount*3, sizeof(float));+ if (model.meshes[meshIndex].normals != NULL)+ {+ memcpy(model.meshes[meshIndex].animNormals, model.meshes[meshIndex].normals, model.meshes[meshIndex].vertexCount*3*sizeof(float));+ }++ meshIndex++; // Move to next mesh+ }++ }++ // Free all cgltf loaded data+ cgltf_free(data);+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);++ // WARNING: cgltf requires the file pointer available while reading data+ UnloadFileData(fileData);++ return model;+}++// Get interpolated pose for bone sampler at a specific time. Returns true on success+static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_accessor *input, cgltf_accessor *output, float time, void *data)+{+ if (interpolationType >= cgltf_interpolation_type_max_enum) return false;++ // Input and output should have the same count+ float tstart = 0.0f;+ float tend = 0.0f;+ int keyframe = 0; // Defaults to first pose++ for (int i = 0; i < (int)input->count - 1; i++)+ {+ cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);+ if (!r1) return false;++ cgltf_bool r2 = cgltf_accessor_read_float(input, i + 1, &tend, 1);+ if (!r2) return false;++ if ((tstart <= time) && (time < tend))+ {+ keyframe = i;+ break;+ }+ }++ // Constant animation, no need to interpolate+ if (FloatEquals(tend, tstart)) return true;++ float duration = fmaxf((tend - tstart), EPSILON);+ float t = (time - tstart)/duration;+ t = (t < 0.0f)? 0.0f : t;+ t = (t > 1.0f)? 1.0f : t;++ if (output->component_type != cgltf_component_type_r_32f) return false;++ if (output->type == cgltf_type_vec3)+ {+ switch (interpolationType)+ {+ case cgltf_interpolation_type_step:+ {+ float tmp[3] = { 0.0f };+ cgltf_accessor_read_float(output, keyframe, tmp, 3);+ Vector3 v1 = {tmp[0], tmp[1], tmp[2]};+ Vector3 *r = data;++ *r = v1;+ } break;+ case cgltf_interpolation_type_linear:+ {+ float tmp[3] = { 0.0f };+ cgltf_accessor_read_float(output, keyframe, tmp, 3);+ Vector3 v1 = {tmp[0], tmp[1], tmp[2]};+ cgltf_accessor_read_float(output, keyframe+1, tmp, 3);+ Vector3 v2 = {tmp[0], tmp[1], tmp[2]};+ Vector3 *r = data;++ *r = Vector3Lerp(v1, v2, t);+ } break;+ case cgltf_interpolation_type_cubic_spline:+ {+ float tmp[3] = { 0.0f };+ cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 3);+ Vector3 v1 = {tmp[0], tmp[1], tmp[2]};+ cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 3);+ Vector3 tangent1 = {tmp[0], tmp[1], tmp[2]};+ cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 3);+ Vector3 v2 = {tmp[0], tmp[1], tmp[2]};+ cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 3);+ Vector3 tangent2 = {tmp[0], tmp[1], tmp[2]};+ Vector3 *r = data;++ *r = Vector3CubicHermite(v1, tangent1, v2, tangent2, t);+ } break;+ default: break;+ }+ }+ else if (output->type == cgltf_type_vec4)+ {+ // Only v4 is for rotations, so we know it's a quaternion+ switch (interpolationType)+ {+ case cgltf_interpolation_type_step:+ {+ float tmp[4] = { 0.0f };+ cgltf_accessor_read_float(output, keyframe, tmp, 4);+ Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};+ Vector4 *r = data;++ *r = v1;+ } break;+ case cgltf_interpolation_type_linear:+ {+ float tmp[4] = { 0.0f };+ cgltf_accessor_read_float(output, keyframe, tmp, 4);+ Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};+ cgltf_accessor_read_float(output, keyframe+1, tmp, 4);+ Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};+ Vector4 *r = data;++ *r = QuaternionSlerp(v1, v2, t);+ } break;+ case cgltf_interpolation_type_cubic_spline:+ {+ float tmp[4] = { 0.0f };+ cgltf_accessor_read_float(output, 3*keyframe+1, tmp, 4);+ Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]};+ cgltf_accessor_read_float(output, 3*keyframe+2, tmp, 4);+ Vector4 outTangent1 = {tmp[0], tmp[1], tmp[2]};+ cgltf_accessor_read_float(output, 3*(keyframe+1)+1, tmp, 4);+ Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};+ cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 4);+ Vector4 inTangent2 = {tmp[0], tmp[1], tmp[2]};+ Vector4 *r = data;++ v1 = QuaternionNormalize(v1);+ v2 = QuaternionNormalize(v2);++ if (Vector4DotProduct(v1, v2) < 0.0f)+ {+ v2 = Vector4Negate(v2);+ }++ outTangent1 = Vector4Scale(outTangent1, duration);+ inTangent2 = Vector4Scale(inTangent2, duration);++ *r = QuaternionCubicHermiteSpline(v1, outTangent1, v2, inTangent2, t);+ } break;+ default: break;+ }+ }++ return true;+}++#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)++static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)+{+ // glTF file loading+ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);++ ModelAnimation *animations = NULL;++ // glTF data loading+ cgltf_options options = { 0 };+ options.file.read = LoadFileGLTFCallback;+ options.file.release = ReleaseFileGLTFCallback;+ cgltf_data *data = NULL;+ cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);++ if (result != cgltf_result_success)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);+ *animCount = 0;+ return NULL;+ }++ result = cgltf_load_buffers(&options, data, fileName);+ if (result != cgltf_result_success) TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load animation buffers", fileName);++ if (result == cgltf_result_success)+ {+ if (data->skins_count == 1)+ {+ cgltf_skin skin = data->skins[0];+ *animCount = (int)data->animations_count;+ animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));++ for (unsigned int i = 0; i < data->animations_count; i++)+ {+ animations[i].bones = LoadBoneInfoGLTF(skin, &animations[i].boneCount);++ cgltf_animation animData = data->animations[i];++ struct Channels {+ cgltf_animation_channel *translate;+ cgltf_animation_channel *rotate;+ cgltf_animation_channel *scale;+ cgltf_interpolation_type interpolationType;+ };++ struct Channels *boneChannels = RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));+ float animDuration = 0.0f;++ for (unsigned int j = 0; j < animData.channels_count; j++)+ {+ cgltf_animation_channel channel = animData.channels[j];+ int boneIndex = -1;++ for (unsigned int k = 0; k < skin.joints_count; k++)+ {+ if (animData.channels[j].target_node == skin.joints[k])+ {+ boneIndex = k;+ break;+ }+ }++ if (boneIndex == -1)+ {+ // Animation channel for a node not in the armature+ continue;+ }++ boneChannels[boneIndex].interpolationType = animData.channels[j].sampler->interpolation;++ if (animData.channels[j].sampler->interpolation != cgltf_interpolation_type_max_enum)+ {+ if (channel.target_path == cgltf_animation_path_type_translation)+ {+ boneChannels[boneIndex].translate = &animData.channels[j];+ }+ else if (channel.target_path == cgltf_animation_path_type_rotation)+ {+ boneChannels[boneIndex].rotate = &animData.channels[j];+ }+ else if (channel.target_path == cgltf_animation_path_type_scale)+ {+ boneChannels[boneIndex].scale = &animData.channels[j];+ }+ else+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Unsupported target_path on channel %d's sampler for animation %d. Skipping.", fileName, j, i);+ }+ }+ else TRACELOG(LOG_WARNING, "MODEL: [%s] Invalid interpolation curve encountered for GLTF animation.", fileName);++ float t = 0.0f;+ cgltf_bool r = cgltf_accessor_read_float(channel.sampler->input, channel.sampler->input->count - 1, &t, 1);++ if (!r)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load input time", fileName);+ continue;+ }++ animDuration = (t > animDuration)? t : animDuration;+ }++ if (animData.name != NULL)+ {+ strncpy(animations[i].name, animData.name, sizeof(animations[i].name));+ animations[i].name[sizeof(animations[i].name) - 1] = '\0';+ }++ animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY) + 1;+ animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));++ for (int j = 0; j < animations[i].frameCount; j++)+ {+ animations[i].framePoses[j] = RL_MALLOC(animations[i].boneCount*sizeof(Transform));+ float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;++ for (int k = 0; k < animations[i].boneCount; k++)+ {+ Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};+ Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};+ Vector3 scale = {skin.joints[k]->scale[0], skin.joints[k]->scale[1], skin.joints[k]->scale[2]};++ if (boneChannels[k].translate)+ {+ if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))+ {+ TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load translate pose data for bone %s", fileName, animations[i].bones[k].name);+ }+ }++ if (boneChannels[k].rotate)+ {+ if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].rotate->sampler->input, boneChannels[k].rotate->sampler->output, time, &rotation))+ {+ TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load rotate pose data for bone %s", fileName, animations[i].bones[k].name);+ }+ }++ if (boneChannels[k].scale)+ {+ if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].scale->sampler->input, boneChannels[k].scale->sampler->output, time, &scale))+ {+ TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load scale pose data for bone %s", fileName, animations[i].bones[k].name);+ }+ }++ animations[i].framePoses[j][k] = (Transform){+ .translation = translation,+ .rotation = rotation,+ .scale = scale+ };+ }++ BuildPoseFromParentJoints(animations[i].bones, animations[i].boneCount, animations[i].framePoses[j]);+ }++ TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s (%d frames, %fs)", fileName, (animData.name != NULL)? animData.name : "NULL", animations[i].frameCount, animDuration);+ RL_FREE(boneChannels);+ }+ }+ else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);++ cgltf_free(data);+ }+ UnloadFileData(fileData);+ return animations;+}+#endif++#if defined(SUPPORT_FILEFORMAT_VOX)+// Load VOX (MagicaVoxel) mesh data+static Model LoadVOX(const char *fileName)+{+ Model model = { 0 };++ int nbvertices = 0;+ int meshescount = 0;++ // Read vox file into buffer+ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);++ if (fileData == 0)+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);+ return model;+ }++ // Read and build voxarray description+ VoxArray3D voxarray = { 0 };+ int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);++ if (ret != VOX_SUCCESS)+ {+ // Error+ UnloadFileData(fileData);++ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName);+ return model;+ }+ else+ {+ // Success: Compute meshes count+ nbvertices = voxarray.vertices.used;+ meshescount = 1 + (nbvertices/65536);++ TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount);+ }++ // Build models from meshes+ model.transform = MatrixIdentity();++ model.meshCount = meshescount;+ model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));++ model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));++ model.materialCount = 1;+ model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));+ model.materials[0] = LoadMaterialDefault();++ // Init model meshes+ int verticesRemain = voxarray.vertices.used;+ int verticesMax = 65532; // 5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536)++ // 6*4 = 12 vertices per voxel+ Vector3 *pvertices = (Vector3 *)voxarray.vertices.array;+ Vector3 *pnormals = (Vector3 *)voxarray.normals.array;+ Color *pcolors = (Color *)voxarray.colors.array;++ unsigned short *pindices = voxarray.indices.array; // 5461*6*6 = 196596 indices max per mesh++ int size = 0;++ for (int i = 0; i < meshescount; i++)+ {+ Mesh *pmesh = &model.meshes[i];+ memset(pmesh, 0, sizeof(Mesh));++ // Copy vertices+ pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain);++ size = pmesh->vertexCount*sizeof(float)*3;+ pmesh->vertices = (float *)RL_MALLOC(size);+ memcpy(pmesh->vertices, pvertices, size);++ // Copy normals+ pmesh->normals = (float *)RL_MALLOC(size);+ memcpy(pmesh->normals, pnormals, size);++ // Copy indices+ size = voxarray.indices.used*sizeof(unsigned short);+ pmesh->indices = (unsigned short *)RL_MALLOC(size);+ memcpy(pmesh->indices, pindices, size);++ pmesh->triangleCount = (pmesh->vertexCount/4)*2;++ // Copy colors+ size = pmesh->vertexCount*sizeof(Color);+ pmesh->colors = RL_MALLOC(size);+ memcpy(pmesh->colors, pcolors, size);++ // First material index+ model.meshMaterial[i] = 0;++ verticesRemain -= verticesMax;+ pvertices += verticesMax;+ pnormals += verticesMax;+ pcolors += verticesMax;+ }++ // Free buffers+ Vox_FreeArrays(&voxarray);+ UnloadFileData(fileData);++ return model;+}+#endif++#if defined(SUPPORT_FILEFORMAT_M3D)+// Hook LoadFileData()/UnloadFileData() calls to M3D loaders+unsigned char *m3d_loaderhook(char *fn, unsigned int *len) { return LoadFileData((const char *)fn, (int *)len); }+void m3d_freehook(void *data) { UnloadFileData((unsigned char *)data); }++// Load M3D mesh data+static Model LoadM3D(const char *fileName)+{+ Model model = { 0 };++ m3d_t *m3d = NULL;+ m3dp_t *prop = NULL;+ int i, j, k, l, n, mi = -2, vcolor = 0;++ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);++ if (fileData != NULL)+ {+ m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);++ if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);+ if (m3d) m3d_free(m3d);+ UnloadFileData(fileData);+ return model;+ }+ else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i faces/%i materials", fileName, m3d->numface, m3d->nummaterial);++ // no face? this is probably just a material library+ if (!m3d->numface)+ {+ m3d_free(m3d);+ UnloadFileData(fileData);+ return model;+ }++ if (m3d->nummaterial > 0)+ {+ model.meshCount = model.materialCount = m3d->nummaterial;+ TRACELOG(LOG_INFO, "MODEL: model has %i material meshes", model.materialCount);+ }+ else+ {+ model.meshCount = 1; model.materialCount = 0;+ TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");+ }++ // We always need a default material, so we add +1+ model.materialCount++;++ // Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise+ // WARNING: Sorting is not needed, valid M3D model files should already be sorted+ // Just keeping the sorting function for reference (Check PR #3363 #3385)+ /*+ for (i = 1; i < m3d->numface; i++)+ {+ if (m3d->face[i-1].materialid <= m3d->face[i].materialid) continue;++ // face[i-1] > face[i]. slide face[i] lower+ m3df_t slider = m3d->face[i];+ j = i-1;++ do+ { // face[j] > slider, face[j+1] is svailable vacant gap+ m3d->face[j+1] = m3d->face[j];+ j = j-1;+ }+ while (j >= 0 && m3d->face[j].materialid > slider.materialid);++ m3d->face[j+1] = slider;+ }+ */++ model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));+ model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));+ model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));++ // Map no material to index 0 with default shader, everything else materialid + 1+ model.materials[0] = LoadMaterialDefault();++ for (i = l = 0, k = -1; i < (int)m3d->numface; i++, l++)+ {+ // Materials are grouped together+ if (mi != m3d->face[i].materialid)+ {+ // there should be only one material switch per material kind, but be bulletproof for non-optimal model files+ if (k + 1 >= model.meshCount)+ {+ model.meshCount++;+ model.meshes = (Mesh *)RL_REALLOC(model.meshes, model.meshCount*sizeof(Mesh));+ memset(&model.meshes[model.meshCount - 1], 0, sizeof(Mesh));+ model.meshMaterial = (int *)RL_REALLOC(model.meshMaterial, model.meshCount*sizeof(int));+ }++ k++;+ mi = m3d->face[i].materialid;++ // Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch+ // if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors+ for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)+ {+ if (!m3d->vertex[m3d->face[j].vertex[0]].color ||+ !m3d->vertex[m3d->face[j].vertex[1]].color ||+ !m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;+ }++ model.meshes[k].vertexCount = l*3;+ model.meshes[k].triangleCount = l;+ model.meshes[k].vertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));+ model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));+ model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));++ // If no map is provided, or we have colors defined, we allocate storage for vertex colors+ // M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors+ if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));++ // If no map is provided and we allocated vertex colors, set them to white+ if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))+ {+ for (int c = 0; c < model.meshes[k].vertexCount*4; c++) model.meshes[k].colors[c] = 255;+ }++ if (m3d->numbone && m3d->numskin)+ {+ model.meshes[k].boneIds = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));+ model.meshes[k].boneWeights = (float *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(float));+ model.meshes[k].animVertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));+ model.meshes[k].animNormals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));+ }++ model.meshMaterial[k] = mi + 1;+ l = 0;+ }++ // Process meshes per material, add triangles+ model.meshes[k].vertices[l*9 + 0] = m3d->vertex[m3d->face[i].vertex[0]].x*m3d->scale;+ model.meshes[k].vertices[l*9 + 1] = m3d->vertex[m3d->face[i].vertex[0]].y*m3d->scale;+ model.meshes[k].vertices[l*9 + 2] = m3d->vertex[m3d->face[i].vertex[0]].z*m3d->scale;+ model.meshes[k].vertices[l*9 + 3] = m3d->vertex[m3d->face[i].vertex[1]].x*m3d->scale;+ model.meshes[k].vertices[l*9 + 4] = m3d->vertex[m3d->face[i].vertex[1]].y*m3d->scale;+ model.meshes[k].vertices[l*9 + 5] = m3d->vertex[m3d->face[i].vertex[1]].z*m3d->scale;+ model.meshes[k].vertices[l*9 + 6] = m3d->vertex[m3d->face[i].vertex[2]].x*m3d->scale;+ model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;+ model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;++ // Without vertex color (full transparency), we use the default color+ if (model.meshes[k].colors != NULL)+ {+ if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)+ memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);+ if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xFF000000)+ memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);+ if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xFF000000)+ memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);+ }++ if (m3d->face[i].texcoord[0] != M3D_UNDEF)+ {+ model.meshes[k].texcoords[l*6 + 0] = m3d->tmap[m3d->face[i].texcoord[0]].u;+ model.meshes[k].texcoords[l*6 + 1] = 1.0f - m3d->tmap[m3d->face[i].texcoord[0]].v;+ model.meshes[k].texcoords[l*6 + 2] = m3d->tmap[m3d->face[i].texcoord[1]].u;+ model.meshes[k].texcoords[l*6 + 3] = 1.0f - m3d->tmap[m3d->face[i].texcoord[1]].v;+ model.meshes[k].texcoords[l*6 + 4] = m3d->tmap[m3d->face[i].texcoord[2]].u;+ model.meshes[k].texcoords[l*6 + 5] = 1.0f - m3d->tmap[m3d->face[i].texcoord[2]].v;+ }++ if (m3d->face[i].normal[0] != M3D_UNDEF)+ {+ model.meshes[k].normals[l*9 + 0] = m3d->vertex[m3d->face[i].normal[0]].x;+ model.meshes[k].normals[l*9 + 1] = m3d->vertex[m3d->face[i].normal[0]].y;+ model.meshes[k].normals[l*9 + 2] = m3d->vertex[m3d->face[i].normal[0]].z;+ model.meshes[k].normals[l*9 + 3] = m3d->vertex[m3d->face[i].normal[1]].x;+ model.meshes[k].normals[l*9 + 4] = m3d->vertex[m3d->face[i].normal[1]].y;+ model.meshes[k].normals[l*9 + 5] = m3d->vertex[m3d->face[i].normal[1]].z;+ model.meshes[k].normals[l*9 + 6] = m3d->vertex[m3d->face[i].normal[2]].x;+ model.meshes[k].normals[l*9 + 7] = m3d->vertex[m3d->face[i].normal[2]].y;+ model.meshes[k].normals[l*9 + 8] = m3d->vertex[m3d->face[i].normal[2]].z;+ }++ // Add skin (vertex / bone weight pairs)+ if (m3d->numbone && m3d->numskin)+ {+ for (n = 0; n < 3; n++)+ {+ int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;++ // Check if there is a skin for this mesh, should be, just failsafe+ if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin))+ {+ for (j = 0; j < 4; j++)+ {+ model.meshes[k].boneIds[l*12 + n*4 + j] = m3d->skin[skinid].boneid[j];+ model.meshes[k].boneWeights[l*12 + n*4 + j] = m3d->skin[skinid].weight[j];+ }+ }+ else+ {+ // raylib does not handle boneless meshes with skeletal animations, so+ // we put all vertices without a bone into a special "no bone" bone+ model.meshes[k].boneIds[l*12 + n*4] = m3d->numbone;+ model.meshes[k].boneWeights[l*12 + n*4] = 1.0f;+ }+ }+ }+ }++ // Load materials+ for (i = 0; i < (int)m3d->nummaterial; i++)+ {+ model.materials[i + 1] = LoadMaterialDefault();++ for (j = 0; j < m3d->material[i].numprop; j++)+ {+ prop = &m3d->material[i].prop[j];++ switch (prop->type)+ {+ case m3dp_Kd:+ {+ memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].color, &prop->value.color, 4);+ model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;+ } break;+ case m3dp_Ks:+ {+ memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].color, &prop->value.color, 4);+ } break;+ case m3dp_Ns:+ {+ model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].value = prop->value.fnum;+ } break;+ case m3dp_Ke:+ {+ memcpy(&model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].color, &prop->value.color, 4);+ model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].value = 0.0f;+ } break;+ case m3dp_Pm:+ {+ model.materials[i + 1].maps[MATERIAL_MAP_METALNESS].value = prop->value.fnum;+ } break;+ case m3dp_Pr:+ {+ model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].value = prop->value.fnum;+ } break;+ case m3dp_Ps:+ {+ model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].color = WHITE;+ model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].value = prop->value.fnum;+ } break;+ default:+ {+ if (prop->type >= 128)+ {+ Image image = { 0 };+ image.data = m3d->texture[prop->value.textureid].d;+ image.width = m3d->texture[prop->value.textureid].w;+ image.height = m3d->texture[prop->value.textureid].h;+ image.mipmaps = 1;+ image.format = (m3d->texture[prop->value.textureid].f == 4)? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 :+ ((m3d->texture[prop->value.textureid].f == 3)? PIXELFORMAT_UNCOMPRESSED_R8G8B8 :+ ((m3d->texture[prop->value.textureid].f == 2)? PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA : PIXELFORMAT_UNCOMPRESSED_GRAYSCALE));++ switch (prop->type)+ {+ case m3dp_map_Kd: model.materials[i + 1].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTextureFromImage(image); break;+ case m3dp_map_Ks: model.materials[i + 1].maps[MATERIAL_MAP_SPECULAR].texture = LoadTextureFromImage(image); break;+ case m3dp_map_Ke: model.materials[i + 1].maps[MATERIAL_MAP_EMISSION].texture = LoadTextureFromImage(image); break;+ case m3dp_map_Km: model.materials[i + 1].maps[MATERIAL_MAP_NORMAL].texture = LoadTextureFromImage(image); break;+ case m3dp_map_Ka: model.materials[i + 1].maps[MATERIAL_MAP_OCCLUSION].texture = LoadTextureFromImage(image); break;+ case m3dp_map_Pm: model.materials[i + 1].maps[MATERIAL_MAP_ROUGHNESS].texture = LoadTextureFromImage(image); break;+ default: break;+ }+ }+ } break;+ }+ }+ }++ // Load bones+ if (m3d->numbone)+ {+ model.boneCount = m3d->numbone + 1;+ model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));+ model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));++ for (i = 0; i < (int)m3d->numbone; i++)+ {+ model.bones[i].parent = m3d->bone[i].parent;+ strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name));+ model.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;+ model.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;+ model.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;+ model.bindPose[i].rotation.x = m3d->vertex[m3d->bone[i].ori].x;+ model.bindPose[i].rotation.y = m3d->vertex[m3d->bone[i].ori].y;+ model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;+ model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;++ // TODO: If the orientation quaternion is not normalized, then that's encoding scaling+ model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);+ model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;++ // Child bones are stored in parent bone relative space, convert that into model space+ if (model.bones[i].parent >= 0)+ {+ model.bindPose[i].rotation = QuaternionMultiply(model.bindPose[model.bones[i].parent].rotation, model.bindPose[i].rotation);+ model.bindPose[i].translation = Vector3RotateByQuaternion(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].rotation);+ model.bindPose[i].translation = Vector3Add(model.bindPose[i].translation, model.bindPose[model.bones[i].parent].translation);+ model.bindPose[i].scale = Vector3Multiply(model.bindPose[i].scale, model.bindPose[model.bones[i].parent].scale);+ }+ }++ // Add a special "no bone" bone+ model.bones[i].parent = -1;+ strcpy(model.bones[i].name, "NO BONE");+ model.bindPose[i].translation.x = 0.0f;+ model.bindPose[i].translation.y = 0.0f;+ model.bindPose[i].translation.z = 0.0f;+ model.bindPose[i].rotation.x = 0.0f;+ model.bindPose[i].rotation.y = 0.0f;+ model.bindPose[i].rotation.z = 0.0f;+ model.bindPose[i].rotation.w = 1.0f;+ model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;+ }++ // Load bone-pose default mesh into animation vertices. These will be updated when UpdateModelAnimation gets+ // called, but not before, however DrawMesh uses these if they exist (so not good if they are left empty)+ if (m3d->numbone && m3d->numskin)+ {+ for (i = 0; i < model.meshCount; i++)+ {+ memcpy(model.meshes[i].animVertices, model.meshes[i].vertices, model.meshes[i].vertexCount*3*sizeof(float));+ memcpy(model.meshes[i].animNormals, model.meshes[i].normals, model.meshes[i].vertexCount*3*sizeof(float));+ }+ }++ m3d_free(m3d);+ UnloadFileData(fileData);+ }++ return model;+}++#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)++// Load M3D animation data+static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)+{+ ModelAnimation *animations = NULL;++ m3d_t *m3d = NULL;+ int i = 0, j = 0;+ *animCount = 0;++ int dataSize = 0;+ unsigned char *fileData = LoadFileData(fileName, &dataSize);++ if (fileData != NULL)+ {+ m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);++ if (!m3d || M3D_ERR_ISFATAL(m3d->errcode))+ {+ TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load M3D data, error code %d", fileName, m3d? m3d->errcode : -2);+ UnloadFileData(fileData);+ return NULL;+ }+ else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i animations, %i bones, %i skins", fileName,+ m3d->numaction, m3d->numbone, m3d->numskin);++ // No animation or bone+skin?+ if (!m3d->numaction || !m3d->numbone || !m3d->numskin)+ {+ m3d_free(m3d);+ UnloadFileData(fileData);+ return NULL;+ }++ animations = RL_MALLOC(m3d->numaction*sizeof(ModelAnimation));+ *animCount = m3d->numaction;++ for (unsigned int a = 0; a < m3d->numaction; a++)+ {+ animations[a].frameCount = m3d->action[a].durationmsec/M3D_ANIMDELAY; animations[a].boneCount = m3d->numbone + 1; animations[a].bones = RL_MALLOC((m3d->numbone + 1)*sizeof(BoneInfo)); animations[a].framePoses = RL_MALLOC(animations[a].frameCount*sizeof(Transform *));
raylib/src/rshapes.c view
@@ -126,7 +126,7 @@ // Draw a pixel void DrawPixel(int posX, int posY, Color color) {- DrawPixelV((Vector2){ (float)posX, (float)posY }, color);+ DrawPixelV((Vector2){ (float)posX, (float)posY }, color); } // Draw a pixel (Vector version)@@ -194,20 +194,19 @@ } // Draw lines sequuence (using gl lines)-void DrawLineStrip(Vector2 *points, int pointCount, Color color)+void DrawLineStrip(const Vector2 *points, int pointCount, Color color) {- if (pointCount >= 2)- {- rlBegin(RL_LINES);- rlColor4ub(color.r, color.g, color.b, color.a);+ if (pointCount < 2) return; // Security check - for (int i = 0; i < pointCount - 1; i++)- {- rlVertex2f(points[i].x, points[i].y);- rlVertex2f(points[i + 1].x, points[i + 1].y);- }- rlEnd();- }+ rlBegin(RL_LINES);+ rlColor4ub(color.r, color.g, color.b, color.a);++ for (int i = 0; i < pointCount - 1; i++)+ {+ rlVertex2f(points[i].x, points[i].y);+ rlVertex2f(points[i + 1].x, points[i + 1].y);+ }+ rlEnd(); } // Draw line using cubic-bezier spline, in-out interpolation, no control points@@ -338,7 +337,7 @@ } // NOTE: In case number of segments is odd, we add one last piece to the cake- if (((unsigned int)segments%2) == 1)+ if ((((unsigned int)segments)%2) == 1) { rlColor4ub(color.r, color.g, color.b, color.a); @@ -807,30 +806,25 @@ } // Draw rectangle outline-// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues+// WARNING: All Draw*Lines() functions use RL_LINES for drawing,+// it implies flushing the current batch and changing draw mode to RL_LINES+// but it solves another issue: https://github.com/raysan5/raylib/issues/3884 void DrawRectangleLines(int posX, int posY, int width, int height, Color color) {-#if defined(SUPPORT_QUADS_DRAW_MODE)- DrawRectangle(posX, posY, width, 1, color);- DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);- DrawRectangle(posX, posY + height - 1, width, 1, color);- DrawRectangle(posX, posY + 1, 1, height - 2, color);-#else rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a);- rlVertex2f(posX + 1, posY + 1);- rlVertex2f(posX + width, posY + 1);+ rlVertex2f((float)posX, (float)posY);+ rlVertex2f((float)posX + (float)width, (float)posY + 1); - rlVertex2f(posX + width, posY + 1);- rlVertex2f(posX + width, posY + height);+ rlVertex2f((float)posX + (float)width, (float)posY + 1);+ rlVertex2f((float)posX + (float)width, (float)posY + (float)height); - rlVertex2f(posX + width, posY + height);- rlVertex2f(posX + 1, posY + height);+ rlVertex2f((float)posX + (float)width, (float)posY + (float)height);+ rlVertex2f((float)posX + 1, (float)posY + (float)height); - rlVertex2f(posX + 1, posY + height);- rlVertex2f(posX + 1, posY + 1);+ rlVertex2f((float)posX + 1, (float)posY + (float)height);+ rlVertex2f((float)posX + 1, (float)posY + 1); rlEnd();-#endif } // Draw rectangle outline with extended parameters@@ -1090,8 +1084,15 @@ #endif } +// Draw rectangle with rounded edges+// TODO: This function should be refactored to use RL_LINES, for consistency with other Draw*Lines()+void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)+{+ DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);+}+ // Draw rectangle with rounded edges outline-void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color)+void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color) { if (lineThick < 0) lineThick = 0; @@ -1382,7 +1383,7 @@ // Draw a triangle fan defined by points // NOTE: First vertex provided is the center, shared by all triangles // By default, following vertex should be provided in counter-clockwise order-void DrawTriangleFan(Vector2 *points, int pointCount, Color color)+void DrawTriangleFan(const Vector2 *points, int pointCount, Color color) { if (pointCount >= 3) {@@ -1413,7 +1414,7 @@ // Draw a triangle strip defined by points // NOTE: Every new vertex connects with previous two-void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)+void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color) { if (pointCount >= 3) {@@ -1567,7 +1568,7 @@ //---------------------------------------------------------------------------------- // Draw spline: linear, minimum 2 points-void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)+void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color) { if (pointCount < 2) return; @@ -1684,7 +1685,7 @@ } // Draw spline: B-Spline, minimum 4 points-void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color)+void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color) { if (pointCount < 4) return; @@ -1756,11 +1757,12 @@ DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); } - DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap+ // Cap circle drawing at the end of every segment+ DrawCircleV(currentPoint, thick/2.0f, color); } // Draw spline: Catmull-Rom, minimum 4 points-void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color)+void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color) { if (pointCount < 4) return; @@ -1822,28 +1824,31 @@ DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); } - DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap+ // Cap circle drawing at the end of every segment+ DrawCircleV(currentPoint, thick/2.0f, color); } // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]-void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color)+void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color) {- if (pointCount < 3) return;-- for (int i = 0; i < pointCount - 2; i++)+ if (pointCount >= 3) {- DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color);+ for (int i = 0; i < pointCount - 2; i += 2) DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color);++ // Cap circle drawing at the end of every segment+ //for (int i = 2; i < pointCount - 2; i += 2) DrawCircleV(points[i], thick/2.0f, color); } } // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]-void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color)+void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color) {- if (pointCount < 4) return;-- for (int i = 0; i < pointCount - 3; i++)+ if (pointCount >= 4) {- DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color);+ for (int i = 0; i < pointCount - 3; i += 3) DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color);++ // Cap circle drawing at the end of every segment+ //for (int i = 3; i < pointCount - 3; i += 3) DrawCircleV(points[i], thick/2.0f, color); } } @@ -2167,8 +2172,10 @@ { bool collision = false; - collision = CheckCollisionCircles(point, 0, center, radius);+ float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y); + if (distanceSquared <= radius*radius) collision = true;+ return collision; } @@ -2192,7 +2199,7 @@ // Check if point is within a polygon described by array of vertices // NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php-bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount)+bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount) { bool inside = false; @@ -2201,7 +2208,7 @@ for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { if ((points[i].y > point.y) != (points[j].y > point.y) &&- (point.x < (points[j].x - points[i].x) * (point.y - points[i].y) / (points[j].y - points[i].y) + points[i].x))+ (point.x < (points[j].x - points[i].x)*(point.y - points[i].y)/(points[j].y - points[i].y) + points[i].x)) { inside = !inside; }@@ -2230,9 +2237,10 @@ float dx = center2.x - center1.x; // X distance between centers float dy = center2.y - center1.y; // Y distance between centers - float distance = sqrtf(dx*dx + dy*dy); // Distance between centers+ float distanceSquared = dx*dx + dy*dy; // Distance between centers squared+ float radiusSum = radius1 + radius2; - if (distance <= (radius1 + radius2)) collision = true;+ collision = (distanceSquared <= (radiusSum*radiusSum)); return collision; }@@ -2312,6 +2320,30 @@ return collision; } +// Check if circle collides with a line created betweeen two points [p1] and [p2]+RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)+{+ float dx = p1.x - p2.x;+ float dy = p1.y - p2.y;++ if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)+ {+ return CheckCollisionCircles(p1, 0, center, radius);+ }++ float lengthSQ = ((dx*dx) + (dy*dy));+ float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);++ if (dotProduct > 1.0f) dotProduct = 1.0f;+ else if (dotProduct < 0.0f) dotProduct = 0.0f;++ float dx2 = (p1.x - (dotProduct*(dx))) - center.x;+ float dy2 = (p1.y - (dotProduct*(dy))) - center.y;+ float distanceSQ = ((dx2*dx2) + (dy2*dy2));++ return (distanceSQ <= radius*radius);+}+ // Get collision rectangle for two rectangles collision Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) {@@ -2345,11 +2377,16 @@ // NOTE: Used by DrawLineBezier() only static float EaseCubicInOut(float t, float b, float c, float d) {- if ((t /= 0.5f*d) < 1) return 0.5f*c*t*t*t + b;+ float result = 0.0f; - t -= 2;+ if ((t /= 0.5f*d) < 1) result = 0.5f*c*t*t*t + b;+ else+ {+ t -= 2;+ result = 0.5f*c*(t*t*t + 2.0f) + b;+ } - return 0.5f*c*(t*t*t + 2.0f) + b;+ return result; } #endif // SUPPORT_MODULE_RSHAPES
raylib/src/rtext.c view
@@ -119,7 +119,7 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //-----------------------------------------------------------------------------------// ...+//... //---------------------------------------------------------------------------------- // Global variables@@ -144,7 +144,7 @@ #if defined(SUPPORT_FILEFORMAT_BDF) static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, int *codepoints, int codepointCount, int *outFontSize); #endif-static int textLineSpacing = 15; // Text vertical line spacing in pixels+static int textLineSpacing = 2; // Text vertical line spacing in pixels (between lines) #if defined(SUPPORT_DEFAULT_FONT) extern void LoadFontDefault(void);@@ -362,11 +362,7 @@ UnloadImage(image); } - if (font.texture.id == 0)- {- TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);- font = GetFontDefault();- }+ if (font.texture.id == 0) TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName); else { SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default, we set point filter (the best performance)@@ -394,7 +390,6 @@ UnloadFileData(fileData); }- else font = GetFontDefault(); return font; }@@ -434,7 +429,7 @@ if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } - if ((x == 0) || (y == 0)) return font;+ if ((x == 0) || (y == 0)) return font; // Security check charSpacing = x; lineSpacing = y;@@ -823,7 +818,7 @@ if (offsetY > (atlas.height - fontSize - padding)) {- for(int j = i + 1; j < glyphCount; j++)+ for (int j = i + 1; j < glyphCount; j++) { TRACELOG(LOG_WARNING, "FONT: Failed to package character (%i)", j); // Make sure remaining recs contain valid data@@ -1035,7 +1030,7 @@ // Save font recs data byteCount += sprintf(txtData + byteCount, "// Font characters rectangles data\n");- byteCount += sprintf(txtData + byteCount, "static const Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount);+ byteCount += sprintf(txtData + byteCount, "static Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount); for (int i = 0; i < font.glyphCount; i++) { byteCount += sprintf(txtData + byteCount, " { %1.0f, %1.0f, %1.0f , %1.0f },\n", font.recs[i].x, font.recs[i].y, font.recs[i].width, font.recs[i].height);@@ -1047,7 +1042,7 @@ // it could be generated from image and recs byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\n"); byteCount += sprintf(txtData + byteCount, "// NOTE: No glyphs.image data provided\n");- byteCount += sprintf(txtData + byteCount, "static const GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount);+ byteCount += sprintf(txtData + byteCount, "static GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount); for (int i = 0; i < font.glyphCount; i++) { byteCount += sprintf(txtData + byteCount, " { %i, %i, %i, %i, { 0 }},\n", font.glyphs[i].value, font.glyphs[i].offsetX, font.glyphs[i].offsetY, font.glyphs[i].advanceX);@@ -1077,7 +1072,7 @@ #endif // We have two possible mechanisms to assign font.recs and font.glyphs data, // that data is already available as global arrays, we two options to assign that data:- // - 1. Data copy. This option consumes more memory and Font MUST be unloaded by user, requiring additional code.+ // - 1. Data copy. This option consumes more memory and Font MUST be unloaded by user, requiring additional code // - 2. Data assignment. This option consumes less memory and Font MUST NOT be unloaded by user because data is on protected DATA segment //#define SUPPORT_FONT_DATA_COPY #if defined(SUPPORT_FONT_DATA_COPY)@@ -1151,7 +1146,7 @@ int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop - int textOffsetY = 0; // Offset between lines (on linebreak '\n')+ float textOffsetY = 0; // Offset between lines (on linebreak '\n') float textOffsetX = 0.0f; // Offset X to next character to draw float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor@@ -1166,7 +1161,7 @@ if (codepoint == '\n') { // NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup- textOffsetY += textLineSpacing;+ textOffsetY += (fontSize + textLineSpacing); textOffsetX = 0.0f; } else@@ -1225,7 +1220,7 @@ // Draw multiple character (codepoints) void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint) {- int textOffsetY = 0; // Offset between lines (on linebreak '\n')+ float textOffsetY = 0; // Offset between lines (on linebreak '\n') float textOffsetX = 0.0f; // Offset X to next character to draw float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor@@ -1237,7 +1232,7 @@ if (codepoints[i] == '\n') { // NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup- textOffsetY += textLineSpacing;+ textOffsetY += (fontSize + textLineSpacing); textOffsetX = 0.0f; } else@@ -1282,7 +1277,7 @@ { Vector2 textSize = { 0 }; - if ((font.texture.id == 0) || (text == NULL)) return textSize;+ if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check int size = TextLength(text); // Get size in bytes of text int tempByteCounter = 0; // Used to count longer text line num chars@@ -1319,7 +1314,7 @@ textWidth = 0; // NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup- textHeight += (float)textLineSpacing;+ textHeight += (fontSize + textLineSpacing); } if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;@@ -1577,7 +1572,7 @@ byLen = TextLength(by); // Count the number of replacements needed- insertPoint = (char*)text;+ insertPoint = (char *)text; for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen; // Allocate returning string and point temp to it@@ -1786,6 +1781,62 @@ return buffer; } +// Get snake case notation version of provided string+// WARNING: Limited functionality, only basic characters set+const char *TextToSnake(const char *text)+{+ static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};+ memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);++ if (text != NULL)+ {+ // Check for next separator to upper case another character+ for (int i = 0, j = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)+ {+ if ((text[j] >= 'A') && (text[j] <= 'Z'))+ {+ if (i >= 1)+ {+ buffer[i] = '_';+ i++;+ }+ buffer[i] = text[j] + 32;+ }+ else buffer[i] = text[j];+ }+ }++ return buffer;+}++// Get Camel case notation version of provided string+// WARNING: Limited functionality, only basic characters set+const char *TextToCamel(const char *text)+{+ static char buffer[MAX_TEXT_BUFFER_LENGTH] = {0};+ memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);++ if (text != NULL)+ {+ // Lower case first character+ if ((text[0] >= 'A') && (text[0] <= 'Z')) buffer[0] = text[0] + 32;+ else buffer[0] = text[0];++ // Check for next separator to upper case another character+ for (int i = 1, j = 1; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)+ {+ if (text[j] != '_') buffer[i] = text[j];+ else+ {+ j++;+ if ((text[j] >= 'a') && (text[j] <= 'z')) buffer[i] = text[j] - 32;+ }+ }+ }++ return buffer;+}+ // Encode text codepoint into UTF-8 text // REQUIRES: memcpy() // WARNING: Allocated memory must be manually freed@@ -1836,8 +1887,7 @@ } // Re-allocate buffer to the actual number of codepoints loaded- int *temp = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int));- if (temp != NULL) codepoints = temp;+ codepoints = (int *)RL_REALLOC(codepoints, codepointCount*sizeof(int)); *count = codepointCount; @@ -2029,21 +2079,21 @@ if (0xf0 == (0xf8 & ptr[0])) { // 4 byte UTF-8 codepoint- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); *codepointSize = 4; } else if (0xe0 == (0xf0 & ptr[0])) { // 3 byte UTF-8 codepoint */- if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); *codepointSize = 3; } else if (0xc0 == (0xe0 & ptr[0])) { // 2 byte UTF-8 codepoint- if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } // 10xxxxxx checks+ if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } // 10xxxxxx checks codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); *codepointSize = 2; }@@ -2240,7 +2290,11 @@ // Fill character image data from full font data font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]); }- else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);+ else+ {+ font.glyphs[i].image = GenImageColor((int)font.recs[i].width, (int)font.recs[i].height, BLACK);+ TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);+ } } UnloadImage(fullFont);@@ -2285,7 +2339,7 @@ int readBytes = 0; // Data bytes read (line) int readVars = 0; // Variables filled by sscanf() - const char *fileText = (const char*)fileData;+ const char *fileText = (const char *)fileData; const char *fileTextPtr = fileText; bool fontMalformed = false; // Is the font malformed@@ -2508,6 +2562,6 @@ return glyphs; }-#endif+#endif // SUPPORT_FILEFORMAT_BDF #endif // SUPPORT_MODULE_RTEXT
raylib/src/rtextures.c view
@@ -71,10 +71,10 @@ #if defined(SUPPORT_MODULE_RTEXTURES) #include "utils.h" // Required for: TRACELOG()-#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2+#include "rlgl.h" // OpenGL abstraction layer to multiple versions -#include <stdlib.h> // Required for: malloc(), free()-#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()]+#include <stdlib.h> // Required for: malloc(), calloc(), free()+#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()] #include <math.h> // Required for: fabsf() [Used in DrawTextureRec()] #include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()] @@ -293,9 +293,12 @@ unsigned char *fileData = LoadFileData(fileName, &dataSize); // Loading image from memory data- if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, dataSize);+ if (fileData != NULL)+ {+ image = LoadImageFromMemory(GetFileExtension(fileName), fileData, dataSize); - RL_FREE(fileData);+ UnloadFileData(fileData);+ } return image; }@@ -311,18 +314,22 @@ if (fileData != NULL) { unsigned char *dataPtr = fileData;- unsigned int size = GetPixelDataSize(width, height, format);+ int size = GetPixelDataSize(width, height, format); - if (headerSize > 0) dataPtr += headerSize;+ if (size <= dataSize) // Security check+ {+ // Offset file data to expected raw image by header size+ if ((headerSize > 0) && ((headerSize + size) <= dataSize)) dataPtr += headerSize; - image.data = RL_MALLOC(size); // Allocate required memory in bytes- memcpy(image.data, dataPtr, size); // Copy required data to image- image.width = width;- image.height = height;- image.mipmaps = 1;- image.format = format;+ image.data = RL_MALLOC(size); // Allocate required memory in bytes+ memcpy(image.data, dataPtr, size); // Copy required data to image+ image.width = width;+ image.height = height;+ image.mipmaps = 1;+ image.format = format;+ } - RL_FREE(fileData);+ UnloadFileData(fileData); } return image;@@ -378,8 +385,8 @@ int offsetX = 0; int offsetY = 0; - if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale) / 2;- else offsetX = (width - svgImage->width*scale) / 2;+ if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale)/2;+ else offsetX = (width - svgImage->width*scale)/2; // Rasterize struct NSVGrasterizer *rast = nsvgCreateRasterizer();@@ -431,7 +438,7 @@ image.mipmaps = 1; image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; - RL_FREE(fileData);+ UnloadFileData(fileData); RL_FREE(delays); // NOTE: Frames delays are discarded } }@@ -458,6 +465,9 @@ Image image = { 0 }; int frameCount = 0; + // Security check for input data+ if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;+ #if defined(SUPPORT_FILEFORMAT_GIF) if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0)) {@@ -492,6 +502,9 @@ { Image image = { 0 }; + // Security check for input data+ if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;+ if ((false) #if defined(SUPPORT_FILEFORMAT_PNG) || (strcmp(fileType, ".png") == 0) || (strcmp(fileType, ".PNG") == 0)@@ -684,8 +697,8 @@ Vector2 scale = GetWindowScaleDPI(); Image image = { 0 }; - image.width = GetScreenWidth()*scale.x;- image.height = GetScreenHeight()*scale.y;+ image.width = (int)(GetScreenWidth()*scale.x);+ image.height = (int)(GetScreenHeight()*scale.y); image.mipmaps = 1; image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; image.data = rlReadScreenPixels(image.width, image.height);@@ -696,11 +709,15 @@ // Check if an image is ready bool IsImageReady(Image image) {- return ((image.data != NULL) && // Validate pixel data available- (image.width > 0) &&- (image.height > 0) && // Validate image size- (image.format > 0) && // Validate image format- (image.mipmaps > 0)); // Validate image mipmaps (at least 1 for basic mipmap level)+ bool result = false;++ if ((image.data != NULL) && // Validate pixel data available+ (image.width > 0) &&+ (image.height > 0) && // Validate image size+ (image.format > 0) && // Validate image format+ (image.mipmaps > 0)) result = true; // Validate image mipmaps (at least 1 for basic mipmap level)++ return result; } // Unload image from CPU memory (RAM)@@ -715,6 +732,7 @@ { int result = 0; + // Security check for input data if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; #if defined(SUPPORT_IMAGE_EXPORT)@@ -802,6 +820,7 @@ unsigned char *fileData = NULL; *dataSize = 0; + // Security check for input data if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return NULL; #if defined(SUPPORT_IMAGE_EXPORT)@@ -905,8 +924,8 @@ #if defined(SUPPORT_IMAGE_GENERATION) // Generate image: linear gradient // The direction value specifies the direction of the gradient (in degrees)-// with 0 being vertical (from top to bottom), 90 being horizontal (from left to right).-// The gradient effectively rotates counter-clockwise by the specified amount.+// with 0 being vertical (from top to bottom), 90 being horizontal (from left to right)+// The gradient effectively rotates counter-clockwise by the specified amount Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end) { Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));@@ -999,8 +1018,8 @@ float distY = fabsf(y - centerY); // Normalize the distances by the dimensions of the gradient rectangle- float normalizedDistX = distX / centerX;- float normalizedDistY = distY / centerY;+ float normalizedDistX = distX/centerX;+ float normalizedDistY = distY/centerY; // Calculate the total normalized Manhattan distance float manhattanDist = fmaxf(normalizedDistX, normalizedDistY);@@ -1596,7 +1615,7 @@ // Scale image depending on text size if (textSize.y != imSize.y) {- float scaleFactor = textSize.y / imSize.y;+ float scaleFactor = textSize.y/imSize.y; TRACELOG(LOG_INFO, "IMAGE: Text scaled by factor: %f", scaleFactor); // Using nearest-neighbor scaling algorithm for default font@@ -1611,6 +1630,174 @@ return imText; } +// Create an image from a selected channel of another image+Image ImageFromChannel(Image image, int selectedChannel)+{+ Image result = { 0 };++ // Security check to avoid program crash+ if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result;++ // Check selected channel is valid+ if (selectedChannel < 0)+ {+ TRACELOG(LOG_WARNING, "Channel cannot be negative. Setting channel to 0.");+ selectedChannel = 0;+ }++ if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ||+ image.format == PIXELFORMAT_UNCOMPRESSED_R32 ||+ image.format == PIXELFORMAT_UNCOMPRESSED_R16)+ {+ if (selectedChannel > 0)+ {+ TRACELOG(LOG_WARNING, "This image has only 1 channel. Setting channel to it.");+ selectedChannel = 0;+ }+ }+ else if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)+ {+ if (selectedChannel > 1)+ {+ TRACELOG(LOG_WARNING, "This image has only 2 channels. Setting channel to alpha.");+ selectedChannel = 1;+ }+ }+ else if (image.format == PIXELFORMAT_UNCOMPRESSED_R5G6B5 ||+ image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8 ||+ image.format == PIXELFORMAT_UNCOMPRESSED_R32G32B32 ||+ image.format == PIXELFORMAT_UNCOMPRESSED_R16G16B16)+ {+ if (selectedChannel > 2)+ {+ TRACELOG(LOG_WARNING, "This image has only 3 channels. Setting channel to red.");+ selectedChannel = 0;+ }+ }++ // Check for RGBA formats+ if (selectedChannel > 3)+ {+ TRACELOG(LOG_WARNING, "ImageFromChannel supports channels 0 to 3 (rgba). Setting channel to alpha.");+ selectedChannel = 3;+ }++ // TODO: Consider other one-channel formats: R16, R32+ result.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;+ result.height = image.height;+ result.width = image.width;+ result.mipmaps = 1;++ unsigned char *pixels = (unsigned char *)RL_CALLOC(image.width*image.height, sizeof(unsigned char)); // Values from 0 to 255++ if (image.format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "IMAGE: Pixel data retrieval not supported for compressed image formats");+ else+ {+ for (int i = 0, k = 0; i < image.width*image.height; i++)+ {+ float pixelValue = -1;+ switch (image.format)+ {+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:+ {+ pixelValue = (float)((unsigned char *)image.data)[i + selectedChannel]/255.0f;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:+ {+ pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f;+ k += 2;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:+ {+ unsigned short pixel = ((unsigned short *)image.data)[i];++ if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);+ else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000011111000000) >> 6)*(1.0f/31);+ else if (selectedChannel == 2) pixelValue = (float)((pixel & 0b0000000000111110) >> 1)*(1.0f/31);+ else if (selectedChannel == 3) pixelValue = ((pixel & 0b0000000000000001) == 0)? 0.0f : 1.0f;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:+ {+ unsigned short pixel = ((unsigned short *)image.data)[i];++ if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);+ else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000011111100000) >> 5)*(1.0f/63);+ else if (selectedChannel == 2) pixelValue = (float)(pixel & 0b0000000000011111)*(1.0f/31);++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:+ {+ unsigned short pixel = ((unsigned short *)image.data)[i];++ if (selectedChannel == 0) pixelValue = (float)((pixel & 0b1111000000000000) >> 12)*(1.0f/15);+ else if (selectedChannel == 1) pixelValue = (float)((pixel & 0b0000111100000000) >> 8)*(1.0f/15);+ else if (selectedChannel == 2) pixelValue = (float)((pixel & 0b0000000011110000) >> 4)*(1.0f/15);+ else if (selectedChannel == 3) pixelValue = (float)(pixel & 0b0000000000001111)*(1.0f/15);++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:+ {+ pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f;+ k += 4;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:+ {+ pixelValue = (float)((unsigned char *)image.data)[k + selectedChannel]/255.0f;+ k += 3;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R32:+ {+ pixelValue = ((float *)image.data)[k];+ k += 1;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:+ {+ pixelValue = ((float *)image.data)[k + selectedChannel];+ k += 3;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:+ {+ pixelValue = ((float *)image.data)[k + selectedChannel];+ k += 4;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R16:+ {+ pixelValue = HalfToFloat(((unsigned short *)image.data)[k]);+ k += 1;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R16G16B16:+ {+ pixelValue = HalfToFloat(((unsigned short *)image.data)[k+selectedChannel]);+ k += 3;++ } break;+ case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:+ {+ pixelValue = HalfToFloat(((unsigned short *)image.data)[k + selectedChannel]);+ k += 4;++ } break;+ default: break;+ }++ pixels[i] = (unsigned char)(pixelValue*255);+ }+ }++ result.data = pixels;++ return result;+}+ // Resize and image to new size using Nearest-Neighbor scaling algorithm void ImageResizeNN(Image *image,int newWidth,int newHeight) {@@ -1993,8 +2180,9 @@ ImageFormat(image, format); } -// Apply box blur-void ImageBlurGaussian(Image *image, int blurSize) {+// Apply box blur to image+void ImageBlurGaussian(Image *image, int blurSize)+{ // Security check to avoid program crash if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return; @@ -2006,7 +2194,8 @@ Vector4 *pixelsCopy1 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4)); Vector4 *pixelsCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4)); - for (int i = 0; i < (image->height)*(image->width); i++) {+ for (int i = 0; i < (image->height*image->width); i++)+ { pixelsCopy1[i].x = pixels[i].r; pixelsCopy1[i].y = pixels[i].g; pixelsCopy1[i].z = pixels[i].b;@@ -2014,7 +2203,8 @@ } // Repeated convolution of rectangular window signal by itself converges to a gaussian distribution- for (int j = 0; j < GAUSSIAN_BLUR_ITERATIONS; j++) {+ for (int j = 0; j < GAUSSIAN_BLUR_ITERATIONS; j++)+ { // Horizontal motion blur for (int row = 0; row < image->height; row++) {@@ -2134,8 +2324,9 @@ ImageFormat(image, format); } -// The kernel matrix is assumed to be square. Only supply the width of the kernel.-void ImageKernelConvolution(Image *image, float* kernel, int kernelSize)+// Apply custom square convolution kernel to image+// NOTE: The convolution kernel matrix is expected to be square+void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize) { if ((image->data == NULL) || (image->width == 0) || (image->height == 0) || kernel == NULL) return; @@ -2178,7 +2369,7 @@ endRange = kernelWidth/2 + 1; } - for(int x = 0; x < image->height; x++)+ for (int x = 0; x < image->height; x++) { for (int y = 0; y < image->width; y++) {@@ -2192,17 +2383,17 @@ if (imgindex >= (unsigned int)(image->width*image->height)) {- temp[kernelWidth * xkabs + ykabs].x = 0.0f;- temp[kernelWidth * xkabs + ykabs].y = 0.0f;- temp[kernelWidth * xkabs + ykabs].z = 0.0f;- temp[kernelWidth * xkabs + ykabs].w = 0.0f;+ temp[kernelWidth*xkabs + ykabs].x = 0.0f;+ temp[kernelWidth*xkabs + ykabs].y = 0.0f;+ temp[kernelWidth*xkabs + ykabs].z = 0.0f;+ temp[kernelWidth*xkabs + ykabs].w = 0.0f; } else {- temp[kernelWidth * xkabs + ykabs].x = ((float)pixels[imgindex].r)/255.0f*kernel[kernelWidth*xkabs + ykabs];- temp[kernelWidth * xkabs + ykabs].y = ((float)pixels[imgindex].g)/255.0f*kernel[kernelWidth*xkabs + ykabs];- temp[kernelWidth * xkabs + ykabs].z = ((float)pixels[imgindex].b)/255.0f*kernel[kernelWidth*xkabs + ykabs];- temp[kernelWidth * xkabs + ykabs].w = ((float)pixels[imgindex].a)/255.0f*kernel[kernelWidth*xkabs + ykabs];+ temp[kernelWidth*xkabs + ykabs].x = ((float)pixels[imgindex].r)/255.0f*kernel[kernelWidth*xkabs + ykabs];+ temp[kernelWidth*xkabs + ykabs].y = ((float)pixels[imgindex].g)/255.0f*kernel[kernelWidth*xkabs + ykabs];+ temp[kernelWidth*xkabs + ykabs].z = ((float)pixels[imgindex].b)/255.0f*kernel[kernelWidth*xkabs + ykabs];+ temp[kernelWidth*xkabs + ykabs].w = ((float)pixels[imgindex].a)/255.0f*kernel[kernelWidth*xkabs + ykabs]; } } }@@ -2645,17 +2836,12 @@ Color *pixels = LoadImageColors(*image); - float cR = (float)color.r/255;- float cG = (float)color.g/255;- float cB = (float)color.b/255;- float cA = (float)color.a/255;-- for (int i = 0; i < image->width * image->height; i++)+ for (int i = 0; i < image->width*image->height; i++) {- unsigned char r = (unsigned char)(((float)pixels[i].r/255*cR)*255.0f);- unsigned char g = (unsigned char)(((float)pixels[i].g/255*cG)*255.0f);- unsigned char b = (unsigned char)(((float)pixels[i].b/255*cB)*255.0f);- unsigned char a = (unsigned char)(((float)pixels[i].a/255*cA)*255.0f);+ unsigned char r = (unsigned char)(((int)pixels[i].r*(int)color.r)/255);+ unsigned char g = (unsigned char)(((int)pixels[i].g*(int)color.g)/255);+ unsigned char b = (unsigned char)(((int)pixels[i].b*(int)color.b)/255);+ unsigned char a = (unsigned char)(((int)pixels[i].a*(int)color.a)/255); pixels[i].r = r; pixels[i].g = g;@@ -2680,7 +2866,7 @@ Color *pixels = LoadImageColors(*image); - for (int i = 0; i < image->width * image->height; i++)+ for (int i = 0; i < image->width*image->height; i++) { pixels[i].r = 255 - pixels[i].r; pixels[i].g = 255 - pixels[i].g;@@ -2717,7 +2903,7 @@ Color *pixels = LoadImageColors(*image); - for (int i = 0; i < image->width * image->height; i++)+ for (int i = 0; i < image->width*image->height; i++) { float pR = (float)pixels[i].r/255.0f; pR -= 0.5f;@@ -2769,7 +2955,7 @@ Color *pixels = LoadImageColors(*image); - for (int i = 0; i < image->width * image->height; i++)+ for (int i = 0; i < image->width*image->height; i++) { int cR = pixels[i].r + brightness; int cG = pixels[i].g + brightness;@@ -2806,7 +2992,7 @@ Color *pixels = LoadImageColors(*image); - for (int i = 0; i < image->width * image->height; i++)+ for (int i = 0; i < image->width*image->height; i++) { if ((pixels[i].r == color.r) && (pixels[i].g == color.g) &&@@ -2925,6 +3111,7 @@ pixels[i].b = 0; pixels[i].a = 255; + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R32G32B32: {@@ -2938,9 +3125,9 @@ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: { pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);- pixels[i].g = (unsigned char)(((float *)image.data)[k]*255.0f);- pixels[i].b = (unsigned char)(((float *)image.data)[k]*255.0f);- pixels[i].a = (unsigned char)(((float *)image.data)[k]*255.0f);+ pixels[i].g = (unsigned char)(((float *)image.data)[k + 1]*255.0f);+ pixels[i].b = (unsigned char)(((float *)image.data)[k + 2]*255.0f);+ pixels[i].a = (unsigned char)(((float *)image.data)[k + 3]*255.0f); k += 4; } break;@@ -2951,6 +3138,7 @@ pixels[i].b = 0; pixels[i].a = 255; + k += 1; } break; case PIXELFORMAT_UNCOMPRESSED_R16G16B16: {@@ -2964,9 +3152,9 @@ case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: { pixels[i].r = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f);- pixels[i].g = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f);- pixels[i].b = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f);- pixels[i].a = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k])*255.0f);+ pixels[i].g = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 1])*255.0f);+ pixels[i].b = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 2])*255.0f);+ pixels[i].a = (unsigned char)(HalfToFloat(((unsigned short *)image.data)[k + 3])*255.0f); k += 4; } break;@@ -3386,98 +3574,112 @@ // Draw line within an image void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color) {- // Using Bresenham's algorithm as described in- // Drawing Lines with Pixels - Joshua Scott - March 2012- // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf+ // Calculate differences in coordinates+ int shortLen = endPosY - startPosY;+ int longLen = endPosX - startPosX;+ bool yLonger = false; - int changeInX = (endPosX - startPosX);- int absChangeInX = (changeInX < 0)? -changeInX : changeInX;- int changeInY = (endPosY - startPosY);- int absChangeInY = (changeInY < 0)? -changeInY : changeInY;+ // Determine if the line is more vertical than horizontal+ if (abs(shortLen) > abs(longLen))+ {+ // Swap the lengths if the line is more vertical+ int temp = shortLen;+ shortLen = longLen;+ longLen = temp;+ yLonger = true;+ } - int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function- //int endV; // Not needed but left for better understanding, check code below- int A, B, P; // See linked paper above, explained down in the main loop- int reversedXY = (absChangeInY < absChangeInX);+ // Initialize variables for drawing loop+ int endVal = longLen;+ int sgnInc = 1; - if (reversedXY)+ // Adjust direction increment based on longLen sign+ if (longLen < 0) {- A = 2*absChangeInY;- B = A - 2*absChangeInX;- P = A - absChangeInX;+ longLen = -longLen;+ sgnInc = -1;+ } - if (changeInX > 0)- {- startU = startPosX;- startV = startPosY;- endU = endPosX;- //endV = endPosY;- }- else- {- startU = endPosX;- startV = endPosY;- endU = startPosX;- //endV = startPosY;+ // Calculate fixed-point increment for shorter length+ int decInc = (longLen == 0)? 0 : (shortLen << 16)/longLen; - // Since start and end are reversed- changeInX = -changeInX;- changeInY = -changeInY;+ // Draw the line pixel by pixel+ if (yLonger)+ {+ // If line is more vertical, iterate over y-axis+ for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc)+ {+ // Calculate pixel position and draw it+ ImageDrawPixel(dst, startPosX + (j >> 16), startPosY + i, color); }-- stepV = (changeInY < 0)? -1 : 1;-- ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered... } else {- A = 2*absChangeInX;- B = A - 2*absChangeInY;- P = A - absChangeInY;-- if (changeInY > 0)+ // If line is more horizontal, iterate over x-axis+ for (int i = 0, j = 0; i != endVal; i += sgnInc, j += decInc) {- startU = startPosY;- startV = startPosX;- endU = endPosY;- //endV = endPosX;+ // Calculate pixel position and draw it+ ImageDrawPixel(dst, startPosX + i, startPosY + (j >> 16), color); }- else- {- startU = endPosY;- startV = endPosX;- endU = startPosY;- //endV = startPosX;+ }+} - // Since start and end are reversed- changeInX = -changeInX;- changeInY = -changeInY;- }+// Draw line within an image (Vector version)+void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)+{+ // Round start and end positions to nearest integer coordinates+ int x1 = (int)(start.x + 0.5f);+ int y1 = (int)(start.y + 0.5f);+ int x2 = (int)(end.x + 0.5f);+ int y2 = (int)(end.y + 0.5f); - stepV = (changeInX < 0)? -1 : 1;+ // Draw a vertical line using ImageDrawLine function+ ImageDrawLine(dst, x1, y1, x2, y2, color);+} - ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below- }+// Draw a line defining thickness within an image+void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color)+{+ // Round start and end positions to nearest integer coordinates+ int x1 = (int)(start.x + 0.5f);+ int y1 = (int)(start.y + 0.5f);+ int x2 = (int)(end.x + 0.5f);+ int y2 = (int)(end.y + 0.5f); - // We already drew the start point. If we started at startU + 0, the line would be crooked and too short- for (int u = startU + 1, v = startV; u <= endU; u++)+ // Calculate differences in x and y coordinates+ int dx = x2 - x1;+ int dy = y2 - y1;++ // Draw the main line between (x1, y1) and (x2, y2)+ ImageDrawLine(dst, x1, y1, x2, y2, color);++ // Determine if the line is more horizontal or vertical+ if (dx != 0 && abs(dy/dx) < 1) {- if (P >= 0)+ // Line is more horizontal+ // Calculate half the width of the line+ int wy = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dx));++ // Draw additional lines above and below the main line+ for (int i = 1; i <= wy; i++) {- v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above- P += B; // Remembers that we corrected our path+ ImageDrawLine(dst, x1, y1 - i, x2, y2 - i, color); // Draw above the main line+ ImageDrawLine(dst, x1, y1 + i, x2, y2 + i, color); // Draw below the main line }- else P += A; // Remembers how far we are from the direct line-- if (reversedXY) ImageDrawPixel(dst, u, v, color);- else ImageDrawPixel(dst, v, u, color); }-}+ else if (dy != 0)+ {+ // Line is more vertical or perfectly horizontal+ // Calculate half the width of the line+ int wx = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dy)); -// Draw line within an image (Vector version)-void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)-{- ImageDrawLine(dst, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color);+ // Draw additional lines to the left and right of the main line+ for (int i = 1; i <= wx; i++)+ {+ ImageDrawLine(dst, x1 - i, y1, x2 - i, y2, color); // Draw left of the main line+ ImageDrawLine(dst, x1 + i, y1, x2 + i, y2, color); // Draw right of the main line+ }+ } } // Draw circle within an image@@ -3594,7 +3796,7 @@ } // Repeat the first row data for all other rows- int bytesPerRow = bytesPerPixel * (int)rec.width;+ int bytesPerRow = bytesPerPixel*(int)rec.width; for (int y = 1; y < (int)rec.height; y++) { memcpy(pSrcPixel + (y*dst->width)*bytesPerPixel, pSrcPixel, bytesPerRow);@@ -3610,6 +3812,194 @@ ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + rec.height - thick), (int)rec.width, thick, color); } +// Draw triangle within an image+void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color)+{+ // Calculate the 2D bounding box of the triangle+ // Determine the minimum and maximum x and y coordinates of the triangle vertices+ int xMin = (int)((v1.x < v2.x)? ((v1.x < v3.x)? v1.x : v3.x) : ((v2.x < v3.x)? v2.x : v3.x));+ int yMin = (int)((v1.y < v2.y)? ((v1.y < v3.y)? v1.y : v3.y) : ((v2.y < v3.y)? v2.y : v3.y));+ int xMax = (int)((v1.x > v2.x)? ((v1.x > v3.x)? v1.x : v3.x) : ((v2.x > v3.x)? v2.x : v3.x));+ int yMax = (int)((v1.y > v2.y)? ((v1.y > v3.y)? v1.y : v3.y) : ((v2.y > v3.y)? v2.y : v3.y));++ // Clamp the bounding box to the image dimensions+ if (xMin < 0) xMin = 0;+ if (yMin < 0) yMin = 0;+ if (xMax > dst->width) xMax = dst->width;+ if (yMax > dst->height) yMax = dst->height;++ // Check the order of the vertices to determine if it's a front or back face+ // NOTE: if signedArea is equal to 0, the face is degenerate+ float signedArea = (v2.x - v1.x)*(v3.y - v1.y) - (v3.x - v1.x)*(v2.y - v1.y);+ bool isBackFace = (signedArea > 0);++ // Barycentric interpolation setup+ // Calculate the step increments for the barycentric coordinates+ int w1XStep = (int)(v3.y - v2.y), w1YStep = (int)(v2.x - v3.x);+ int w2XStep = (int)(v1.y - v3.y), w2YStep = (int)(v3.x - v1.x);+ int w3XStep = (int)(v2.y - v1.y), w3YStep = (int)(v1.x - v2.x);++ // If the triangle is a back face, invert the steps+ if (isBackFace)+ {+ w1XStep = -w1XStep, w1YStep = -w1YStep;+ w2XStep = -w2XStep, w2YStep = -w2YStep;+ w3XStep = -w3XStep, w3YStep = -w3YStep;+ }++ // Calculate the initial barycentric coordinates for the top-left point of the bounding box+ int w1Row = (int)((xMin - v2.x)*w1XStep + w1YStep*(yMin - v2.y));+ int w2Row = (int)((xMin - v3.x)*w2XStep + w2YStep*(yMin - v3.y));+ int w3Row = (int)((xMin - v1.x)*w3XStep + w3YStep*(yMin - v1.y));++ // Rasterization loop+ // Iterate through each pixel in the bounding box+ for (int y = yMin; y <= yMax; y++)+ {+ int w1 = w1Row;+ int w2 = w2Row;+ int w3 = w3Row;++ for (int x = xMin; x <= xMax; x++)+ {+ // Check if the pixel is inside the triangle using barycentric coordinates+ // If it is then we can draw the pixel with the given color+ if ((w1 | w2 | w3) >= 0) ImageDrawPixel(dst, x, y, color);++ // Increment the barycentric coordinates for the next pixel+ w1 += w1XStep;+ w2 += w2XStep;+ w3 += w3XStep;+ }++ // Move to the next row in the bounding box+ w1Row += w1YStep;+ w2Row += w2YStep;+ w3Row += w3YStep;+ }+}++// Draw triangle with interpolated colors within an image+void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)+{+ // Calculate the 2D bounding box of the triangle+ // Determine the minimum and maximum x and y coordinates of the triangle vertices+ int xMin = (int)((v1.x < v2.x)? ((v1.x < v3.x)? v1.x : v3.x) : ((v2.x < v3.x)? v2.x : v3.x));+ int yMin = (int)((v1.y < v2.y)? ((v1.y < v3.y)? v1.y : v3.y) : ((v2.y < v3.y)? v2.y : v3.y));+ int xMax = (int)((v1.x > v2.x)? ((v1.x > v3.x)? v1.x : v3.x) : ((v2.x > v3.x)? v2.x : v3.x));+ int yMax = (int)((v1.y > v2.y)? ((v1.y > v3.y)? v1.y : v3.y) : ((v2.y > v3.y)? v2.y : v3.y));++ // Clamp the bounding box to the image dimensions+ if (xMin < 0) xMin = 0;+ if (yMin < 0) yMin = 0;+ if (xMax > dst->width) xMax = dst->width;+ if (yMax > dst->height) yMax = dst->height;++ // Check the order of the vertices to determine if it's a front or back face+ // NOTE: if signedArea is equal to 0, the face is degenerate+ float signedArea = (v2.x - v1.x)*(v3.y - v1.y) - (v3.x - v1.x)*(v2.y - v1.y);+ bool isBackFace = (signedArea > 0);++ // Barycentric interpolation setup+ // Calculate the step increments for the barycentric coordinates+ int w1XStep = (int)(v3.y - v2.y), w1YStep = (int)(v2.x - v3.x);+ int w2XStep = (int)(v1.y - v3.y), w2YStep = (int)(v3.x - v1.x);+ int w3XStep = (int)(v2.y - v1.y), w3YStep = (int)(v1.x - v2.x);++ // If the triangle is a back face, invert the steps+ if (isBackFace)+ {+ w1XStep = -w1XStep, w1YStep = -w1YStep;+ w2XStep = -w2XStep, w2YStep = -w2YStep;+ w3XStep = -w3XStep, w3YStep = -w3YStep;+ }++ // Calculate the initial barycentric coordinates for the top-left point of the bounding box+ int w1Row = (int)((xMin - v2.x)*w1XStep + w1YStep*(yMin - v2.y));+ int w2Row = (int)((xMin - v3.x)*w2XStep + w2YStep*(yMin - v3.y));+ int w3Row = (int)((xMin - v1.x)*w3XStep + w3YStep*(yMin - v1.y));++ // Calculate the inverse of the sum of the barycentric coordinates for normalization+ // NOTE 1: Here, we act as if we multiply by 255 the reciprocal, which avoids additional+ // calculations in the loop. This is acceptable because we are only interpolating colors.+ // NOTE 2: This sum remains constant throughout the triangle+ float wInvSum = 255.0f/(w1Row + w2Row + w3Row);++ // Rasterization loop+ // Iterate through each pixel in the bounding box+ for (int y = yMin; y <= yMax; y++)+ {+ int w1 = w1Row;+ int w2 = w2Row;+ int w3 = w3Row;++ for (int x = xMin; x <= xMax; x++)+ {+ // Check if the pixel is inside the triangle using barycentric coordinates+ if ((w1 | w2 | w3) >= 0)+ {+ // Compute the normalized barycentric coordinates+ unsigned char aW1 = (unsigned char)((float)w1*wInvSum);+ unsigned char aW2 = (unsigned char)((float)w2*wInvSum);+ unsigned char aW3 = (unsigned char)((float)w3*wInvSum);++ // Interpolate the color using the barycentric coordinates+ Color finalColor = { 0 };+ finalColor.r = (c1.r*aW1 + c2.r*aW2 + c3.r*aW3)/255;+ finalColor.g = (c1.g*aW1 + c2.g*aW2 + c3.g*aW3)/255;+ finalColor.b = (c1.b*aW1 + c2.b*aW2 + c3.b*aW3)/255;+ finalColor.a = (c1.a*aW1 + c2.a*aW2 + c3.a*aW3)/255;++ // Draw the pixel with the interpolated color+ ImageDrawPixel(dst, x, y, finalColor);+ }++ // Increment the barycentric coordinates for the next pixel+ w1 += w1XStep;+ w2 += w2XStep;+ w3 += w3XStep;+ }++ // Move to the next row in the bounding box+ w1Row += w1YStep;+ w2Row += w2YStep;+ w3Row += w3YStep;+ }+}++// Draw triangle outline within an image+void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color)+{+ ImageDrawLine(dst, (int)v1.x, (int)v1.y, (int)v2.x, (int)v2.y, color);+ ImageDrawLine(dst, (int)v2.x, (int)v2.y, (int)v3.x, (int)v3.y, color);+ ImageDrawLine(dst, (int)v3.x, (int)v3.y, (int)v1.x, (int)v1.y, color);+}++// Draw a triangle fan defined by points within an image (first vertex is the center)+void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color)+{+ if (pointCount >= 3)+ {+ for (int i = 1; i < pointCount - 1; i++)+ {+ ImageDrawTriangle(dst, points[0], points[i], points[i + 1], color);+ }+ }+}++// Draw a triangle strip defined by points within an image+void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color)+{+ if (pointCount >= 3)+ {+ for (int i = 2; i < pointCount; i++)+ {+ if ((i%2) == 0) ImageDrawTriangle(dst, points[i], points[i - 2], points[i - 1], color);+ else ImageDrawTriangle(dst, points[i], points[i - 1], points[i - 2], color);+ }+ }+}+ // Draw an image (source) within an image (destination) // NOTE: Color tint is applied to source image void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint)@@ -3934,13 +4324,17 @@ // Check if a texture is ready bool IsTextureReady(Texture2D texture) {+ bool result = false;+ // TODO: Validate maximum texture size supported by GPU? - return ((texture.id > 0) && // Validate OpenGL id- (texture.width > 0) &&- (texture.height > 0) && // Validate texture size- (texture.format > 0) && // Validate texture pixel format- (texture.mipmaps > 0)); // Validate texture mipmaps (at least 1 for basic mipmap level)+ if ((texture.id > 0) && // Validate OpenGL id+ (texture.width > 0) &&+ (texture.height > 0) && // Validate texture size+ (texture.format > 0) && // Validate texture pixel format+ (texture.mipmaps > 0)) result = true; // Validate texture mipmaps (at least 1 for basic mipmap level)++ return result; } // Unload texture from GPU memory (VRAM)@@ -3957,9 +4351,13 @@ // Check if a render texture is ready bool IsRenderTextureReady(RenderTexture2D target) {- return ((target.id > 0) && // Validate OpenGL id- IsTextureReady(target.depth) && // Validate FBO depth texture/renderbuffer- IsTextureReady(target.texture)); // Validate FBO texture+ bool result = false;++ if ((target.id > 0) && // Validate OpenGL id+ IsTextureReady(target.depth) && // Validate FBO depth texture/renderbuffer+ IsTextureReady(target.texture)) result = true; // Validate FBO texture++ return result; } // Unload render texture from GPU memory (VRAM)@@ -4217,7 +4615,7 @@ // NOTE: Vertex position can be transformed using matrices // but the process is way more costly than just calculating- // the vertex positions manually, like done above.+ // the vertex positions manually, like done above // I leave here the old implementation for educational purposes, // just in case someone wants to do some performance test /*@@ -4467,16 +4865,27 @@ // Get color with alpha applied, alpha goes from 0.0f to 1.0f Color Fade(Color color, float alpha) {+ Color result = color;+ if (alpha < 0.0f) alpha = 0.0f; else if (alpha > 1.0f) alpha = 1.0f; - return (Color){ color.r, color.g, color.b, (unsigned char)(255.0f*alpha) };+ result.a = (unsigned char)(255.0f*alpha);++ return result; } // Get hexadecimal value for a Color int ColorToInt(Color color) {- return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);+ int result = 0;++ result = (int)(((unsigned int)color.r << 24) |+ ((unsigned int)color.g << 16) |+ ((unsigned int)color.b << 8) |+ (unsigned int)color.a);++ return result; } // Get color normalized as float [0..1]@@ -4598,15 +5007,10 @@ { Color result = color; - float cR = (float)tint.r/255;- float cG = (float)tint.g/255;- float cB = (float)tint.b/255;- float cA = (float)tint.a/255;-- unsigned char r = (unsigned char)(((float)color.r/255*cR)*255.0f);- unsigned char g = (unsigned char)(((float)color.g/255*cG)*255.0f);- unsigned char b = (unsigned char)(((float)color.b/255*cB)*255.0f);- unsigned char a = (unsigned char)(((float)color.a/255*cA)*255.0f);+ unsigned char r = (unsigned char)(((int)color.r*(int)tint.r)/255);+ unsigned char g = (unsigned char)(((int)color.g*(int)tint.g)/255);+ unsigned char b = (unsigned char)(((int)color.b*(int)tint.b)/255);+ unsigned char a = (unsigned char)(((int)color.a*(int)tint.a)/255); result.r = r; result.g = g;@@ -4695,10 +5099,14 @@ // Get color with alpha applied, alpha goes from 0.0f to 1.0f Color ColorAlpha(Color color, float alpha) {+ Color result = color;+ if (alpha < 0.0f) alpha = 0.0f; else if (alpha > 1.0f) alpha = 1.0f; - return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};+ result.a = (unsigned char)(255.0f*alpha);++ return result; } // Get src alpha-blended into dst color with tint@@ -4997,22 +5405,35 @@ //---------------------------------------------------------------------------------- // Module specific Functions Definition //-----------------------------------------------------------------------------------// From https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308+// Convert half-float (stored as unsigned short) to float+// REF: https://stackoverflow.com/questions/1659440/32-bit-to-16-bit-floating-point-conversion/60047308#60047308+static float HalfToFloat(unsigned short x)+{+ float result = 0.0f; -static float HalfToFloat(unsigned short x) {- const unsigned int e = (x&0x7C00)>>10; // exponent- const unsigned int m = (x&0x03FF)<<13; // mantissa+ const unsigned int e = (x & 0x7C00) >> 10; // Exponent+ const unsigned int m = (x & 0x03FF) << 13; // Mantissa const float fm = (float)m;- const unsigned int v = (*(unsigned int*)&fm)>>23; // evil log2 bit hack to count leading zeros in denormalized format- const unsigned int r = (x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000)); // sign : normalized : denormalized- return *(float*)&r;+ const unsigned int v = (*(unsigned int*)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format+ const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized++ result = *(float *)&r;++ return result; } -static unsigned short FloatToHalf(float x) {- const unsigned int b = (*(unsigned int*)&x)+0x00001000; // round-to-nearest-even: add last bit after truncated mantissa- const unsigned int e = (b&0x7F800000)>>23; // exponent- const unsigned int m = b&0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding- return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate+// Convert float to half-float (stored as unsigned short)+static unsigned short FloatToHalf(float x)+{+ unsigned short result = 0;++ const unsigned int b = (*(unsigned int*) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa+ const unsigned int e = (b & 0x7F800000) >> 23; // Exponent+ const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding++ result = (b & 0x80000000) >> 16 | (e > 112)*((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))*((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143)*0x7FFF; // sign : normalized : denormalized : saturate++ return result; } // Get pixel data from image as Vector4 array (float normalized)
raylib/src/utils.c view
@@ -41,7 +41,7 @@ #if defined(PLATFORM_ANDROID) #include <errno.h> // Required for: Android error types #include <android/log.h> // Required for: Android log system: __android_log_vprint()- #include <android/asset_manager.h> // Required for: Android assets manager: AAsset, AAssetManager_open(), ...+ #include <android/asset_manager.h> // Required for: Android assets manager: AAsset, AAssetManager_open()... #endif #include <stdlib.h> // Required for: exit()
src/Raylib/Core.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE TemplateHaskell #-} @@ -6,6 +5,7 @@ module Raylib.Core ( -- * High level initWindow,+ initWindowUnmanaged, windowShouldClose, closeWindow, isWindowReady,@@ -134,6 +134,7 @@ getApplicationDirectory, changeDirectory, isPathFile,+ isFileNameValid, loadDirectoryFiles, loadDirectoryFilesEx, isFileDropped,@@ -152,7 +153,7 @@ stopAutomationEventRecording, playAutomationEvent, peekAutomationEventList,- freeAutomationEventList,+ unloadAutomationEventList, isKeyPressed, isKeyPressedRepeat, isKeyDown,@@ -334,6 +335,7 @@ c'getApplicationDirectory, c'changeDirectory, c'isPathFile,+ c'isFileNameValid, c'loadDirectoryFiles, c'loadDirectoryFilesEx, c'unloadDirectoryFiles,@@ -416,7 +418,6 @@ import Foreign ( Ptr, Storable (peek, poke, sizeOf),- castFunPtr, castPtr, finalizeForeignPtr, fromBool,@@ -440,7 +441,7 @@ withCString, ) import Foreign.Ptr (nullPtr)-import Raylib.Internal (WindowResources, addAutomationEventList, addFunPtr, addShaderId, defaultWindowResources, shaderLocations, unloadAutomationEventLists, unloadFrameBuffers, unloadFunPtrs, unloadShaders, unloadSingleAutomationEventList, unloadSingleShader, unloadTextures, unloadVaoIds, unloadVboIds)+import Raylib.Internal (WindowResources, defaultWindowResources, shaderLocations, unloadSingleAutomationEventList, unloadSingleShader, releaseNonAudioWindowResources) import Raylib.Internal.Foreign (configsToBitflag, pop, popCArray, popCString, withFreeable, withFreeableArray, withFreeableArrayLen, withMaybeCString) import Raylib.Internal.TH (genNative) import Raylib.Types@@ -619,6 +620,7 @@ ("c'getApplicationDirectory", "GetApplicationDirectory_", "rl_bindings.h", [t|IO CString|], False), ("c'changeDirectory", "ChangeDirectory_", "rl_bindings.h", [t|CString -> IO CBool|], False), ("c'isPathFile", "IsPathFile_", "rl_bindings.h", [t|CString -> IO CBool|], False),+ ("c'isFileNameValid", "IsFileNameValid_", "rl_bindings.h", [t|CString -> IO CBool|], False), ("c'loadDirectoryFiles", "LoadDirectoryFiles_", "rl_bindings.h", [t|CString -> IO (Ptr FilePathList)|], False), ("c'loadDirectoryFilesEx", "LoadDirectoryFilesEx_", "rl_bindings.h", [t|CString -> CString -> CInt -> IO (Ptr FilePathList)|], False), ("c'unloadDirectoryFiles", "UnloadDirectoryFiles_", "rl_bindings.h", [t|Ptr FilePathList -> IO ()|], False),@@ -690,23 +692,24 @@ Int -> Int -> String ->- -- | This value must be passed to some @load*@ and @unload*@ functions for+ -- | This value can be used with `managed` when loading resources for -- automatic memory management. IO WindowResources initWindow width height title = withCString title (c'initWindow (fromIntegral width) (fromIntegral height)) >> defaultWindowResources +initWindowUnmanaged ::+ Int ->+ Int ->+ String ->+ IO ()+initWindowUnmanaged width height title = withCString title (c'initWindow (fromIntegral width) (fromIntegral height))+ windowShouldClose :: IO Bool windowShouldClose = toBool <$> c'windowShouldClose -closeWindow :: WindowResources -> IO ()+closeWindow :: Maybe WindowResources -> IO () closeWindow wr = do- unloadShaders wr- unloadTextures wr- unloadFrameBuffers wr- unloadVaoIds wr- unloadVboIds wr- unloadAutomationEventLists wr- unloadFunPtrs wr+ mapM_ releaseNonAudioWindowResources wr c'closeWindow isWindowReady :: IO Bool@@ -925,17 +928,11 @@ loadVrStereoConfig :: VrDeviceInfo -> IO VrStereoConfig loadVrStereoConfig deviceInfo = withFreeable deviceInfo c'loadVrStereoConfig >>= pop -loadShader :: Maybe String -> Maybe String -> WindowResources -> IO Shader-loadShader vsFileName fsFileName wr = do- shader <- withMaybeCString vsFileName (withMaybeCString fsFileName . c'loadShader) >>= pop- addShaderId (shader'id shader) wr- return shader+loadShader :: Maybe String -> Maybe String -> IO Shader+loadShader vsFileName fsFileName = withMaybeCString vsFileName (withMaybeCString fsFileName . c'loadShader) >>= pop -loadShaderFromMemory :: Maybe String -> Maybe String -> WindowResources -> IO Shader-loadShaderFromMemory vsCode fsCode wr = do- shader <- withMaybeCString vsCode (withMaybeCString fsCode . c'loadShaderFromMemory) >>= pop- addShaderId (shader'id shader) wr- return shader+loadShaderFromMemory :: Maybe String -> Maybe String -> IO Shader+loadShaderFromMemory vsCode fsCode = withMaybeCString vsCode (withMaybeCString fsCode . c'loadShaderFromMemory) >>= pop isShaderReady :: Shader -> IO Bool isShaderReady shader = toBool <$> withFreeable shader c'isShaderReady@@ -992,10 +989,7 @@ setShaderValueTexture :: Shader -> Int -> Texture -> IO () setShaderValueTexture shader locIndex tex = withFreeable shader (\s -> withFreeable tex (c'setShaderValueTexture s (fromIntegral locIndex))) --- | Unloads a shader from GPU memory (VRAM). Shaders are automatically unloaded--- when `closeWindow` is called, so manually unloading shaders is not required.--- In larger projects, you may want to manually unload shaders to avoid having--- them in VRAM for too long.+-- | Unloads a `managed` shader from GPU memory (VRAM) unloadShader :: Shader -> WindowResources -> IO () unloadShader shader = unloadSingleShader (shader'id shader) @@ -1059,31 +1053,27 @@ openURL :: String -> IO () openURL url = withCString url c'openURL -setLoadFileDataCallback :: LoadFileDataCallback -> WindowResources -> IO C'LoadFileDataCallback-setLoadFileDataCallback callback window = do+setLoadFileDataCallback :: LoadFileDataCallback -> IO C'LoadFileDataCallback+setLoadFileDataCallback callback = do c <- createLoadFileDataCallback callback- addFunPtr (castFunPtr c) window c'setLoadFileDataCallback c return c -setSaveFileDataCallback :: (Storable a) => SaveFileDataCallback a -> WindowResources -> IO C'SaveFileDataCallback-setSaveFileDataCallback callback window = do+setSaveFileDataCallback :: (Storable a) => SaveFileDataCallback a -> IO C'SaveFileDataCallback+setSaveFileDataCallback callback = do c <- createSaveFileDataCallback callback- addFunPtr (castFunPtr c) window c'setSaveFileDataCallback c return c -setLoadFileTextCallback :: LoadFileTextCallback -> WindowResources -> IO C'LoadFileTextCallback-setLoadFileTextCallback callback window = do+setLoadFileTextCallback :: LoadFileTextCallback -> IO C'LoadFileTextCallback+setLoadFileTextCallback callback = do c <- createLoadFileTextCallback callback- addFunPtr (castFunPtr c) window c'setLoadFileTextCallback c return c -setSaveFileTextCallback :: SaveFileTextCallback -> WindowResources -> IO C'SaveFileTextCallback-setSaveFileTextCallback callback window = do+setSaveFileTextCallback :: SaveFileTextCallback -> IO C'SaveFileTextCallback+setSaveFileTextCallback callback = do c <- createSaveFileTextCallback callback- addFunPtr (castFunPtr c) window c'setSaveFileTextCallback c return c @@ -1154,6 +1144,9 @@ isPathFile :: String -> IO Bool isPathFile path = toBool <$> withCString path c'isPathFile +isFileNameValid :: String -> IO Bool+isFileNameValid path = toBool <$> withCString path c'isFileNameValid+ loadDirectoryFiles :: String -> IO FilePathList loadDirectoryFiles dirPath = withCString dirPath c'loadDirectoryFiles >>= pop @@ -1243,12 +1236,11 @@ exportAutomationEventList :: AutomationEventList -> String -> IO Bool exportAutomationEventList list fileName = toBool <$> withFreeable list (withCString fileName . c'exportAutomationEventList) -setAutomationEventList :: AutomationEventList -> WindowResources -> IO AutomationEventListRef-setAutomationEventList list wr = do+setAutomationEventList :: AutomationEventList -> IO AutomationEventListRef+setAutomationEventList list = do ptr <- malloc poke ptr list c'setAutomationEventList ptr- addAutomationEventList (castPtr ptr) wr return ptr setAutomationEventBaseFrame :: Int -> IO ()@@ -1266,8 +1258,9 @@ peekAutomationEventList :: AutomationEventListRef -> IO AutomationEventList peekAutomationEventList = peek -freeAutomationEventList :: AutomationEventListRef -> WindowResources -> IO ()-freeAutomationEventList list = unloadSingleAutomationEventList (castPtr list)+-- | Unloads a `managed` automation event list from CPU memory (RAM)+unloadAutomationEventList :: AutomationEventListRef -> WindowResources -> IO ()+unloadAutomationEventList list = unloadSingleAutomationEventList (castPtr list) isKeyPressed :: KeyboardKey -> IO Bool isKeyPressed key = toBool <$> c'isKeyPressed (fromIntegral $ fromEnum key)
src/Raylib/Core/Audio.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE TemplateHaskell #-} @@ -154,7 +153,7 @@ CUInt (..), withCString, )-import Raylib.Internal (WindowResources, addAudioBuffer, addAudioBufferAlias, addCtxData, unloadAudioBuffers, unloadCtxData, unloadSingleAudioBuffer, unloadSingleAudioBufferAlias, unloadSingleCtxDataPtr, addFunPtr, unloadSingleFunPtr)+import Raylib.Internal (WindowResources, unloadSingleAudioBuffer, unloadSingleAudioBufferAlias, unloadSingleCtxDataPtr, addFunPtr, unloadSingleFunPtr, releaseAudioWindowResources) import Raylib.Internal.Foreign ( pop, popCArray,@@ -166,7 +165,7 @@ ( AudioCallback, AudioStream (audioStream'buffer), C'AudioCallback,- Music (music'ctxData, music'ctxType, music'stream),+ Music (music'ctxData, music'ctxType), Sound (sound'stream), Wave (wave'channels, wave'frameCount), )@@ -244,10 +243,9 @@ initAudioDevice :: IO () initAudioDevice = c'initAudioDevice -closeAudioDevice :: WindowResources -> IO ()+closeAudioDevice :: Maybe WindowResources -> IO () closeAudioDevice wr = do- unloadCtxData wr- unloadAudioBuffers wr+ mapM_ releaseAudioWindowResources wr c'closeAudioDevice isAudioDeviceReady :: IO Bool@@ -265,35 +263,23 @@ loadWaveFromMemory :: String -> [Integer] -> IO Wave loadWaveFromMemory fileType fileData = withCString fileType (\f -> withFreeableArrayLen (map fromIntegral fileData) (\size d -> c'loadWaveFromMemory f d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop -loadSound :: String -> WindowResources -> IO Sound-loadSound fileName wr = do- sound <- withCString fileName c'loadSound >>= pop- addAudioBuffer (castPtr (audioStream'buffer (sound'stream sound))) wr- return sound+loadSound :: String -> IO Sound+loadSound fileName = withCString fileName c'loadSound >>= pop -loadSoundFromWave :: Wave -> WindowResources -> IO Sound-loadSoundFromWave wave wr = do- sound <- withFreeable wave c'loadSoundFromWave >>= pop- addAudioBuffer (castPtr (audioStream'buffer (sound'stream sound))) wr- return sound+loadSoundFromWave :: Wave -> IO Sound+loadSoundFromWave wave = withFreeable wave c'loadSoundFromWave >>= pop -loadSoundAlias :: Sound -> WindowResources -> IO Sound-loadSoundAlias source wr = do- sound <- withFreeable source c'loadSoundAlias >>= pop- addAudioBufferAlias (castPtr (audioStream'buffer (sound'stream sound))) wr- return sound+loadSoundAlias :: Sound -> IO Sound+loadSoundAlias source = withFreeable source c'loadSoundAlias >>= pop --- | Unloads a sound alias from RAM+-- | Unloads a `managed` sound alias from RAM unloadSoundAlias :: Sound -> WindowResources -> IO () unloadSoundAlias sound = unloadSingleAudioBufferAlias (castPtr (audioStream'buffer (sound'stream sound))) updateSound :: Sound -> Ptr () -> Int -> IO () updateSound sound dataValue sampleCount = withFreeable sound (\s -> c'updateSound s dataValue (fromIntegral sampleCount)) --- | Unloads a sound from RAM. Sounds are automatically unloaded--- when `closeAudioDevice` is called, so manually unloading sounds is--- not required. In larger projects, you may want to manually unload--- sounds to avoid having them in RAM for too long.+-- | Unloads a `managed` sound from RAM unloadSound :: Sound -> WindowResources -> IO () unloadSound sound = unloadAudioStream (sound'stream sound) @@ -337,9 +323,9 @@ waveCopy wave = withFreeable wave c'waveCopy >>= pop waveCrop :: Wave -> Int -> Int -> IO Wave-waveCrop wave initSample finalSample = do+waveCrop wave initFrame finalFrame = do new <- waveCopy wave- withFreeable new (\w -> c'waveCrop w (fromIntegral initSample) (fromIntegral finalSample) >> peek w)+ withFreeable new (\w -> c'waveCrop w (fromIntegral initFrame) (fromIntegral finalFrame) >> peek w) waveFormat :: Wave -> Int -> Int -> Int -> IO () waveFormat wave sampleRate sampleSize channels = do@@ -352,26 +338,16 @@ wave (\w -> map realToFrac <$> (popCArray (fromIntegral $ wave'frameCount wave * wave'channels wave) =<< c'loadWaveSamples w)) -loadMusicStream :: String -> WindowResources -> IO Music-loadMusicStream fileName wr = do- music <- withCString fileName c'loadMusicStream >>= pop- addAudioBuffer (castPtr (audioStream'buffer $ music'stream music)) wr- addCtxData (fromEnum $ music'ctxType music) (music'ctxData music) wr- return music+loadMusicStream :: String -> IO Music+loadMusicStream fileName = withCString fileName c'loadMusicStream >>= pop -loadMusicStreamFromMemory :: String -> [Integer] -> WindowResources -> IO Music-loadMusicStreamFromMemory fileType streamData wr = do- music <- withCString fileType (\t -> withFreeableArrayLen (map fromIntegral streamData) (\size d -> c'loadMusicStreamFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop- addAudioBuffer (castPtr (audioStream'buffer $ music'stream music)) wr- addCtxData (fromEnum $ music'ctxType music) (music'ctxData music) wr- return music+loadMusicStreamFromMemory :: String -> [Integer] -> IO Music+loadMusicStreamFromMemory fileType streamData =+ withCString fileType (\t -> withFreeableArrayLen (map fromIntegral streamData) (\size d -> c'loadMusicStreamFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop --- | Unloads a music stream from RAM. Music streams are automatically unloaded--- when `closeAudioDevice` is called, so manually unloading music streams is--- not required. In larger projects, you may want to manually unload music--- streams to avoid having them in RAM for too long.+-- | Unloads a `managed` music stream from RAM unloadMusicStream :: Music -> WindowResources -> IO ()-unloadMusicStream music = unloadSingleCtxDataPtr (fromEnum $ music'ctxType music) (music'ctxData music)+unloadMusicStream music = unloadSingleCtxDataPtr (fromEnum (music'ctxType music)) (music'ctxData music) isMusicReady :: Music -> IO Bool isMusicReady music = toBool <$> withFreeable music c'isMusicReady@@ -412,16 +388,10 @@ getMusicTimePlayed :: Music -> IO Float getMusicTimePlayed music = realToFrac <$> withFreeable music c'getMusicTimePlayed -loadAudioStream :: Integer -> Integer -> Integer -> WindowResources -> IO AudioStream-loadAudioStream sampleRate sampleSize channels wr = do- stream <- c'loadAudioStream (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels) >>= pop- addAudioBuffer (castPtr (audioStream'buffer stream)) wr- return stream+loadAudioStream :: Integer -> Integer -> Integer -> IO AudioStream+loadAudioStream sampleRate sampleSize channels = c'loadAudioStream (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels) >>= pop --- | Unloads an audio stream from RAM. Audio streams are automatically unloaded--- when `closeAudioDevice` is called, so manually unloading audio streams is--- not required. In larger projects, you may want to manually unload audio--- streams to avoid having them in RAM for too long.+-- | Unloads a `managed` audio stream from RAM unloadAudioStream :: AudioStream -> WindowResources -> IO () unloadAudioStream stream = unloadSingleAudioBuffer (castPtr $ audioStream'buffer stream)
src/Raylib/Core/Camera.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Bindings to @rcamera@ (raylib.h)
src/Raylib/Core/Models.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Bindings to @rmodels@@@ -27,6 +26,7 @@ drawGrid, loadModel, loadModelFromMesh,+ loadModelFromMeshManaged, unloadModel, isModelReady, getModelBoundingBox,@@ -163,7 +163,7 @@ withCString, ) import GHC.IO (unsafePerformIO)-import Raylib.Internal (WindowResources, addShaderId, addTextureId, addVaoId, addVboIds, unloadSingleShader, unloadSingleTexture, unloadSingleVaoId, unloadSingleVboIdList)+import Raylib.Internal (WindowResources, unloadSingleShader, unloadSingleTexture, unloadSingleVaoId, unloadSingleVboIdList, addToWindowResources) import Raylib.Internal.Foreign ( pop, popCArray,@@ -189,7 +189,7 @@ Shader (shader'id), Texture (texture'id), Vector2,- Vector3,+ Vector3, MaterialMapIndex, ) $( genNative@@ -332,24 +332,20 @@ drawGrid :: Int -> Float -> IO () drawGrid slices spacing = c'drawGrid (fromIntegral slices) (realToFrac spacing) -loadModel :: String -> WindowResources -> IO Model-loadModel fileName wr = do- model <- withCString fileName c'loadModel >>= pop- forM_ (model'meshes model) (`storeMeshData` wr)- storeMaterialData (model'materials model) wr- return model+loadModel :: String -> IO Model+loadModel fileName = withCString fileName c'loadModel >>= pop -loadModelFromMesh :: Mesh -> WindowResources -> IO Model-loadModelFromMesh mesh wr = do- model <- with mesh c'loadModelFromMesh >>= pop- storeMaterialData (model'materials model) wr+-- | Use `loadModelFromMeshManaged` for a resource-managed version+loadModelFromMesh :: Mesh -> IO Model+loadModelFromMesh mesh = with mesh c'loadModelFromMesh >>= pop++loadModelFromMeshManaged :: Mesh -> WindowResources -> IO Model+loadModelFromMeshManaged mesh wr = do+ model <- loadModelFromMesh mesh+ forM_ (model'materials model) (addToWindowResources wr) return model --- | Unloads a model from GPU memory (VRAM). This unloads its associated--- meshes and materials. Models are automatically unloaded when `Raylib.Core.closeWindow`--- is called, so manually unloading models is not required. In larger projects,--- you may want to manually unload models to avoid having them in VRAM for too--- long.+-- | Unloads a `managed` model from GPU memory (VRAM) unloadModel :: Model -> WindowResources -> IO () unloadModel model wr = do forM_ (model'meshes model) (`unloadMesh` wr)@@ -385,28 +381,18 @@ drawBillboardPro :: Camera3D -> Texture -> Rectangle -> Vector3 -> Vector3 -> Vector2 -> Vector2 -> Float -> Color -> IO () drawBillboardPro camera texture source position up size origin rotation tint = withFreeable camera (\c -> withFreeable texture (\t -> withFreeable source (\s -> withFreeable position (\p -> withFreeable up (\u -> withFreeable size (\sz -> withFreeable origin (\o -> withFreeable tint (c'drawBillboardPro c t s p u sz o (realToFrac rotation))))))))) -uploadMesh :: Mesh -> Bool -> WindowResources -> IO Mesh-uploadMesh mesh dynamic wr = withFreeable mesh (\m -> c'uploadMesh m (fromBool dynamic) >> peek m >>= (`storeMeshData` wr))+uploadMesh :: Mesh -> Bool -> IO Mesh+uploadMesh mesh dynamic = withFreeable mesh (\m -> c'uploadMesh m (fromBool dynamic) >> peek m) updateMeshBuffer :: Mesh -> Int -> Ptr () -> Int -> Int -> IO () updateMeshBuffer mesh index dataValue dataSize offset = withFreeable mesh (\m -> c'updateMeshBuffer m (fromIntegral index) dataValue (fromIntegral dataSize) (fromIntegral offset)) --- | Unloads a mesh from GPU memory (VRAM). Meshes are--- automatically unloaded when `Raylib.Core.closeWindow` is called, so manually unloading--- meshes is not required. In larger projects, you may want to--- manually unload meshes to avoid having them in VRAM for too long.+-- | Unloads a `managed` mesh from GPU memory (VRAM) unloadMesh :: Mesh -> WindowResources -> IO () unloadMesh mesh wr = do unloadSingleVaoId (mesh'vaoId mesh) wr unloadSingleVboIdList (mesh'vboId mesh) wr --- Internal-storeMeshData :: Mesh -> WindowResources -> IO Mesh-storeMeshData mesh wr = do- addVaoId (mesh'vaoId mesh) wr- addVboIds (mesh'vboId mesh) wr- return mesh- drawMesh :: Mesh -> Material -> Matrix -> IO () drawMesh mesh material transform = withFreeable mesh (\m -> withFreeable material (withFreeable transform . c'drawMesh m)) @@ -425,41 +411,41 @@ genMeshTangents :: Mesh -> IO Mesh genMeshTangents mesh = withFreeable mesh (\m -> c'genMeshTangents m >> peek m) -genMeshPoly :: Int -> Float -> WindowResources -> IO Mesh-genMeshPoly sides radius wr = c'genMeshPoly (fromIntegral sides) (realToFrac radius) >>= pop >>= (`storeMeshData` wr)+genMeshPoly :: Int -> Float -> IO Mesh+genMeshPoly sides radius = c'genMeshPoly (fromIntegral sides) (realToFrac radius) >>= pop -genMeshPlane :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh-genMeshPlane width _length resX resZ wr = c'genMeshPlane (realToFrac width) (realToFrac _length) (fromIntegral resX) (fromIntegral resZ) >>= pop >>= (`storeMeshData` wr)+genMeshPlane :: Float -> Float -> Int -> Int -> IO Mesh+genMeshPlane width _length resX resZ = c'genMeshPlane (realToFrac width) (realToFrac _length) (fromIntegral resX) (fromIntegral resZ) >>= pop -genMeshCube :: Float -> Float -> Float -> WindowResources -> IO Mesh-genMeshCube width height _length wr = c'genMeshCube (realToFrac width) (realToFrac height) (realToFrac _length) >>= pop >>= (`storeMeshData` wr)+genMeshCube :: Float -> Float -> Float -> IO Mesh+genMeshCube width height _length = c'genMeshCube (realToFrac width) (realToFrac height) (realToFrac _length) >>= pop -genMeshSphere :: Float -> Int -> Int -> WindowResources -> IO Mesh-genMeshSphere radius rings slices wr = c'genMeshSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop >>= (`storeMeshData` wr)+genMeshSphere :: Float -> Int -> Int -> IO Mesh+genMeshSphere radius rings slices = c'genMeshSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop -genMeshHemiSphere :: Float -> Int -> Int -> WindowResources -> IO Mesh-genMeshHemiSphere radius rings slices wr = c'genMeshHemiSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop >>= (`storeMeshData` wr)+genMeshHemiSphere :: Float -> Int -> Int -> IO Mesh+genMeshHemiSphere radius rings slices = c'genMeshHemiSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop -genMeshCylinder :: Float -> Float -> Int -> WindowResources -> IO Mesh-genMeshCylinder radius height slices wr = c'genMeshCylinder (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop >>= (`storeMeshData` wr)+genMeshCylinder :: Float -> Float -> Int -> IO Mesh+genMeshCylinder radius height slices = c'genMeshCylinder (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop -genMeshCone :: Float -> Float -> Int -> WindowResources -> IO Mesh-genMeshCone radius height slices wr = c'genMeshCone (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop >>= (`storeMeshData` wr)+genMeshCone :: Float -> Float -> Int -> IO Mesh+genMeshCone radius height slices = c'genMeshCone (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop -genMeshTorus :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh-genMeshTorus radius size radSeg sides wr = c'genMeshTorus (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop >>= (`storeMeshData` wr)+genMeshTorus :: Float -> Float -> Int -> Int -> IO Mesh+genMeshTorus radius size radSeg sides = c'genMeshTorus (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop -genMeshKnot :: Float -> Float -> Int -> Int -> WindowResources -> IO Mesh-genMeshKnot radius size radSeg sides wr = c'genMeshKnot (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop >>= (`storeMeshData` wr)+genMeshKnot :: Float -> Float -> Int -> Int -> IO Mesh+genMeshKnot radius size radSeg sides = c'genMeshKnot (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop -genMeshHeightmap :: Image -> Vector3 -> WindowResources -> IO Mesh-genMeshHeightmap heightmap size wr = withFreeable heightmap (withFreeable size . c'genMeshHeightmap) >>= pop >>= (`storeMeshData` wr)+genMeshHeightmap :: Image -> Vector3 -> IO Mesh+genMeshHeightmap heightmap size = withFreeable heightmap (withFreeable size . c'genMeshHeightmap) >>= pop -genMeshCubicmap :: Image -> Vector3 -> WindowResources -> IO Mesh-genMeshCubicmap cubicmap cubeSize wr = withFreeable cubicmap (withFreeable cubeSize . c'genMeshCubicmap) >>= pop >>= (`storeMeshData` wr)+genMeshCubicmap :: Image -> Vector3 -> IO Mesh+genMeshCubicmap cubicmap cubeSize = withFreeable cubicmap (withFreeable cubeSize . c'genMeshCubicmap) >>= pop -loadMaterials :: String -> WindowResources -> IO [Material]-loadMaterials fileName wr =+loadMaterials :: String -> IO [Material]+loadMaterials fileName = withCString fileName ( \f ->@@ -469,27 +455,11 @@ ptr <- c'loadMaterials f n num <- peek n materials <- popCArray (fromIntegral num) ptr- storeMaterialData materials wr return materials ) ) --- Internal-storeMaterialData :: [Material] -> WindowResources -> IO ()-storeMaterialData materials wr =- forM_- materials- ( \mat -> do- addShaderId (shader'id $ material'shader mat) wr- case material'maps mat of- Nothing -> return ()- (Just maps) -> forM_ maps (\m -> addTextureId (texture'id $ materialMap'texture m) wr)- )---- | Unloads a material from GPU memory (VRAM). Materials are--- automatically unloaded when `Raylib.Core.closeWindow` is called, so manually unloading--- materials is not required. In larger projects, you may want to--- manually unload materials to avoid having them in VRAM for too long.+-- | Unloads a `managed` material from GPU memory (VRAM) unloadMaterial :: Material -> WindowResources -> IO () unloadMaterial material wr = do unloadSingleShader (shader'id $ material'shader material) wr@@ -503,8 +473,8 @@ isMaterialReady :: Material -> IO Bool isMaterialReady material = toBool <$> withFreeable material c'isMaterialReady -setMaterialTexture :: Material -> Int -> Texture -> IO Material-setMaterialTexture material mapType texture = withFreeable material (\m -> withFreeable texture (c'setMaterialTexture m (fromIntegral mapType)) >> peek m)+setMaterialTexture :: Material -> MaterialMapIndex -> Texture -> IO Material+setMaterialTexture material mapType texture = withFreeable material (\m -> withFreeable texture (c'setMaterialTexture m (fromIntegral (fromEnum mapType))) >> peek m) setModelMeshMaterial :: Model -> Int -> Int -> IO Model setModelMeshMaterial model meshId materialId = withFreeable model (\m -> c'setModelMeshMaterial m (fromIntegral meshId) (fromIntegral materialId) >> peek m)
src/Raylib/Core/Shapes.hs view
@@ -1,5 +1,5 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE PatternSynonyms #-} -- | Bindings to @rshapes@ module Raylib.Core.Shapes@@ -36,6 +36,7 @@ drawRectangleLinesEx, drawRectangleRounded, drawRectangleRoundedLines,+ drawRectangleRoundedLinesEx, drawTriangle, drawTriangleLines, drawTriangleFan,@@ -67,6 +68,7 @@ checkCollisionPointPoly, checkCollisionLines, checkCollisionPointLine,+ checkCollisionCircleLine, getCollisionRec, -- * Native@@ -102,6 +104,7 @@ c'drawRectangleLinesEx, c'drawRectangleRounded, c'drawRectangleRoundedLines,+ c'drawRectangleRoundedLinesEx, c'drawTriangle, c'drawTriangleLines, c'drawTriangleFan,@@ -133,6 +136,7 @@ c'checkCollisionPointPoly, c'checkCollisionLines, c'checkCollisionPointLine,+ c'checkCollisionCircleLine, c'getCollisionRec ) where@@ -147,7 +151,7 @@ import GHC.IO (unsafePerformIO) import Raylib.Internal.Foreign (pop, withFreeable, withFreeableArray, withFreeableArrayLen) import Raylib.Internal.TH (genNative)-import Raylib.Types (Color, Rectangle, Texture, Vector2 (Vector2))+import Raylib.Types (Color, Rectangle, Texture, Vector2, pattern Vector2) $( genNative [ ("c'setShapesTexture", "SetShapesTexture_", "rl_bindings.h", [t|Ptr Texture -> Ptr Rectangle -> IO ()|], False),@@ -181,7 +185,8 @@ ("c'drawRectangleLines", "DrawRectangleLines_", "rl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False), ("c'drawRectangleLinesEx", "DrawRectangleLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> Ptr Color -> IO ()|], False), ("c'drawRectangleRounded", "DrawRectangleRounded_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|], False),- ("c'drawRectangleRoundedLines", "DrawRectangleRoundedLines_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()|], False),+ ("c'drawRectangleRoundedLines", "DrawRectangleRoundedLines_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> Ptr Color -> IO ()|], False),+ ("c'drawRectangleRoundedLinesEx", "DrawRectangleRoundedLinesEx_", "rl_bindings.h", [t|Ptr Rectangle -> CFloat -> CInt -> CFloat -> Ptr Color -> IO ()|], False), ("c'drawTriangle", "DrawTriangle_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False), ("c'drawTriangleLines", "DrawTriangleLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False), ("c'drawTriangleFan", "DrawTriangleFan_", "rl_bindings.h", [t|Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),@@ -213,6 +218,7 @@ ("c'checkCollisionPointPoly", "CheckCollisionPointPoly_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|], False), ("c'checkCollisionLines", "CheckCollisionLines_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|], False), ("c'checkCollisionPointLine", "CheckCollisionPointLine_", "rl_bindings.h", [t|Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CInt -> IO CBool|], False),+ ("c'checkCollisionCircleLine", "CheckCollisionCircleLine_", "rl_bindings.h", [t|Ptr Vector2 -> CFloat -> Ptr Vector2 -> Ptr Vector2 -> IO CBool|], False), ("c'getCollisionRec", "GetCollisionRec_", "rl_bindings.h", [t|Ptr Rectangle -> Ptr Rectangle -> IO (Ptr Rectangle)|], False) ] )@@ -399,10 +405,14 @@ drawRectangleRounded rect roundness segments color = withFreeable rect (\r -> withFreeable color $ c'drawRectangleRounded r (realToFrac roundness) (fromIntegral segments)) -drawRectangleRoundedLines :: Rectangle -> Float -> Int -> Float -> Color -> IO ()-drawRectangleRoundedLines rect roundness segments thickness color =- withFreeable rect (\r -> withFreeable color $ c'drawRectangleRoundedLines r (realToFrac roundness) (fromIntegral segments) (realToFrac thickness))+drawRectangleRoundedLines :: Rectangle -> Float -> Int -> Color -> IO ()+drawRectangleRoundedLines rect roundness segments color =+ withFreeable rect (\r -> withFreeable color $ c'drawRectangleRoundedLines r (realToFrac roundness) (fromIntegral segments)) +drawRectangleRoundedLinesEx :: Rectangle -> Float -> Int -> Float -> Color -> IO ()+drawRectangleRoundedLinesEx rect roundness segments thickness color =+ withFreeable rect (\r -> withFreeable color $ c'drawRectangleRoundedLinesEx r (realToFrac roundness) (fromIntegral segments) (realToFrac thickness))+ drawTriangle :: Vector2 -> Vector2 -> Vector2 -> Color -> IO () drawTriangle v1 v2 v3 color = withFreeable@@ -540,6 +550,10 @@ checkCollisionPointLine :: Vector2 -> Vector2 -> Vector2 -> Int -> Bool checkCollisionPointLine point p1 p2 threshold = unsafePerformIO $ toBool <$> withFreeable point (\p -> withFreeable p1 (\ptr1 -> withFreeable p2 (\ptr2 -> c'checkCollisionPointLine p ptr1 ptr2 (fromIntegral threshold))))++checkCollisionCircleLine :: Vector2 -> Float -> Vector2 -> Vector2 -> Bool+checkCollisionCircleLine center radius p1 p2 =+ unsafePerformIO $ toBool <$> withFreeable center (\c -> withFreeable p1 (\ptr1 -> withFreeable p2 (\ptr2 -> c'checkCollisionCircleLine c (realToFrac radius) ptr1 ptr2))) getCollisionRec :: Rectangle -> Rectangle -> Rectangle getCollisionRec rec1 rec2 =
src/Raylib/Core/Text.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Bindings to @rtext@@@ -62,11 +61,11 @@ c'getCodepointCount, c'getCodepointNext, c'getCodepointPrevious,- c'codepointToUTF8+ c'codepointToUTF8, ) where -import Foreign (Ptr, Storable (peek, sizeOf), toBool)+import Foreign (Ptr, Storable (peek, sizeOf), nullPtr, toBool) import Foreign.C ( CBool (..), CFloat (..),@@ -76,7 +75,7 @@ peekCString, withCString, )-import Raylib.Internal (WindowResources, addTextureId, unloadSingleTexture)+import Raylib.Internal (WindowResources, unloadSingleTexture) import Raylib.Internal.Foreign ( pop, popCArray,@@ -134,40 +133,57 @@ getFontDefault :: IO Font getFontDefault = c'getFontDefault >>= pop -loadFont :: String -> WindowResources -> IO Font-loadFont fileName wr = do- font <- withCString fileName c'loadFont >>= pop- addTextureId (texture'id $ font'texture font) wr- return font+loadFont :: String -> IO Font+loadFont fileName = withCString fileName c'loadFont >>= pop -loadFontEx :: String -> Int -> [Int] -> Int -> WindowResources -> IO Font-loadFontEx fileName fontSize fontChars glyphCount wr = do- font <- withCString fileName (\f -> withFreeableArray (map fromIntegral fontChars) (\c -> c'loadFontEx f (fromIntegral fontSize) c (fromIntegral glyphCount))) >>= pop- addTextureId (texture'id $ font'texture font) wr- return font+loadFontEx :: String -> Int -> Maybe [Int] -> IO Font+loadFontEx fileName fontSize codepoints =+ withCString+ fileName+ ( \f -> case codepoints of+ Just codepoints' -> withFreeableArrayLen (map fromIntegral codepoints') (\l c -> c'loadFontEx f (fromIntegral fontSize) c (fromIntegral l))+ Nothing -> c'loadFontEx f (fromIntegral fontSize) nullPtr 0+ )+ >>= pop -loadFontFromImage :: Image -> Color -> Int -> WindowResources -> IO Font-loadFontFromImage image key firstChar wr = do- font <- withFreeable image (\i -> withFreeable key (\k -> c'loadFontFromImage i k (fromIntegral firstChar))) >>= pop- addTextureId (texture'id $ font'texture font) wr- return font+loadFontFromImage :: Image -> Color -> Int -> IO Font+loadFontFromImage image key firstChar = withFreeable image (\i -> withFreeable key (\k -> c'loadFontFromImage i k (fromIntegral firstChar))) >>= pop -loadFontFromMemory :: String -> [Integer] -> Int -> [Int] -> Int -> WindowResources -> IO Font-loadFontFromMemory fileType fileData fontSize fontChars glyphCount wr = do- font <- withCString fileType (\t -> withFreeableArrayLen (map fromIntegral fileData) (\size d -> withFreeableArray (map fromIntegral fontChars) (\c -> c'loadFontFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount)))) >>= pop- addTextureId (texture'id $ font'texture font) wr- return font+loadFontFromMemory :: String -> [Integer] -> Int -> Maybe [Int] -> IO Font+loadFontFromMemory fileType fileData fontSize codepoints =+ withCString+ fileType+ ( \t ->+ withFreeableArrayLen+ (map fromIntegral fileData)+ ( \size d ->+ case codepoints of+ Just codepoints' ->+ withFreeableArrayLen+ (map fromIntegral codepoints')+ ( \l c -> c'loadFontFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral l)+ )+ Nothing -> c'loadFontFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) nullPtr 0+ )+ )+ >>= pop -loadFontData :: [Integer] -> Int -> [Int] -> Int -> FontType -> IO GlyphInfo-loadFontData fileData fontSize fontChars glyphCount fontType = withFreeableArrayLen (map fromIntegral fileData) (\size d -> withFreeableArray (map fromIntegral fontChars) (\c -> c'loadFontData d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount) (fromIntegral $ fromEnum fontType))) >>= pop+loadFontData :: [Integer] -> Int -> Maybe [Int] -> FontType -> IO GlyphInfo+loadFontData fileData fontSize codepoints fontType =+ withFreeableArrayLen+ (map fromIntegral fileData)+ ( \size d ->+ case codepoints of+ Just codepoints' ->+ withFreeableArrayLen (map fromIntegral codepoints') (\l c -> c'loadFontData d (fromIntegral (size * sizeOf (0 :: CUChar))) (fromIntegral fontSize) c (fromIntegral l) (fromIntegral (fromEnum fontType)))+ Nothing -> c'loadFontData d (fromIntegral (size * sizeOf (0 :: CUChar))) (fromIntegral fontSize) nullPtr 0 (fromIntegral (fromEnum fontType))+ )+ >>= pop genImageFontAtlas :: [GlyphInfo] -> [[Rectangle]] -> Int -> Int -> Int -> Int -> IO Image genImageFontAtlas chars recs glyphCount fontSize padding packMethod = withFreeableArray chars (\c -> withFreeableArray2D recs (\r -> c'genImageFontAtlas c r (fromIntegral glyphCount) (fromIntegral fontSize) (fromIntegral padding) (fromIntegral packMethod))) >>= pop --- | Unloads a font from GPU memory (VRAM). Fonts are automatically unloaded--- when `Raylib.Core.closeWindow` is called, so manually unloading fonts is not required.--- In larger projects, you may want to manually unload fonts to avoid having--- them in VRAM for too long.+-- | Unloads a `managed` font from GPU memory (VRAM) unloadFont :: Font -> WindowResources -> IO () unloadFont font = unloadSingleTexture (texture'id $ font'texture font)
src/Raylib/Core/Textures.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Bindings to @rtextures@@@ -26,6 +25,7 @@ genImageCellular, genImageText, imageFromImage,+ imageFromChannel, imageText, imageTextEx, imageFormat,@@ -70,6 +70,11 @@ imageDrawRectangleV, imageDrawRectangleRec, imageDrawRectangleLines,+ imageDrawTriangle,+ imageDrawTriangleEx,+ imageDrawTriangleLines,+ imageDrawTriangleFan,+ imageDrawTriangleStrip, imageDraw, imageDrawText, imageDrawTextEx,@@ -133,6 +138,7 @@ c'genImageText, c'imageCopy, c'imageFromImage,+ c'imageFromChannel, c'imageText, c'imageTextEx, c'imageFormat,@@ -177,6 +183,11 @@ c'imageDrawRectangleV, c'imageDrawRectangleRec, c'imageDrawRectangleLines,+ c'imageDrawTriangle,+ c'imageDrawTriangleEx,+ c'imageDrawTriangleLines,+ c'imageDrawTriangleFan,+ c'imageDrawTriangleStrip, c'imageDraw, c'imageDrawText, c'imageDrawTextEx,@@ -233,7 +244,7 @@ withCString, ) import GHC.IO (unsafePerformIO)-import Raylib.Internal (WindowResources, addFrameBuffer, addTextureId, unloadSingleFrameBuffer, unloadSingleTexture)+import Raylib.Internal (WindowResources, unloadSingleFrameBuffer, unloadSingleTexture) import qualified Raylib.Internal as I import Raylib.Internal.Foreign ( pop,@@ -285,6 +296,7 @@ ("c'genImageText", "GenImageText_", "rl_bindings.h", [t|CInt -> CInt -> CString -> IO (Ptr Image)|], False), ("c'imageCopy", "ImageCopy_", "rl_bindings.h", [t|Ptr Image -> IO (Ptr Image)|], False), ("c'imageFromImage", "ImageFromImage_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> IO (Ptr Image)|], False),+ ("c'imageFromChannel", "ImageFromChannel_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO (Ptr Image)|], False), ("c'imageText", "ImageText_", "rl_bindings.h", [t|CString -> CInt -> Ptr Color -> IO (Ptr Image)|], False), ("c'imageTextEx", "ImageTextEx_", "rl_bindings.h", [t|Ptr Font -> CString -> CFloat -> CFloat -> Ptr Color -> IO (Ptr Image)|], False), ("c'imageFormat", "ImageFormat_", "rl_bindings.h", [t|Ptr Image -> CInt -> IO ()|], False),@@ -329,6 +341,11 @@ ("c'imageDrawRectangleV", "ImageDrawRectangleV_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False), ("c'imageDrawRectangleRec", "ImageDrawRectangleRec_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> Ptr Color -> IO ()|], False), ("c'imageDrawRectangleLines", "ImageDrawRectangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Rectangle -> CInt -> Ptr Color -> IO ()|], False),+ ("c'imageDrawTriangle", "ImageDrawTriangle_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),+ ("c'imageDrawTriangleEx", "ImageDrawTriangleEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> Ptr Color -> Ptr Color -> IO ()|], False),+ ("c'imageDrawTriangleLines", "ImageDrawTriangleLines_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> Ptr Color -> IO ()|], False),+ ("c'imageDrawTriangleFan", "ImageDrawTriangleFan_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False),+ ("c'imageDrawTriangleStrip", "ImageDrawTriangleStrip_", "rl_bindings.h", [t|Ptr Image -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()|], False), ("c'imageDraw", "ImageDraw_", "rl_bindings.h", [t|Ptr Image -> Ptr Image -> Ptr Rectangle -> Ptr Rectangle -> Ptr Color -> IO ()|], False), ("c'imageDrawText", "ImageDrawText_", "rl_bindings.h", [t|Ptr Image -> CString -> CInt -> CInt -> CInt -> Ptr Color -> IO ()|], False), ("c'imageDrawTextEx", "ImageDrawTextEx_", "rl_bindings.h", [t|Ptr Image -> Ptr Font -> CString -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()|], False),@@ -487,13 +504,16 @@ imageFromImage :: Image -> Rectangle -> IO Image imageFromImage image rect = withFreeable image (withFreeable rect . c'imageFromImage) >>= pop +imageFromChannel :: Image -> Int -> IO Image+imageFromChannel image channel = withFreeable image (\i -> c'imageFromChannel i (fromIntegral channel)) >>= pop+ imageText :: String -> Int -> Color -> IO Image imageText text fontSize color =- withCString text (\t -> withFreeable color $ c'imageText t (fromIntegral fontSize)) >>= pop+ withCString text (\t -> withFreeable color (c'imageText t (fromIntegral fontSize))) >>= pop imageTextEx :: Font -> String -> Float -> Float -> Color -> IO Image imageTextEx font text fontSize spacing tint =- withFreeable font (\f -> withCString text (\t -> withFreeable tint $ c'imageTextEx f t (realToFrac fontSize) (realToFrac spacing))) >>= pop+ withFreeable font (\f -> withCString text (\t -> withFreeable tint (c'imageTextEx f t (realToFrac fontSize) (realToFrac spacing)))) >>= pop imageFormat :: Image -> PixelFormat -> IO Image imageFormat image newFormat =@@ -638,6 +658,21 @@ imageDrawRectangleLines :: Image -> Rectangle -> Int -> Color -> IO Image imageDrawRectangleLines image rectangle thickness color = withFreeable image (\i -> withFreeable rectangle (\r -> withFreeable color (c'imageDrawRectangleLines i r (fromIntegral thickness))) >> peek i) +imageDrawTriangle :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> IO Image+imageDrawTriangle image v1 v2 v3 color = withFreeable image (\i -> withFreeable v1 (\p1 -> withFreeable v2 (\p2 -> withFreeable v3 (\p3 -> withFreeable color (\c -> c'imageDrawTriangle i p1 p2 p3 c)))) >> peek i)++imageDrawTriangleEx :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> Color -> Color -> IO Image+imageDrawTriangleEx image v1 v2 v3 c1 c2 c3 = withFreeable image (\i -> withFreeable v1 (\p1 -> withFreeable v2 (\p2 -> withFreeable v3 (\p3 -> withFreeable c1 (\q1 -> withFreeable c2 (\q2 -> withFreeable c3 (\q3 -> c'imageDrawTriangleEx i p1 p2 p3 q1 q2 q3)))))) >> peek i)++imageDrawTriangleLines :: Image -> Vector2 -> Vector2 -> Vector2 -> Color -> IO Image+imageDrawTriangleLines image v1 v2 v3 color = withFreeable image (\i -> withFreeable v1 (\p1 -> withFreeable v2 (\p2 -> withFreeable v3 (\p3 -> withFreeable color (\c -> c'imageDrawTriangleLines i p1 p2 p3 c)))) >> peek i)++imageDrawTriangleFan :: Image -> [Vector2] -> Color -> IO Image+imageDrawTriangleFan image points color = withFreeable image (\i -> withFreeableArrayLen points (\l p -> withFreeable color (c'imageDrawTriangleFan i p (fromIntegral l))) >> peek i)++imageDrawTriangleStrip :: Image -> [Vector2] -> Color -> IO Image+imageDrawTriangleStrip image points color = withFreeable image (\i -> withFreeableArrayLen points (\l p -> withFreeable color (c'imageDrawTriangleStrip i p (fromIntegral l))) >> peek i)+ imageDraw :: Image -> Image -> Rectangle -> Rectangle -> Color -> IO Image imageDraw image source srcRec dstRec tint = withFreeable image (\i -> withFreeable source (\s -> withFreeable srcRec (\sr -> withFreeable dstRec (withFreeable tint . c'imageDraw i s sr))) >> peek i) @@ -647,30 +682,17 @@ imageDrawTextEx :: Image -> Font -> String -> Vector2 -> Float -> Float -> Color -> IO Image imageDrawTextEx image font text position fontSize spacing tint = withFreeable image (\i -> withFreeable font (\f -> withCString text (\t -> withFreeable position (\p -> withFreeable tint (c'imageDrawTextEx i f t p (realToFrac fontSize) (realToFrac spacing))))) >> peek i) -loadTexture :: String -> WindowResources -> IO Texture-loadTexture fileName wr = do- texture <- withCString fileName c'loadTexture >>= pop- addTextureId (texture'id texture) wr- return texture+loadTexture :: String -> IO Texture+loadTexture fileName = withCString fileName c'loadTexture >>= pop -loadTextureFromImage :: Image -> WindowResources -> IO Texture-loadTextureFromImage image wr = do- texture <- withFreeable image c'loadTextureFromImage >>= pop- addTextureId (texture'id texture) wr- return texture+loadTextureFromImage :: Image -> IO Texture+loadTextureFromImage image = withFreeable image c'loadTextureFromImage >>= pop -loadTextureCubemap :: Image -> CubemapLayout -> WindowResources -> IO Texture-loadTextureCubemap image layout wr = do- texture <- withFreeable image (\i -> c'loadTextureCubemap i (fromIntegral $ fromEnum layout)) >>= pop- addTextureId (texture'id texture) wr- return texture+loadTextureCubemap :: Image -> CubemapLayout -> IO Texture+loadTextureCubemap image layout = withFreeable image (\i -> c'loadTextureCubemap i (fromIntegral $ fromEnum layout)) >>= pop -loadRenderTexture :: Int -> Int -> WindowResources -> IO RenderTexture-loadRenderTexture width height wr = do- renderTexture <- c'loadRenderTexture (fromIntegral width) (fromIntegral height) >>= pop- addFrameBuffer (renderTexture'id renderTexture) wr- addTextureId (texture'id $ renderTexture'texture renderTexture) wr- return renderTexture+loadRenderTexture :: Int -> Int -> IO RenderTexture+loadRenderTexture width height = c'loadRenderTexture (fromIntegral width) (fromIntegral height) >>= pop isTextureReady :: Texture -> IO Bool isTextureReady texture = toBool <$> withFreeable texture c'isTextureReady@@ -678,17 +700,11 @@ isRenderTextureReady :: RenderTexture -> IO Bool isRenderTextureReady renderTexture = toBool <$> withFreeable renderTexture c'isRenderTextureReady --- | Unloads a texture from GPU memory (VRAM). Textures are automatically unloaded--- when `Raylib.Core.closeWindow` is called, so manually unloading textures is not required.--- In larger projects, you may want to manually unload textures to avoid having--- them in VRAM for too long.+-- | Unloads a `managed` texture from GPU memory (VRAM) unloadTexture :: Texture -> WindowResources -> IO () unloadTexture texture = unloadSingleTexture (texture'id texture) --- | Unloads a render texture from GPU memory (VRAM). Render textures are--- automatically unloaded when `Raylib.Core.closeWindow` is called, so manually unloading--- render textures is not required. In larger projects, you may want to--- manually unload render textures to avoid having them in VRAM for too long.+-- | Unloads a `managed` render texture from GPU memory (VRAM) unloadRenderTexture :: RenderTexture -> WindowResources -> IO () unloadRenderTexture renderTexture wr = do unloadSingleTexture (texture'id $ renderTexture'texture renderTexture) wr
src/Raylib/Internal.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE CPP #-}-{-# OPTIONS -Wall #-} {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE TemplateHaskell #-} @@ -7,6 +6,11 @@ module Raylib.Internal ( WindowResources (..), defaultWindowResources,+ releaseNonAudioWindowResources,+ releaseAudioWindowResources,+ releaseAllWindowResources,+ Closeable (..),+ managed, -- * Unloading individual resources unloadSingleShader,@@ -44,6 +48,18 @@ addAutomationEventList, addFunPtr, + -- * Native unload functions+ c'rlUnloadShaderProgram,+ c'rlUnloadTexture,+ c'rlUnloadFramebuffer,+ c'rlUnloadVertexArray,+ c'rlUnloadVertexBuffer,+ c'unloadMusicStreamData,+ c'unloadAudioBuffer,+ c'unloadAudioBufferAlias,+ c'getPixelDataSize,+ _unloadAutomationEventList,+ -- * Miscellaneous c'rlGetShaderIdDefault, getPixelDataSize,@@ -55,7 +71,7 @@ import Data.List (delete) import Data.Map (Map) import qualified Data.Map as Map-import Foreign (FunPtr, Ptr, Storable (peekByteOff), free, freeHaskellFunPtr)+import Foreign (FunPtr, Ptr, Storable (peekByteOff), free, freeHaskellFunPtr, castFunPtr) import Foreign.C (CInt (..), CUInt (..)) import GHC.IO (unsafePerformIO) import Raylib.Internal.TH (genNative)@@ -84,6 +100,27 @@ funPtrs :: IORef [FunPtr ()] } +-- | Typeclass to conveniently release resources+class Closeable a where+ -- | Release a resource; this is only necessary when using an unmanaged resource+ --+ -- WARNING: Do not use this on a managed resource, doing so will cause it to be freed twice+ close :: a -> IO ()++ -- | Add an unmanaged resource to a `WindowResources` handle to be freed later+ addToWindowResources :: WindowResources -> a -> IO ()++instance {-# OVERLAPPABLE #-} (Closeable a) => Closeable [a] where+ close xs = forM_ xs close+ addToWindowResources window xs = forM_ xs (addToWindowResources window)++-- | Use this when loading a resource for automatic memory management+managed :: (Closeable a) => WindowResources -> IO a -> IO a+managed window resource = do+ resource' <- resource+ addToWindowResources window resource'+ return resource'+ defaultWindowResources :: IO WindowResources defaultWindowResources = do sIds <- newIORef []@@ -357,6 +394,30 @@ addFunPtr :: FunPtr () -> WindowResources -> IO () addFunPtr fPtr wr = do modifyIORef (funPtrs wr) (\xs -> if fPtr `elem` xs then xs else fPtr : xs)++instance Closeable (FunPtr a) where+ close fun = freeHaskellFunPtr fun+ addToWindowResources window fun = addFunPtr (castFunPtr fun) window++releaseNonAudioWindowResources :: WindowResources -> IO ()+releaseNonAudioWindowResources wr = do+ unloadShaders wr+ unloadTextures wr+ unloadFrameBuffers wr+ unloadVaoIds wr+ unloadVboIds wr+ unloadAutomationEventLists wr+ unloadFunPtrs wr++releaseAudioWindowResources :: WindowResources -> IO ()+releaseAudioWindowResources wr = do+ unloadCtxData wr+ unloadAudioBuffers wr++releaseAllWindowResources :: WindowResources -> IO ()+releaseAllWindowResources wr = do+ releaseNonAudioWindowResources wr+ releaseAudioWindowResources wr _unloadAutomationEventList :: Ptr () -> IO () _unloadAutomationEventList ptr = (free =<< (peekByteOff ptr 8 :: IO (Ptr ()))) >> free ptr
src/Raylib/Internal/Foreign.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} @@ -45,6 +44,7 @@ import Foreign (FunPtr, Ptr, Storable (peek, peekByteOff, poke, sizeOf), allocaBytes, castPtr, malloc, newArray, nullPtr, peekArray, plusPtr, pokeArray0, with, withArray, withArrayLen) import Foreign.C (CFloat, CInt, CString, CUChar, CUInt, peekCString, withCString) import Foreign.C.Types (CBool, CChar, CShort, CUShort)+import Linear (V2, V3, V4) -- Internal utility functions @@ -110,6 +110,12 @@ ( \i -> do let val = arr !! i in rlFreeDependents val (plusPtr ptr (i * sizeOf val)) )++instance Freeable (V2 a)++instance Freeable (V3 a)++instance Freeable (V4 a) rlFreeMaybeArray :: (Freeable a, Storable a) => Maybe [a] -> Ptr a -> IO () rlFreeMaybeArray Nothing _ = return ()
src/Raylib/Internal/TH.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS -Wall -Wno-unrecognised-pragmas #-}-{-# HLINT ignore "Unused LANGUAGE pragma" #-} {-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TupleSections #-}
src/Raylib/Internal/Web/Processable.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE CPP #-}-{-# OPTIONS -Wall #-} {-# LANGUAGE ConstrainedClassMethods #-} -- | Internal code to convert Haskell types to raw bytes
src/Raylib/Types.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS -Wall #-}- -- | -- -- Each @Types@ module has up to 4 sections: one for enumerations, one for
src/Raylib/Types/Core.hs view
@@ -1,5 +1,7 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-} -- | Bindings for types used in all raylib modules module Raylib.Types.Core@@ -15,9 +17,21 @@ Gesture (..), -- * Structures- Vector2 (..),- Vector3 (..),- Vector4 (..),+ Vector2,+ Vector3,+ Vector4,+ pattern Vector2,+ vector2'x,+ vector2'y,+ pattern Vector3,+ vector3'x,+ vector3'y,+ vector3'z,+ pattern Vector4,+ vector4'x,+ vector4'y,+ vector4'z,+ vector4'w, vectorToColor, Matrix (..), Color (..),@@ -124,8 +138,11 @@ newCString, peekCString, )+import Linear (V2(V2), V3(V3), V4(V4))+import Raylib.Internal (Closeable(..), _unloadAutomationEventList, addAutomationEventList) import Raylib.Internal.Foreign (Freeable (rlFreeDependents), c'free, peekStaticArray, pokeStaticArray) + --------------------------------------- -- core enums ------------------------- ---------------------------------------@@ -640,50 +657,31 @@ -- core structures -------------------- --------------------------------------- -data Vector2 = Vector2- { vector2'x :: Float,- vector2'y :: Float- }- deriving (Eq, Show, Freeable) -instance Storable Vector2 where- sizeOf _ = 8- alignment _ = 4- peek _p = do- x <- realToFrac <$> peek (p'vector2'x _p)- y <- realToFrac <$> peek (p'vector2'y _p)- return $ Vector2 x y- poke _p (Vector2 x y) = do- poke (p'vector2'x _p) (realToFrac x)- poke (p'vector2'y _p) (realToFrac y)- return ()+type Vector2 = V2 Float +pattern Vector2 :: Float -> Float -> Vector2+pattern Vector2+ { vector2'x ,+ vector2'y+ } = V2 vector2'x vector2'y+{-# COMPLETE Vector2 :: V2 #-}+ p'vector2'x :: Ptr Vector2 -> Ptr CFloat p'vector2'x = (`plusPtr` 0) p'vector2'y :: Ptr Vector2 -> Ptr CFloat p'vector2'y = (`plusPtr` 4) -data Vector3 = Vector3- { vector3'x :: Float,- vector3'y :: Float,- vector3'z :: Float- }- deriving (Eq, Show, Freeable)+type Vector3 = V3 Float -instance Storable Vector3 where- sizeOf _ = 12- alignment _ = 4- peek _p = do- x <- realToFrac <$> peek (p'vector3'x _p)- y <- realToFrac <$> peek (p'vector3'y _p)- z <- realToFrac <$> peek (p'vector3'z _p)- return $ Vector3 x y z- poke _p (Vector3 x y z) = do- poke (p'vector3'x _p) (realToFrac x)- poke (p'vector3'y _p) (realToFrac y)- poke (p'vector3'z _p) (realToFrac z)- return ()+pattern Vector3 :: Float -> Float -> Float -> Vector3+pattern Vector3+ { vector3'x ,+ vector3'y ,+ vector3'z+ } = V3 vector3'x vector3'y vector3'z+{-# COMPLETE Vector3 :: V3 #-} p'vector3'x :: Ptr Vector3 -> Ptr CFloat p'vector3'x = (`plusPtr` 0)@@ -694,29 +692,16 @@ p'vector3'z :: Ptr Vector3 -> Ptr CFloat p'vector3'z = (`plusPtr` 8) -data Vector4 = Vector4- { vector4'x :: Float,- vector4'y :: Float,- vector4'z :: Float,- vector4'w :: Float- }- deriving (Eq, Show, Freeable)+type Vector4 = V4 Float -instance Storable Vector4 where- sizeOf _ = 16- alignment _ = 4- peek _p = do- x <- realToFrac <$> peek (p'vector4'x _p)- y <- realToFrac <$> peek (p'vector4'y _p)- z <- realToFrac <$> peek (p'vector4'z _p)- w <- realToFrac <$> peek (p'vector4'w _p)- return $ Vector4 x y z w- poke _p (Vector4 x y z w) = do- poke (p'vector4'x _p) (realToFrac x)- poke (p'vector4'y _p) (realToFrac y)- poke (p'vector4'z _p) (realToFrac z)- poke (p'vector4'w _p) (realToFrac w)- return ()+pattern Vector4 :: a -> a -> a -> a -> V4 a+pattern Vector4+ { vector4'x,+ vector4'y,+ vector4'z,+ vector4'w+ } = V4 vector4'x vector4'y vector4'z vector4'w+{-# COMPLETE Vector4 :: V4 #-} vectorToColor :: Vector4 -> Color vectorToColor (Vector4 x y z w) = Color (round $ x * 255) (round $ y * 255) (round $ z * 255) (round $ w * 255)@@ -1159,6 +1144,10 @@ c'free . castPtr =<< peek (p'automationEventList'events ptr) type AutomationEventListRef = Ptr AutomationEventList++instance Closeable AutomationEventListRef where+ close = _unloadAutomationEventList . castPtr+ addToWindowResources window listRef = addAutomationEventList (castPtr listRef) window --------------------------------------- -- core callbacks ---------------------
src/Raylib/Types/Core/Audio.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} -{-# OPTIONS -Wall #-}- -- | Bindings for types used in @raudio@ module Raylib.Types.Core.Audio ( -- * Enumerations@@ -85,6 +83,7 @@ CUChar, CUInt, )+import Raylib.Internal (Closeable (..), c'unloadAudioBuffer, addAudioBuffer, c'unloadMusicStreamData, addCtxData) import Raylib.Internal.Foreign (Freeable (rlFreeDependents), c'free, peekMaybe, peekStaticArray, pokeMaybe, pokeStaticArray) ---------------------------------------@@ -476,6 +475,10 @@ poke (p'audioStream'channels _p) (fromIntegral channels) return () +instance Closeable AudioStream where+ close stream = c'unloadAudioBuffer (castPtr (audioStream'buffer stream))+ addToWindowResources window stream = addAudioBuffer (castPtr (audioStream'buffer stream)) window+ -- maybe p'audioStream'buffer :: Ptr AudioStream -> Ptr (Ptr RAudioBuffer) p'audioStream'buffer = (`plusPtr` 0)@@ -511,6 +514,10 @@ poke (p'sound'frameCount _p) (fromIntegral frameCount) return () +instance Closeable Sound where+ close sound = close (sound'stream sound)+ addToWindowResources window = addToWindowResources window . sound'stream+ p'sound'stream :: Ptr Sound -> Ptr AudioStream p'sound'stream = (`plusPtr` 0) @@ -543,6 +550,10 @@ poke (p'music'ctxType _p) ctxType poke (p'music'ctxData _p) ctxData return ()++instance Closeable Music where+ close music = c'unloadMusicStreamData (fromIntegral (fromEnum (music'ctxType music))) (music'ctxData music)+ addToWindowResources window music = addCtxData (fromEnum $ music'ctxType music) (music'ctxData music) window p'music'stream :: Ptr Music -> Ptr AudioStream p'music'stream = (`plusPtr` 0)
src/Raylib/Types/Core/Camera.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} -{-# OPTIONS -Wall #-}- -- | Bindings for camera-related types module Raylib.Types.Core.Camera ( -- * Enumerations
src/Raylib/Types/Core/Models.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-}--{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} -- | Bindings for types used mainly in @rmodels@ module Raylib.Types.Core.Models@@ -81,7 +80,7 @@ ) where -import Control.Monad (forM_, unless)+import Control.Monad (forM_, unless, when) import Foreign ( ForeignPtr, Ptr,@@ -112,9 +111,9 @@ castCharToCChar, peekCString, )-import Raylib.Internal (c'rlGetShaderIdDefault)+import Raylib.Internal (Closeable (addToWindowResources, close), addShaderId, addTextureId, addVaoId, addVboIds, c'rlGetShaderIdDefault, c'rlUnloadShaderProgram, c'rlUnloadTexture, c'rlUnloadVertexArray, c'rlUnloadVertexBuffer) import Raylib.Internal.Foreign (Freeable (rlFreeDependents), c'free, freeMaybePtr, newMaybeArray, p'free, peekMaybeArray, peekStaticArray, pokeStaticArray, rightPad, rlFree, rlFreeMaybeArray)-import Raylib.Types.Core (Color, Matrix, Quaternion, Vector2 (Vector2), Vector3 (Vector3), Vector4 (Vector4))+import Raylib.Types.Core (Color, Matrix, Quaternion, Vector2, Vector3, Vector4, pattern Vector2, pattern Vector3, pattern Vector4) import Raylib.Types.Core.Textures (Texture (texture'id)) ---------------------------------------@@ -369,6 +368,16 @@ poke (p'mesh'vboId _p) =<< newMaybeArray (map fromIntegral <$> vboId) return () +instance Closeable Mesh where+ close mesh = do+ c'rlUnloadVertexArray (fromIntegral (mesh'vaoId mesh))+ case mesh'vboId mesh of+ Nothing -> return ()+ Just vbos -> forM_ vbos (c'rlUnloadVertexBuffer . fromIntegral)+ addToWindowResources window mesh = do+ addVaoId (mesh'vaoId mesh) window+ addVboIds (mesh'vboId mesh) window+ p'mesh'vertexCount :: Ptr Mesh -> Ptr CInt p'mesh'vertexCount = (`plusPtr` 0) @@ -477,6 +486,13 @@ else poke (p'shader'locs _p) locsArr return () +instance Closeable Shader where+ close shader = do+ shaderIdDefault <- c'rlGetShaderIdDefault+ unless (sId == shaderIdDefault) (c'rlUnloadShaderProgram sId)+ where sId = fromIntegral (shader'id shader)+ addToWindowResources window shader = addShaderId (shader'id shader) window+ p'shader'id :: Ptr Shader -> Ptr CUInt p'shader'id = (`plusPtr` 0) @@ -545,6 +561,27 @@ pokeStaticArray (p'material'params _p) (map realToFrac params) return () +instance Closeable Material where+ close mat = do+ let sId = fromIntegral (shader'id (material'shader mat))+ shaderIdDefault <- c'rlGetShaderIdDefault+ unless (sId == shaderIdDefault) (c'rlUnloadShaderProgram sId)+ case material'maps mat of+ Nothing -> return ()+ (Just maps) ->+ forM_+ maps+ ( \m ->+ let tId =+ fromIntegral (texture'id (materialMap'texture m))+ in when (tId > 0) (c'rlUnloadTexture tId)+ )+ addToWindowResources window mat = do+ addShaderId (shader'id $ material'shader mat) window+ case material'maps mat of+ Nothing -> return ()+ (Just maps) -> forM_ maps (\m -> addTextureId (texture'id $ materialMap'texture m) window)+ p'material'shader :: Ptr Material -> Ptr Shader p'material'shader = (`plusPtr` 0) @@ -652,6 +689,14 @@ poke (p'model'bones _p) =<< newMaybeArray bones poke (p'model'bindPose _p) =<< newMaybeArray bindPose return ()++instance Closeable Model where+ close model = do+ forM_ (model'meshes model) close+ forM_ (model'materials model) close+ addToWindowResources window model = do+ forM_ (model'meshes model) (addToWindowResources window)+ forM_ (model'materials model) (addToWindowResources window) p'model'transform :: Ptr Model -> Ptr Matrix p'model'transform = (`plusPtr` 0)
src/Raylib/Types/Core/Text.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS -Wall #-}- -- | Bindings for types used in @rtext@ module Raylib.Types.Core.Text ( -- * Enumerations@@ -35,6 +33,7 @@ import Foreign.C ( CInt (..), )+import Raylib.Internal (Closeable(..)) import Raylib.Internal.Foreign (Freeable (rlFreeDependents), c'free, rlFree) import Raylib.Types.Core (Rectangle) import Raylib.Types.Core.Textures (Image, Texture, p'image'data)@@ -123,6 +122,10 @@ poke (p'font'recs _p) =<< newArray recs poke (p'font'glyphs _p) =<< newArray glyphs return ()++instance Closeable Font where+ close font = close (font'texture font)+ addToWindowResources window font = addToWindowResources window (font'texture font) p'font'baseSize :: Ptr Font -> Ptr CInt p'font'baseSize = (`plusPtr` 0)
src/Raylib/Types/Core/Textures.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} -{-# OPTIONS -Wall #-}- -- | Bindings for types used mainly in @rtextures@ module Raylib.Types.Core.Textures ( -- * Enumerations@@ -57,9 +55,10 @@ CUChar, CUInt, )-import Raylib.Internal (getPixelDataSize)+import Raylib.Internal (getPixelDataSize, Closeable (..), c'rlUnloadTexture, addTextureId, c'rlUnloadFramebuffer, addFrameBuffer) import Raylib.Internal.Foreign (Freeable (rlFreeDependents), c'free) import Raylib.Types.Core (Rectangle)+import Control.Monad (when) --------------------------------------- -- textures enums ---------------------@@ -271,6 +270,10 @@ poke (p'texture'format _p) format return () +instance Closeable Texture where+ close texture = let tId = fromIntegral (texture'id texture) in when (tId > 0) (c'rlUnloadTexture tId)+ addToWindowResources window texture = addTextureId (texture'id texture) window+ p'texture'id :: Ptr Texture -> Ptr CUInt p'texture'id = (`plusPtr` 0) @@ -310,6 +313,15 @@ poke (p'renderTexture'texture _p) texture poke (p'renderTexture'depth _p) depth return ()++instance Closeable RenderTexture where+ close renderTexture = do+ let fbId = fromIntegral (renderTexture'id renderTexture)+ when (fbId > 0) (c'rlUnloadFramebuffer fbId)+ close (renderTexture'texture renderTexture)+ addToWindowResources window renderTexture = do+ addFrameBuffer (renderTexture'id renderTexture) window+ addToWindowResources window (renderTexture'texture renderTexture) p'renderTexture'id :: Ptr RenderTexture -> Ptr CUInt p'renderTexture'id = (`plusPtr` 0)
src/Raylib/Types/Util/GUI.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE DeriveAnyClass #-} -- | Bindings for types used in @raygui@@@ -510,15 +509,19 @@ ArrowPadding | -- | DropdownBox items separation DropdownItemsSpacing+ | -- | DropdownBox arrow hidden+ DropdownArrowHidden deriving (Eq, Show) instance Enum GuiDropdownBoxProperty where fromEnum x = case x of ArrowPadding -> 16 DropdownItemsSpacing -> 17+ DropdownArrowHidden -> 18 toEnum x = case x of 16 -> ArrowPadding 17 -> DropdownItemsSpacing+ 18 -> DropdownArrowHidden n -> error $ "(GuiDropdownBoxProperty.toEnum) Invalid value: " ++ show n instance Storable GuiDropdownBoxProperty where@@ -585,6 +588,8 @@ ScrollbarWidth | -- | ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE) ScrollbarSide+ | -- | ListView items border width+ ListItemsBorderWidth deriving (Eq, Show) instance Enum GuiListViewProperty where@@ -593,11 +598,13 @@ ListItemsSpacing -> 17 ScrollbarWidth -> 18 ScrollbarSide -> 19+ ListItemsBorderWidth -> 20 toEnum x = case x of 16 -> ListItemsHeight 17 -> ListItemsSpacing 18 -> ScrollbarWidth 19 -> ScrollbarSide+ 20 -> ListItemsBorderWidth n -> error $ "(GuiListViewProperty.toEnum) Invalid value: " ++ show n instance Storable GuiListViewProperty where@@ -868,11 +875,11 @@ | IconWarning | IconHelpBox | IconInfoBox- | Icon223- | Icon224- | Icon225- | Icon226- | Icon227+ | IconPriority+ | IconLayersIso+ | IconLayers2+ | IconMLayers+ | IconMaps | Icon228 | Icon229 | Icon230@@ -1128,11 +1135,11 @@ IconWarning -> 220 IconHelpBox -> 221 IconInfoBox -> 222- Icon223 -> 223- Icon224 -> 224- Icon225 -> 225- Icon226 -> 226- Icon227 -> 227+ IconPriority -> 223+ IconLayersIso -> 224+ IconLayers2 -> 225+ IconMLayers -> 226+ IconMaps -> 227 Icon228 -> 228 Icon229 -> 229 Icon230 -> 230@@ -1385,11 +1392,11 @@ 220 -> IconWarning 221 -> IconHelpBox 222 -> IconInfoBox- 223 -> Icon223- 224 -> Icon224- 225 -> Icon225- 226 -> Icon226- 227 -> Icon227+ 223 -> IconPriority+ 224 -> IconLayersIso+ 225 -> IconLayers2+ 226 -> IconMLayers+ 227 -> IconMaps 228 -> Icon228 229 -> Icon229 230 -> Icon230
src/Raylib/Types/Util/RLGL.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} -{-# OPTIONS -Wall #-}- -- | Bindings for types used in @rlgl@ module Raylib.Types.Util.RLGL ( -- * Enumerations@@ -793,33 +791,37 @@ rlVertexBuffer'vertices :: [Vector3], -- | Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) rlVertexBuffer'texcoords :: [Vector2],+ -- | Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)+ rlVertexBuffer'normals :: [Vector3], -- | Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) rlVertexBuffer'colors :: [Color], -- | Vertex indices (in case vertex data comes indexed) (6 indices per quad) rlVertexBuffer'indices :: [Integer], -- | OpenGL Vertex Array Object id rlVertexBuffer'vaoId :: Integer,- -- | OpenGL Vertex Buffer Objects id (4 types of vertex data)+ -- | OpenGL Vertex Buffer Objects id (5 types of vertex data) rlVertexBuffer'vboId :: [Integer] } deriving (Eq, Show) instance Storable RLVertexBuffer where- sizeOf _ = 64+ sizeOf _ = 72 alignment _ = 8 peek _p = do elementCount <- fromIntegral <$> peek (p'rlVertexBuffer'elementCount _p) vertices <- peekArray elementCount =<< peek (p'rlVertexBuffer'vertices _p) texcoords <- peekArray elementCount =<< peek (p'rlVertexBuffer'texcoords _p)+ normals <- peekArray elementCount =<< peek (p'rlVertexBuffer'normals _p) colors <- peekArray elementCount =<< peek (p'rlVertexBuffer'colors _p) indices <- map fromIntegral <$> (peekArray elementCount =<< peek (p'rlVertexBuffer'indices _p)) vaoId <- fromIntegral <$> peek (p'rlVertexBuffer'vaoId _p)- vboId <- map fromIntegral <$> peekStaticArray 4 (p'rlVertexBuffer'vboId _p)- return $ RLVertexBuffer elementCount vertices texcoords colors indices vaoId vboId- poke _p (RLVertexBuffer elementCount vertices texcoords colors indices vaoId vboId) = do+ vboId <- map fromIntegral <$> peekStaticArray 5 (p'rlVertexBuffer'vboId _p)+ return $ RLVertexBuffer elementCount vertices texcoords normals colors indices vaoId vboId+ poke _p (RLVertexBuffer elementCount vertices texcoords normals colors indices vaoId vboId) = do poke (p'rlVertexBuffer'elementCount _p) (fromIntegral elementCount) poke (p'rlVertexBuffer'vertices _p) =<< newArray vertices poke (p'rlVertexBuffer'texcoords _p) =<< newArray texcoords+ poke (p'rlVertexBuffer'normals _p) =<< newArray normals poke (p'rlVertexBuffer'colors _p) =<< newArray colors poke (p'rlVertexBuffer'indices _p) =<< newArray (map fromIntegral indices) poke (p'rlVertexBuffer'vaoId _p) (fromIntegral vaoId)@@ -838,19 +840,23 @@ p'rlVertexBuffer'texcoords = (`plusPtr` 16) -- array (rlVertexBuffer'elementCount)+p'rlVertexBuffer'normals :: Ptr RLVertexBuffer -> Ptr (Ptr Vector3)+p'rlVertexBuffer'normals = (`plusPtr` 24)++-- array (rlVertexBuffer'elementCount) p'rlVertexBuffer'colors :: Ptr RLVertexBuffer -> Ptr (Ptr Color)-p'rlVertexBuffer'colors = (`plusPtr` 24)+p'rlVertexBuffer'colors = (`plusPtr` 32) -- array (rlVertexBuffer'elementCount) p'rlVertexBuffer'indices :: Ptr RLVertexBuffer -> Ptr (Ptr CUInt)-p'rlVertexBuffer'indices = (`plusPtr` 32)+p'rlVertexBuffer'indices = (`plusPtr` 40) p'rlVertexBuffer'vaoId :: Ptr RLVertexBuffer -> Ptr CUInt-p'rlVertexBuffer'vaoId = (`plusPtr` 40)+p'rlVertexBuffer'vaoId = (`plusPtr` 48) --- static array (4)+-- static array (5) p'rlVertexBuffer'vboId :: Ptr RLVertexBuffer -> Ptr CUInt-p'rlVertexBuffer'vboId = (`plusPtr` 44)+p'rlVertexBuffer'vboId = (`plusPtr` 52) instance Freeable RLVertexBuffer where rlFreeDependents _ ptr = do
src/Raylib/Util.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskellQuotes #-} @@ -21,12 +20,16 @@ whileWindowOpen_, whileWindowOpen0, + -- * Resource management+ WindowResources,+ Closeable (close),+ managed,+ -- * Miscellaneous cameraDirectionRay, setMaterialShader, inGHCi, inWeb,- WindowResources, Freeable (..), ) where@@ -35,7 +38,7 @@ import Control.Monad.Catch (MonadMask, bracket, bracket_) import Control.Monad.IO.Class (MonadIO (liftIO)) import Raylib.Core (beginBlendMode, beginDrawing, beginMode2D, beginMode3D, beginScissorMode, beginShaderMode, beginTextureMode, beginVrStereoMode, closeWindow, endBlendMode, endDrawing, endMode2D, endMode3D, endScissorMode, endShaderMode, endTextureMode, endVrStereoMode, initWindow, setTargetFPS, windowShouldClose)-import Raylib.Internal (WindowResources)+import Raylib.Internal (WindowResources, Closeable (..), managed) import Raylib.Internal.Foreign (Freeable (..)) import Raylib.Types ( BlendMode,@@ -77,7 +80,7 @@ Int -> (WindowResources -> m b) -> m b-withWindow w h title fps = bracket (liftIO $ initWindow w h title <* setTargetFPS fps) (liftIO . closeWindow)+withWindow w h title fps = bracket (liftIO $ initWindow w h title <* setTargetFPS fps) (liftIO . closeWindow . Just) drawing :: (MonadIO m, MonadMask m) => m b -> m b drawing = bracket_ (liftIO beginDrawing) (liftIO endDrawing)@@ -237,7 +240,7 @@ runRaylibProgram startup mainLoop shouldClose teardown = do st <- startup helper st- where helper s = shouldClose s >>= (\close -> if close then teardown s else mainLoop s >>= helper)+ where helper s = shouldClose s >>= (\toClose -> if toClose then teardown s else mainLoop s >>= helper) #endif
src/Raylib/Util/Camera.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} -- | Bindings to @rcamera@ (rcamera.h) --@@ -21,7 +21,7 @@ ) where -import Raylib.Types (Camera, Camera3D (..), CameraProjection (CameraOrthographic, CameraPerspective), Matrix, Vector3 (..))+import Raylib.Types (Camera, Camera3D (..), CameraProjection (CameraOrthographic, CameraPerspective), Matrix, Vector3, vector3'y) import Raylib.Util.Math (Vector (..), clamp, deg2Rad, matrixLookAt, matrixOrtho, matrixPerspective, vector3Angle, vector3CrossProduct, vector3RotateByAxisAngle) -- | The camera's forward vector (normalized)
src/Raylib/Util/Colors.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS -Wall #-}- -- | Simple color palette defined in raylib.h module Raylib.Util.Colors ( lightGray,
src/Raylib/Util/GUI.hs view
@@ -1,5 +1,5 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE PatternSynonyms #-} -- | -- Bindings to @raygui@@@ -17,6 +17,7 @@ -- should make your own retained mode GUI. module Raylib.Util.GUI ( -- * High level+ -- ** Global gui state control functions guiEnable, guiDisable,@@ -135,6 +136,7 @@ guiDropdownBox, guiSpinner, guiValueBox,+ guiValueBoxFloat, guiTextBox, guiSlider, guiSliderBar,@@ -195,6 +197,7 @@ c'guiDropdownBox, c'guiSpinner, c'guiValueBox,+ c'guiValueBoxFloat, c'guiTextBox, c'guiSlider, c'guiSliderBar,@@ -211,7 +214,7 @@ c'guiColorBarAlpha, c'guiColorBarHue, c'guiColorPickerHSV,- c'guiColorPanelHSV+ c'guiColorPanelHSV, ) where @@ -231,8 +234,7 @@ import Raylib.Core.Textures (colorToInt, getColor) import Raylib.Internal.Foreign (pop, popCArray, popCString, withCStringBuffer, withFreeable, withFreeableArrayLen, withMaybe, withMaybeCString) import Raylib.Internal.TH (genNative)-import Raylib.Types (Color (Color), Font, GuiControl (Default), GuiControlProperty (..), GuiDefaultProperty (..), GuiIconName, GuiState, GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode, Rectangle (Rectangle), Vector2 (Vector2), Vector3 (Vector3))-+import Raylib.Types (Color (Color), Font, GuiControl (Default), GuiControlProperty (..), GuiDefaultProperty (..), GuiIconName, GuiState, GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode, Rectangle (Rectangle), Vector2, pattern Vector2, Vector3, pattern Vector3) $( genNative [ ("c'guiEnable", "GuiEnable_", "rgui_bindings.h", [t|IO ()|], False), ("c'guiDisable", "GuiDisable_", "rgui_bindings.h", [t|IO ()|], False),@@ -273,6 +275,7 @@ ("c'guiDropdownBox", "GuiDropdownBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CBool -> IO CInt|], False), ("c'guiSpinner", "GuiSpinner_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|], False), ("c'guiValueBox", "GuiValueBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> Ptr CInt -> CInt -> CInt -> CBool -> IO CInt|], False),+ ("c'guiValueBoxFloat", "GuiValueBoxFloat_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CBool -> IO CInt|], False), ("c'guiTextBox", "GuiTextBox_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CInt -> CBool -> IO CInt|], False), ("c'guiSlider", "GuiSlider_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|], False), ("c'guiSliderBar", "GuiSliderBar_", "rgui_bindings.h", [t|Ptr Rectangle -> CString -> CString -> Ptr CFloat -> CFloat -> CFloat -> IO CInt|], False),@@ -882,6 +885,48 @@ ) ) )++-- | Value box control for float values+guiValueBoxFloat ::+ Rectangle ->+ Maybe String ->+ -- | The current text representation+ String ->+ -- | Text representation buffer size; if `Nothing`, then it will+ -- automatically allocate a buffer large enough to fit the number+ Maybe Int ->+ -- | The current value+ Float ->+ -- | `True` if the value box should be editable, `False` otherwise+ Bool ->+ -- | A tuple, the first element is whether the value box was toggled (i.e.+ -- the edit mode should be toggled), the second and thirds elements are the+ -- updated value and text representation+ IO (Bool, Float, String)+guiValueBoxFloat bounds text textValue bufferSize value editMode =+ unwrap+ <$> withFreeable+ bounds+ ( \b ->+ withMaybeCString+ text+ ( \t ->+ withCStringBuffer+ textValue+ bufferSize+ ( \_ tv ->+ withFreeable+ (realToFrac value)+ ( \v -> do+ changed <- c'guiValueBoxFloat b t tv v (fromBool editMode)+ value' <- peek v+ return (toBool changed, realToFrac value')+ )+ )+ )+ )+ where+ unwrap ((a, b), c) = (a, b, c) -- | Text Box control, updates input text guiTextBox ::
src/Raylib/Util/GUI/Styles.hs view
@@ -1,11 +1,11 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Predefined styles that come with raygui. Calling one of these functions -- will activate that style. To return to the default style, simply call -- `Raylib.Util.GUI.guiLoadStyleDefault`. module Raylib.Util.GUI.Styles- ( guiLoadStyleAshes,+ ( guiLoadStyleAmber,+ guiLoadStyleAshes, guiLoadStyleBluish, guiLoadStyleCandy, guiLoadStyleCherry,@@ -22,7 +22,8 @@ import Raylib.Internal.TH (genNative) $( genNative- [ ("c'guiLoadStyleAshes", "GuiLoadStyleAshes_", "rgui_bindings.h", [t|IO ()|], False),+ [ ("c'guiLoadStyleAmber", "GuiLoadStyleAmber_", "rgui_bindings.h", [t|IO ()|], False),+ ("c'guiLoadStyleAshes", "GuiLoadStyleAshes_", "rgui_bindings.h", [t|IO ()|], False), ("c'guiLoadStyleBluish", "GuiLoadStyleBluish_", "rgui_bindings.h", [t|IO ()|], False), ("c'guiLoadStyleCandy", "GuiLoadStyleCandy_", "rgui_bindings.h", [t|IO ()|], False), ("c'guiLoadStyleCherry", "GuiLoadStyleCherry_", "rgui_bindings.h", [t|IO ()|], False),@@ -35,6 +36,9 @@ ("c'guiLoadStyleTerminal", "GuiLoadStyleTerminal_", "rgui_bindings.h", [t|IO ()|], False) ] )++guiLoadStyleAmber :: IO ()+guiLoadStyleAmber = c'guiLoadStyleAmber guiLoadStyleAshes :: IO () guiLoadStyleAshes = c'guiLoadStyleAshes
src/Raylib/Util/Lenses.hs view
@@ -1,18 +1,15 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} -- | Lenses for raylib types module Raylib.Util.Lenses where +import Control.Lens (Lens', lens) import Raylib.Internal.TH (genLenses) import qualified Raylib.Types as RL $( genLenses- [ - -- Raylib.Types.Core- ''RL.Vector2,- ''RL.Vector3,- ''RL.Vector4,+ [ -- Raylib.Types.Core ''RL.Matrix, ''RL.Color, ''RL.Rectangle,@@ -59,3 +56,30 @@ ''RL.GuiStyleProp ] )++_vector2'x :: Lens' RL.Vector2 Float+_vector2'x = lens RL.vector2'x (\x v -> x {RL.vector2'x = v})++_vector2'y :: Lens' RL.Vector2 Float+_vector2'y = lens RL.vector2'y (\x v -> x {RL.vector2'y = v})++_vector3'x :: Lens' RL.Vector3 Float+_vector3'x = lens RL.vector3'x (\x v -> x {RL.vector3'x = v})++_vector3'y :: Lens' RL.Vector3 Float+_vector3'y = lens RL.vector3'y (\x v -> x {RL.vector3'y = v})++_vector3'z :: Lens' RL.Vector3 Float+_vector3'z = lens RL.vector3'z (\x v -> x {RL.vector3'z = v})++_vector4'x :: Lens' RL.Vector4 Float+_vector4'x = lens RL.vector4'x (\x v -> x {RL.vector4'x = v})++_vector4'y :: Lens' RL.Vector4 Float+_vector4'y = lens RL.vector4'y (\x v -> x {RL.vector4'y = v})++_vector4'z :: Lens' RL.Vector4 Float+_vector4'z = lens RL.vector4'z (\x v -> x {RL.vector4'z = v})++_vector4'w :: Lens' RL.Vector4 Float+_vector4'w = lens RL.vector4'w (\x v -> x {RL.vector4'w = v})
src/Raylib/Util/Math.hs view
@@ -1,4 +1,6 @@-{-# OPTIONS -Wall #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-} -- | Bindings to @raymath@ --@@ -39,6 +41,7 @@ vector3Transform, vector3RotateByQuaternion, vector3RotateByAxisAngle,+ vector3CubicHermite, vector3Reflect, vector3Barycenter, vector3Unproject,@@ -71,6 +74,7 @@ matrixPerspective, matrixOrtho, matrixLookAt,+ matrixDecompose, -- * Quaternion math quaternionIdentity,@@ -80,6 +84,7 @@ quaternionLerp, quaternionNLerp, quaternionSLerp,+ quaternionCubicHermiteSpline, quaternionFromVector3ToVector3, quaternionFromMatrix, quaternionToMatrix,@@ -92,8 +97,7 @@ where import Data.Foldable (foldl')-import Raylib.Types (Matrix (..), Quaternion, Vector2 (Vector2), Vector3 (Vector3), Vector4 (Vector4))-+import Raylib.Types (Matrix (..), Quaternion, Vector2, pattern Vector2, Vector3, pattern Vector3, Vector4, pattern Vector4) epsilon :: Float epsilon = 0.000001 @@ -196,7 +200,7 @@ -- | Equivalent of `zipWith` over a vector zipWithV :: (Float -> Float -> Float) -> a -> a -> a- + -- | Equivalent of `zipWith3` over a vector zipWithV3 :: (Float -> Float -> Float -> Float) -> a -> a -> a -> a @@ -492,6 +496,29 @@ wv = vector3CrossProduct w v wwv = vector3CrossProduct w wv +-- | Cubic hermite interpolation between two vectors and their tangents+-- as described in the [GLTF 2.0 specification](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic)+vector3CubicHermite ::+ -- | Vector 1+ Vector3 ->+ -- | Tangent for vector 1+ Vector3 ->+ -- | Vector 2+ Vector3 ->+ -- | Tangent for vector 2+ Vector3 ->+ -- | Interpolation amount+ Float ->+ Vector3+vector3CubicHermite (Vector3 x1 y1 z1) (Vector3 tx1 ty1 tz1) (Vector3 x2 y2 z2) (Vector3 tx2 ty2 tz2) a =+ Vector3+ ((2 * a3 - 3 * a2 + 1) * x1 + (a3 - 2 * a2 + a) * tx1 + (-2 * a3 + 3 * a2) * x2 + (a3 - a2) * tx2)+ ((2 * a3 - 3 * a2 + 1) * y1 + (a3 - 2 * a2 + a) * ty1 + (-2 * a3 + 3 * a2) * y2 + (a3 - a2) * ty2)+ ((2 * a3 - 3 * a2 + 1) * z1 + (a3 - 2 * a2 + a) * tz1 + (-2 * a3 + 3 * a2) * z2 + (a3 - a2) * tz2)+ where+ a2 = a * a+ a3 = a2 * a+ -- | Reflect 3D vector to normal vector3Reflect :: -- | Input vector@@ -908,6 +935,35 @@ vx@(Vector3 xx xy xz) = vectorNormalize $ vector3CrossProduct up vz vy@(Vector3 yx yy yz) = vector3CrossProduct vz vx +-- | Decompose a transformation matrix into its rotational, translational and scaling components+matrixDecompose :: Matrix -> (Vector3, Quaternion, Vector3)+matrixDecompose (Matrix m0 m4 m8 m12 m1 m5 m9 m13 m2 m6 m10 m14 m3 m7 m11 m15) =+ (translation, rotation, scale)+ where+ a = m0+ b = m4+ c = m8+ d = m1+ e = m5+ f = m9+ g = m2+ h = m6+ i = m10+ translation = Vector3 m12 m13 m14+ a' = e*i - f*h+ b' = f*g - d*i+ c' = d*h - e*g+ det = a*a' + b*b' + c*c'+ abc = Vector3 a b c+ def = Vector3 d e f+ ghi = Vector3 g h i+ scalex = magnitude abc+ scaley = magnitude def+ scalez = magnitude ghi+ s = Vector3 scalex scaley scalez+ scale@(Vector3 sx sy sz) = if det < 0 then additiveInverse s else s+ rotation = if floatEquals det 0 then quaternionIdentity else quaternionFromMatrix (Matrix (m0 / sx) m4 m8 m12 m1 (m5 / sy) m9 m13 m2 m6 (m10 / sz) m14 m3 m7 m11 m15)+ ------------------------------------------------ -- Quaternion math ----------------------------- ------------------------------------------------@@ -976,6 +1032,33 @@ q2' = if dot < 0 then additiveInverse q2 else q2 dot = q1 |.| q2++-- | Quaternion cubic spline interpolation using the Cubic Hermite Spline algorithm+-- as described in the [GLTF 2.0 specification](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic)+quaternionCubicHermiteSpline ::+ -- | Quaternion 1+ Quaternion ->+ -- | Out tangent 1+ Quaternion ->+ -- | Quaternion 2+ Quaternion ->+ -- | In tangent 2+ Quaternion ->+ -- | Interpolation amount+ Float ->+ Quaternion+quaternionCubicHermiteSpline q1 outTangent1 q2 inTangent2 t = vectorNormalize (p0 |+| m0 |+| p1 |+| m1)+ where+ t2 = t * t+ t3 = t2 * t+ h00 = 2 * t3 - 3 * t2 + 1+ h10 = t3 - 2 * t2 + t+ h01 = -2 * t3 + 3 * t2+ h11 = t3 - t2+ p0 = q1 |* h00+ m0 = outTangent1 |* h10+ p1 = q2 |* h01+ m1 = inTangent2 |* h11 -- | Quaternion based on the rotation between two vectors quaternionFromVector3ToVector3 :: Vector3 -> Vector3 -> Quaternion
src/Raylib/Util/RLGL.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} -- | Bindings to @rlgl@@@ -17,6 +16,9 @@ rlFrustum, rlOrtho, rlViewport,+ rlSetClipPlanes,+ rlGetCullDistanceNear,+ rlGetCullDistanceFar, -- ** Vertex level operations rlBegin,@@ -209,6 +211,9 @@ c'rlFrustum, c'rlOrtho, c'rlViewport,+ c'rlSetClipPlanes,+ c'rlGetCullDistanceNear,+ c'rlGetCullDistanceFar, c'rlBegin, c'rlVertex2i, c'rlVertex2f,@@ -415,6 +420,9 @@ ("c'rlFrustum", "rlFrustum_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|], False), ("c'rlOrtho", "rlOrtho_", "rlgl_bindings.h", [t|CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()|], False), ("c'rlViewport", "rlViewport_", "rlgl_bindings.h", [t|CInt -> CInt -> CInt -> CInt -> IO ()|], False),+ ("c'rlSetClipPlanes", "rlSetClipPlanes_", "rlgl_bindings.h", [t|CDouble -> CDouble -> IO ()|], False),+ ("c'rlGetCullDistanceNear", "rlGetCullDistanceNear", "rlgl_bindings.h", [t|IO CDouble|], False),+ ("c'rlGetCullDistanceFar", "rlGetCullDistanceFar", "rlgl_bindings.h", [t|IO CDouble|], False), ("c'rlBegin", "rlBegin_", "rlgl_bindings.h", [t|CInt -> IO ()|], False), ("c'rlVertex2i", "rlVertex2i_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|], False), ("c'rlVertex2f", "rlVertex2f_", "rlgl_bindings.h", [t|CFloat -> CFloat -> IO ()|], False),@@ -472,7 +480,7 @@ ("c'rlUpdateVertexBufferElements", "rlUpdateVertexBufferElements_", "rlgl_bindings.h", [t|CUInt -> Ptr () -> CInt -> CInt -> IO ()|], False), ("c'rlUnloadVertexArray", "rlUnloadVertexArray_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False), ("c'rlUnloadVertexBuffer", "rlUnloadVertexBuffer_", "rlgl_bindings.h", [t|CUInt -> IO ()|], False),- ("c'rlSetVertexAttribute", "rlSetVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CBool -> CInt -> Ptr () -> IO ()|], False),+ ("c'rlSetVertexAttribute", "rlSetVertexAttribute_", "rlgl_bindings.h", [t|CUInt -> CInt -> CInt -> CBool -> CInt -> CInt -> IO ()|], False), ("c'rlSetVertexAttributeDivisor", "rlSetVertexAttributeDivisor_", "rlgl_bindings.h", [t|CUInt -> CInt -> IO ()|], False), ("c'rlSetVertexAttributeDefault", "rlSetVertexAttributeDefault_", "rlgl_bindings.h", [t|CInt -> Ptr () -> CInt -> CInt -> IO ()|], False), ("c'rlDrawVertexArray", "rlDrawVertexArray_", "rlgl_bindings.h", [t|CInt -> CInt -> IO ()|], False),@@ -605,6 +613,18 @@ rlViewport :: Int -> Int -> Int -> Int -> IO () rlViewport x y width height = c'rlViewport (fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height) +-- | Set clip planes distances+rlSetClipPlanes :: Double -> Double -> IO ()+rlSetClipPlanes near far = c'rlSetClipPlanes (realToFrac near) (realToFrac far)++-- | Get cull plane distance near+rlGetCullDistanceNear :: IO Double+rlGetCullDistanceNear = realToFrac <$> c'rlGetCullDistanceNear++-- | Get cull plane distance far+rlGetCullDistanceFar :: IO Double+rlGetCullDistanceFar = realToFrac <$> c'rlGetCullDistanceFar+ -- | Initialize drawing mode (how to organize vertex) rlBegin :: RLDrawMode -> IO () rlBegin mode = c'rlBegin (fromIntegral $ fromEnum mode)@@ -975,9 +995,9 @@ -- TODO: improve types for the functions below -- | Set vertex attribute (the type must be a valid GLenum value)-rlSetVertexAttribute :: Integer -> Int -> Int -> Bool -> Int -> Ptr () -> IO ()-rlSetVertexAttribute index compSize aType normalized stride =- c'rlSetVertexAttribute (fromIntegral index) (fromIntegral compSize) (fromIntegral aType) (fromBool normalized) (fromIntegral stride)+rlSetVertexAttribute :: Integer -> Int -> Int -> Bool -> Int -> Int -> IO ()+rlSetVertexAttribute index compSize aType normalized stride offset =+ c'rlSetVertexAttribute (fromIntegral index) (fromIntegral compSize) (fromIntegral aType) (fromBool normalized) (fromIntegral stride) (fromIntegral offset) -- | Set vertex attribute divisor rlSetVertexAttributeDivisor :: Integer -> Int -> IO ()