@@ -15,7 +15,7 @@ use renzora_editor_framework::{
1515} ;
1616use renzora:: core:: ShapeRegistry ;
1717use renzora_theme:: ThemeManager ;
18- use renzora_undo:: { self , CompoundCmd , ReparentCmd , SetHierarchyOrderCmd , SpawnEntityCmd , SpawnEntityKind , SpawnShapeCmd , UndoCommand , UndoContext } ;
18+ use renzora_undo:: { self , CompoundCmd , RenameCmd , ReparentCmd , SetHierarchyOrderCmd , SpawnEntityCmd , SpawnEntityKind , SpawnShapeCmd , UndoCommand , UndoContext } ;
1919
2020use cache:: { HierarchyDirty , HierarchyTreeCache } ;
2121use state:: { filter_tree, HierarchyState } ;
@@ -293,6 +293,71 @@ impl EditorPanel for HierarchyPanel {
293293 }
294294 }
295295
296+ // Batch Rename dialog
297+ if state. batch_rename_active {
298+ let count = state. batch_rename_entities . len ( ) ;
299+ let mut open = true ;
300+ egui:: Window :: new ( "Batch Rename" )
301+ . collapsible ( false )
302+ . resizable ( false )
303+ . open ( & mut open)
304+ . anchor ( egui:: Align2 :: CENTER_CENTER , [ 0.0 , 0.0 ] )
305+ . show ( ui. ctx ( ) , |ui| {
306+ ui. horizontal ( |ui| {
307+ ui. label ( "Base name:" ) ;
308+ ui. text_edit_singleline ( & mut state. batch_rename_base ) ;
309+ } ) ;
310+ ui. horizontal ( |ui| {
311+ ui. label ( "Start at:" ) ;
312+ ui. add ( egui:: DragValue :: new ( & mut state. batch_rename_start ) . range ( 0 ..=9999 ) ) ;
313+ } ) ;
314+ ui. add_space ( 4.0 ) ;
315+ ui. label (
316+ egui:: RichText :: new ( format ! (
317+ "Preview: {}_{:02}, {}_{:02}, … ({} entities)" ,
318+ state. batch_rename_base,
319+ state. batch_rename_start,
320+ state. batch_rename_base,
321+ state. batch_rename_start + 1 ,
322+ count,
323+ ) )
324+ . size ( 11.0 )
325+ . color ( theme. text . muted . to_color32 ( ) ) ,
326+ ) ;
327+ ui. add_space ( 4.0 ) ;
328+ ui. horizontal ( |ui| {
329+ if ui. button ( "Rename" ) . clicked ( ) && !state. batch_rename_base . is_empty ( ) {
330+ let entities = state. batch_rename_entities . clone ( ) ;
331+ let base = state. batch_rename_base . clone ( ) ;
332+ let start = state. batch_rename_start ;
333+ commands. push ( move |world : & mut World | {
334+ let mut cmds: Vec < Box < dyn UndoCommand > > = Vec :: new ( ) ;
335+ for ( i, entity) in entities. iter ( ) . enumerate ( ) {
336+ let old = world
337+ . get :: < Name > ( * entity)
338+ . map ( |n| n. as_str ( ) . to_string ( ) )
339+ . unwrap_or_default ( ) ;
340+ let new = format ! ( "{}_{:02}" , base, start as usize + i) ;
341+ cmds. push ( Box :: new ( RenameCmd { entity : * entity, old, new } ) ) ;
342+ }
343+ renzora_undo:: execute (
344+ world,
345+ UndoContext :: Scene ,
346+ Box :: new ( CompoundCmd { label : "Batch Rename" . to_string ( ) , cmds } ) ,
347+ ) ;
348+ } ) ;
349+ state. batch_rename_active = false ;
350+ }
351+ if ui. button ( "Cancel" ) . clicked ( ) {
352+ state. batch_rename_active = false ;
353+ }
354+ } ) ;
355+ } ) ;
356+ if !open {
357+ state. batch_rename_active = false ;
358+ }
359+ }
360+
296361 // Read the cached entity tree. Rebuilt by `update_hierarchy_cache`
297362 // (Update schedule) only when the tree actually changed. When no
298363 // search is active we read directly from the cache (no clone);
0 commit comments