Merge pull request #85869 from paulloz/dotnet-warning-out-of-date-properties

.NET: Add a warning in the inspector when properties might be out of sync
This commit is contained in:
Rémi Verschelde 2024-01-03 15:43:41 +01:00
commit 11d1844e66
No known key found for this signature in database
GPG key ID: C3336907360768E1
5 changed files with 136 additions and 3 deletions

View file

@ -788,9 +788,7 @@ static void _find_changed_scripts_for_external_editor(Node *p_base, Node *p_curr
}
void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_for_script) {
if (!bool(EDITOR_GET("text_editor/external/use_external_editor"))) {
return;
}
bool use_external_editor = bool(EDITOR_GET("text_editor/external/use_external_editor"));
ERR_FAIL_NULL(get_tree());
@ -804,6 +802,10 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
for (const Ref<Script> &E : scripts) {
Ref<Script> scr = E;
if (!use_external_editor && !scr->get_language()->overrides_external_editor()) {
continue; // We're not using an external editor for this script.
}
if (p_for_script.is_valid() && p_for_script != scr) {
continue;
}

View file

@ -2246,6 +2246,17 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
} else {
p_instance_to_update->update(propnames, values);
}
} else if (placeholders.size()) {
uint64_t script_modified_time = FileAccess::get_modified_time(get_path());
uint64_t last_valid_build_time = GDMono::get_singleton()->get_project_assembly_modified_time();
if (script_modified_time > last_valid_build_time) {
for (PlaceHolderScriptInstance *instance : placeholders) {
Object *owner = instance->get_owner();
if (owner->get_script_instance() == instance) {
owner->notify_property_list_changed();
}
}
}
}
}
#endif

View file

@ -9,6 +9,7 @@ using System.Linq;
using GodotTools.Build;
using GodotTools.Ides;
using GodotTools.Ides.Rider;
using GodotTools.Inspector;
using GodotTools.Internals;
using GodotTools.ProjectEditor;
using JetBrains.Annotations;
@ -45,6 +46,7 @@ namespace GodotTools
// TODO Use WeakReference once we have proper serialization.
private WeakRef _exportPluginWeak;
private WeakRef _inspectorPluginWeak;
public GodotIdeManager GodotIdeManager { get; private set; }
@ -52,6 +54,8 @@ namespace GodotTools
public bool SkipBuildBeforePlaying { get; set; } = false;
public DateTime LastValidBuildDateTime { get; private set; }
[UsedImplicitly]
private bool CreateProjectSolutionIfNeeded()
{
@ -437,6 +441,21 @@ namespace GodotTools
}
}
private void UpdateLastValidBuildDateTime()
{
var dllName = $"{GodotSharpDirs.ProjectAssemblyName}.dll";
var path = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, "Debug", dllName);
LastValidBuildDateTime = File.GetLastWriteTime(path);
}
private void BuildFinished(BuildResult buildResult)
{
if (buildResult == BuildResult.Success)
{
UpdateLastValidBuildDateTime();
}
}
private void BuildStateChanged()
{
if (_bottomPanelBtn != null)
@ -447,6 +466,8 @@ namespace GodotTools
{
base._EnablePlugin();
UpdateLastValidBuildDateTime();
ProjectSettings.SettingsChanged += GodotSharpDirs.DetermineProjectLocation;
if (Instance != null)
@ -615,6 +636,12 @@ namespace GodotTools
AddExportPlugin(exportPlugin);
_exportPluginWeak = WeakRef(exportPlugin);
// Inspector plugin
var inspectorPlugin = new InspectorPlugin();
AddInspectorPlugin(inspectorPlugin);
_inspectorPluginWeak = WeakRef(inspectorPlugin);
BuildManager.BuildFinished += BuildFinished;
BuildManager.Initialize();
RiderPathManager.Initialize();
@ -627,6 +654,10 @@ namespace GodotTools
base._DisablePlugin();
_editorSettings.SettingsChanged -= OnSettingsChanged;
// Custom signals aren't automatically disconnected currently.
MSBuildPanel.BuildStateChanged -= BuildStateChanged;
BuildManager.BuildFinished -= BuildFinished;
}
public override void _ExitTree()
@ -661,6 +692,13 @@ namespace GodotTools
_exportPluginWeak.Dispose();
}
if (IsInstanceValid(_inspectorPluginWeak))
{
(_inspectorPluginWeak.GetRef().AsGodotObject() as InspectorPlugin)?.Dispose();
_inspectorPluginWeak.Dispose();
}
GodotIdeManager?.Dispose();
}

View file

@ -0,0 +1,37 @@
using Godot;
using GodotTools.Internals;
namespace GodotTools.Inspector
{
public partial class InspectorOutOfSyncWarning : HBoxContainer
{
public override void _Ready()
{
SetAnchorsPreset(LayoutPreset.TopWide);
var iconTexture = GetThemeIcon("StatusWarning", "EditorIcons");
var icon = new TextureRect()
{
Texture = iconTexture,
ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional,
CustomMinimumSize = iconTexture.GetSize(),
};
icon.SizeFlagsVertical = SizeFlags.ShrinkCenter;
var label = new Label()
{
Text = "This inspector might be out of date. Please build the C# project.".TTR(),
AutowrapMode = TextServer.AutowrapMode.WordSmart,
CustomMinimumSize = new Vector2(100f, 0f),
};
label.AddThemeColorOverride("font_color", GetThemeColor("warning_color", "Editor"));
label.SizeFlagsHorizontal = SizeFlags.Fill | SizeFlags.Expand;
AddChild(icon);
AddChild(label);
}
}
}

View file

@ -0,0 +1,45 @@
using System.Collections.Generic;
using Godot;
using GodotTools.Utils;
namespace GodotTools.Inspector
{
public partial class InspectorPlugin : EditorInspectorPlugin
{
public override bool _CanHandle(GodotObject godotObject)
{
foreach (var script in EnumerateScripts(godotObject))
{
if (script is CSharpScript)
{
return true;
}
}
return false;
}
public override void _ParseBegin(GodotObject godotObject)
{
foreach (var script in EnumerateScripts(godotObject))
{
if (script is not CSharpScript) continue;
if (File.GetLastWriteTime(script.ResourcePath) > GodotSharpEditor.Instance.LastValidBuildDateTime)
{
AddCustomControl(new InspectorOutOfSyncWarning());
break;
}
}
}
private static IEnumerable<Script> EnumerateScripts(GodotObject godotObject)
{
var script = godotObject.GetScript().As<Script>();
while (script != null)
{
yield return script;
script = script.GetBaseScript();
}
}
}
}