os_test.gd 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. extends Node
  2. @onready var rtl: RichTextLabel = $HBoxContainer/Features
  3. @onready var csharp_test: Node = $CSharpTest
  4. # Line number for alternate line coloring. Incremented by 1 each time a line is added
  5. # (ignoring headers).
  6. var line_count := 0
  7. # Returns a human-readable string from a date and time, date, or time dictionary.
  8. func datetime_to_string(date: Dictionary) -> void:
  9. if (
  10. date.has("year")
  11. and date.has("month")
  12. and date.has("day")
  13. and date.has("hour")
  14. and date.has("minute")
  15. and date.has("second")
  16. ):
  17. # Date and time.
  18. return "{year}-{month}-{day} {hour}:{minute}:{second}".format({
  19. year = str(date.year).pad_zeros(2),
  20. month = str(date.month).pad_zeros(2),
  21. day = str(date.day).pad_zeros(2),
  22. hour = str(date.hour).pad_zeros(2),
  23. minute = str(date.minute).pad_zeros(2),
  24. second = str(date.second).pad_zeros(2),
  25. })
  26. elif date.has("year") and date.has("month") and date.has("day"):
  27. # Date only.
  28. return "{year}-{month}-{day}".format({
  29. year = str(date.year).pad_zeros(2),
  30. month = str(date.month).pad_zeros(2),
  31. day = str(date.day).pad_zeros(2),
  32. })
  33. else:
  34. # Time only.
  35. return "{hour}:{minute}:{second}".format({
  36. hour = str(date.hour).pad_zeros(2),
  37. minute = str(date.minute).pad_zeros(2),
  38. second = str(date.second).pad_zeros(2),
  39. })
  40. func scan_midi_inputs() -> String:
  41. if DisplayServer.get_name() == "headless":
  42. # Workaround for <https://github.com/godotengine/godot/issues/52821>.
  43. return ""
  44. OS.open_midi_inputs()
  45. var devices := ", ".join(OS.get_connected_midi_inputs())
  46. OS.close_midi_inputs()
  47. return devices
  48. func add_header(header: String) -> void:
  49. rtl.append_text("\n[font_size=24][color=#5cf]{header}[/color][/font_size]\n[font_size=1]\n[/font_size]".format({
  50. header = header,
  51. }))
  52. # Also print to the terminal for easy copy-pasting and headless usage.
  53. print_rich("\n[b][u][color=blue]{header}[/color][/u][/b]\n".format({
  54. header = header,
  55. }))
  56. func add_line(key: String, value: Variant) -> void:
  57. line_count += 1
  58. var original_value: Variant = value
  59. if typeof(original_value) == TYPE_BOOL:
  60. # Colorize boolean values.
  61. value = "[color=6f7]true[/color]" if original_value else "[color=#f76]false[/color]"
  62. rtl.append_text("{bgcolor}[color=#9df]{key}:[/color] {value}{bgcolor_end}\n".format({
  63. key = key,
  64. value = value if str(value) != "" else "[color=#fff8](empty)[/color]",
  65. bgcolor = "[bgcolor=#8883]" if line_count % 2 == 0 else "",
  66. bgcolor_end = "[/bgcolor]" if line_count % 2 == 0 else "",
  67. }))
  68. if typeof(original_value) == TYPE_BOOL:
  69. # Colorize boolean values (`print_rich()`-friendly version, using basic colors only).
  70. value = "[color=green]true[/color]" if original_value else "[color=red]false[/color]"
  71. # Also print to the terminal for easy copy-pasting and headless usage.
  72. print_rich("[b][color=cyan]{key}:[/color][/b] {value}".format({
  73. key = key,
  74. value = value if str(value) != "" else "[code](empty)[/code]",
  75. }))
  76. func _ready() -> void:
  77. # Grab focus so that the list can be scrolled (for keyboard/controller-friendly navigation).
  78. rtl.grab_focus()
  79. add_header("Audio")
  80. add_line("Mix rate", "%d Hz" % AudioServer.get_mix_rate())
  81. add_line("Output latency", "%f ms" % (AudioServer.get_output_latency() * 1000))
  82. add_line("Output device list", ", ".join(AudioServer.get_output_device_list()))
  83. add_line("Capture device list", ", ".join(AudioServer.get_input_device_list()))
  84. add_line("Connected MIDI inputs", scan_midi_inputs())
  85. add_header("Date and time")
  86. add_line("Date and time (local)", Time.get_datetime_string_from_system(false, true))
  87. add_line("Date and time (UTC)", Time.get_datetime_string_from_system(true, true))
  88. add_line("Date (local)", Time.get_date_string_from_system(false))
  89. add_line("Date (UTC)", Time.get_date_string_from_system(true))
  90. add_line("Time (local)", Time.get_time_string_from_system(false))
  91. add_line("Time (UTC)", Time.get_time_string_from_system(true))
  92. add_line("Timezone", Time.get_time_zone_from_system())
  93. add_line("UNIX time", Time.get_unix_time_from_system())
  94. add_header("Display")
  95. add_line("Screen count", DisplayServer.get_screen_count())
  96. add_line("DPI", DisplayServer.screen_get_dpi())
  97. add_line("Scale factor", DisplayServer.screen_get_scale())
  98. add_line("Maximum scale factor", DisplayServer.screen_get_max_scale())
  99. add_line("Startup screen position", DisplayServer.screen_get_position())
  100. add_line("Startup screen size", DisplayServer.screen_get_size())
  101. add_line("Startup screen refresh rate", ("%f Hz" % DisplayServer.screen_get_refresh_rate()) if DisplayServer.screen_get_refresh_rate() > 0.0 else "")
  102. add_line("Usable (safe) area rectangle", DisplayServer.get_display_safe_area())
  103. add_line("Screen orientation", [
  104. "Landscape",
  105. "Portrait",
  106. "Landscape (reverse)",
  107. "Portrait (reverse)",
  108. "Landscape (defined by sensor)",
  109. "Portrait (defined by sensor)",
  110. "Defined by sensor",
  111. ][DisplayServer.screen_get_orientation()])
  112. add_header("Engine")
  113. add_line("Version", Engine.get_version_info()["string"])
  114. add_line("Compiled for architecture", Engine.get_architecture_name())
  115. add_line("Command-line arguments", str(OS.get_cmdline_args()))
  116. add_line("Is debug build", OS.is_debug_build())
  117. add_line("Executable path", OS.get_executable_path())
  118. add_line("User data directory", OS.get_user_data_dir())
  119. add_line("Filesystem is persistent", OS.is_userfs_persistent())
  120. add_line("Process ID (PID)", OS.get_process_id())
  121. add_line("Main thread ID", OS.get_main_thread_id())
  122. add_line("Thread caller ID", OS.get_thread_caller_id())
  123. add_line("Memory information", OS.get_memory_info())
  124. add_line("Static memory usage", OS.get_static_memory_usage())
  125. add_line("Static memory peak usage", OS.get_static_memory_peak_usage())
  126. add_header("Environment")
  127. add_line("Value of `PATH`", OS.get_environment("PATH"))
  128. # Check for case-sensitivity behavior across platforms.
  129. add_line("Value of `path`", OS.get_environment("path"))
  130. add_header("Hardware")
  131. add_line("Model name", OS.get_model_name())
  132. add_line("Processor name", OS.get_processor_name())
  133. add_line("Processor count", OS.get_processor_count())
  134. add_line("Device unique ID", OS.get_unique_id())
  135. add_header("Input")
  136. add_line("Device has touch screen", DisplayServer.is_touchscreen_available())
  137. var has_virtual_keyboard := DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD)
  138. add_line("Device has virtual keyboard", has_virtual_keyboard)
  139. if has_virtual_keyboard:
  140. add_line("Virtual keyboard height", DisplayServer.virtual_keyboard_get_height())
  141. add_header("Localization")
  142. add_line("Locale", OS.get_locale())
  143. add_line("Language", OS.get_locale_language())
  144. add_header("Mobile")
  145. add_line("Granted permissions", OS.get_granted_permissions())
  146. add_header(".NET (C#)")
  147. var csharp_enabled := ResourceLoader.exists("res://CSharpTest.cs")
  148. add_line("Mono module enabled", "Yes" if csharp_enabled else "No")
  149. if csharp_enabled:
  150. csharp_test.set_script(load("res://CSharpTest.cs"))
  151. add_line("Operating system", csharp_test.OperatingSystem())
  152. add_line("Platform type", csharp_test.PlatformType())
  153. add_header("Software")
  154. add_line("OS name", OS.get_name())
  155. add_line("OS version", OS.get_version())
  156. add_line("Distribution name", OS.get_distribution_name())
  157. add_line("System dark mode supported", DisplayServer.is_dark_mode_supported())
  158. add_line("System dark mode enabled", DisplayServer.is_dark_mode())
  159. add_line("System accent color", "#%s" % DisplayServer.get_accent_color().to_html())
  160. add_line("System fonts", "%d fonts available" % OS.get_system_fonts().size())
  161. add_line("System font path (\"sans-serif\")", OS.get_system_font_path("sans-serif"))
  162. add_line("System font path (\"sans-serif\") for English text", ", ".join(OS.get_system_font_path_for_text("sans-serif", "Hello")))
  163. add_line("System font path (\"sans-serif\") for Chinese text", ", ".join(OS.get_system_font_path_for_text("sans-serif", "你好")))
  164. add_line("System font path (\"sans-serif\") for Japanese text", ", ".join(OS.get_system_font_path_for_text("sans-serif", "こんにちは")))
  165. add_header("Security")
  166. add_line("Is sandboxed", OS.is_sandboxed())
  167. add_line("Entropy (8 random bytes)", OS.get_entropy(8))
  168. add_line("System CA certificates", ("Available (%d bytes)" % OS.get_system_ca_certificates().length()) if not OS.get_system_ca_certificates().is_empty() else "Not available")
  169. add_header("Engine directories")
  170. add_line("User data", OS.get_data_dir())
  171. add_line("Configuration", OS.get_config_dir())
  172. add_line("Cache", OS.get_cache_dir())
  173. add_header("System directories")
  174. add_line("Desktop", OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP))
  175. add_line("DCIM", OS.get_system_dir(OS.SYSTEM_DIR_DCIM))
  176. add_line("Documents", OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS))
  177. add_line("Downloads", OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS))
  178. add_line("Movies", OS.get_system_dir(OS.SYSTEM_DIR_MOVIES))
  179. add_line("Music", OS.get_system_dir(OS.SYSTEM_DIR_MUSIC))
  180. add_line("Pictures", OS.get_system_dir(OS.SYSTEM_DIR_PICTURES))
  181. add_line("Ringtones", OS.get_system_dir(OS.SYSTEM_DIR_RINGTONES))
  182. add_header("Video")
  183. add_line("Adapter name", RenderingServer.get_video_adapter_name())
  184. add_line("Adapter vendor", RenderingServer.get_video_adapter_vendor())
  185. if ProjectSettings.get_setting_with_override("rendering/renderer/rendering_method") != "gl_compatibility":
  186. # Querying the adapter type isn't supported in Compatibility.
  187. add_line("Adapter type", [
  188. "Other (Unknown)",
  189. "Integrated",
  190. "Discrete",
  191. "Virtual",
  192. "CPU",
  193. ][RenderingServer.get_video_adapter_type()])
  194. add_line("Adapter graphics API version", RenderingServer.get_video_adapter_api_version())
  195. var video_adapter_driver_info := OS.get_video_adapter_driver_info()
  196. if video_adapter_driver_info.size() > 0:
  197. add_line("Adapter driver name", video_adapter_driver_info[0])
  198. if video_adapter_driver_info.size() > 1:
  199. add_line("Adapter driver version", video_adapter_driver_info[1])