Merge pull request #38131 from akien-mga/3.2-cherrypicks

Cherry-picks for the 3.2 branch (future 3.2.2) - 3rd batch
This commit is contained in:
Rémi Verschelde 2020-04-23 12:43:10 +02:00 committed by GitHub
commit ed27b7e6b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 261 additions and 104 deletions

View File

@ -828,12 +828,11 @@ public:
static const int HIDDEN = 1;
static const int ON_TOP = 2;
private:
protected:
int current_state;
List<EditorSpatialGizmo *> current_gizmos;
HashMap<String, Vector<Ref<SpatialMaterial> > > materials;
protected:
static void _bind_methods();
virtual bool has_gizmo(Spatial *p_spatial);
virtual Ref<EditorSpatialGizmo> create_gizmo(Spatial *p_spatial);

View File

@ -57,17 +57,18 @@ void TileMapEditor::_notification(int p_what) {
} break;
case NOTIFICATION_ENTER_TREE: {
get_tree()->connect("node_removed", this, "_node_removed");
FALLTHROUGH;
}
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (is_visible_in_tree()) {
_update_palette();
}
FALLTHROUGH;
}
case NOTIFICATION_ENTER_TREE: {
get_tree()->connect("node_removed", this, "_node_removed");
paint_button->set_icon(get_icon("Edit", "EditorIcons"));
bucket_fill_button->set_icon(get_icon("Bucket", "EditorIcons"));
picker_button->set_icon(get_icon("ColorPick", "EditorIcons"));

View File

@ -4075,6 +4075,25 @@ JointSpatialGizmoPlugin::JointSpatialGizmoPlugin() {
create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1)));
create_material("joint_body_a_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1)));
create_material("joint_body_b_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1)));
update_timer = memnew(Timer);
update_timer->set_name("JointGizmoUpdateTimer");
update_timer->set_wait_time(1.0 / 120.0);
update_timer->connect("timeout", this, "incremental_update_gizmos");
update_timer->set_autostart(true);
EditorNode::get_singleton()->call_deferred("add_child", update_timer);
}
void JointSpatialGizmoPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("incremental_update_gizmos"), &JointSpatialGizmoPlugin::incremental_update_gizmos);
}
void JointSpatialGizmoPlugin::incremental_update_gizmos() {
if (!current_gizmos.empty()) {
update_idx++;
update_idx = update_idx % current_gizmos.size();
redraw(current_gizmos[update_idx]);
}
}
bool JointSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) {

View File

@ -390,6 +390,14 @@ class JointSpatialGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(JointSpatialGizmoPlugin, EditorSpatialGizmoPlugin);
Timer *update_timer;
uint64_t update_idx = 0;
void incremental_update_gizmos();
protected:
static void _bind_methods();
public:
bool has_gizmo(Spatial *p_spatial);
String get_name() const;

View File

@ -2683,6 +2683,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) {
LocalVarNode *local_var = branch->body->variables[e->key()];
local_var->assign = e->value();
local_var->set_datatype(local_var->assign->get_datatype());
local_var->assignments++;
IdentifierNode *id2 = alloc_node<IdentifierNode>();
id2->name = local_var->name;
@ -3673,6 +3674,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("A constant named \"" + String(name) + "\" already exists in the outer class scope (at line" + itos(outer_class->constant_expressions[name].expression->line) + ").");
return;
}
for (int i = 0; i < outer_class->variables.size(); i++) {
if (outer_class->variables[i].identifier == name) {
_set_error("A variable named \"" + String(name) + "\" already exists in the outer class scope (at line " + itos(outer_class->variables[i].line) + ").");
return;
}
}
outer_class = outer_class->owner;
}
@ -6568,6 +6575,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
node_type = _reduce_identifier_type(&base_type, member_id->name, op->line, true);
#ifdef DEBUG_ENABLED
if (!node_type.has_type) {
_mark_line_as_unsafe(op->line);
_add_warning(GDScriptWarning::UNSAFE_PROPERTY_ACCESS, op->line, member_id->name.operator String(), base_type.to_string());
}
#endif // DEBUG_ENABLED

View File

@ -0,0 +1,27 @@
using System.IO;
namespace GodotTools.Core
{
public static class FileUtils
{
public static void SaveBackupCopy(string filePath)
{
string backupPathBase = filePath + ".old";
string backupPath = backupPathBase;
const int maxAttempts = 5;
int attempt = 1;
while (File.Exists(backupPath) && attempt <= maxAttempts)
{
backupPath = backupPathBase + "." + (attempt);
attempt++;
}
if (attempt > maxAttempts + 1)
return;
File.Copy(filePath, backupPath, overwrite: true);
}
}
}

