No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CharacterEditor.gd 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. tool
  2. extends ScrollContainer
  3. var editor_reference
  4. onready var master_tree = get_node('../MasterTree')
  5. var opened_character_data
  6. var portrait_entry = load("res://addons/dialogic/Editor/CharacterEditor/PortraitEntry.tscn")
  7. onready var nodes = {
  8. 'editor': $HBoxContainer/Container,
  9. 'name': $HBoxContainer/Container/Name/LineEdit,
  10. 'description': $HBoxContainer/Container/Description/TextEdit,
  11. 'file': $HBoxContainer/Container/FileName/LineEdit,
  12. 'color': $HBoxContainer/Container/Color/ColorPickerButton,
  13. 'default_speaker': $HBoxContainer/Container/Actions/DefaultSpeaker,
  14. 'display_name_checkbox': $HBoxContainer/Container/Name/CheckBox,
  15. 'display_name': $HBoxContainer/Container/DisplayName/LineEdit,
  16. 'new_portrait_button': $HBoxContainer/Container/ScrollContainer/VBoxContainer/HBoxContainer/Button,
  17. 'portrait_preview': $HBoxContainer/VBoxContainer/Control/TextureRect,
  18. 'scale': $HBoxContainer/VBoxContainer/HBoxContainer/Scale,
  19. 'offset_x': $HBoxContainer/VBoxContainer/HBoxContainer/OffsetX,
  20. 'offset_y': $HBoxContainer/VBoxContainer/HBoxContainer/OffsetY,
  21. }
  22. func _ready():
  23. nodes['new_portrait_button'].connect('pressed', self, '_on_New_Portrait_Button_pressed')
  24. nodes['display_name_checkbox'].connect('toggled', self, '_on_display_name_toggled')
  25. nodes['name'].connect('text_changed', self, '_on_name_changed')
  26. nodes['color'].connect('color_changed', self, '_on_color_changed')
  27. func _on_display_name_toggled(button_pressed):
  28. $HBoxContainer/Container/DisplayName.visible = button_pressed
  29. func _on_name_changed(value):
  30. var item = master_tree.get_selected()
  31. item.set_text(0, value)
  32. func _on_color_changed(color):
  33. var item = master_tree.get_selected()
  34. item.set_icon_modulate(0, color)
  35. func clear_character_editor():
  36. nodes['file'].text = ''
  37. nodes['name'].text = ''
  38. nodes['description'].text = ''
  39. nodes['color'].color = Color('#ffffff')
  40. nodes['default_speaker'].pressed = false
  41. nodes['display_name_checkbox'].pressed = false
  42. nodes['display_name'].text = ''
  43. nodes['portraits'] = []
  44. nodes['scale'].value = 100
  45. nodes['offset_x'].value = 0
  46. nodes['offset_y'].value = 0
  47. # Clearing portraits
  48. for p in $HBoxContainer/Container/ScrollContainer/VBoxContainer/PortraitList.get_children():
  49. p.queue_free()
  50. nodes['portrait_preview'].texture = null
  51. # Character Creation
  52. func create_character():
  53. var character_file = 'character-' + str(OS.get_unix_time()) + '.json'
  54. var character = {
  55. 'color': '#ffffff',
  56. 'id': character_file,
  57. 'default_speaker': false,
  58. 'portraits': []
  59. }
  60. var directory = Directory.new()
  61. if not directory.dir_exists(DialogicUtil.get_path('WORKING_DIR')):
  62. directory.make_dir(DialogicUtil.get_path('WORKING_DIR'))
  63. if not directory.dir_exists(DialogicUtil.get_path('CHAR_DIR')):
  64. directory.make_dir(DialogicUtil.get_path('CHAR_DIR'))
  65. var file = File.new()
  66. file.open(DialogicUtil.get_path('CHAR_DIR', character_file), File.WRITE)
  67. file.store_line(to_json(character))
  68. file.close()
  69. character['metadata'] = {'file': character_file}
  70. return character
  71. func new_character():
  72. # This event creates and selects the new timeline
  73. master_tree.add_character(create_character()['metadata'], true)
  74. # Saving and Loading
  75. func generate_character_data_to_save():
  76. var default_speaker: bool = nodes['default_speaker'].pressed
  77. var portraits = []
  78. for p in $HBoxContainer/Container/ScrollContainer/VBoxContainer/PortraitList.get_children():
  79. var entry = {}
  80. entry['name'] = p.get_node("NameEdit").text
  81. entry['path'] = p.get_node("PathEdit").text
  82. portraits.append(entry)
  83. var info_to_save = {
  84. 'id': nodes['file'].text,
  85. 'description': nodes['description'].text,
  86. 'color': '#' + nodes['color'].color.to_html(),
  87. 'default_speaker': default_speaker,
  88. 'portraits': portraits,
  89. 'display_name_bool': nodes['display_name_checkbox'].pressed,
  90. 'display_name': nodes['display_name'].text,
  91. 'scale': nodes['scale'].value,
  92. 'offset_x': nodes['offset_x'].value,
  93. 'offset_y': nodes['offset_y'].value,
  94. }
  95. # Adding name later for cases when no name is provided
  96. if nodes['name'].text != '':
  97. info_to_save['name'] = nodes['name'].text
  98. return info_to_save
  99. func save_character():
  100. var path = DialogicUtil.get_path('CHAR_DIR', nodes['file'].text)
  101. var info_to_save = generate_character_data_to_save()
  102. if info_to_save['id']:
  103. var file = File.new()
  104. file.open(path, File.WRITE)
  105. file.store_line(to_json(info_to_save))
  106. file.close()
  107. opened_character_data = info_to_save
  108. func load_character(path):
  109. var data = DialogicUtil.load_json(path)
  110. clear_character_editor()
  111. opened_character_data = data
  112. nodes['file'].text = data['id']
  113. nodes['default_speaker'].pressed = false
  114. if data.has('name'):
  115. nodes['name'].text = data['name']
  116. if data.has('description'):
  117. nodes['description'].text = data['description']
  118. if data.has('color'):
  119. nodes['color'].color = Color(data['color'])
  120. if data.has('default_speaker'):
  121. if data['default_speaker']:
  122. nodes['default_speaker'].pressed = true
  123. if data.has('display_name_bool'):
  124. nodes['display_name_checkbox'].pressed = data['display_name_bool']
  125. if data.has('display_name'):
  126. nodes['display_name'].text = data['display_name']
  127. if data.has('scale'):
  128. nodes['scale'].value = float(data['scale'])
  129. if data.has('offset_x'):
  130. nodes['offset_x'].value = data['offset_x']
  131. nodes['offset_y'].value = data['offset_y']
  132. # Portraits
  133. var default_portrait = create_portrait_entry()
  134. default_portrait.get_node('NameEdit').text = 'Default'
  135. default_portrait.get_node('NameEdit').editable = false
  136. if data.has('portraits'):
  137. for p in data['portraits']:
  138. if p['name'] == 'Default':
  139. default_portrait.get_node('PathEdit').text = p['path']
  140. default_portrait.update_preview(p['path'])
  141. else:
  142. create_portrait_entry(p['name'], p['path'])
  143. # Portraits
  144. func _on_New_Portrait_Button_pressed():
  145. create_portrait_entry('', '', true)
  146. func create_portrait_entry(p_name = '', path = '', grab_focus = false):
  147. var p = portrait_entry.instance()
  148. p.editor_reference = editor_reference
  149. p.image_node = nodes['portrait_preview']
  150. var p_list = $HBoxContainer/Container/ScrollContainer/VBoxContainer/PortraitList
  151. p_list.add_child(p)
  152. if p_name != '':
  153. p.get_node("NameEdit").text = p_name
  154. if path != '':
  155. p.get_node("PathEdit").text = path
  156. if grab_focus:
  157. p.get_node("NameEdit").grab_focus()
  158. p._on_ButtonSelect_pressed()
  159. return p