Drawing.fs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. namespace RL
  2. open Raylib_CsLo
  3. open Garnet.Composition
  4. open RL.Components
  5. open RL.Mapping
  6. open System.Numerics
  7. open System.Collections.Generic
  8. module Drawing =
  9. type PlayerRefresh = { s : SharedState }
  10. type RefreshCall =
  11. | MapClear of s : SharedState
  12. | MapFullRefresh of s : SharedState
  13. | ActorRefresh of s : SharedState
  14. | ActorPointSet of s : SharedState * pset : list<Point2D>
  15. | MapPointSetRefresh of s : SharedState * pset : list<Point2D>
  16. | MapPointSetClear of s : SharedState * pset : list<Point2D> * clearc : Color
  17. | MapPointSetModColor of s : SharedState * pset : list<Point2D> * modc : (Color -> Color)
  18. //
  19. // Draw call buffer definition
  20. //
  21. type DrawCallContainer() =
  22. let calls = List<RefreshCall>()
  23. member val Calls = calls with get
  24. member _.Clear() = calls.Clear()
  25. member _.ClearMap(s : SharedState) = calls.Add(RefreshCall.MapClear(s))
  26. member _.RefreshMapFull(s : SharedState) = calls.Add(RefreshCall.MapFullRefresh(s))
  27. member _.RefreshActors(s : SharedState) = calls.Add(RefreshCall.ActorRefresh(s))
  28. member _.RefreshActorsPointSet(s : SharedState, p : list<Point2D>) = calls.Add(RefreshCall.ActorPointSet(s, p))
  29. member _.RefreshMapPoints(s : SharedState, p : list<Point2D>) = calls.Add(RefreshCall.MapPointSetRefresh(s, p))
  30. member _.RefreshMapPointsColorMod(s : SharedState, p : list<Point2D>, m : Color -> Color) = calls.Add(RefreshCall.MapPointSetModColor(s, p, m))
  31. member _.ClearMapPoints(s : SharedState, p : list<Point2D>, c : Color) = calls.Add(RefreshCall.MapPointSetClear(s, p, c))
  32. //
  33. // System backend function definitions
  34. //
  35. let inline internal MapClearSystem(ss : SharedState) =
  36. Raylib.BeginTextureMode(ss.MapLayer)
  37. Raylib.ClearBackground(Color(0,0,0,0))
  38. Raylib.EndTextureMode()
  39. let inline internal MapFullRefreshSystem(c : Container, ss : SharedState) =
  40. Raylib.BeginTextureMode(ss.MapLayer)
  41. Raylib.ClearBackground(Color(0,0,0,0))
  42. let result, map : bool * Mapping.RLMap = c.TryGetResource("Map")
  43. if result then
  44. for y in 0 .. map.Height - 1 do
  45. for x in 0 .. map.Width - 1 do
  46. let tile = map.GetTile x y
  47. ss.SpriteSheet.DrawSprite(
  48. tile.sprite.spriteID,
  49. Vector2(single x, single y),
  50. tile.sprite.color)
  51. Raylib.EndTextureMode()
  52. let inline internal ActorRefreshSystem(c : Container, ss : SharedState) =
  53. Raylib.BeginTextureMode(ss.ActorLayer) // Start a draw mode for the actor layer texture.
  54. Raylib.ClearBackground(Color(0,0,0,0)) // Clear the layer to full alpha.
  55. for e in c.Query<Sprite, Point2D>() do
  56. ss.SpriteSheet.DrawSprite(
  57. e.Value1.spriteID,
  58. e.Value2.ToVector,
  59. e.Value1.color)
  60. Raylib.EndTextureMode() // End the draw mode block.
  61. // Refreshes the actors only within the provided point set.
  62. let inline internal ActorPointSetRefreshSystem(c : Container, ss : SharedState, pset : list<Point2D>) =
  63. Raylib.BeginTextureMode(ss.ActorLayer)
  64. Raylib.ClearBackground(Color(0,0,0,0))
  65. for e in c.Query<Sprite, Point2D>() do
  66. let visible = pset |> Seq.contains e.Value2
  67. if visible then
  68. ss.SpriteSheet.DrawSprite(
  69. e.Value1.spriteID,
  70. e.Value2.ToVector,
  71. e.Value1.color)
  72. Raylib.EndTextureMode()
  73. // Refreshes the tiles only within a provided point set.
  74. let inline internal MapPointSetRefreshSystem(c : Container, ss : SharedState, pset : list<Point2D>) =
  75. Raylib.BeginTextureMode(ss.MapLayer)
  76. let result, map : bool * Mapping.RLMap = c.TryGetResource("Map")
  77. if result then
  78. for point in pset do
  79. let tile = map.GetTile point.x point.y
  80. ss.SpriteSheet.DrawSprite(
  81. tile.sprite.spriteID,
  82. Vector2(single point.x, single point.y),
  83. tile.sprite.color)
  84. Raylib.EndTextureMode()
  85. // Wipes the points in the provided set to a color.
  86. let inline internal MapPointSetClearSystem(ss : SharedState, pset : list<Point2D>, clearc : Color) =
  87. Raylib.BeginTextureMode(ss.MapLayer)
  88. for point in pset do
  89. ss.SpriteSheet.DrawSprite(
  90. 0xDB,
  91. Vector2(single point.x, single point.y),
  92. clearc)
  93. Raylib.EndTextureMode()
  94. // Refreshes the tiles within the point set, applying a modifier function to their color.
  95. let inline internal MapPointSetModColorSystem(c : Container, ss : SharedState, pset : list<Point2D>, modc : Color -> Color) =
  96. Raylib.BeginTextureMode(ss.MapLayer)
  97. let result, map : bool * Mapping.RLMap = c.TryGetResource("Map")
  98. if result then
  99. for point in pset do
  100. let tile = map.GetTile point.x point.y
  101. ss.SpriteSheet.DrawSprite(
  102. tile.sprite.spriteID,
  103. Vector2(single point.x, single point.y),
  104. modc tile.sprite.color)
  105. Raylib.EndTextureMode()
  106. //
  107. // Draw system implementation
  108. //
  109. type Container with
  110. member c.RegisterDrawingSystem =
  111. c.On<RefreshCall> <| fun r ->
  112. match r with
  113. | MapClear(s) -> MapClearSystem(s)
  114. | MapFullRefresh(s) -> MapFullRefreshSystem(c, s)
  115. | ActorRefresh(s) -> ActorRefreshSystem(c, s)
  116. | ActorPointSet(s, p) -> ActorPointSetRefreshSystem(c, s, p)
  117. | MapPointSetRefresh(s, p) -> MapPointSetRefreshSystem(c, s, p)
  118. | MapPointSetClear(s, p, cc) -> MapPointSetClearSystem(s, p, cc)
  119. | MapPointSetModColor(s, p, mc) -> MapPointSetModColorSystem(c, s, p, mc)
  120. member c.RegisterPlayerRefresh =
  121. c.On<PlayerRefresh> <| fun r ->
  122. let result, map : bool * RLMap = c.TryGetResource("Map")
  123. let result2, draw : bool * DrawCallContainer = c.TryGetResource("Draw")
  124. if result && result2 then
  125. let vis = map.GetPointsVisible
  126. draw.RefreshMapPoints(r.s, vis) // Refresh the visible points.
  127. draw.RefreshActorsPointSet(r.s, vis) // Refresh any visible actors.
  128. draw.RefreshMapPointsColorMod( // Refresh the explored points with a desaturated tile color.
  129. r.s, map.GetPointsExploredExclusive,
  130. (fun c -> Color(c.r - 100uy, c.g - 100uy, c.b - 100uy, c.a)))
  131. let init(c : Container) =
  132. Disposable.Create[c.RegisterDrawingSystem; c.RegisterPlayerRefresh] |> ignore