@@ -295,6 +295,9 @@ struct InspectorView: View {
295295
296296 let sortedComponents = sortEntityComponents ( componentOption_Editor: mergedComponents)
297297
298+ // Static Batching Section - Show for any entity with renderable hierarchy
299+ StaticBatchingEditorView ( entityId: entityId, refreshView: refreshView)
300+
298301 ForEach ( sortedComponents, id: \. id) { editor_component in
299302 VStack ( alignment: . leading, spacing: 4 ) {
300303 HStack {
@@ -458,6 +461,102 @@ struct InspectorView: View {
458461 }
459462 */
460463
464+ // Standalone Static Batching Section
465+ struct StaticBatchingEditorView : View {
466+ let entityId : EntityID
467+ let refreshView : ( ) -> Void
468+
469+ @State private var staticBatchCheckboxState : Bool = false
470+
471+ // Check if entity or any of its children have RenderComponent
472+ private func hasRenderableHierarchy( entityId: EntityID ) -> Bool {
473+ // Check self
474+ if hasComponent ( entityId: entityId, componentType: RenderComponent . self) {
475+ return true
476+ }
477+
478+ // Check children recursively
479+ let children = getEntityChildren ( parentId: entityId)
480+ for child in children {
481+ if hasRenderableHierarchy ( entityId: child) {
482+ return true
483+ }
484+ }
485+
486+ return false
487+ }
488+
489+ // Check if entity or any of its children have StaticBatchComponent
490+ private func isMarkedAsStatic( entityId: EntityID ) -> Bool {
491+ // Check self
492+ if hasComponent ( entityId: entityId, componentType: StaticBatchComponent . self) {
493+ return true
494+ }
495+
496+ // Check children recursively
497+ let children = getEntityChildren ( parentId: entityId)
498+ for child in children {
499+ if isMarkedAsStatic ( entityId: child) {
500+ return true
501+ }
502+ }
503+
504+ return false
505+ }
506+
507+ var body : some View {
508+ // Only show if entity or children have RenderComponent (but not lights)
509+ if hasRenderableHierarchy ( entityId: entityId) , hasComponent ( entityId: entityId, componentType: LightComponent . self) == false {
510+ VStack ( alignment: . leading, spacing: 4 ) {
511+ Text ( " Static Batching " )
512+ . font ( . headline)
513+ . frame ( maxWidth: . infinity, alignment: . leading)
514+
515+ let hasOwnRenderComponent = hasComponent ( entityId: entityId, componentType: RenderComponent . self)
516+ let labelText = hasOwnRenderComponent ? " Mark as Static " : " Mark Children as Static "
517+ let helpText = hasOwnRenderComponent
518+ ? " Enable static batching for this entity (combines geometry to reduce draw calls) "
519+ : " Enable static batching for all children of this entity (combines geometry to reduce draw calls) "
520+
521+ Toggle ( isOn: Binding (
522+ get: { staticBatchCheckboxState } ,
523+ set: { isStatic in
524+ if isStatic {
525+ setEntityStaticBatchComponent ( entityId: entityId)
526+ } else {
527+ removeEntityStaticBatchComponent ( entityId: entityId)
528+ }
529+ staticBatchCheckboxState = isStatic
530+ refreshView ( )
531+ }
532+ ) ) {
533+ HStack {
534+ Image ( systemName: " square.3.layers.3d " )
535+ . foregroundColor ( . blue)
536+ Text ( labelText)
537+ . font ( . callout)
538+ }
539+ }
540+ . padding ( . vertical, 6 )
541+ . padding ( . horizontal, 8 )
542+ . background ( Color . secondary. opacity ( 0.05 ) )
543+ . cornerRadius ( 8 )
544+ . help ( helpText)
545+ . onAppear {
546+ // Update checkbox state when view appears
547+ staticBatchCheckboxState = isMarkedAsStatic ( entityId: entityId)
548+ }
549+ . onChange ( of: entityId) { newEntityId in
550+ // Update checkbox state when entity selection changes
551+ staticBatchCheckboxState = isMarkedAsStatic ( entityId: newEntityId)
552+ }
553+ }
554+
555+ Divider ( )
556+ }
557+ }
558+ }
559+
461560struct RenderingEditorView : View {
462561 let entityId : EntityID
463562 let asset : Asset ?
@@ -685,15 +784,33 @@ struct TransformationEditorView: View {
685784 let entityId : EntityID
686785 let refreshView : ( ) -> Void
687786
787+ @State private var showStaticBatchWarning = false
788+
688789 var body : some View {
689790 Text ( " Transform Properties " )
791+
792+ // Warning banner if entity is marked as static
793+ if hasComponent ( entityId: entityId, componentType: StaticBatchComponent . self) {
794+ HStack {
795+ Image ( systemName: " exclamationmark.triangle.fill " )
796+ . foregroundColor ( . orange)
797+ Text ( " This entity is marked for static batching. Transforming it will disable batching. " )
798+ . font ( . caption)
799+ . foregroundColor ( . orange)
800+ }
801+ . padding ( 6 )
802+ . background ( Color . orange. opacity ( 0.1 ) )
803+ . cornerRadius ( 6 )
804+ }
805+
690806 let localTransformComponent = scene. get ( component: LocalTransformComponent . self, for: entityId)
691807 let position = getLocalPosition ( entityId: entityId)
692808 let orientation = simd_float3 ( localTransformComponent!. rotationX, localTransformComponent!. rotationY, localTransformComponent!. rotationZ)
693809 let scale = getScale ( entityId: entityId)
694810 TextInputVectorView ( label: " Position " , value: Binding (
695811 get: { position } ,
696812 set: { newPosition in
813+ handleTransformChange ( )
697814 translateTo ( entityId: entityId, position: newPosition)
698815 refreshView ( )
699816 }
@@ -702,6 +819,7 @@ struct TransformationEditorView: View {
702819 TextInputVectorView ( label: " Orientation " , value: Binding (
703820 get: { orientation } ,
704821 set: { newOrientation in
822+ handleTransformChange ( )
705823 applyAxisRotations ( entityId: entityId, axis: newOrientation)
706824 refreshView ( )
707825 }
@@ -710,11 +828,22 @@ struct TransformationEditorView: View {
710828 TextInputVectorView ( label: " Scale " , value: Binding (
711829 get: { scale } ,
712830 set: { newScale in
831+ handleTransformChange ( )
713832 scaleTo ( entityId: entityId, scale: newScale)
714833 refreshView ( )
715834 }
716835 ) )
717836 }
837+
838+ private func handleTransformChange( ) {
839+ if hasComponent ( entityId: entityId, componentType: StaticBatchComponent . self) {
840+ removeEntityStaticBatchComponent ( entityId: entityId)
841+ // Optionally regenerate batches without this entity
842+ if isBatchingEnabled ( ) {
843+ generateBatches ( )
844+ }
845+ }
846+ }
718847}
719848
720849struct AnimationEditorView : View {
0 commit comments