View File

@ -31,6 +31,7 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileUtils.cs" />
<Compile Include="ProcessExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StringExtensions.cs" />

View File

@ -153,7 +153,12 @@ EndProject";
var result = regex.Replace(input,m => dict[m.Value]);
if (result != input)
{
// Save a copy of the solution before replacing it
FileUtils.SaveBackupCopy(slnPath);
File.WriteAllText(slnPath, result);
}
}
}
}

View File

@ -9,8 +9,28 @@ using Microsoft.Build.Construction;
namespace GodotTools.ProjectEditor
{
public sealed class MSBuildProject
{
public ProjectRootElement Root { get; }
public bool HasUnsavedChanges => Root.HasUnsavedChanges;
public void Save() => Root.Save();
public MSBuildProject(ProjectRootElement root)
{
Root = root;
}
}
public static class ProjectUtils
{
public static MSBuildProject Open(string path)
{
var root = ProjectRootElement.Open(path);
return root != null ? new MSBuildProject(root) : null;
}
public static void AddItemToProjectChecked(string projectPath, string itemType, string include)
{
var dir = Directory.GetParent(projectPath).FullName;
@ -43,7 +63,6 @@ namespace GodotTools.ProjectEditor
public static void RemoveItemFromProjectChecked(string projectPath, string itemType, string include)
{
var dir = Directory.GetParent(projectPath).FullName;
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
@ -59,8 +78,6 @@ namespace GodotTools.ProjectEditor
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
bool dirty = false;
var oldFolderNormalized = oldFolder.NormalizePath();
var newFolderNormalized = newFolder.NormalizePath();
string absOldFolderNormalized = Path.GetFullPath(oldFolderNormalized).NormalizePath();
@ -71,10 +88,9 @@ namespace GodotTools.ProjectEditor
string absPathNormalized = Path.GetFullPath(item.Include).NormalizePath();
string absNewIncludeNormalized = absNewFolderNormalized + absPathNormalized.Substring(absOldFolderNormalized.Length);
item.Include = absNewIncludeNormalized.RelativeToPath(dir).Replace("/", "\\");
dirty = true;
}
if (dirty)
if (root.HasUnsavedChanges)
root.Save();
}
@ -150,12 +166,9 @@ namespace GodotTools.ProjectEditor
}
/// Simple function to make sure the Api assembly references are configured correctly
public static void FixApiHintPath(string projectPath)
public static void FixApiHintPath(MSBuildProject project)
{
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
bool dirty = false;
var root = project.Root;
void AddPropertyIfNotPresent(string name, string condition, string value)
{
@ -170,7 +183,6 @@ namespace GodotTools.ProjectEditor
}
root.AddProperty(name, value).Condition = " " + condition + " ";
dirty = true;
}
AddPropertyIfNotPresent(name: "ApiConfiguration",
@ -212,7 +224,6 @@ namespace GodotTools.ProjectEditor
}
referenceWithHintPath.AddMetadata("HintPath", hintPath);
dirty = true;
return;
}
@ -221,14 +232,12 @@ namespace GodotTools.ProjectEditor
{
// Found a Reference item without a HintPath
referenceWithoutHintPath.AddMetadata("HintPath", hintPath);
dirty = true;
return;
}
}
// Found no Reference item at all. Add it.
root.AddItem("Reference", referenceName).Condition = " " + condition + " ";
dirty = true;
}
const string coreProjectName = "GodotSharp";
@ -242,17 +251,11 @@ namespace GodotTools.ProjectEditor
SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath);
SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath);
if (dirty)
root.Save();
}
public static void MigrateFromOldConfigNames(string projectPath)
public static void MigrateFromOldConfigNames(MSBuildProject project)
{
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
bool dirty = false;
var root = project.Root;
bool hasGodotProjectGeneratorVersion = false;
bool foundOldConfiguration = false;
@ -267,7 +270,6 @@ namespace GodotTools.ProjectEditor
{
configItem.Value = "Debug";
foundOldConfiguration = true;
dirty = true;
}
}
@ -275,7 +277,6 @@ namespace GodotTools.ProjectEditor
{
root.PropertyGroups.First(g => g.Condition == string.Empty)?
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
dirty = true;
}
if (!foundOldConfiguration)
@ -299,33 +300,21 @@ namespace GodotTools.ProjectEditor
void MigrateConditions(string oldCondition, string newCondition)
{
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition))
{
propertyGroup.Condition = " " + newCondition + " ";
dirty = true;
}
foreach (var propertyGroup in root.PropertyGroups)
{
foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition))
{
prop.Condition = " " + newCondition + " ";
dirty = true;
}
}
foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition))
{
itemGroup.Condition = " " + newCondition + " ";
dirty = true;
}
foreach (var itemGroup in root.ItemGroups)
{
foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition))
{
item.Condition = " " + newCondition + " ";
dirty = true;
}
}
}
@ -340,10 +329,6 @@ namespace GodotTools.ProjectEditor
MigrateConfigurationConditions("Release", "ExportRelease");
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
}
if (dirty)
root.Save();
}
}
}

