throaway2854 commited on
Commit
3d1e39b
·
verified ·
1 Parent(s): 4ffccf2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +238 -247
app.py CHANGED
@@ -5,7 +5,6 @@ import random
5
  from PIL import Image
6
  import base64
7
  import io
8
- from functools import partial
9
 
10
  # Define categories at the top so they are accessible throughout the code
11
  categories = [
@@ -84,7 +83,7 @@ class DataManager:
84
  self.save_category_tags()
85
 
86
  def get_characters(self):
87
- # Load character images
88
  for char in self.characters:
89
  image_path = char.get('image_path')
90
  if image_path and os.path.exists(image_path):
@@ -181,33 +180,209 @@ class DataManager:
181
  return True
182
  return False
183
 
184
- def character_creation_app(data_manager, refresh_characters_fn):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  with gr.Tab("Character Creation"):
186
  gr.Markdown("## Create a New Character")
187
  with gr.Row():
188
- name_input = gr.Textbox(label="Character Name")
189
- traits_input = gr.Textbox(label="Traits/Appearance Tags (comma separated)")
190
  image_input = gr.Image(label="Upload Character Image", type="filepath")
191
- # New gender selection input
192
  gender_input = gr.Radio(choices=["Boy", "Girl"], label="Gender")
193
  save_button = gr.Button("Save Character")
194
  output = gr.Textbox(label="Status", interactive=False)
195
 
196
- def save_character(name, traits, image_path, gender):
197
- if not name or not traits or not gender:
198
- return "Please enter all fields."
199
  # Check for duplicate names
200
  existing_names = [char['name'] for char in data_manager.get_characters()]
201
  if name in existing_names:
202
- return f"Character with name '{name}' already exists. Please choose a different name."
203
 
204
  character = {'name': name, 'traits': traits, 'gender': gender, 'image': image_path}
205
 
206
  data_manager.add_character(character)
207
- refresh_characters_fn()
208
- return f"Character '{name}' saved successfully."
209
 
210
- save_button.click(save_character, inputs=[name_input, traits_input, image_input, gender_input], outputs=output)
 
 
 
 
211
 
212
  # Divider
213
  gr.Markdown("---")
@@ -215,20 +390,19 @@ def character_creation_app(data_manager, refresh_characters_fn):
215
  # Display Existing Characters
216
  gr.Markdown("## Existing Characters")
217
 
218
- # Container to hold the list of characters
219
- characters_container = gr.Column()
220
 
221
- def list_characters():
222
  characters = data_manager.get_characters()
223
  if not characters:
224
- return [gr.Markdown("No characters created yet.")]
225
 
226
  components = []
227
  for char in characters:
228
  with gr.Accordion(label=char['name'], open=False):
229
  with gr.Row():
230
  if char['image']:
231
- # Display the image using filepath
232
  img_display = gr.Image(value=char['image'], label="Character Image", type="filepath", interactive=False)
233
  else:
234
  img_display = gr.Markdown("**No Image Provided**")
@@ -246,67 +420,64 @@ def character_creation_app(data_manager, refresh_characters_fn):
246
  edit_interface = gr.Column(visible=False)
247
  with edit_interface:
248
  with gr.Row():
249
- edit_name = gr.Textbox(label="Character Name", value=char['name'])
250
- edit_traits = gr.Textbox(label="Traits/Appearance Tags (comma separated)", value=', '.join(char['traits']))
251
  edit_image = gr.Image(label="Upload New Character Image", type="filepath")
252
  edit_gender = gr.Radio(choices=["Boy", "Girl"], label="Gender", value=char['gender'])
253
  save_edit_btn = gr.Button("Save Changes")
254
  save_edit_output = gr.Textbox(label="Edit Status", interactive=False)
255
 
256
  def save_edit(original_name, new_name, new_traits, new_image_path, new_gender):
257
- if not new_name or not new_traits or not new_gender:
258
- return "Please enter all fields."
259
  # If the name has changed, check for duplicates
260
  if new_name != original_name:
261
  existing_names = [c['name'] for c in data_manager.get_characters()]
262
  if new_name in existing_names:
263
- return f"Character with name '{new_name}' already exists. Please choose a different name."
264
  updated_char = {
265
  'name': new_name,
266
  'traits': new_traits,
267
  'gender': new_gender,
268
- 'image': new_image_path
269
  }
270
  success = data_manager.update_character(original_name, updated_char)
271
  if success:
272
- refresh_characters_fn()
273
- return f"Character '{new_name}' updated successfully."
274
  else:
275
- return "Failed to update character."
276
 
277
  save_edit_btn.click(
278
  save_edit,
279
- inputs=[gr.State(char['name']), edit_name, edit_traits, edit_image, edit_gender],
280
- outputs=save_edit_output
281
  )
282
 
283
  # Define edit functionality
284
- def toggle_edit_visibility(event, current_visibility=False):
285
- return not current_visibility
286
 
287
  edit_btn.click(
288
- toggle_edit_visibility,
289
  inputs=None,
290
  outputs=edit_interface
291
  )
292
 
293
  # Define delete functionality
294
  def confirm_delete(char_name):
295
- return f"Are you sure you want to delete '{char_name}'?"
296
 
297
- def perform_delete(char_name):
298
- success = data_manager.delete_character(char_name)
299
- if success:
300
- refresh_characters_fn()
301
- return f"Character '{char_name}' deleted successfully."
302
- else:
303
- return f"Failed to delete character '{char_name}'."
304
-
305
- def show_confirmation(message):
306
- return message, True
307
 
308
  delete_btn.click(
309
- lambda name: confirm_delete(name),
310
  inputs=[char['name']],
311
  outputs=[delete_output, delete_output]
312
  )
@@ -315,213 +486,36 @@ def character_creation_app(data_manager, refresh_characters_fn):
315
  delete_cancel = gr.Button("Cancel Delete", visible=False)
316
 
317
  # Show confirmation buttons when delete is clicked
 
 
 
 
 
318
  delete_btn.click(
319
- lambda: gr.update(visible=True),
320
- inputs=None,
321
- outputs=[delete_confirm]
322
  )
323
 
324
  # Handle delete confirmation
325
  delete_confirm.click(
326
  perform_delete,
327
- inputs=[char['name']],
328
- outputs=delete_output
329
  )
330
 
 
331
  delete_cancel.click(
332
- lambda: "",
333
- outputs=delete_output
 
334
  )
 
335
 
336
- # Add spacing or separator if needed
337
- components.append("")
338
- return components
339
-
340
- def refresh_characters():
341
- return list_characters()
342
-
343
- characters_container.render(list_characters())
344
-
345
- # Refresh Button to reload characters
346
- refresh_button = gr.Button("Refresh Characters")
347
-
348
- refresh_button.click(fn=refresh_characters, outputs=characters_container)
349
-
350
- def prompt_generator_app(data_manager):
351
- with gr.Tab("Prompt Generator"):
352
- gr.Markdown("## Prompt Generator")
353
-
354
- # Add a refresh tags button
355
- refresh_tags_button = gr.Button("Refresh Tags")
356
-
357
- inputs = {}
358
- tag_displays = {}
359
- for category_name, var_name in categories:
360
- tags_list = data_manager.get_category_tags(var_name)
361
- tags_string = ', '.join(tags_list)
362
- max_tags = len(tags_list)
363
- if max_tags == 0:
364
- default_value = 0
365
- else:
366
- default_value = min(1, max_tags)
367
- with gr.Group():
368
- gr.Markdown(f"### {category_name}")
369
- tag_display = gr.Markdown(f"**Tags:** {tags_string}")
370
- tag_num = gr.Slider(minimum=0, maximum=max_tags, step=1, value=default_value, label=f"Number of {category_name} Tags to Select")
371
- inputs[f"{var_name}_num"] = tag_num
372
- tag_displays[var_name] = (tag_display, tag_num)
373
-
374
- # For Character Selection
375
- with gr.Group():
376
- gr.Markdown("### Character Selection")
377
-
378
- # Get the list of characters
379
- def get_character_options():
380
- characters = data_manager.get_characters()
381
- character_options = []
382
- for char in characters:
383
- option_label = f"{char['name']} ({char['gender']})"
384
- character_options.append(option_label)
385
- return character_options
386
-
387
- character_options = get_character_options()
388
- character_select = gr.CheckboxGroup(choices=character_options, label="Select Characters", interactive=True)
389
-
390
- refresh_characters_button = gr.Button("Refresh Character List")
391
-
392
- def refresh_characters_fn():
393
- new_options = get_character_options()
394
- return new_options
395
-
396
- refresh_characters_button.click(
397
- lambda: get_character_options(),
398
- outputs=character_select
399
- )
400
-
401
- random_characters = gr.Checkbox(label="Select Random Characters")
402
- num_characters = gr.Slider(minimum=1, maximum=10, step=1, value=1, label="Number of Characters (if random)")
403
-
404
- generate_button = gr.Button("Generate Prompt")
405
- prompt_output = gr.Textbox(label="Generated Prompt", lines=5)
406
 
407
- def generate_prompt(*args):
408
- arg_idx = 0
409
-
410
- prompt_tags = []
411
- for category_name, var_name in categories:
412
- tags_list = data_manager.get_category_tags(var_name)
413
- tags_num = args[arg_idx]
414
- arg_idx += 1
415
-
416
- if tags_list and tags_num > 0:
417
- selected_tags = random.sample(tags_list, min(len(tags_list), int(tags_num)))
418
- prompt_tags.extend(selected_tags)
419
-
420
- # Handle Characters
421
- selected_character_options = args[arg_idx]
422
- random_chars = args[arg_idx + 1]
423
- num_random_chars = args[arg_idx + 2]
424
-
425
- arg_idx += 3
426
-
427
- characters = data_manager.get_characters()
428
-
429
- if random_chars:
430
- num = min(len(characters), int(num_random_chars))
431
- selected_chars = random.sample(characters, num)
432
- else:
433
- # Extract selected character names from options
434
- selected_chars = []
435
- for option in selected_character_options:
436
- name = option.split(' (')[0]
437
- for char in characters:
438
- if char['name'] == name:
439
- selected_chars.append(char)
440
- break
441
-
442
- # Determine the number of boys and girls
443
- num_girls = sum(1 for char in selected_chars if char.get('gender') == 'Girl')
444
- num_boys = sum(1 for char in selected_chars if char.get('gender') == 'Boy')
445
-
446
- # Build the initial character count tags
447
- character_count_tags = []
448
- if num_girls > 0:
449
- character_count_tags.append(f"{num_girls}girl" if num_girls == 1 else f"{num_girls}girls")
450
- if num_boys > 0:
451
- character_count_tags.append(f"{num_boys}boy" if num_boys == 1 else f"{num_boys}boys")
452
-
453
- prompt_parts = []
454
-
455
- if character_count_tags:
456
- prompt_parts.append(', '.join(character_count_tags))
457
-
458
- # Build character descriptions
459
- character_descriptions = []
460
- for idx, char in enumerate(selected_chars):
461
- # Get traits for the character
462
- traits = ', '.join(char['traits'])
463
- # Create a description for each character
464
- # For SDXL models, use the format "[char1 description] AND [char2 description]"
465
- # Each character's description is enclosed in parentheses
466
- character_description = f"({traits})"
467
- character_descriptions.append(character_description)
468
-
469
- # Join character descriptions appropriately for SDXL models
470
- if character_descriptions:
471
- character_descriptions_str = ' AND '.join(character_descriptions)
472
- prompt_parts.append(character_descriptions_str)
473
-
474
- # Append selected prompt tags from categories
475
- if prompt_tags:
476
- prompt_tags_str = ', '.join(prompt_tags)
477
- prompt_parts.append(prompt_tags_str)
478
-
479
- # Load persistent tags
480
- persistent_tags = data_manager.get_persistent_tags()
481
- if persistent_tags:
482
- persistent_tags_str = ', '.join(persistent_tags)
483
- prompt_parts.append(persistent_tags_str)
484
-
485
- # Add ending tags
486
- ending_tags = "source_anime, score_9, score_8_up, score_7_up, masterpiece, best quality, very aesthetic, absurdres, anime artwork, anime style, vibrant, studio anime, highly detailed"
487
- prompt_parts.append(ending_tags)
488
-
489
- prompt_string = ', '.join(prompt_parts)
490
-
491
- return prompt_string
492
-
493
- # Prepare the list of inputs for the generate_prompt function
494
- inputs_list = []
495
- for category_name, var_name in categories:
496
- inputs_list.append(inputs[f"{var_name}_num"])
497
- # Add character_select directly to inputs
498
- inputs_list.extend([character_select, random_characters, num_characters])
499
-
500
- generate_button.click(generate_prompt, inputs=inputs_list, outputs=prompt_output)
501
-
502
- # Function to refresh tags display and sliders
503
- def refresh_tags():
504
- updates = []
505
- for category_name, var_name in categories:
506
- # Reload tags from data_manager
507
- tags_list = data_manager.get_category_tags(var_name)
508
- tags_string = ', '.join(tags_list)
509
- max_tags = len(tags_list)
510
- if max_tags == 0:
511
- slider_value = 0
512
- else:
513
- slider_value = min(1, max_tags)
514
- # Update the tag display and slider
515
- tag_display, tag_num = tag_displays[var_name]
516
- updates.append(gr.Markdown.update(value=f"**Tags:** {tags_string}"))
517
- updates.append(gr.Slider.update(maximum=max_tags, value=slider_value))
518
- return updates
519
-
520
- # Prepare the outputs list
521
- outputs = [component for pair in tag_displays.values() for component in pair]
522
-
523
- # Connect the refresh_tags function to the refresh_tags_button
524
- refresh_tags_button.click(refresh_tags, outputs=outputs)
525
 
526
  def tags_app(data_manager):
527
  with gr.Tab("Tags"):
@@ -535,7 +529,6 @@ def tags_app(data_manager):
535
  save_button = gr.Button(f"Save {category_name} Tags")
536
  status_output = gr.Textbox(label="", interactive=False)
537
 
538
- # Function to save tags
539
  def make_save_category_tags_fn(var_name, category_name):
540
  def fn(tags_string):
541
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
@@ -553,22 +546,20 @@ def tags_app(data_manager):
553
  save_persistent_tags_button = gr.Button("Save Persistent Tags")
554
  persistent_status_output = gr.Textbox(label="", interactive=False)
555
 
556
- def save_persistent_tags(tags_string):
557
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
558
  data_manager.set_persistent_tags(tags_list)
559
  return "Persistent tags saved successfully."
560
 
561
- save_persistent_tags_button.click(save_persistent_tags, inputs=persistent_tags_input, outputs=persistent_status_output)
562
 
563
  def main():
564
  data_manager = DataManager(base_dir='/data')
565
  with gr.Blocks() as demo:
566
  with gr.Tabs():
567
- with gr.Row():
568
- with gr.Column():
569
- prompt_generator_app(data_manager)
570
- character_creation_app(data_manager, refresh_characters_fn=lambda: None)
571
- tags_app(data_manager)
572
 
573
  demo.launch()
574
 
 
5
  from PIL import Image
6
  import base64
7
  import io
 
8
 
9
  # Define categories at the top so they are accessible throughout the code
10
  categories = [
 
83
  self.save_category_tags()
84
 
85
  def get_characters(self):
86
+ # Ensure images paths are up-to-date
87
  for char in self.characters:
88
  image_path = char.get('image_path')
89
  if image_path and os.path.exists(image_path):
 
180
  return True
181
  return False
182
 
183
+ def prompt_generator_app(data_manager):
184
+ with gr.Tab("Prompt Generator"):
185
+ gr.Markdown("## Prompt Generator")
186
+
187
+ # Add a refresh tags button
188
+ refresh_tags_button = gr.Button("Refresh Tags")
189
+
190
+ inputs = {}
191
+ tag_displays = {}
192
+ for category_name, var_name in categories:
193
+ tags_list = data_manager.get_category_tags(var_name)
194
+ tags_string = ', '.join(tags_list)
195
+ max_tags = len(tags_list)
196
+ if max_tags == 0:
197
+ default_value = 0
198
+ else:
199
+ default_value = min(1, max_tags)
200
+ with gr.Group():
201
+ gr.Markdown(f"### {category_name}")
202
+ tag_display = gr.Markdown(f"**Tags:** {tags_string}")
203
+ tag_num = gr.Slider(minimum=0, maximum=max_tags, step=1, value=default_value, label=f"Number of {category_name} Tags to Select")
204
+ inputs[f"{var_name}_num"] = tag_num
205
+ tag_displays[var_name] = (tag_display, tag_num)
206
+
207
+ # For Character Selection
208
+ with gr.Group():
209
+ gr.Markdown("### Character Selection")
210
+
211
+ # Get the list of characters
212
+ def get_character_options():
213
+ characters = data_manager.get_characters()
214
+ character_options = []
215
+ for char in characters:
216
+ option_label = f"{char['name']} ({char['gender']})"
217
+ character_options.append(option_label)
218
+ return character_options
219
+
220
+ character_options = get_character_options()
221
+ character_select = gr.CheckboxGroup(choices=character_options, label="Select Characters", interactive=True)
222
+
223
+ refresh_characters_button = gr.Button("Refresh Character List")
224
+
225
+ def refresh_characters():
226
+ new_options = get_character_options()
227
+ return gr.CheckboxGroup.update(choices=new_options)
228
+
229
+ refresh_characters_button.click(refresh_characters, outputs=character_select)
230
+
231
+ random_characters = gr.Checkbox(label="Select Random Characters")
232
+ num_characters = gr.Slider(minimum=1, maximum=10, step=1, value=1, label="Number of Characters (if random)")
233
+
234
+ generate_button = gr.Button("Generate Prompt")
235
+ prompt_output = gr.Textbox(label="Generated Prompt", lines=5)
236
+
237
+ def generate_prompt(*args):
238
+ arg_idx = 0
239
+
240
+ prompt_tags = []
241
+ for category_name, var_name in categories:
242
+ tags_list = data_manager.get_category_tags(var_name)
243
+ tags_num = args[arg_idx]
244
+ arg_idx += 1
245
+
246
+ if tags_list and tags_num > 0:
247
+ selected_tags = random.sample(tags_list, min(len(tags_list), int(tags_num)))
248
+ prompt_tags.extend(selected_tags)
249
+
250
+ # Handle Characters
251
+ selected_character_options = args[arg_idx]
252
+ random_chars = args[arg_idx + 1]
253
+ num_random_chars = args[arg_idx + 2]
254
+
255
+ arg_idx += 3
256
+
257
+ characters = data_manager.get_characters()
258
+
259
+ if random_chars:
260
+ num = min(len(characters), int(num_random_chars))
261
+ selected_chars = random.sample(characters, num)
262
+ else:
263
+ # Extract selected character names from options
264
+ selected_chars = []
265
+ for option in selected_character_options:
266
+ name = option.split(' (')[0]
267
+ for char in characters:
268
+ if char['name'] == name:
269
+ selected_chars.append(char)
270
+ break
271
+
272
+ # Determine the number of boys and girls
273
+ num_girls = sum(1 for char in selected_chars if char.get('gender') == 'Girl')
274
+ num_boys = sum(1 for char in selected_chars if char.get('gender') == 'Boy')
275
+
276
+ # Build the initial character count tags
277
+ character_count_tags = []
278
+ if num_girls > 0:
279
+ character_count_tags.append(f"{num_girls}girl" if num_girls == 1 else f"{num_girls}girls")
280
+ if num_boys > 0:
281
+ character_count_tags.append(f"{num_boys}boy" if num_boys == 1 else f"{num_boys}boys")
282
+
283
+ prompt_parts = []
284
+
285
+ if character_count_tags:
286
+ prompt_parts.append(', '.join(character_count_tags))
287
+
288
+ # Build character descriptions
289
+ character_descriptions = []
290
+ for idx, char in enumerate(selected_chars):
291
+ # Get traits for the character
292
+ traits = ', '.join(char['traits'])
293
+ # Create a description for each character
294
+ # For SDXL models, use the format "[char1 description] AND [char2 description]"
295
+ # Each character's description is enclosed in parentheses
296
+ character_description = f"({traits})"
297
+ character_descriptions.append(character_description)
298
+
299
+ # Join character descriptions appropriately for SDXL models
300
+ if character_descriptions:
301
+ character_descriptions_str = ' AND '.join(character_descriptions)
302
+ prompt_parts.append(character_descriptions_str)
303
+
304
+ # Append selected prompt tags from categories
305
+ if prompt_tags:
306
+ prompt_tags_str = ', '.join(prompt_tags)
307
+ prompt_parts.append(prompt_tags_str)
308
+
309
+ # Load persistent tags
310
+ persistent_tags = data_manager.get_persistent_tags()
311
+ if persistent_tags:
312
+ persistent_tags_str = ', '.join(persistent_tags)
313
+ prompt_parts.append(persistent_tags_str)
314
+
315
+ # Add ending tags
316
+ ending_tags = "source_anime, score_9, score_8_up, score_7_up, masterpiece, best quality, very aesthetic, absurdres, anime artwork, anime style, vibrant, studio anime, highly detailed"
317
+ prompt_parts.append(ending_tags)
318
+
319
+ prompt_string = ', '.join(prompt_parts)
320
+
321
+ return prompt_string
322
+
323
+ # Prepare the list of inputs for the generate_prompt function
324
+ inputs_list = []
325
+ for category_name, var_name in categories:
326
+ inputs_list.append(inputs[f"{var_name}_num"])
327
+ # Add character_select directly to inputs
328
+ inputs_list.extend([character_select, random_characters, num_characters])
329
+
330
+ generate_button.click(generate_prompt, inputs=inputs_list, outputs=prompt_output)
331
+
332
+ # Function to refresh tags display and sliders
333
+ def refresh_tags():
334
+ updates = []
335
+ for category_name, var_name in categories:
336
+ # Reload tags from data_manager
337
+ tags_list = data_manager.get_category_tags(var_name)
338
+ tags_string = ', '.join(tags_list)
339
+ max_tags = len(tags_list)
340
+ if max_tags == 0:
341
+ slider_value = 0
342
+ else:
343
+ slider_value = min(1, max_tags)
344
+ # Update the tag display and slider
345
+ tag_display, tag_num = tag_displays[var_name]
346
+ updates.append(gr.Markdown.update(value=f"**Tags:** {tags_string}"))
347
+ updates.append(gr.Slider.update(maximum=max_tags, value=slider_value))
348
+ return updates
349
+
350
+ # Prepare the outputs list
351
+ outputs = [component for pair in tag_displays.values() for component in pair]
352
+
353
+ # Connect the refresh_tags function to the refresh_tags_button
354
+ refresh_tags_button.click(refresh_tags, outputs=outputs)
355
+
356
+ def character_creation_app(data_manager):
357
  with gr.Tab("Character Creation"):
358
  gr.Markdown("## Create a New Character")
359
  with gr.Row():
360
+ name_input = gr.Textbox(label="Character Name", placeholder="Enter unique character name")
361
+ traits_input = gr.Textbox(label="Traits/Appearance Tags (comma separated)", placeholder="e.g., blue hair, green eyes, tall")
362
  image_input = gr.Image(label="Upload Character Image", type="filepath")
 
363
  gender_input = gr.Radio(choices=["Boy", "Girl"], label="Gender")
364
  save_button = gr.Button("Save Character")
365
  output = gr.Textbox(label="Status", interactive=False)
366
 
367
+ def save_character(name, traits, image_path, gender, characters_container):
368
+ if not name.strip() or not traits.strip() or not gender:
369
+ return "Please enter all fields.", None
370
  # Check for duplicate names
371
  existing_names = [char['name'] for char in data_manager.get_characters()]
372
  if name in existing_names:
373
+ return f"Character with name '{name}' already exists. Please choose a different name.", None
374
 
375
  character = {'name': name, 'traits': traits, 'gender': gender, 'image': image_path}
376
 
377
  data_manager.add_character(character)
378
+ # After adding, re-render the character list
379
+ return f"Character '{name}' saved successfully.", list_characters(data_manager)
380
 
381
+ save_button.click(
382
+ save_character,
383
+ inputs=[name_input, traits_input, image_input, gender_input, gr.State()],
384
+ outputs=[output, "characters_renderer"]
385
+ )
386
 
387
  # Divider
388
  gr.Markdown("---")
 
390
  # Display Existing Characters
391
  gr.Markdown("## Existing Characters")
392
 
393
+ # Renderer for characters
394
+ characters_renderer = gr.Column(label="Characters")
395
 
396
+ def list_characters(data_manager):
397
  characters = data_manager.get_characters()
398
  if not characters:
399
+ return gr.Markdown("No characters created yet.")
400
 
401
  components = []
402
  for char in characters:
403
  with gr.Accordion(label=char['name'], open=False):
404
  with gr.Row():
405
  if char['image']:
 
406
  img_display = gr.Image(value=char['image'], label="Character Image", type="filepath", interactive=False)
407
  else:
408
  img_display = gr.Markdown("**No Image Provided**")
 
420
  edit_interface = gr.Column(visible=False)
421
  with edit_interface:
422
  with gr.Row():
423
+ edit_name = gr.Textbox(label="Character Name", value=char['name'], placeholder="Enter new name")
424
+ edit_traits = gr.Textbox(label="Traits/Appearance Tags (comma separated)", value=', '.join(char['traits']), placeholder="e.g., red hair, blue eyes")
425
  edit_image = gr.Image(label="Upload New Character Image", type="filepath")
426
  edit_gender = gr.Radio(choices=["Boy", "Girl"], label="Gender", value=char['gender'])
427
  save_edit_btn = gr.Button("Save Changes")
428
  save_edit_output = gr.Textbox(label="Edit Status", interactive=False)
429
 
430
  def save_edit(original_name, new_name, new_traits, new_image_path, new_gender):
431
+ if not new_name.strip() or not new_traits.strip() or not new_gender:
432
+ return "Please enter all fields.", None
433
  # If the name has changed, check for duplicates
434
  if new_name != original_name:
435
  existing_names = [c['name'] for c in data_manager.get_characters()]
436
  if new_name in existing_names:
437
+ return f"Character with name '{new_name}' already exists. Please choose a different name.", None
438
  updated_char = {
439
  'name': new_name,
440
  'traits': new_traits,
441
  'gender': new_gender,
442
+ 'image': new_image_path if new_image_path else data_manager.characters[[c['name'] for c in data_manager.get_characters()].index(original_name)]['image']
443
  }
444
  success = data_manager.update_character(original_name, updated_char)
445
  if success:
446
+ return f"Character '{new_name}' updated successfully.", list_characters(data_manager)
 
447
  else:
448
+ return "Failed to update character.", None
449
 
450
  save_edit_btn.click(
451
  save_edit,
452
+ inputs=[gr.State(char['name']), edit_name, edit_traits, edit_image, edit_gender],
453
+ outputs=[save_edit_output, "characters_renderer"]
454
  )
455
 
456
  # Define edit functionality
457
+ def toggle_edit_visibility():
458
+ return gr.update(visible=True)
459
 
460
  edit_btn.click(
461
+ lambda: True,
462
  inputs=None,
463
  outputs=edit_interface
464
  )
465
 
466
  # Define delete functionality
467
  def confirm_delete(char_name):
468
+ return f"Are you sure you want to delete '{char_name}'?", True
469
 
470
+ def perform_delete(char_name, confirm):
471
+ if confirm:
472
+ success = data_manager.delete_character(char_name)
473
+ if success:
474
+ return f"Character '{char_name}' deleted successfully.", list_characters(data_manager)
475
+ else:
476
+ return f"Failed to delete character '{char_name}'.", None
477
+ return "Deletion cancelled.", None
 
 
478
 
479
  delete_btn.click(
480
+ confirm_delete,
481
  inputs=[char['name']],
482
  outputs=[delete_output, delete_output]
483
  )
 
486
  delete_cancel = gr.Button("Cancel Delete", visible=False)
487
 
488
  # Show confirmation buttons when delete is clicked
489
+ def show_delete_buttons(message):
490
+ if "Are you sure" in message:
491
+ return gr.update(visible=True), gr.update(visible=True)
492
+ return gr.update(visible=False), gr.update(visible=False)
493
+
494
  delete_btn.click(
495
+ show_delete_buttons,
496
+ inputs=[delete_output],
497
+ outputs=[delete_confirm, delete_cancel]
498
  )
499
 
500
  # Handle delete confirmation
501
  delete_confirm.click(
502
  perform_delete,
503
+ inputs=[char['name'], gr.Checkbox(label="", value=True)],
504
+ outputs=[delete_output, "characters_renderer"]
505
  )
506
 
507
+ # Handle delete cancellation
508
  delete_cancel.click(
509
+ lambda: ("Deletion cancelled.", None),
510
+ inputs=None,
511
+ outputs=[delete_output, "characters_renderer"]
512
  )
513
+ return components
514
 
515
+ def list_characters_render():
516
+ return list_characters(data_manager)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
517
 
518
+ characters_renderer.render(list_characters(data_manager))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
 
520
  def tags_app(data_manager):
521
  with gr.Tab("Tags"):
 
529
  save_button = gr.Button(f"Save {category_name} Tags")
530
  status_output = gr.Textbox(label="", interactive=False)
531
 
 
532
  def make_save_category_tags_fn(var_name, category_name):
533
  def fn(tags_string):
534
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
 
546
  save_persistent_tags_button = gr.Button("Save Persistent Tags")
547
  persistent_status_output = gr.Textbox(label="", interactive=False)
548
 
549
+ def save_persistent_tags_fn(tags_string):
550
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
551
  data_manager.set_persistent_tags(tags_list)
552
  return "Persistent tags saved successfully."
553
 
554
+ save_persistent_tags_button.click(save_persistent_tags_fn, inputs=persistent_tags_input, outputs=persistent_status_output)
555
 
556
  def main():
557
  data_manager = DataManager(base_dir='/data')
558
  with gr.Blocks() as demo:
559
  with gr.Tabs():
560
+ prompt_generator_app(data_manager)
561
+ character_creation_app(data_manager)
562
+ tags_app(data_manager)
 
 
563
 
564
  demo.launch()
565