packages feed

mischief-math-0.1.0.0: src/Mischief/Math/Transform/Plugin.hs

{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

module Mischief.Math.Transform.Plugin where

import Mischief.ECS
import Mischief.ECS.App.Schedules (First)
import Mischief.ECS.Relationships.ChildOf qualified as ChildOf
import Mischief.Math.Transform (GlobalTransform (GlobalTransform), Transform, composeTransforms)

data TransformPlugin

instance Plugin TransformPlugin where
  init = do
    schedule @First $ systems propTransform

propTransform :: System ()
propTransform = do
  query_ qiterTransform

qiterTransform :: Query System ()
qiterTransform = do
  root <- [q|Entity / Without ChildOf -> *|]
  dirty <- qlift $ check [qf|Changed Transform|] root
  if dirty
    then do
      trans <- qget root [qd|Transform|]
      qlift $ insert (GlobalTransform trans) root
      child <- qiterE =<< qlift (ChildOf.children root)
      qpropTransformRec child (GlobalTransform trans)
    else
      qiterTransformRec root

-- | Recursively iterates downwards and starts propagating the transform when finding a dirty entity.
qiterTransformRec :: Entity -> Query System ()
qiterTransformRec entity = do
  child <- qiterE =<< qlift (ChildOf.children entity)
  dirty <- qlift $ check [qf|Changed Transform|] child

  if dirty
    then do
      global <- qget entity [qd|GlobalTransform|]
      qpropTransformRec child global
    else do
      qiterTransformRec child

-- | Given an entity and its parent's Global Transform, propagates the Global Transform downwards.
qpropTransformRec :: Entity -> GlobalTransform -> Query System ()
qpropTransformRec entity (GlobalTransform global) = do
  transform <- qget entity [qd|Transform|]

  let global' = global `composeTransforms` transform
  qlift $ insert (GlobalTransform global') entity

  child <- qiterE =<< qlift (ChildOf.children entity)
  qpropTransformRec child (GlobalTransform global')