View File

@ -168,13 +168,13 @@ namespace GodotTools.Export
// Add dependency assemblies
var dependencies = new Godot.Collections.Dictionary<string, string>();
var assemblies = new Godot.Collections.Dictionary<string, string>();
string projectDllName = GodotSharpEditor.ProjectAssemblyName;
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
dependencies[projectDllName] = projectDllSrcPath;
assemblies[projectDllName] = projectDllSrcPath;
if (platform == OS.Platforms.Android)
{
@ -184,15 +184,15 @@ namespace GodotTools.Export
if (!File.Exists(monoAndroidAssemblyPath))
throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
dependencies["Mono.Android"] = monoAndroidAssemblyPath;
assemblies["Mono.Android"] = monoAndroidAssemblyPath;
}
string bclDir = DeterminePlatformBclDir(platform);
var initialDependencies = dependencies.Duplicate();
internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, bclDir, dependencies);
var initialAssemblies = assemblies.Duplicate();
internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
AddI18NAssemblies(dependencies, bclDir);
AddI18NAssemblies(assemblies, bclDir);
string outputDataDir = null;
@ -211,22 +211,34 @@ namespace GodotTools.Export
Directory.CreateDirectory(outputDataGameAssembliesDir);
}
foreach (var dependency in dependencies)
foreach (var assembly in assemblies)
{
void AddToAssembliesDir(string fileSrcPath)
{
string dependSrcPath = dependency.Value;
if (assembliesInsidePck)
{
string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile());
AddFile(dependSrcPath, dependDstPath);
string fileDstPath = Path.Combine(resAssembliesDir, fileSrcPath.GetFile());
AddFile(fileSrcPath, fileDstPath);
}
else
{
string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile());
File.Copy(dependSrcPath, dependDstPath);
Debug.Assert(outputDataDir != null);
string fileDstPath = Path.Combine(outputDataDir, "Assemblies", fileSrcPath.GetFile());
File.Copy(fileSrcPath, fileDstPath);
}
}
string assemblySrcPath = assembly.Value;
string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null);
string pdbSrcPath = assemblyPathWithoutExtension + ".pdb";
AddToAssembliesDir(assemblySrcPath);
if (File.Exists(pdbSrcPath))
AddToAssembliesDir(pdbSrcPath);
}
// AOT compilation
bool aotEnabled = platform == OS.Platforms.iOS || (bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
@ -254,7 +266,7 @@ namespace GodotTools.Export
ToolchainPath = aotToolchainPath
};
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, dependencies);
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
}
}
@ -366,7 +378,7 @@ namespace GodotTools.Export
if (PlatformRequiresCustomBcl(platform))
throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
platformBclDir = typeof(object).Assembly.Location; // Use the one we're running on
platformBclDir = typeof(object).Assembly.Location.GetBaseDir(); // Use the one we're running on
}
}
@ -425,7 +437,7 @@ namespace GodotTools.Export
}
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies,
string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies);
private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
}
}

View File

