Audit of raylib.h public-facing API for naming, parameter, and methodology inconsistencies.
DrawCircle(int centerX, int centerY, float radius, Color color)— radius isfloatImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color)— radius isint
DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)— thick isfloatImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color)— thick isint
DrawText(..., int fontSize, ...)andImageText(..., int fontSize, ...)—intDrawTextEx(..., float fontSize, ...)andImageTextEx(..., float fontSize, ...)—float- This is arguably deliberate (base=simple int, Ex=precise float), but it means the two versions produce subtly different results for the same fontSize value.
ImageColorBrightness(Image *image, int brightness)— int, range -255 to 255ColorBrightness(Color color, float factor)— float, range -1.0f to 1.0f
ImageColorContrast(Image *image, float contrast)— range -100 to 100ColorContrast(Color color, float contrast)— range -1.0f to 1.0f- Both are
float, but a user would expect the same range for the same concept.
- Everywhere else in the API, the
Vsuffix means "Vector2 parameter version" (e.g.,DrawCircleV,DrawLineV,DrawPixelV). - Here
Vmeans "vertical gradient" andHmeans "horizontal gradient". This is a naming collision.
DrawCircle(int centerX, int centerY, ...)— base uses intsDrawCircleV(Vector2 center, ...)— V variant uses Vector2DrawCircleGradient(Vector2 center, ...)— uses Vector2 directly with no int version and noVsuffix. Should be eitherDrawCircleGradient(int centerX, int centerY, ...)or namedDrawCircleGradientV.
SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count)— theVsuffix here adds acountparameter for array uniforms, a third meaning of theVsuffix.
DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)— comment: "Draw a regular polygon (Vector version)". There's noDrawPolythat takesint centerX, int centerY.
- The draw function uses
Quadratic, the evaluate function usesQuad. Same spline type, different abbreviations.
DrawCylinder(Vector3 position, ..., int slices, Color color)DrawCylinderEx(Vector3 startPos, Vector3 endPos, ..., int sides, Color color)- Same concept (circular subdivision count), different parameter names.
DrawSphere(Vector3 centerPos, ...)—centerPosDrawCube(Vector3 position, ...)—positionDrawPlane(Vector3 centerPos, ...)—centerPosDrawCylinder(Vector3 position, ...)—position
PlaySound/StopSound/PauseSound/IsSoundPlayingPlayMusicStream/StopMusicStream/PauseMusicStream/IsMusicStreamPlayingPlayAudioStream/StopAudioStream/PauseAudioStream/IsAudioStreamPlaying- Music is its own type (not an AudioStream from the user's perspective), yet it carries the "Stream" suffix inconsistently.
IsMusicValiddrops "Stream" butIsMusicStreamPlayingkeeps it.
DrawText(..., Color color)butDrawTextEx(..., Color tint)ImageDrawText(..., Color color)butImageDrawTextEx(..., Color tint)DrawTexture(..., Color tint)— always tint- The base text functions use
color, the extended versions usetint.
DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color)- Both have rings and slices, but in opposite order.
SetGamepadMappings(const char *mappings)returnsint. Every otherSet*function in the API returnsvoid.
FileExists(...)returnsboolFileRename(...)/FileRemove(...)/FileCopy(...)/FileMove(...)returnintMakeDirectory(...)returnsint(0 on success)ChangeDirectory(...)returnsbool(true on success)- No consistent convention for success/failure indication.
CompressData(const unsigned char *data, ...)— correctly constComputeCRC32(unsigned char *data, ...)— missing constComputeMD5(unsigned char *data, ...)— missing constComputeSHA1(unsigned char *data, ...)— missing constComputeSHA256(unsigned char *data, ...)— missing const- These functions should not modify the input data.
SaveFileData(const char *fileName, void *data, int dataSize)—datashould beconst void *, it's being read not written.
GetPixelColor(void *srcPtr, int format)— srcPtr should beconst void *.
Fade(Color color, float alpha)— "Get color with alpha applied"ColorAlpha(Color color, float alpha)— "Get color with alpha applied"- Identical signatures, identical descriptions.
- Both: "Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure"
- The descriptions don't explain how they differ.
- All other boolean queries use
Is*prefix:IsWindowReady,IsKeyPressed,IsFileDropped, etc. WindowShouldCloseis the notable exception.
- 3D:
GetScreenToWorldRay,GetWorldToScreen— no "3D" suffix - 2D:
GetWorldToScreen2D,GetScreenToWorld2D— has "2D" suffix - Asymmetric naming.
UpdateSound(Sound sound, const void *data, int sampleCount)— usessampleCountUpdateAudioStream(AudioStream stream, const void *data, int frameCount)— usesframeCount- Samples and frames are different units (frame = samples * channels). Easy to misuse.
ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color)— int version existsImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color)— jumps straight to Rectangle, no int version- Unlike
DrawRectangleLines(int posX, int posY, int width, int height, Color color)which has an int version.
Verb tense inconsistency — most comments use imperative ("Draw", "Check", "End"), but some use third-person ("Draws", "Checks", "Ends")
"End" vs "Ends":
EndDrawing→ "End canvas drawing and swap buffers" (imperative)EndMode2D→ "Ends 2D mode with custom camera" (third-person)EndMode3D→ "Ends 3D mode and returns to default 2D orthographic mode" (third-person)EndTextureMode→ "Ends drawing to render texture" (third-person)EndShaderMode→ "End custom shader drawing" (imperative)EndBlendMode→ "End blending mode" (imperative)
"Check" vs "Checks":
- All
Is*Validin the audio module use "Checks":IsWaveValid→ "Checks if wave data is valid",IsSoundValid→ "Checks if a sound is valid",IsMusicValid→ "Checks if a music stream is valid",IsAudioStreamValid→ "Checks if an audio stream is valid" - All other
Is*functions use "Check":IsImageValid→ "Check if an image is valid",IsTextureValid→ "Check if a texture is valid", etc.
"Draw" vs "Draws":
DrawTextureNPatch→ "Draws a texture (or part of it) that stretches or shrinks nicely" (third-person)- All other Draw functions use imperative: "Draw a Texture2D", "Draw a line", etc.
Cursor functions use third-person:
ShowCursor→ "Shows cursor"EnableCursor→ "Enables cursor (unlock cursor)"DisableCursor→ "Disables cursor (lock cursor)"- But
EnableEventWaiting→ "Enable waiting for events..." (imperative)
"Updates" instead of "Update":
UpdateMusicStream→ "Updates buffers for music streaming" (third-person)UpdateAudioStream→ "Update audio stream buffers with data" (imperative)
CheckCollisionCircleLinecomment: "betweeen" — triple 'e' typo. Should be "between".IsGestureDetectedcomment: "Check if a gesture have been detected" — should be "has been detected".DrawTextCodepointscomment: "Draw multiple character (codepoint)" — should be "characters" (plural).TextIsEqualcomment: "Check if two text string are equal" — should be "strings" (plural).LoadImageFromScreencomment: "Load image from screen buffer and (screenshot)" — dangling "and" with nothing after it.SetMusicPitchcomment: "Set pitch for a music" — grammatically wrong, should be "for music" or "for a music stream".SetMusicPancomment: "Set pan for a music" — same issue.GetWorldToScreenExcomment: "Get size position for a 3d world space position" — should be "Get screen space position".SetConfigFlagscomment: "Setup init configuration flags (view FLAGS)" — "Setup" should be "Set up" (verb form), and "view FLAGS" is vague.ClearBackgroundcomment: "Set background color (framebuffer clear color)" — describes a "Set" action but the function is named "Clear".
SetSoundPan: "Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)"SetMusicPan: "Set pan for a music (-1.0 left, 0.0 center, 1.0 right)"SetAudioStreamPan: "Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered)"- Three different description styles for identical parameter semantics.
- "Check if a key has been pressed once" (with article)
- "Check if file exists" (no article)
- "Unload sound" (no article) vs "Unload a sound alias" (with article)
- No consistent rule for when to include articles.
- Comment says "(Vector version)" but there is no non-Vector
DrawPolythat takesint centerX, int centerY. The comment implies a variant that doesn't exist.
DrawRectangleRoundedLines: "Draw rectangle lines with rounded edges"DrawRectangleRoundedLinesEx: "Draw rectangle with rounded edges outline"- Different phrasing for the same concept hierarchy.
These are the most impactful because they can cause real bugs or API misuse.
-
Add missing
constqualifiers:ComputeCRC32(unsigned char *data, ...)→ComputeCRC32(const unsigned char *data, ...)- Same for
ComputeMD5,ComputeSHA1,ComputeSHA256 SaveFileData(..., void *data, ...)→SaveFileData(..., const void *data, ...)GetPixelColor(void *srcPtr, ...)→GetPixelColor(const void *srcPtr, ...)
-
Unify
ImageDraw*parameter types to matchDraw*equivalents:ImageDrawCircle/ImageDrawCircleV/ImageDrawCircleLines/ImageDrawCircleLinesV: changeint radius→float radiusto matchDrawCircleImageDrawLineEx: changeint thick→float thickto matchDrawLineEx
-
Unify brightness/contrast ranges:
ImageColorBrightness: change tofloatin range -1.0f to 1.0f (matchingColorBrightness)ImageColorContrast: change range to -1.0f to 1.0f (matchingColorContrast)- These are breaking changes, so they should be versioned or documented clearly.
-
Fix
DrawCapsule/DrawCapsuleWiresparameter order:- Change from
(... int slices, int rings, ...)→(... int rings, int slices, ...)to matchDrawSphereEx/DrawSphereWires
- Change from
-
Unify
DrawCylinder/DrawCylinderExsubdivision parameter name:DrawCylinderEx/DrawCylinderWiresEx: renamesides→slicesto matchDrawCylinder/DrawCylinderWires
These improve learnability and reduce confusion, but require deprecation cycles.
-
Rename
DrawRectangleGradientV/DrawRectangleGradientH:- →
DrawRectangleGradientVertical/DrawRectangleGradientHorizontal - This eliminates the
V-suffix collision (V=Vector everywhere else). - Keep old names as
#definealiases for backwards compatibility.
- →
-
Rename
SetShaderValueV:- →
SetShaderValueArrayorSetShaderValueCount - Eliminates the third meaning of the
Vsuffix.
- →
-
Rename
GetSplinePointBezierQuad:- →
GetSplinePointBezierQuadraticto matchDrawSplineBezierQuadratic
- →
-
Standardize Music function naming:
- Either drop "Stream" everywhere:
PlayMusic,StopMusic,PauseMusic,IsMusicPlaying,LoadMusic,UnloadMusic - Or keep it everywhere: rename
IsMusicValid→IsMusicStreamValid,SetMusicVolume→SetMusicStreamVolume, etc. - Dropping "Stream" is cleaner since
Musicis already a distinct type.
- Either drop "Stream" everywhere:
-
Deprecate
Fadein favor ofColorAlpha:Fadeis the legacy name,ColorAlphafollows theColor*naming convention.- Keep
Fadeas a#definealias.
-
Fix
DrawCircleGradientto follow the int/V pattern:- Add
DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)as the base version. - Rename current function to
DrawCircleGradientV.
- Add
-
Standardize 3D position parameter names:
- Pick one convention:
positionfor all, sincecenterPosis redundant (the position is always the center for these shapes).
- Pick one convention:
These can all be done in a single pass without any API changes.
-
Standardize verb tense to imperative (base form):
- "Ends 2D mode" → "End 2D mode"
- "Ends 3D mode" → "End 3D mode"
- "Ends drawing to render texture" → "End drawing to render texture"
- "Shows cursor" → "Show cursor"
- "Enables cursor" → "Enable cursor"
- "Disables cursor" → "Disable cursor"
- "Checks if..." → "Check if..." (audio module Is*Valid functions)
- "Draws a texture..." → "Draw a texture..."
- "Updates buffers..." → "Update buffers..."
-
Fix typos and grammar:
- "betweeen" → "between" (CheckCollisionCircleLine)
- "a gesture have been" → "a gesture has been" (IsGestureDetected)
- "multiple character" → "multiple characters" (DrawTextCodepoints)
- "two text string are" → "two text strings are" (TextIsEqual)
- "screen buffer and (screenshot)" → "screen buffer (screenshot)" (LoadImageFromScreen)
- "for a music" → "for music" (SetMusicPitch, SetMusicPan)
- "Get size position" → "Get screen space position" (GetWorldToScreenEx)
- "Setup init configuration flags (view FLAGS)" → "Set up initial configuration flags" (SetConfigFlags)
-
Fix misleading comments:
ClearBackground: "Set background color" → "Clear background with given color"DrawPoly: Remove "(Vector version)" since no int version exists. → "Draw a regular polygon"GetCodepoint: Differentiate fromGetCodepointNext— "Get next codepoint in a UTF-8 encoded string (equivalent to GetCodepointNext)" or clarify that it's a legacy alias.DrawRectangleRoundedLinesEx: "Draw rectangle with rounded edges outline" → "Draw rectangle outline with rounded edges and line thickness"
-
Standardize pan descriptions:
- Use a single format everywhere: "Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)"
- Apply to
SetMusicPanandSetAudioStreamPanas well.
-
Standardize article usage:
- Adopt one rule: use articles for countable nouns ("Unload a sound", "Check if a file exists"), omit for mass/abstract nouns.
-
Add missing
color→tintconsistency:- The
tintnaming is more accurate (color is multiplied with texture/font color). - Update
DrawTextandImageDrawTextparameter names fromcolor→tintto match theirExvariants.
- The
-
Add suffix to 3D screen-space functions for symmetry:
- Add aliases:
GetScreenToWorldRay3D=GetScreenToWorldRay,GetWorldToScreen3D=GetWorldToScreen - This makes the 2D/3D naming symmetric.
- Add aliases:
-
Unify
UpdateSound/UpdateAudioStreamunit naming:- Both should use
frameCount(the standard audio term).sampleCountinUpdateSoundis misleading. - Or both should clearly document what unit is expected.
- Both should use
This section identifies families of functions that define a pattern (Base, V, Ex, Lines, Wires, Pro, Rec, etc.) and then finds other functions of the same nature that are missing variants to complete the pattern.
Legend: Base = int params, V = Vector2 params, Lines = outline (int), LinesV = outline (Vector2), LinesEx = outline with thickness, Ex = extended, Pro = origin+rotation, Rec = Rectangle params, Gradient = gradient fill
| Shape | Base | V | Lines | LinesV | LinesEx | Ex | Pro | Rec | Gradient |
|---|---|---|---|---|---|---|---|---|---|
| Pixel | YES | YES | - | - | - | - | - | - | - |
| Line | YES | YES | - | - | - | YES | - | - | - |
| Circle | YES | YES | YES | YES | - | - | - | - | YES(V only) |
| Ellipse | YES | YES | YES | YES | - | - | - | - | - |
| Ring | - | YES | - | YES | - | - | - | - | - |
| Rectangle | YES | YES | YES | - | YES(Rec) | - | YES | YES | YES |
| Triangle | - | YES | - | YES | - | - | - | - | - |
| Poly | - | YES | - | YES | YES | - | - | - | - |
Gaps to fill:
-
DrawCircleLinesEx(Vector2 center, float radius, float lineThick, Color color)- Circle has Base/V/Lines/LinesV but no LinesEx with thickness.
- Rectangle has
DrawRectangleLinesExwith thickness — circle should too.
-
DrawEllipseLinesEx(int centerX, int centerY, float radiusH, float radiusV, float lineThick, Color color)and V variant- Ellipse has Lines/LinesV but no thickness variant.
- Follows the same pattern gap as Circle.
-
DrawCircleGradientint-param versionDrawCircleGradientcurrently takesVector2 centerdirectly, breaking the Base/V pattern.- Missing:
DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)as the int-based version. - Current function should be renamed
DrawCircleGradientVor the int version should be added.
-
DrawEllipseGradient(int centerX, int centerY, float radiusH, float radiusV, Color inner, Color outer)and V variant- Circle has a gradient fill, ellipse does not. Ellipse is a generalization of circle — this is a natural gap.
-
DrawRectangleLinesV(Vector2 position, Vector2 size, Color color)- Rectangle has Base/V pair and Lines, but no LinesV.
- Every other shape with both Base/V and Lines also has LinesV (Circle, Ellipse).
-
DrawTriangleEx(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)ImageDrawTriangleExexists (per-vertex colors), but the GPUDrawTriangleExdoes not.- The Image version defines a modality that the GPU version doesn't match.
-
DrawRingLinesEx(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, float lineThick, Color color)- Ring has Base and Lines but no LinesEx with thickness.
Legend: Base = simple params, V = Vector3 size, Ex = two-point/extended, Wires = outline, WiresV = outline with Vector3 size, WiresEx = outline extended
| Shape | Base | V | Ex | Wires | WiresV | WiresEx |
|---|---|---|---|---|---|---|
| Cube | YES | YES | - | YES | YES | - |
| Sphere | YES | - | YES | YES* | - | - |
| Cylinder | YES | - | YES | YES | - | YES |
| Capsule | YES* | - | - | YES* | - | - |
| Model | YES | - | YES | YES | - | YES |
*Sphere DrawSphereWires requires rings/slices (like Ex), there is no simple wires version matching DrawSphere.
*Capsule always requires all subdivision params — no simple version exists.
Gaps to fill:
-
DrawSphereWiresSimple(Vector3 centerPos, float radius, Color color)(or just a default-param version)DrawSphere(pos, radius, color)exists as a simple version (uses default rings/slices internally).DrawSphereWires(pos, radius, rings, slices, color)always requires subdivision params.- The pattern set by Cube:
DrawCube/DrawCubeWiresare symmetric (both simple). Sphere breaks this.
-
DrawCapsuleSimple(Vector3 startPos, Vector3 endPos, float radius, Color color)(or without subdivision params)- Capsule has no simple version. Both
DrawCapsuleandDrawCapsuleWiresrequireslicesandrings. DrawSphereprovides a simple version with default subdivisions — Capsule should too.
- Capsule has no simple version. Both
-
DrawTriangleLines3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)DrawTriangle3Dexists (filled) but no wireframe version.- In 2D,
DrawTriangle/DrawTriangleLinesis a complete pair. DrawTriangleStrip3Dexists but there's noDrawTriangleStripLines3Deither.
-
3D primitives (Line3D, Point3D, Circle3D) lack Ex/variant coverage
DrawLine3Dhas no thickness variant (unlike 2DDrawLineEx).DrawCircle3Dhas no filled version — it only draws the outline. In 2D,DrawCircleis filled andDrawCircleLinesis outline. In 3D the only variant is outline-like.
Functions that exist in Draw* (GPU rendering) but are missing from ImageDraw* (CPU software rendering):
| Draw* function | ImageDraw* equivalent | Status |
|---|---|---|
DrawCircleGradient |
ImageDrawCircleGradient |
MISSING |
DrawCircleSector |
ImageDrawCircleSector |
MISSING |
DrawCircleSectorLines |
ImageDrawCircleSectorLines |
MISSING |
DrawEllipse |
ImageDrawEllipse |
MISSING |
DrawEllipseV |
ImageDrawEllipseV |
MISSING |
DrawEllipseLines |
ImageDrawEllipseLines |
MISSING |
DrawEllipseLinesV |
ImageDrawEllipseLinesV |
MISSING |
DrawRing |
ImageDrawRing |
MISSING |
DrawRingLines |
ImageDrawRingLines |
MISSING |
DrawRectanglePro |
ImageDrawRectanglePro |
MISSING |
DrawRectangleGradientV |
ImageDrawRectangleGradientV |
MISSING |
DrawRectangleGradientH |
ImageDrawRectangleGradientH |
MISSING |
DrawRectangleGradientEx |
ImageDrawRectangleGradientEx |
MISSING |
DrawRectangleRounded |
ImageDrawRectangleRounded |
MISSING |
DrawRectangleRoundedLines |
ImageDrawRectangleRoundedLines |
MISSING |
DrawPoly |
ImageDrawPoly |
MISSING |
DrawPolyLines |
ImageDrawPolyLines |
MISSING |
DrawLineStrip |
ImageDrawLineStrip |
MISSING |
DrawLineBezier |
ImageDrawLineBezier |
MISSING |
DrawLineDashed |
ImageDrawLineDashed |
MISSING |
DrawTextPro |
ImageDrawTextPro |
MISSING |
And one reverse gap — exists in ImageDraw but not Draw:
| ImageDraw* function | Draw* equivalent | Status |
|---|---|---|
ImageDrawTriangleEx (per-vertex colors) |
DrawTriangleEx |
MISSING |
| Resource | Load | FromMemory | IsValid | Unload | Export | AsCode | ToMemory |
|---|---|---|---|---|---|---|---|
| Image | YES | YES | YES | YES | YES | YES | YES |
| Texture | YES | - | YES | YES | - | - | - |
| RenderTexture | YES | - | YES | YES | - | - | - |
| Font | YES | YES | YES | YES | - | YES | - |
| Shader | YES | YES | YES | YES | - | - | - |
| Model | YES | - | YES | YES | - | - | - |
| Mesh | Gen* | - | - | YES | YES | YES | - |
| Material | YES | - | YES | YES | - | - | - |
| Wave | YES | YES | YES | YES | YES | YES | - |
| Sound | YES | - | YES | YES | - | - | - |
| Music | YES | YES | YES | YES | - | - | - |
| AudioStream | YES | - | YES | YES | - | - | - |
Gaps to fill:
-
IsMeshValid(Mesh mesh)- Every other resource type has an
Is*Validfunction. Mesh is the only one missing it.
- Every other resource type has an
-
LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)- Image has
LoadImageFromMemory. To load a texture from memory, you must goLoadImageFromMemory→LoadTextureFromImage→UnloadImage(3 steps). - A convenience function would match the pattern.
- Image has
-
LoadModelFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)- Image, Wave, Font, Music, and Shader all have
*FromMemoryvariants. Model does not.
- Image, Wave, Font, Music, and Shader all have
-
LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)- Wave has
LoadWaveFromMemory. To load a Sound from memory requiresLoadWaveFromMemory→LoadSoundFromWave→UnloadWave.
- Wave has
-
ExportFont(Font font, const char *fileName)- Image, Mesh, and Wave all have both
ExportandExportAsCode. Font only hasExportFontAsCode.
- Image, Mesh, and Wave all have both
-
ExportModel(Model model, const char *fileName)- Model has no export at all.
ExportMeshexists but only exports individual meshes, not the full model with materials and skeleton.
- Model has no export at all.
| Feature | Sound | Music | AudioStream |
|---|---|---|---|
| Play | PlaySound | PlayMusicStream | PlayAudioStream |
| Stop | StopSound | StopMusicStream | StopAudioStream |
| Pause | PauseSound | PauseMusicStream | PauseAudioStream |
| Resume | ResumeSound | ResumeMusicStream | ResumeAudioStream |
| IsPlaying | IsSoundPlaying | IsMusicStreamPlaying | IsAudioStreamPlaying |
| SetVolume | SetSoundVolume | SetMusicVolume | SetAudioStreamVolume |
| SetPitch | SetSoundPitch | SetMusicPitch | SetAudioStreamPitch |
| SetPan | SetSoundPan | SetMusicPan | SetAudioStreamPan |
| Update | UpdateSound | UpdateMusicStream | UpdateAudioStream |
| Seek | - | SeekMusicStream | - |
| GetTimeLength | - | GetMusicTimeLength | - |
| GetTimePlayed | - | GetMusicTimePlayed | - |
Gaps to fill:
-
GetSoundTimeLength(Sound sound)- Music has
GetMusicTimeLength. Sound hasframeCountin the struct but no API to query duration in seconds.
- Music has
-
GetSoundTimePlayed(Sound sound)- Music has
GetMusicTimePlayed. No equivalent for Sound.
- Music has
-
SeekSound(Sound sound, float position)- Music has
SeekMusicStream. Sound has no seek capability. - (May be less useful for short sounds, but the modality gap exists.)
- Music has
The following are the gaps most likely to trip up users who learn one part of the API and expect the pattern to hold elsewhere:
| Priority | Gap | Rationale |
|---|---|---|
| High | IsMeshValid missing |
Every other resource has it |
| High | DrawSphereWires has no simple form |
DrawSphere has one; Cube pair is symmetric |
| High | DrawCircleGradient skips int base form |
Breaks Base/V convention |
| High | ImageDrawCircle uses int radius vs DrawCircle float radius |
Type mismatch across parallel APIs |
| High | DrawTriangleEx (per-vertex colors) missing from GPU |
Exists in ImageDraw but not Draw |
| Medium | DrawRectangleLinesV missing |
Circle/Ellipse have LinesV, Rectangle doesn't |
| Medium | DrawCircleLinesEx (thickness) missing |
Rectangle has LinesEx, Circle doesn't |
| Medium | DrawTriangleLines3D missing |
2D has the pair, 3D doesn't |
| Medium | No ImageDrawEllipse* functions |
Ellipse exists in Draw but not ImageDraw |
| Medium | LoadTextureFromMemory missing |
Shortcut for common Image→Texture pipeline |
| Low | GetSoundTimeLength/GetSoundTimePlayed missing |
Music has them, Sound doesn't |
| Low | ExportFont/ExportModel missing |
Other resources have Export |
| Low | ImageDrawPoly/ImageDrawRing missing |
GPU Draw has them, ImageDraw doesn't |
This section tags each gap from Section 9 with an implementation-confidence rating after reading the actual .c implementations. The goal is to isolate gaps that can be filled mechanically (no design decisions required) from those that need API-design input.
All Section 1–7 claims were verified against src/rshapes.c, src/rtextures.c, src/rmodels.c, src/raudio.c, src/rcore.c, and src/raylib.h. Additional findings surfaced during verification:
- Header/impl parameter-name mismatch:
raylib.hdeclaresDrawCylinder(..., int slices, ...)andDrawCylinderWires(..., int slices, ...), butrmodels.c:577andrmodels.c:695define them withint sides. C allows this (names aren't part of the linkage), but it's an additional source of confusion and an implementation-file fix in its own right. IsRenderTextureValidconfirmed present (raylib.h:1447) — not actually a gap.ImageDrawTriangleFanandImageDrawTriangleStripconfirmed present (raylib.h:1433–1434).DrawSphereimplementation (rmodels.c:433) is a one-liner:DrawSphereEx(centerPos, radius, 16, 16, color). This confirms the "default rings/slices" pattern used for auto-filling the sphere-wires simple-form gap.Soundstruct (raylib.h:487) embedsAudioStream stream+unsigned int frameCount— identical layout to Music for duration purposes, makingGetSoundTimeLengtha one-liner.LoadSoundFromWave(raudio.c:944) is a simple composition from Wave → AudioBuffer → Sound, makingLoadSoundFromMemorya 3-line wrapper.LoadTextureFromImage(rtextures.c:4126) +LoadImageFromMemory(rtextures.c:411) meansLoadTextureFromMemoryis also a trivial composition.IsMeshValidpattern derivable fromIsModelValid(rmodels.c:1171): checkvertices != NULL,vertexCount > 0,vaoId != 0(and optionally that each set vbo pointer has a matching non-zero VBO slot).
These gaps have a single obvious implementation derivable directly from existing code. No API-design decisions required. All are additive (new function names), so no breaking changes.
bool IsMeshValid(Mesh mesh)
{
bool result = false;
if ((mesh.vertices != NULL) &&
(mesh.vertexCount > 0) &&
(mesh.vaoId > 0)) result = true;
// Mirror IsModelValid's per-attribute VBO check
if (result)
{
if ((mesh.vertices != NULL) && (mesh.vboId[0] == 0)) result = false;
if ((mesh.texcoords != NULL) && (mesh.vboId[1] == 0)) result = false;
if ((mesh.normals != NULL) && (mesh.vboId[2] == 0)) result = false;
if ((mesh.colors != NULL) && (mesh.vboId[3] == 0)) result = false;
if ((mesh.tangents != NULL) && (mesh.vboId[4] == 0)) result = false;
if ((mesh.texcoords2 != NULL)&& (mesh.vboId[5] == 0)) result = false;
if ((mesh.indices != NULL) && (mesh.vboId[6] == 0)) result = false;
}
return result;
}Pattern is lifted verbatim from IsModelValid (rmodels.c:1171–1200).
float GetSoundTimeLength(Sound sound)
{
if (sound.stream.sampleRate == 0) return 0.0f;
return (float)sound.frameCount/sound.stream.sampleRate;
}Identical formula to GetMusicTimeLength (raudio.c:2076–2083).
H3 — LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize) → raudio.c
Sound LoadSoundFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
{
Wave wave = LoadWaveFromMemory(fileType, fileData, dataSize);
Sound sound = LoadSoundFromWave(wave);
UnloadWave(wave);
return sound;
}Mirrors the documented 3-step workflow the audit calls out as a gap.
H4 — LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize) → rtextures.c
Texture2D LoadTextureFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
{
Image image = LoadImageFromMemory(fileType, fileData, dataSize);
Texture2D texture = LoadTextureFromImage(image);
UnloadImage(image);
return texture;
}Same composition pattern.
void DrawTriangleLines3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex3f(v1.x, v1.y, v1.z); rlVertex3f(v2.x, v2.y, v2.z);
rlVertex3f(v2.x, v2.y, v2.z); rlVertex3f(v3.x, v3.y, v3.z);
rlVertex3f(v3.x, v3.y, v3.z); rlVertex3f(v1.x, v1.y, v1.z);
rlEnd();
}Direct analogue of DrawLine3D (rmodels.c:189) composed three times. No design questions.
Implementable as a ring with full sweep:
void DrawCircleLinesEx(Vector2 center, float radius, float lineThick, Color color)
{
if (lineThick < 0.0f) lineThick = 0.0f;
float inner = radius - lineThick*0.5f;
float outer = radius + lineThick*0.5f;
if (inner < 0.0f) inner = 0.0f;
DrawRing(center, inner, outer, 0.0f, 360.0f, 36, color);
}Uses 36 segments to match DrawCircleV → DrawCircleSector(..., 36, ...) (rshapes.c:324). Matches DrawRectangleLinesEx modality (thickness-aware outline).
H7 — ImageDrawLineStrip(Image *dst, const Vector2 *points, int pointCount, Color color) → rtextures.c
void ImageDrawLineStrip(Image *dst, const Vector2 *points, int pointCount, Color color)
{
for (int i = 0; i < pointCount - 1; i++)
ImageDrawLineV(dst, points[i], points[i + 1], color);
}Matches GPU DrawLineStrip (rshapes.c). One-liner composition.
H8 — ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rotation, Color color) → rtextures.c
Already has ImageDrawTriangle available — compute the 4 rotated corners (identical math to DrawRectanglePro at rshapes.c:738–772), then call ImageDrawTriangle twice to fill the quad. High confidence — the corner math is already written and can be copied verbatim.
Not strictly a gap but a one-line comment fix that's part of gap analysis's audio modality: standardize SetMusicPan / SetAudioStreamPan comment formats to match SetSoundPan.
These have a clear implementation path but require one small API-design choice (e.g., parameter order, default values, naming when the obvious slot is taken).
Blocker: the obvious name is already taken by the Vector2 version. Options:
- (a) Add
DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)and rename the existing one toDrawCircleGradientV. Breaking change; needs deprecation shim. - (b) Add only
DrawCircleGradientVas an alias and leave the wrong name in place. Preserves compat but keeps the wart. - Decision needed from the maintainer; the implementation itself is one line either way.
Blocker: existing DrawRectangleLines takes ints. A float-accurate V variant needs to either (a) delegate to DrawRectangleLinesEx({x,y,w,h}, 1.0f, color) (introduces 1px default thickness — subtle semantic shift from int version) or (b) replicate the RL_LINES code from DrawRectangleLines (rshapes.c:870–883) with float vertices.
Implementation is obvious; the pick is stylistic.
Geometry: two ring outlines at inner and outer of a nominal ring, plus radial line caps. Math is a straightforward extension of DrawRing (rshapes.c:553) but there are ambiguity questions (cap style — straight or rounded?). Medium confidence — needs a style pick.
CPU-side radial gradient. Implementable by iterating a bounding box, computing per-pixel distance, and lerping colors. Medium confidence — need to pick color-space (sRGB linear vs gamma).
Port DrawEllipse (rshapes.c:514) to CPU. The outline version can use a midpoint-ellipse algorithm; the fill version can scan-line. Math is textbook; just takes more code than the simpler gaps.
Annulus fill: iterate bounding box of outer circle, write pixel if innerRadius² ≤ dx²+dy² ≤ outerRadius². Same approach for sector angles. Medium confidence.
Regular polygon fill. Can be expressed as fan of ImageDrawTriangle calls from center; outline is a loop of ImageDrawLineV. Medium confidence.
Per-pixel interpolation between color corners. Straightforward but pick a color-interpolation space (match GPU version — GPU is linear sRGB in fragment blend; CPU should mirror).
3-vertex draw with rlColor4ub per vertex (see DrawTriangle3D rmodels.c:232 for the pattern — just one color there). Implementation is 6 lines; "Ex" is shorthand for per-vertex color, no design debate.
void DrawTriangleEx(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3)
{
rlBegin(RL_TRIANGLES);
rlColor4ub(c1.r,c1.g,c1.b,c1.a); rlVertex2f(v1.x, v1.y);
rlColor4ub(c2.r,c2.g,c2.b,c2.a); rlVertex2f(v2.x, v2.y);
rlColor4ub(c3.r,c3.g,c3.b,c3.a); rlVertex2f(v3.x, v3.y);
rlEnd();
}Actually classify this as High-confidence (H10) — listed here only because the suffix "Ex" currently has a variety of meanings across the API, so the maintainer may prefer a different name (DrawTriangleColors, etc.).
Do not auto-implement these — they require design decisions or backend plumbing.
| Gap | Blocker |
|---|---|
DrawSphereWires simple-form |
Adding a new function with no rings/slices requires picking a name (collides with existing). Same issue for DrawCapsuleSimple. C has no overloading. |
GetSoundTimePlayed(Sound) |
Sound does not track playback cursor itself — would need to query the underlying ma_decoder/AudioBuffer via miniaudio internals. Backend-specific. |
SeekSound(Sound, float) |
Same backend issue as above; Sound is decoded in full at load time, so seeking is writing into the ma_data_source directly. |
ExportFont(Font, fileName) |
Requires choosing a file format. FNT (re-encoding glyphs) and BMFont are candidates. Raylib's glyph rasterization is one-way (TTF → Font); round-tripping needs new serialization code. |
ExportModel(Model, fileName) |
Requires a target format (OBJ loses skeleton, glTF is heavy). Raylib bundles cgltf but only in read mode. |
LoadModelFromMemory |
Model loaders in raylib (OBJ/IQM/glTF/VOX/M3D) consume file paths for embedded texture resolution. Memory loading needs a virtual-path or callback shim. |
ExportFontAsCode already exists, but ExportFont (data) does not |
Same as ExportFont above. |
DrawEllipseGradient |
Needs a choice: radial along ellipse geometry, or linear? No existing precedent. |
DrawLineDashed/DrawLineBezier ImageDraw variants |
CPU rasterization; doable but moderate effort and needs pixel-level sub-stepping decisions. |
DrawTextPro ImageDraw variant |
Requires rotated text rasterization at pixel level — significant new code. |
Header/impl slices vs sides mismatch for DrawCylinder* |
Fix is trivial (rename in .c to match .h), but maintainers may prefer the other direction since sides is arguably more correct for a polygon-count term. Needs a call. |
Safe to auto-implement now (9 items): H1 IsMeshValid, H2 GetSoundTimeLength, H3 LoadSoundFromMemory, H4 LoadTextureFromMemory, H5 DrawTriangleLines3D, H6 DrawCircleLinesEx, H7 ImageDrawLineStrip, H8 ImageDrawRectanglePro, H10 (=M9) DrawTriangleEx.
Each of these is a pure addition that follows an already-established pattern in the code, compiles as a tight wrapper or copy of adjacent logic, and doesn't require the maintainer to weigh in on naming or semantics. All others should wait for a design pass.