@ -1,4 +1,5 @@
using Godot;
using GodotTools.Core;
using GodotTools.Export;
using GodotTools.Utils;
using System;
@ -450,13 +451,27 @@ namespace GodotTools
{
// Migrate solution from old configuration names to: Debug, ExportDebug and ExportRelease
DotNetSolution.MigrateFromOldConfigNames(GodotSharpDirs.ProjectSlnPath);
// Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease
ProjectUtils.MigrateFromOldConfigNames(GodotSharpDirs.ProjectCsProjPath);
// Apply the other fixes after configurations are migrated
var msbuildProject = ProjectUtils.Open(GodotSharpDirs.ProjectCsProjPath)
?? throw new Exception("Cannot open C# project");
// NOTE: The order in which changes are made to the project is important
// Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease
ProjectUtils.MigrateFromOldConfigNames(msbuildProject);
// Apply the other fixes only after configurations have been migrated
// Make sure the existing project has Api assembly references configured correctly
ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
ProjectUtils.FixApiHintPath(msbuildProject);
if (msbuildProject.HasUnsavedChanges)
{
// Save a copy of the project before replacing it
FileUtils.SaveBackupCopy(GodotSharpDirs.ProjectCsProjPath);
msbuildProject.Save();
}
}
catch (Exception e)
{

View File

@ -231,14 +231,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje
return err;
}
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies,
MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) {
Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies);
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies);
Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies);
return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
}
MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {

View File

@ -50,13 +50,13 @@ String get_assemblyref_name(MonoImage *p_image, int index) {
return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME]));
}
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies) {
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) {
MonoImage *image = p_assembly->get_image();
for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
String ref_name = get_assemblyref_name(image, i);
if (r_dependencies.has(ref_name))
if (r_assembly_dependencies.has(ref_name))
continue;
GDMonoAssembly *ref_assembly = NULL;
@ -93,17 +93,17 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String>
ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
// Use the path we got from the search. Don't try to get the path from the loaded assembly as we can't trust it will be from the selected BCL dir.
r_dependencies[ref_name] = path;
r_assembly_dependencies[ref_name] = path;
Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_assembly_dependencies);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
}
return OK;
}
Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) {
Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) {
MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
ERR_FAIL_NULL_V(export_domain, FAILED);
_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
@ -113,16 +113,16 @@ Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencie
Vector<String> search_dirs;
GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) {
for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
String assembly_name = *key;
String assembly_path = p_initial_dependencies[*key];
String assembly_path = p_initial_assemblies[*key];
GDMonoAssembly *assembly = NULL;
bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies);
Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies);
if (err != OK)
return err;
}

View File

@ -41,8 +41,8 @@ namespace GodotSharpExport {
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies);
Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
} // namespace GodotSharpExport

View File

@ -128,12 +128,8 @@ void gd_mono_profiler_init() {
}
}
#if defined(DEBUG_ENABLED)
void gd_mono_debug_init() {
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
#ifdef TOOLS_ENABLED
@ -158,6 +154,10 @@ void gd_mono_debug_init() {
return; // Exported games don't use the project settings to setup the debugger agent
#endif
// Debugging enabled
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
// --debugger-agent=help
const char *options[] = {
"--soft-breakpoints",
@ -166,7 +166,6 @@ void gd_mono_debug_init() {
mono_jit_parse_options(2, (char **)options);
}
#endif // defined(DEBUG_ENABLED)
#endif // !defined(JAVASCRIPT_ENABLED)
#if defined(JAVASCRIPT_ENABLED)
@ -174,6 +173,7 @@ MonoDomain *gd_initialize_mono_runtime() {
const char *vfs_prefix = "managed";
int enable_debugging = 0;
// TODO: Provide a way to enable debugging on WASM release builds.
#ifdef DEBUG_ENABLED
enable_debugging = 1;
#endif
@ -184,9 +184,7 @@ MonoDomain *gd_initialize_mono_runtime() {
}
#else
MonoDomain *gd_initialize_mono_runtime() {
#ifdef DEBUG_ENABLED
gd_mono_debug_init();
#endif
#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
// I don't know whether this actually matters or not
@ -1388,6 +1386,9 @@ bool _GodotSharp::is_runtime_initialized() {
void _GodotSharp::_reload_assemblies(bool p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
// This method may be called more than once with `call_deferred`, so we need to check
// again if reloading is needed to avoid reloading multiple times unnecessarily.
if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed())
CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload);
#endif
}

View File

@ -281,6 +281,13 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) {
MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type.");
} break;

View File

@ -132,6 +132,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return Variant::POOL_COLOR_ARRAY;
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
return Variant::ARRAY;
} break;
case MONO_TYPE_CLASS: {
@ -217,6 +221,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type) {
switch (p_array_type.type_encoding) {
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY: {
MonoArrayType *array_type = mono_type_get_array_type(p_array_type.type_class->get_mono_type());
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
r_elem_type = ManagedType::from_class(array_type_class);
return true;
} break;
case MONO_TYPE_GENERICINST: {
MonoReflectionType *array_reftype = mono_type_get_object(mono_domain_get(), p_array_type.type_class->get_mono_type());
@ -511,6 +522,10 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return (MonoObject *)PoolColorArray_to_mono_array(p_var->operator PoolColorArray());
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
return (MonoObject *)Array_to_mono_array(p_var->operator Array(), array_type_class);
ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed array of unmarshallable element type.");
} break;
@ -805,6 +820,10 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return mono_array_to_PoolColorArray((MonoArray *)p_obj);
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
return mono_array_to_Array((MonoArray *)p_obj);
if (p_fail_with_err) {
ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant.");
} else {
@ -970,6 +989,18 @@ MonoArray *Array_to_mono_array(const Array &p_array) {
return ret;
}
MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class) {
int length = p_array.size();
MonoArray *ret = mono_array_new(mono_domain_get(), p_array_type_class->get_mono_ptr(), length);
for (int i = 0; i < length; i++) {
MonoObject *boxed = variant_to_mono_object(p_array[i]);
mono_array_setref(ret, i, boxed);
}
return ret;
}
Array mono_array_to_Array(MonoArray *p_array) {
Array ret;
if (!p_array)

View File

@ -125,6 +125,7 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
// Array
MonoArray *Array_to_mono_array(const Array &p_array);
MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class);
Array mono_array_to_Array(MonoArray *p_array);
// PoolIntArray

View File

@ -90,7 +90,9 @@ android {
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
doNotStrip '**/*.so'
// Should be uncommented for development purpose within Android Studio
// doNotStrip '**/*.so'
}
// Both signing and zip-aligning will be done at export time

View File

@ -26,7 +26,9 @@ android {
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
doNotStrip '**/*.so'
// Should be uncommented for development purpose within Android Studio
// doNotStrip '**/*.so'
}
sourceSets {

View File

@ -950,13 +950,13 @@ void AnimationPlayer::_animation_process(float p_delta) {
play(queued.front()->get());
String new_name = playback.assigned;
queued.pop_front();
if (end_notify)
if (end_notify || playback.seeked)
emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name);
} else {
//stop();
playing = false;
_set_process(false);
if (end_notify)
if (end_notify || playback.seeked)
emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned);
}
end_reached = false;

View File

@ -151,6 +151,8 @@ Files extracted from upstream source:
- `jpgd*.{c,h}`
Patches in the `patches` directory should be re-applied after updates.
## libogg

View File

@ -2126,7 +2126,7 @@ namespace jpgd {
int jpeg_decoder::decode_next_mcu_row()
{
if (setjmp(m_jmp_state))
if (::setjmp(m_jmp_state))
return JPGD_FAILED;
const bool chroma_y_filtering = ((m_flags & cFlagBoxChromaFiltering) == 0) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
@ -3042,7 +3042,7 @@ namespace jpgd {
jpeg_decoder::jpeg_decoder(jpeg_decoder_stream* pStream, uint32_t flags)
{
if (setjmp(m_jmp_state))
if (::setjmp(m_jmp_state))
return;
decode_init(pStream, flags);
}
@ -3055,7 +3055,7 @@ namespace jpgd {
if (m_error_code)
return JPGD_FAILED;
if (setjmp(m_jmp_state))
if (::setjmp(m_jmp_state))
return JPGD_FAILED;
decode_start();

View File

@ -0,0 +1,31 @@
diff --git a/thirdparty/jpeg-compressor/jpgd.cpp b/thirdparty/jpeg-compressor/jpgd.cpp
index a0c494db61..257d0b7574 100644
--- a/thirdparty/jpeg-compressor/jpgd.cpp
+++ b/thirdparty/jpeg-compressor/jpgd.cpp
@@ -2126,7 +2126,7 @@ namespace jpgd {
int jpeg_decoder::decode_next_mcu_row()
{
- if (setjmp(m_jmp_state))
+ if (::setjmp(m_jmp_state))
return JPGD_FAILED;
const bool chroma_y_filtering = ((m_flags & cFlagBoxChromaFiltering) == 0) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
@@ -3042,7 +3042,7 @@ namespace jpgd {
jpeg_decoder::jpeg_decoder(jpeg_decoder_stream* pStream, uint32_t flags)
{
- if (setjmp(m_jmp_state))
+ if (::setjmp(m_jmp_state))
return;
decode_init(pStream, flags);
}
@@ -3055,7 +3055,7 @@ namespace jpgd {
if (m_error_code)
return JPGD_FAILED;
- if (setjmp(m_jmp_state))
+ if (::setjmp(m_jmp_state))
return JPGD_FAILED;
decode_start();