Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
ca0ce5b46e | |||
3388d68dff | |||
50b603c7dc | |||
f744d99179 | |||
3f1a620102 | |||
bbde1b1f09 | |||
66a89c7925 | |||
f580b1efdc | |||
483071716e |
34
.github/workflows/linux_builds.yml
vendored
34
.github/workflows/linux_builds.yml
vendored
|
@ -12,6 +12,10 @@ jobs:
|
||||||
runs-on: "ubuntu-20.04"
|
runs-on: "ubuntu-20.04"
|
||||||
name: Editor (target=release_debug, tools=yes, tests=yes)
|
name: Editor (target=release_debug, tools=yes, tests=yes)
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
@ -58,18 +62,31 @@ jobs:
|
||||||
python --version
|
python --version
|
||||||
scons --version
|
scons --version
|
||||||
|
|
||||||
|
- name: Set up .NET Sdk
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: '5.0.x'
|
||||||
|
|
||||||
# We should always be explicit with our flags usage here since it's gonna be sure to always set those flags
|
# We should always be explicit with our flags usage here since it's gonna be sure to always set those flags
|
||||||
- name: Compilation
|
- name: Compilation
|
||||||
env:
|
env:
|
||||||
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
||||||
run: |
|
run: |
|
||||||
scons tools=yes tests=yes target=release_debug
|
scons tools=yes tests=yes target=release_debug module_mono_enabled=yes
|
||||||
ls -l bin/
|
ls -l bin/
|
||||||
|
|
||||||
|
- name: Generate C# glue
|
||||||
|
run: |
|
||||||
|
./bin/godot.linuxbsd.opt.tools.64.mono --generate-mono-glue ./modules/mono/glue
|
||||||
|
|
||||||
|
- name: Build .NET solutions
|
||||||
|
run: |
|
||||||
|
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-target=release_debug --godot-platform=linuxbsd
|
||||||
|
|
||||||
# Execute unit tests for the editor
|
# Execute unit tests for the editor
|
||||||
- name: Unit Tests
|
- name: Unit Tests
|
||||||
run: |
|
run: |
|
||||||
./bin/godot.linuxbsd.opt.tools.64 --test
|
./bin/godot.linuxbsd.opt.tools.64.mono --test
|
||||||
|
|
||||||
# Download, unzip and setup SwiftShader library [4466040]
|
# Download, unzip and setup SwiftShader library [4466040]
|
||||||
- name: Download SwiftShader
|
- name: Download SwiftShader
|
||||||
|
@ -85,7 +102,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo "Running --doctool to see if this changes the public API without updating the documentation."
|
echo "Running --doctool to see if this changes the public API without updating the documentation."
|
||||||
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
|
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
|
||||||
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.opt.tools.64 --doctool . 2>&1 > /dev/null || true
|
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.opt.tools.64.mono --doctool . 2>&1 > /dev/null || true
|
||||||
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
|
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
|
@ -190,6 +207,10 @@ jobs:
|
||||||
runs-on: "ubuntu-20.04"
|
runs-on: "ubuntu-20.04"
|
||||||
name: Template w/ Mono (target=release, tools=no)
|
name: Template w/ Mono (target=release, tools=no)
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
@ -236,11 +257,16 @@ jobs:
|
||||||
python --version
|
python --version
|
||||||
scons --version
|
scons --version
|
||||||
|
|
||||||
|
- name: Set up .NET Sdk
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: '5.0.x'
|
||||||
|
|
||||||
- name: Compilation
|
- name: Compilation
|
||||||
env:
|
env:
|
||||||
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
||||||
run: |
|
run: |
|
||||||
scons target=release tools=no module_mono_enabled=yes mono_glue=no
|
scons target=release tools=no module_mono_enabled=yes
|
||||||
ls -l bin/
|
ls -l bin/
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
|
|
|
@ -1293,20 +1293,6 @@
|
||||||
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60">
|
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60">
|
||||||
This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
|
This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
|
||||||
</member>
|
</member>
|
||||||
<member name="mono/debugger_agent/port" type="int" setter="" getter="" default="23685">
|
|
||||||
</member>
|
|
||||||
<member name="mono/debugger_agent/wait_for_debugger" type="bool" setter="" getter="" default="false">
|
|
||||||
</member>
|
|
||||||
<member name="mono/debugger_agent/wait_timeout" type="int" setter="" getter="" default="3000">
|
|
||||||
</member>
|
|
||||||
<member name="mono/profiler/args" type="String" setter="" getter="" default=""log:calls,alloc,sample,output=output.mlpd"">
|
|
||||||
</member>
|
|
||||||
<member name="mono/profiler/enabled" type="bool" setter="" getter="" default="false">
|
|
||||||
</member>
|
|
||||||
<member name="mono/project/auto_update_project" type="bool" setter="" getter="" default="true">
|
|
||||||
</member>
|
|
||||||
<member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0">
|
|
||||||
</member>
|
|
||||||
<member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10">
|
<member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10">
|
||||||
Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size].
|
Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size].
|
||||||
</member>
|
</member>
|
||||||
|
|
|
@ -1944,20 +1944,6 @@ bool Main::start() {
|
||||||
ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
|
ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MODULE_MONO_ENABLED
|
|
||||||
// Hack to define Mono-specific project settings even on non-Mono builds,
|
|
||||||
// so that we don't lose their descriptions and default values in DocData.
|
|
||||||
// Default values should be synced with mono_gd/gd_mono.cpp.
|
|
||||||
GLOBAL_DEF("mono/debugger_agent/port", 23685);
|
|
||||||
GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
|
|
||||||
GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
|
|
||||||
GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd");
|
|
||||||
GLOBAL_DEF("mono/profiler/enabled", false);
|
|
||||||
GLOBAL_DEF("mono/unhandled_exception_policy", 0);
|
|
||||||
// From editor/csharp_project.cpp.
|
|
||||||
GLOBAL_DEF("mono/project/auto_update_project", true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DocTools doc;
|
DocTools doc;
|
||||||
doc.generate(doc_base);
|
doc.generate(doc_base);
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,6 @@ Import("env_modules")
|
||||||
|
|
||||||
env_mono = env_modules.Clone()
|
env_mono = env_modules.Clone()
|
||||||
|
|
||||||
if env_mono["tools"]:
|
|
||||||
# NOTE: It is safe to generate this file here, since this is still executed serially
|
|
||||||
import build_scripts.gen_cs_glue_version as gen_cs_glue_version
|
|
||||||
|
|
||||||
gen_cs_glue_version.generate_header("glue/GodotSharp", "glue/cs_glue_version.gen.h")
|
|
||||||
|
|
||||||
# Glue sources
|
|
||||||
if env_mono["mono_glue"]:
|
|
||||||
env_mono.Append(CPPDEFINES=["MONO_GLUE_ENABLED"])
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
if not os.path.isfile("glue/mono_glue.gen.cpp"):
|
|
||||||
raise RuntimeError("Mono glue sources not found. Did you forget to run '--generate-mono-glue'?")
|
|
||||||
|
|
||||||
if env_mono["tools"] or env_mono["target"] != "release":
|
if env_mono["tools"] or env_mono["target"] != "release":
|
||||||
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
||||||
|
|
||||||
|
@ -29,22 +14,6 @@ if env_mono["tools"] or env_mono["target"] != "release":
|
||||||
|
|
||||||
mono_configure.configure(env, env_mono)
|
mono_configure.configure(env, env_mono)
|
||||||
|
|
||||||
if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]:
|
|
||||||
# Build Godot API solution
|
|
||||||
import build_scripts.api_solution_build as api_solution_build
|
|
||||||
|
|
||||||
api_sln_cmd = api_solution_build.build(env_mono)
|
|
||||||
|
|
||||||
# Build GodotTools
|
|
||||||
import build_scripts.godot_tools_build as godot_tools_build
|
|
||||||
|
|
||||||
godot_tools_build.build(env_mono, api_sln_cmd)
|
|
||||||
|
|
||||||
# Build Godot.NET.Sdk
|
|
||||||
import build_scripts.godot_net_sdk_build as godot_net_sdk_build
|
|
||||||
|
|
||||||
godot_net_sdk_build.build(env_mono)
|
|
||||||
|
|
||||||
# Add sources
|
# Add sources
|
||||||
|
|
||||||
env_mono.add_source_files(env.modules_sources, "*.cpp")
|
env_mono.add_source_files(env.modules_sources, "*.cpp")
|
||||||
|
@ -60,3 +29,5 @@ if env["platform"] in ["osx", "iphone"]:
|
||||||
|
|
||||||
if env["tools"]:
|
if env["tools"]:
|
||||||
env_mono.add_source_files(env.modules_sources, "editor/*.cpp")
|
env_mono.add_source_files(env.modules_sources, "editor/*.cpp")
|
||||||
|
|
||||||
|
env_mono.Prepend(CPPPATH=["#modules/gdnative/include/"])
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
# Build the Godot API solution
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from SCons.Script import Dir
|
|
||||||
|
|
||||||
|
|
||||||
def build_api_solution(source, target, env):
|
|
||||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
|
||||||
|
|
||||||
module_dir = env["module_dir"]
|
|
||||||
|
|
||||||
solution_path = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
|
|
||||||
|
|
||||||
build_config = env["solution_build_config"]
|
|
||||||
|
|
||||||
extra_msbuild_args = ["/p:NoWarn=1591"] # Ignore missing documentation warnings
|
|
||||||
|
|
||||||
from .solution_builder import build_solution
|
|
||||||
|
|
||||||
build_solution(env, solution_path, build_config, extra_msbuild_args=extra_msbuild_args)
|
|
||||||
|
|
||||||
# Copy targets
|
|
||||||
|
|
||||||
core_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharp", "bin", build_config))
|
|
||||||
editor_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharpEditor", "bin", build_config))
|
|
||||||
|
|
||||||
dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir))
|
|
||||||
|
|
||||||
if not os.path.isdir(dst_dir):
|
|
||||||
assert not os.path.isfile(dst_dir)
|
|
||||||
os.makedirs(dst_dir)
|
|
||||||
|
|
||||||
def copy_target(target_path):
|
|
||||||
from shutil import copy
|
|
||||||
|
|
||||||
filename = os.path.basename(target_path)
|
|
||||||
|
|
||||||
src_path = os.path.join(core_src_dir, filename)
|
|
||||||
if not os.path.isfile(src_path):
|
|
||||||
src_path = os.path.join(editor_src_dir, filename)
|
|
||||||
|
|
||||||
copy(src_path, target_path)
|
|
||||||
|
|
||||||
for scons_target in target:
|
|
||||||
copy_target(str(scons_target))
|
|
||||||
|
|
||||||
|
|
||||||
def build(env_mono):
|
|
||||||
assert env_mono["tools"]
|
|
||||||
|
|
||||||
target_filenames = [
|
|
||||||
"GodotSharp.dll",
|
|
||||||
"GodotSharp.pdb",
|
|
||||||
"GodotSharp.xml",
|
|
||||||
"GodotSharpEditor.dll",
|
|
||||||
"GodotSharpEditor.pdb",
|
|
||||||
"GodotSharpEditor.xml",
|
|
||||||
]
|
|
||||||
|
|
||||||
depend_cmd = []
|
|
||||||
|
|
||||||
for build_config in ["Debug", "Release"]:
|
|
||||||
output_dir = Dir("#bin").abspath
|
|
||||||
editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config)
|
|
||||||
|
|
||||||
targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames]
|
|
||||||
|
|
||||||
cmd = env_mono.CommandNoCache(
|
|
||||||
targets, depend_cmd, build_api_solution, module_dir=os.getcwd(), solution_build_config=build_config
|
|
||||||
)
|
|
||||||
env_mono.AlwaysBuild(cmd)
|
|
||||||
|
|
||||||
# Make the Release build of the API solution depend on the Debug build.
|
|
||||||
# We do this in order to prevent SCons from building them in parallel,
|
|
||||||
# which can freak out MSBuild. In many cases, one of the builds would
|
|
||||||
# hang indefinitely requiring a key to be pressed for it to continue.
|
|
||||||
depend_cmd = cmd
|
|
||||||
|
|
||||||
return depend_cmd
|
|
307
modules/mono/build_scripts/build_assemblies.py
Executable file
307
modules/mono/build_scripts/build_assemblies.py
Executable file
|
@ -0,0 +1,307 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
def find_dotnet_cli():
|
||||||
|
if os.name == "nt":
|
||||||
|
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||||
|
hint_dir = hint_dir.strip('"')
|
||||||
|
hint_path = os.path.join(hint_dir, "dotnet")
|
||||||
|
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||||
|
return hint_path
|
||||||
|
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||||
|
return hint_path + ".exe"
|
||||||
|
else:
|
||||||
|
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||||
|
hint_dir = hint_dir.strip('"')
|
||||||
|
hint_path = os.path.join(hint_dir, "dotnet")
|
||||||
|
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||||
|
return hint_path
|
||||||
|
|
||||||
|
|
||||||
|
def find_msbuild_standalone_windows():
|
||||||
|
msbuild_tools_path = find_msbuild_tools_path_reg()
|
||||||
|
|
||||||
|
if msbuild_tools_path:
|
||||||
|
return os.path.join(msbuild_tools_path, "MSBuild.exe")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_msbuild_mono_windows(mono_prefix):
|
||||||
|
assert mono_prefix is not None
|
||||||
|
|
||||||
|
mono_bin_dir = os.path.join(mono_prefix, "bin")
|
||||||
|
msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat")
|
||||||
|
|
||||||
|
if os.path.isfile(msbuild_mono):
|
||||||
|
return msbuild_mono
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_msbuild_mono_unix():
|
||||||
|
import sys
|
||||||
|
|
||||||
|
hint_dirs = []
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
hint_dirs[:0] = [
|
||||||
|
"/Library/Frameworks/Mono.framework/Versions/Current/bin",
|
||||||
|
"/usr/local/var/homebrew/linked/mono/bin",
|
||||||
|
]
|
||||||
|
|
||||||
|
for hint_dir in hint_dirs:
|
||||||
|
hint_path = os.path.join(hint_dir, "msbuild")
|
||||||
|
if os.path.isfile(hint_path):
|
||||||
|
return hint_path
|
||||||
|
elif os.path.isfile(hint_path + ".exe"):
|
||||||
|
return hint_path + ".exe"
|
||||||
|
|
||||||
|
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||||
|
hint_dir = hint_dir.strip('"')
|
||||||
|
hint_path = os.path.join(hint_dir, "msbuild")
|
||||||
|
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||||
|
return hint_path
|
||||||
|
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||||
|
return hint_path + ".exe"
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_msbuild_tools_path_reg():
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
program_files = os.getenv("PROGRAMFILES(X86)")
|
||||||
|
if not program_files:
|
||||||
|
program_files = os.getenv("PROGRAMFILES")
|
||||||
|
vswhere = os.path.join(program_files, "Microsoft Visual Studio", "Installer", "vswhere.exe")
|
||||||
|
|
||||||
|
vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
parts = line.decode("utf-8").split(":", 1)
|
||||||
|
|
||||||
|
if len(parts) < 2 or parts[0] != "installationPath":
|
||||||
|
continue
|
||||||
|
|
||||||
|
val = parts[1].strip()
|
||||||
|
|
||||||
|
if not val:
|
||||||
|
raise ValueError("Value of `installationPath` entry is empty")
|
||||||
|
|
||||||
|
# Since VS2019, the directory is simply named "Current"
|
||||||
|
msbuild_dir = os.path.join(val, "MSBuild", "Current", "Bin")
|
||||||
|
if os.path.isdir(msbuild_dir):
|
||||||
|
return msbuild_dir
|
||||||
|
|
||||||
|
# Directory name "15.0" is used in VS 2017
|
||||||
|
return os.path.join(val, "MSBuild", "15.0", "Bin")
|
||||||
|
|
||||||
|
raise ValueError("Cannot find `installationPath` entry")
|
||||||
|
except ValueError as e:
|
||||||
|
print("Error reading output from vswhere: " + str(e))
|
||||||
|
except OSError:
|
||||||
|
pass # Fine, vswhere not found
|
||||||
|
except (subprocess.CalledProcessError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ToolsLocation:
|
||||||
|
dotnet_cli: str = ""
|
||||||
|
msbuild_standalone: str = ""
|
||||||
|
msbuild_mono: str = ""
|
||||||
|
mono_bin_dir: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
def find_any_msbuild_tool(mono_prefix):
|
||||||
|
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild
|
||||||
|
|
||||||
|
# Find dotnet CLI
|
||||||
|
dotnet_cli = find_dotnet_cli()
|
||||||
|
if dotnet_cli:
|
||||||
|
return ToolsLocation(dotnet_cli=dotnet_cli)
|
||||||
|
|
||||||
|
# Find standalone MSBuild
|
||||||
|
if os.name == "nt":
|
||||||
|
msbuild_standalone = find_msbuild_standalone_windows()
|
||||||
|
if msbuild_standalone:
|
||||||
|
return ToolsLocation(msbuild_standalone=msbuild_standalone)
|
||||||
|
|
||||||
|
if mono_prefix:
|
||||||
|
# Find Mono's MSBuild
|
||||||
|
if os.name == "nt":
|
||||||
|
msbuild_mono = find_msbuild_mono_windows(mono_prefix)
|
||||||
|
if msbuild_mono:
|
||||||
|
return ToolsLocation(msbuild_mono=msbuild_mono)
|
||||||
|
else:
|
||||||
|
msbuild_mono = find_msbuild_mono_unix()
|
||||||
|
if msbuild_mono:
|
||||||
|
return ToolsLocation(msbuild_mono=msbuild_mono)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
|
||||||
|
if msbuild_args is None:
|
||||||
|
msbuild_args = []
|
||||||
|
|
||||||
|
using_msbuild_mono = False
|
||||||
|
|
||||||
|
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild
|
||||||
|
if tools.dotnet_cli:
|
||||||
|
args = [tools.dotnet_cli, "msbuild"]
|
||||||
|
elif tools.msbuild_standalone:
|
||||||
|
args = [tools.msbuild_standalone]
|
||||||
|
elif tools.msbuild_mono:
|
||||||
|
args = [tools.msbuild_mono]
|
||||||
|
using_msbuild_mono = True
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Path to MSBuild or dotnet CLI not provided.")
|
||||||
|
|
||||||
|
args += [sln]
|
||||||
|
|
||||||
|
if len(msbuild_args) > 0:
|
||||||
|
args += msbuild_args
|
||||||
|
|
||||||
|
print("Running MSBuild: ", " ".join(shlex.quote(arg) for arg in args), flush=True)
|
||||||
|
|
||||||
|
msbuild_env = os.environ.copy()
|
||||||
|
|
||||||
|
# Needed when running from Developer Command Prompt for VS
|
||||||
|
if "PLATFORM" in msbuild_env:
|
||||||
|
del msbuild_env["PLATFORM"]
|
||||||
|
|
||||||
|
if using_msbuild_mono:
|
||||||
|
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
|
||||||
|
# building with Mono's MSBuild. They must point to the batch files
|
||||||
|
# in Mono's bin directory to make sure they are executed with Mono.
|
||||||
|
msbuild_env.update(
|
||||||
|
{
|
||||||
|
"CscToolExe": os.path.join(tools.mono_bin_dir, "csc.bat"),
|
||||||
|
"VbcToolExe": os.path.join(tools.mono_bin_dir, "vbc.bat"),
|
||||||
|
"FscToolExe": os.path.join(tools.mono_bin_dir, "fsharpc.bat"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return subprocess.call(args, env=msbuild_env)
|
||||||
|
|
||||||
|
|
||||||
|
def build_godot_api(msbuild_tool, module_dir, output_dir):
|
||||||
|
target_filenames = [
|
||||||
|
"GodotSharp.dll",
|
||||||
|
"GodotSharp.pdb",
|
||||||
|
"GodotSharp.xml",
|
||||||
|
"GodotSharpEditor.dll",
|
||||||
|
"GodotSharpEditor.pdb",
|
||||||
|
"GodotSharpEditor.xml",
|
||||||
|
"GodotPlugins.dll",
|
||||||
|
"GodotPlugins.pdb",
|
||||||
|
"GodotPlugins.runtimeconfig.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
for build_config in ["Debug", "Release"]:
|
||||||
|
editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config)
|
||||||
|
|
||||||
|
targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames]
|
||||||
|
|
||||||
|
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
|
||||||
|
exit_code = run_msbuild(
|
||||||
|
msbuild_tool,
|
||||||
|
sln=sln,
|
||||||
|
msbuild_args=["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"],
|
||||||
|
)
|
||||||
|
if exit_code != 0:
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
# Copy targets
|
||||||
|
|
||||||
|
core_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharp", "bin", build_config))
|
||||||
|
editor_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharpEditor", "bin", build_config))
|
||||||
|
plugins_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotPlugins", "bin", build_config, "net5.0"))
|
||||||
|
|
||||||
|
if not os.path.isdir(editor_api_dir):
|
||||||
|
assert not os.path.isfile(editor_api_dir)
|
||||||
|
os.makedirs(editor_api_dir)
|
||||||
|
|
||||||
|
def copy_target(target_path):
|
||||||
|
from shutil import copy
|
||||||
|
|
||||||
|
filename = os.path.basename(target_path)
|
||||||
|
|
||||||
|
src_path = os.path.join(core_src_dir, filename)
|
||||||
|
if not os.path.isfile(src_path):
|
||||||
|
src_path = os.path.join(editor_src_dir, filename)
|
||||||
|
if not os.path.isfile(src_path):
|
||||||
|
src_path = os.path.join(plugins_src_dir, filename)
|
||||||
|
|
||||||
|
print(f"Copying assembly to {target_path}...")
|
||||||
|
copy(src_path, target_path)
|
||||||
|
|
||||||
|
for scons_target in targets:
|
||||||
|
copy_target(scons_target)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_all(msbuild_tool, module_dir, output_dir, godot_target, godot_platform):
|
||||||
|
# Godot API
|
||||||
|
exit_code = build_godot_api(msbuild_tool, module_dir, output_dir)
|
||||||
|
if exit_code != 0:
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
# GodotTools
|
||||||
|
sln = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln")
|
||||||
|
args = ["/restore", "/t:Build", "/p:Configuration=" + ("Debug" if godot_target == "debug" else "Release")] + (
|
||||||
|
["/p:GodotPlatform=" + godot_platform] if godot_platform else []
|
||||||
|
)
|
||||||
|
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
|
||||||
|
if exit_code != 0:
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
# Godot.NET.Sdk
|
||||||
|
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
|
||||||
|
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=["/restore", "/t:Build", "/p:Configuration=Release"])
|
||||||
|
if exit_code != 0:
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Builds all Godot .NET solutions")
|
||||||
|
parser.add_argument("--godot-output-dir", type=str, required=True)
|
||||||
|
parser.add_argument("--godot-target", choices=["debug", "release_debug", "release"], type=str, required=True)
|
||||||
|
parser.add_argument("--godot-platform", type=str, default="")
|
||||||
|
parser.add_argument("--mono-prefix", type=str, default="")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
this_script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
module_dir = os.path.abspath(os.path.join(this_script_dir, os.pardir))
|
||||||
|
|
||||||
|
output_dir = os.path.abspath(args.godot_output_dir)
|
||||||
|
|
||||||
|
msbuild_tool = find_any_msbuild_tool(args.mono_prefix)
|
||||||
|
|
||||||
|
if msbuild_tool is None:
|
||||||
|
print("Unable to find MSBuild")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
exit_code = build_all(msbuild_tool, module_dir, output_dir, args.godot_target, args.godot_platform)
|
||||||
|
sys.exit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,20 +0,0 @@
|
||||||
def generate_header(solution_dir, version_header_dst):
|
|
||||||
import os
|
|
||||||
|
|
||||||
latest_mtime = 0
|
|
||||||
for root, dirs, files in os.walk(solution_dir, topdown=True):
|
|
||||||
dirs[:] = [d for d in dirs if d not in ["Generated"]] # Ignored generated files
|
|
||||||
files = [f for f in files if f.endswith(".cs")]
|
|
||||||
for file in files:
|
|
||||||
filepath = os.path.join(root, file)
|
|
||||||
mtime = os.path.getmtime(filepath)
|
|
||||||
latest_mtime = mtime if mtime > latest_mtime else latest_mtime
|
|
||||||
|
|
||||||
glue_version = int(latest_mtime) # The latest modified time will do for now
|
|
||||||
|
|
||||||
with open(version_header_dst, "w") as version_header:
|
|
||||||
version_header.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
|
||||||
version_header.write("#ifndef CS_GLUE_VERSION_H\n")
|
|
||||||
version_header.write("#define CS_GLUE_VERSION_H\n\n")
|
|
||||||
version_header.write("#define CS_GLUE_VERSION UINT32_C(" + str(glue_version) + ")\n")
|
|
||||||
version_header.write("\n#endif // CS_GLUE_VERSION_H\n")
|
|
|
@ -1,55 +0,0 @@
|
||||||
# Build Godot.NET.Sdk solution
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from SCons.Script import Dir
|
|
||||||
|
|
||||||
|
|
||||||
def build_godot_net_sdk(source, target, env):
|
|
||||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
|
||||||
|
|
||||||
module_dir = env["module_dir"]
|
|
||||||
|
|
||||||
solution_path = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
|
|
||||||
build_config = "Release"
|
|
||||||
|
|
||||||
from .solution_builder import build_solution
|
|
||||||
|
|
||||||
extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]]
|
|
||||||
|
|
||||||
build_solution(env, solution_path, build_config, extra_msbuild_args)
|
|
||||||
# No need to copy targets. The Godot.NET.Sdk csproj takes care of copying them.
|
|
||||||
|
|
||||||
|
|
||||||
def get_nupkgs_versions(props_file):
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
tree = ET.parse(props_file)
|
|
||||||
root = tree.getroot()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"Godot.NET.Sdk": root.find("./PropertyGroup/PackageVersion_Godot_NET_Sdk").text.strip(),
|
|
||||||
"Godot.SourceGenerators": root.find("./PropertyGroup/PackageVersion_Godot_SourceGenerators").text.strip(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def build(env_mono):
|
|
||||||
assert env_mono["tools"]
|
|
||||||
|
|
||||||
output_dir = Dir("#bin").abspath
|
|
||||||
editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools")
|
|
||||||
nupkgs_dir = os.path.join(editor_tools_dir, "nupkgs")
|
|
||||||
|
|
||||||
module_dir = os.getcwd()
|
|
||||||
|
|
||||||
nupkgs_versions = get_nupkgs_versions(os.path.join(module_dir, "SdkPackageVersions.props"))
|
|
||||||
|
|
||||||
target_filenames = [
|
|
||||||
"Godot.NET.Sdk.%s.nupkg" % nupkgs_versions["Godot.NET.Sdk"],
|
|
||||||
"Godot.SourceGenerators.%s.nupkg" % nupkgs_versions["Godot.SourceGenerators"],
|
|
||||||
]
|
|
||||||
|
|
||||||
targets = [os.path.join(nupkgs_dir, filename) for filename in target_filenames]
|
|
||||||
|
|
||||||
cmd = env_mono.CommandNoCache(targets, [], build_godot_net_sdk, module_dir=module_dir)
|
|
||||||
env_mono.AlwaysBuild(cmd)
|
|
|
@ -1,38 +0,0 @@
|
||||||
# Build GodotTools solution
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from SCons.Script import Dir
|
|
||||||
|
|
||||||
|
|
||||||
def build_godot_tools(source, target, env):
|
|
||||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
|
||||||
|
|
||||||
module_dir = env["module_dir"]
|
|
||||||
|
|
||||||
solution_path = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln")
|
|
||||||
build_config = "Debug" if env["target"] == "debug" else "Release"
|
|
||||||
|
|
||||||
from .solution_builder import build_solution
|
|
||||||
|
|
||||||
extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]]
|
|
||||||
|
|
||||||
build_solution(env, solution_path, build_config, extra_msbuild_args)
|
|
||||||
# No need to copy targets. The GodotTools csproj takes care of copying them.
|
|
||||||
|
|
||||||
|
|
||||||
def build(env_mono, api_sln_cmd):
|
|
||||||
assert env_mono["tools"]
|
|
||||||
|
|
||||||
output_dir = Dir("#bin").abspath
|
|
||||||
editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools")
|
|
||||||
|
|
||||||
target_filenames = ["GodotTools.dll"]
|
|
||||||
|
|
||||||
if env_mono["target"] == "debug":
|
|
||||||
target_filenames += ["GodotTools.pdb"]
|
|
||||||
|
|
||||||
targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames]
|
|
||||||
|
|
||||||
cmd = env_mono.CommandNoCache(targets, api_sln_cmd, build_godot_tools, module_dir=os.getcwd())
|
|
||||||
env_mono.AlwaysBuild(cmd)
|
|
|
@ -1,53 +0,0 @@
|
||||||
def generate_compressed_config(config_src, output_dir):
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
# Source file
|
|
||||||
with open(os.path.join(output_dir, "android_mono_config.gen.cpp"), "w") as cpp:
|
|
||||||
with open(config_src, "rb") as f:
|
|
||||||
buf = f.read()
|
|
||||||
decompr_size = len(buf)
|
|
||||||
import zlib
|
|
||||||
|
|
||||||
buf = zlib.compress(buf)
|
|
||||||
compr_size = len(buf)
|
|
||||||
|
|
||||||
bytes_seq_str = ""
|
|
||||||
for i, buf_idx in enumerate(range(compr_size)):
|
|
||||||
if i > 0:
|
|
||||||
bytes_seq_str += ", "
|
|
||||||
bytes_seq_str += str(buf[buf_idx])
|
|
||||||
|
|
||||||
cpp.write(
|
|
||||||
"""/* THIS FILE IS GENERATED DO NOT EDIT */
|
|
||||||
#include "android_mono_config.h"
|
|
||||||
|
|
||||||
#ifdef ANDROID_ENABLED
|
|
||||||
|
|
||||||
#include "core/io/compression.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// config
|
|
||||||
static const int config_compressed_size = %d;
|
|
||||||
static const int config_uncompressed_size = %d;
|
|
||||||
static const unsigned char config_compressed_data[] = { %s };
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
String get_godot_android_mono_config() {
|
|
||||||
Vector<uint8_t> data;
|
|
||||||
data.resize(config_uncompressed_size);
|
|
||||||
uint8_t* w = data.ptrw();
|
|
||||||
Compression::decompress(w, config_uncompressed_size, config_compressed_data,
|
|
||||||
config_compressed_size, Compression::MODE_DEFLATE);
|
|
||||||
String s;
|
|
||||||
if (s.parse_utf8((const char *)w, data.size())) {
|
|
||||||
ERR_FAIL_V(String());
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ANDROID_ENABLED
|
|
||||||
"""
|
|
||||||
% (compr_size, decompr_size, bytes_seq_str)
|
|
||||||
)
|
|
|
@ -1,28 +0,0 @@
|
||||||
<configuration>
|
|
||||||
<dllmap wordsize="32" dll="i:cygwin1.dll" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="i:cygwin1.dll" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap wordsize="32" dll="libc" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="libc" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap wordsize="32" dll="intl" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="intl" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap wordsize="32" dll="libintl" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="libintl" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.so" />
|
|
||||||
<dllmap dll="System.Native" target="libmono-native.so" />
|
|
||||||
<dllmap wordsize="32" dll="i:msvcrt" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="i:msvcrt" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap wordsize="32" dll="i:msvcrt.dll" target="/system/lib/libc.so" />
|
|
||||||
<dllmap wordsize="64" dll="i:msvcrt.dll" target="/system/lib64/libc.so" />
|
|
||||||
<dllmap wordsize="32" dll="sqlite" target="/system/lib/libsqlite.so" />
|
|
||||||
<dllmap wordsize="64" dll="sqlite" target="/system/lib64/libsqlite.so" />
|
|
||||||
<dllmap wordsize="32" dll="sqlite3" target="/system/lib/libsqlite.so" />
|
|
||||||
<dllmap wordsize="64" dll="sqlite3" target="/system/lib64/libsqlite.so" />
|
|
||||||
<dllmap wordsize="32" dll="liblog" target="/system/lib/liblog.so" />
|
|
||||||
<dllmap wordsize="64" dll="liblog" target="/system/lib64/liblog.so" />
|
|
||||||
<dllmap dll="i:kernel32.dll">
|
|
||||||
<dllentry dll="__Internal" name="CopyMemory" target="mono_win32_compat_CopyMemory"/>
|
|
||||||
<dllentry dll="__Internal" name="FillMemory" target="mono_win32_compat_FillMemory"/>
|
|
||||||
<dllentry dll="__Internal" name="MoveMemory" target="mono_win32_compat_MoveMemory"/>
|
|
||||||
<dllentry dll="__Internal" name="ZeroMemory" target="mono_win32_compat_ZeroMemory"/>
|
|
||||||
</dllmap>
|
|
||||||
</configuration>
|
|
|
@ -1,65 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from SCons.Script import Dir, Environment
|
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
from . import mono_reg_utils as monoreg
|
|
||||||
|
|
||||||
|
|
||||||
android_arch_dirs = {
|
|
||||||
"armv7": "armeabi-v7a",
|
|
||||||
"arm64v8": "arm64-v8a",
|
|
||||||
"x86": "x86",
|
|
||||||
"x86_64": "x86_64",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_android_out_dir(env):
|
|
||||||
return os.path.join(
|
|
||||||
Dir("#platform/android/java/lib/libs").abspath,
|
|
||||||
"release" if env["target"] == "release" else "debug",
|
|
||||||
android_arch_dirs[env["android_arch"]],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def find_name_in_dir_files(directory, names, prefixes=[""], extensions=[""]):
|
|
||||||
for extension in extensions:
|
|
||||||
if extension and not extension.startswith("."):
|
|
||||||
extension = "." + extension
|
|
||||||
for prefix in prefixes:
|
|
||||||
for curname in names:
|
|
||||||
if os.path.isfile(os.path.join(directory, prefix + curname + extension)):
|
|
||||||
return curname
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def find_file_in_dir(directory, names, prefixes=[""], extensions=[""]):
|
|
||||||
for extension in extensions:
|
|
||||||
if extension and not extension.startswith("."):
|
|
||||||
extension = "." + extension
|
|
||||||
for prefix in prefixes:
|
|
||||||
for curname in names:
|
|
||||||
filename = prefix + curname + extension
|
|
||||||
if os.path.isfile(os.path.join(directory, filename)):
|
|
||||||
return filename
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def copy_file(src_dir, dst_dir, src_name, dst_name=""):
|
|
||||||
from shutil import copy
|
|
||||||
|
|
||||||
src_path = os.path.join(Dir(src_dir).abspath, src_name)
|
|
||||||
dst_dir = Dir(dst_dir).abspath
|
|
||||||
|
|
||||||
if not os.path.isdir(dst_dir):
|
|
||||||
os.makedirs(dst_dir)
|
|
||||||
|
|
||||||
if dst_name:
|
|
||||||
copy(src_path, os.path.join(dst_dir, dst_name))
|
|
||||||
else:
|
|
||||||
copy(src_path, dst_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def is_desktop(platform):
|
def is_desktop(platform):
|
||||||
|
@ -71,504 +11,162 @@ def is_unix_like(platform):
|
||||||
|
|
||||||
|
|
||||||
def module_supports_tools_on(platform):
|
def module_supports_tools_on(platform):
|
||||||
return platform not in ["android", "javascript", "iphone"]
|
return is_desktop(platform)
|
||||||
|
|
||||||
|
|
||||||
def find_wasm_src_dir(mono_root):
|
|
||||||
hint_dirs = [
|
|
||||||
os.path.join(mono_root, "src"),
|
|
||||||
os.path.join(mono_root, "../src"),
|
|
||||||
]
|
|
||||||
for hint_dir in hint_dirs:
|
|
||||||
if os.path.isfile(os.path.join(hint_dir, "driver.c")):
|
|
||||||
return hint_dir
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def configure(env, env_mono):
|
def configure(env, env_mono):
|
||||||
bits = env["bits"]
|
# is_android = env["platform"] == "android"
|
||||||
is_android = env["platform"] == "android"
|
# is_javascript = env["platform"] == "javascript"
|
||||||
is_javascript = env["platform"] == "javascript"
|
# is_ios = env["platform"] == "iphone"
|
||||||
is_ios = env["platform"] == "iphone"
|
# is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
|
||||||
is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
|
|
||||||
|
|
||||||
tools_enabled = env["tools"]
|
tools_enabled = env["tools"]
|
||||||
mono_static = env["mono_static"]
|
|
||||||
copy_mono_root = env["copy_mono_root"]
|
|
||||||
|
|
||||||
mono_prefix = env["mono_prefix"]
|
|
||||||
mono_bcl = env["mono_bcl"]
|
|
||||||
|
|
||||||
mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"]
|
|
||||||
|
|
||||||
if is_android and not env["android_arch"] in android_arch_dirs:
|
|
||||||
raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"])
|
|
||||||
|
|
||||||
if tools_enabled and not module_supports_tools_on(env["platform"]):
|
if tools_enabled and not module_supports_tools_on(env["platform"]):
|
||||||
# TODO:
|
|
||||||
# Android: We have to add the data directory to the apk, concretely the Api and Tools folders.
|
|
||||||
raise RuntimeError("This module does not currently support building for this platform with tools enabled")
|
raise RuntimeError("This module does not currently support building for this platform with tools enabled")
|
||||||
|
|
||||||
if is_android and mono_static:
|
if env["tools"] or env["target"] != "release":
|
||||||
# FIXME: When static linking and doing something that requires libmono-native, we get a dlopen error as 'libmono-native'
|
|
||||||
# seems to depend on 'libmonosgen-2.0'. Could be fixed by re-directing to '__Internal' with a dllmap or in the dlopen hook.
|
|
||||||
raise RuntimeError("Statically linking Mono is not currently supported for this platform")
|
|
||||||
|
|
||||||
if not mono_static and (is_javascript or is_ios):
|
|
||||||
raise RuntimeError("Dynamically linking Mono is not currently supported for this platform")
|
|
||||||
|
|
||||||
if not mono_prefix and (os.getenv("MONO32_PREFIX") or os.getenv("MONO64_PREFIX")):
|
|
||||||
print(
|
|
||||||
"WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the"
|
|
||||||
" 'mono_prefix' SCons parameter instead"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Although we don't support building with tools for any platform where we currently use static AOT,
|
|
||||||
# if these are supported in the future, we won't be using static AOT for them as that would be
|
|
||||||
# too restrictive for the editor. These builds would probably be made to only use the interpreter.
|
|
||||||
mono_aot_static = (is_ios and not is_ios_sim) and not env["tools"]
|
|
||||||
|
|
||||||
# Static AOT is only supported on the root domain
|
|
||||||
mono_single_appdomain = mono_aot_static
|
|
||||||
|
|
||||||
if mono_single_appdomain:
|
|
||||||
env_mono.Append(CPPDEFINES=["GD_MONO_SINGLE_APPDOMAIN"])
|
|
||||||
|
|
||||||
if (env["tools"] or env["target"] != "release") and not mono_single_appdomain:
|
|
||||||
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
||||||
|
|
||||||
if env["platform"] == "windows":
|
dotnet_root = env["dotnet_root"]
|
||||||
mono_root = mono_prefix
|
|
||||||
|
|
||||||
if not mono_root and os.name == "nt":
|
if not dotnet_root:
|
||||||
mono_root = monoreg.find_mono_root_dir(bits)
|
dotnet_exe = find_executable("dotnet")
|
||||||
|
if dotnet_exe:
|
||||||
|
dotnet_exe_realpath = os.path.realpath(dotnet_exe) # Eliminate symbolic links
|
||||||
|
dotnet_root = os.path.abspath(os.path.join(dotnet_exe_realpath, os.pardir))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Cannot find .NET Core Sdk")
|
||||||
|
|
||||||
if not mono_root:
|
print("Found .NET Core Sdk root directory: " + dotnet_root)
|
||||||
raise RuntimeError(
|
|
||||||
"Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
|
dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
|
||||||
|
|
||||||
|
runtime_identifier = determine_runtime_identifier(env)
|
||||||
|
|
||||||
|
# TODO: In the future, if it can't be found this way, we want to obtain it
|
||||||
|
# from the runtime.{runtime_identifier}.Microsoft.NETCore.DotNetAppHost NuGet package.
|
||||||
|
app_host_search_version = "5.0"
|
||||||
|
app_host_version = find_app_host_version(dotnet_cmd, app_host_search_version)
|
||||||
|
if not app_host_version:
|
||||||
|
raise RuntimeError("Cannot find .NET app host for version: " + app_host_search_version)
|
||||||
|
|
||||||
|
app_host_dir = os.path.join(
|
||||||
|
dotnet_root,
|
||||||
|
"packs",
|
||||||
|
"Microsoft.NETCore.App.Host." + runtime_identifier,
|
||||||
|
app_host_version,
|
||||||
|
"runtimes",
|
||||||
|
runtime_identifier,
|
||||||
|
"native",
|
||||||
)
|
)
|
||||||
|
|
||||||
print("Found Mono root directory: " + mono_root)
|
def check_app_host_file_exists(file):
|
||||||
|
file_path = os.path.join(app_host_dir, file)
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
raise RuntimeError("File not found: " + file_path)
|
||||||
|
|
||||||
mono_lib_path = os.path.join(mono_root, "lib")
|
# TODO:
|
||||||
|
# All libnethost does for us is provide a function to find hostfxr.
|
||||||
|
# If we could handle that logic ourselves we could void linking it.
|
||||||
|
|
||||||
env.Append(LIBPATH=mono_lib_path)
|
# nethost file names:
|
||||||
env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
|
# static: libnethost.a/lib
|
||||||
|
# shared: libnethost.a/dylib and nethost.dll
|
||||||
|
check_app_host_file_exists("libnethost.lib" if os.name == "nt" else "libnethost.a")
|
||||||
|
check_app_host_file_exists("nethost.h")
|
||||||
|
check_app_host_file_exists("hostfxr.h")
|
||||||
|
check_app_host_file_exists("coreclr_delegates.h")
|
||||||
|
|
||||||
lib_suffixes = [".lib"]
|
env.Append(LIBPATH=[app_host_dir])
|
||||||
|
env_mono.Prepend(CPPPATH=app_host_dir)
|
||||||
|
|
||||||
if not env.msvc:
|
libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
|
||||||
# MingW supports both '.a' and '.lib'
|
|
||||||
lib_suffixes.insert(0, ".a")
|
|
||||||
|
|
||||||
if mono_static:
|
if env["platform"] == "windows":
|
||||||
if env.msvc:
|
if env.msvc:
|
||||||
mono_static_lib_name = "libmono-static-sgen"
|
env.Append(LINKFLAGS="libnethost.lib")
|
||||||
else:
|
else:
|
||||||
mono_static_lib_name = "libmonosgen-2.0"
|
env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
|
||||||
|
|
||||||
mono_static_lib_file = find_file_in_dir(mono_lib_path, [mono_static_lib_name], extensions=lib_suffixes)
|
|
||||||
|
|
||||||
if not mono_static_lib_file:
|
|
||||||
raise RuntimeError("Could not find static mono library in: " + mono_lib_path)
|
|
||||||
|
|
||||||
if env.msvc:
|
|
||||||
env.Append(LINKFLAGS=mono_static_lib_file)
|
|
||||||
|
|
||||||
env.Append(LINKFLAGS="Mincore.lib")
|
|
||||||
env.Append(LINKFLAGS="msvcrt.lib")
|
|
||||||
env.Append(LINKFLAGS="LIBCMT.lib")
|
|
||||||
env.Append(LINKFLAGS="Psapi.lib")
|
|
||||||
else:
|
|
||||||
mono_static_lib_file_path = os.path.join(mono_lib_path, mono_static_lib_file)
|
|
||||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_static_lib_file_path, "-Wl,-no-whole-archive"])
|
|
||||||
|
|
||||||
env.Append(LIBS=["psapi"])
|
|
||||||
env.Append(LIBS=["version"])
|
|
||||||
else:
|
|
||||||
mono_lib_file = find_file_in_dir(mono_lib_path, mono_lib_names, extensions=lib_suffixes)
|
|
||||||
|
|
||||||
if not mono_lib_file:
|
|
||||||
raise RuntimeError("Could not find mono library in: " + mono_lib_path)
|
|
||||||
|
|
||||||
if env.msvc:
|
|
||||||
env.Append(LINKFLAGS=mono_lib_file)
|
|
||||||
else:
|
|
||||||
mono_lib_file_path = os.path.join(mono_lib_path, mono_lib_file)
|
|
||||||
env.Append(LINKFLAGS=mono_lib_file_path)
|
|
||||||
|
|
||||||
mono_bin_path = os.path.join(mono_root, "bin")
|
|
||||||
|
|
||||||
mono_dll_file = find_file_in_dir(mono_bin_path, mono_lib_names, prefixes=["", "lib"], extensions=[".dll"])
|
|
||||||
|
|
||||||
if not mono_dll_file:
|
|
||||||
raise RuntimeError("Could not find mono shared library in: " + mono_bin_path)
|
|
||||||
|
|
||||||
copy_file(mono_bin_path, "#bin", mono_dll_file)
|
|
||||||
else:
|
else:
|
||||||
is_apple = env["platform"] in ["osx", "iphone"]
|
is_apple = env["platform"] in ["osx", "iphone"]
|
||||||
is_macos = is_apple and not is_ios
|
# is_macos = is_apple and not is_ios
|
||||||
|
|
||||||
sharedlib_ext = ".dylib" if is_apple else ".so"
|
# if is_ios and not is_ios_sim:
|
||||||
|
# env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
|
||||||
mono_root = mono_prefix
|
|
||||||
mono_lib_path = ""
|
|
||||||
mono_so_file = ""
|
|
||||||
|
|
||||||
if not mono_root and (is_android or is_javascript or is_ios):
|
|
||||||
raise RuntimeError(
|
|
||||||
"Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
|
|
||||||
)
|
|
||||||
|
|
||||||
if not mono_root and is_macos:
|
|
||||||
# Try with some known directories under OSX
|
|
||||||
hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"]
|
|
||||||
for hint_dir in hint_dirs:
|
|
||||||
if os.path.isdir(hint_dir):
|
|
||||||
mono_root = hint_dir
|
|
||||||
break
|
|
||||||
|
|
||||||
# We can't use pkg-config to link mono statically,
|
|
||||||
# but we can still use it to find the mono root directory
|
|
||||||
if not mono_root and mono_static:
|
|
||||||
mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
|
|
||||||
if not mono_root:
|
|
||||||
raise RuntimeError(
|
|
||||||
"Building with mono_static=yes, but failed to find the mono prefix with pkg-config; "
|
|
||||||
+ "specify one manually with the 'mono_prefix' SCons parameter"
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_ios and not is_ios_sim:
|
|
||||||
env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
|
|
||||||
|
|
||||||
if mono_root:
|
|
||||||
print("Found Mono root directory: " + mono_root)
|
|
||||||
|
|
||||||
mono_lib_path = os.path.join(mono_root, "lib")
|
|
||||||
|
|
||||||
env.Append(LIBPATH=[mono_lib_path])
|
|
||||||
env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
|
|
||||||
|
|
||||||
mono_lib = find_name_in_dir_files(mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[".a"])
|
|
||||||
|
|
||||||
if not mono_lib:
|
|
||||||
raise RuntimeError("Could not find mono library in: " + mono_lib_path)
|
|
||||||
|
|
||||||
env_mono.Append(CPPDEFINES=["_REENTRANT"])
|
|
||||||
|
|
||||||
if mono_static:
|
|
||||||
if not is_javascript:
|
|
||||||
env.Append(LINKFLAGS=["-rdynamic"])
|
|
||||||
|
|
||||||
mono_lib_file = os.path.join(mono_lib_path, "lib" + mono_lib + ".a")
|
|
||||||
|
|
||||||
if is_apple:
|
if is_apple:
|
||||||
if is_macos:
|
env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
|
||||||
env.Append(LINKFLAGS=["-Wl,-force_load," + mono_lib_file])
|
|
||||||
else:
|
else:
|
||||||
arch = env["arch"]
|
env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
|
||||||
|
|
||||||
def copy_mono_lib(libname_wo_ext):
|
|
||||||
copy_file(
|
|
||||||
mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Copy Mono libraries to the output folder. These are meant to be bundled with
|
|
||||||
# the export templates and added to the Xcode project when exporting a game.
|
|
||||||
copy_mono_lib("lib" + mono_lib)
|
|
||||||
copy_mono_lib("libmono-native")
|
|
||||||
copy_mono_lib("libmono-profiler-log")
|
|
||||||
|
|
||||||
if not is_ios_sim:
|
|
||||||
copy_mono_lib("libmono-ee-interp")
|
|
||||||
copy_mono_lib("libmono-icall-table")
|
|
||||||
copy_mono_lib("libmono-ilgen")
|
|
||||||
else:
|
|
||||||
assert is_desktop(env["platform"]) or is_android or is_javascript
|
|
||||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_lib_file, "-Wl,-no-whole-archive"])
|
|
||||||
|
|
||||||
if is_javascript:
|
|
||||||
env.Append(LIBS=["mono-icall-table", "mono-native", "mono-ilgen", "mono-ee-interp"])
|
|
||||||
|
|
||||||
wasm_src_dir = os.path.join(mono_root, "src")
|
|
||||||
if not os.path.isdir(wasm_src_dir):
|
|
||||||
raise RuntimeError("Could not find mono wasm src directory")
|
|
||||||
|
|
||||||
# Ideally this should be defined only for 'driver.c', but I can't fight scons for another 2 hours
|
|
||||||
env_mono.Append(CPPDEFINES=["CORE_BINDINGS"])
|
|
||||||
|
|
||||||
env_mono.add_source_files(
|
|
||||||
env.modules_sources,
|
|
||||||
[
|
|
||||||
os.path.join(wasm_src_dir, "driver.c"),
|
|
||||||
os.path.join(wasm_src_dir, "zlib-helper.c"),
|
|
||||||
os.path.join(wasm_src_dir, "corebindings.c"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
env.Append(
|
|
||||||
LINKFLAGS=[
|
|
||||||
"--js-library",
|
|
||||||
os.path.join(wasm_src_dir, "library_mono.js"),
|
|
||||||
"--js-library",
|
|
||||||
os.path.join(wasm_src_dir, "binding_support.js"),
|
|
||||||
"--js-library",
|
|
||||||
os.path.join(wasm_src_dir, "dotnet_support.js"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
env.Append(LIBS=[mono_lib])
|
|
||||||
|
|
||||||
if is_macos:
|
|
||||||
env.Append(LIBS=["iconv", "pthread"])
|
|
||||||
elif is_android:
|
|
||||||
pass # Nothing
|
|
||||||
elif is_ios:
|
|
||||||
pass # Nothing, linking is delegated to the exported Xcode project
|
|
||||||
elif is_javascript:
|
|
||||||
env.Append(LIBS=["m", "rt", "dl", "pthread"])
|
|
||||||
else:
|
|
||||||
env.Append(LIBS=["m", "rt", "dl", "pthread"])
|
|
||||||
|
|
||||||
if not mono_static:
|
|
||||||
mono_so_file = find_file_in_dir(
|
|
||||||
mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]
|
|
||||||
)
|
|
||||||
|
|
||||||
if not mono_so_file:
|
|
||||||
raise RuntimeError("Could not find mono shared library in: " + mono_lib_path)
|
|
||||||
else:
|
|
||||||
assert not mono_static
|
|
||||||
|
|
||||||
# TODO: Add option to force using pkg-config
|
|
||||||
print("Mono root directory not found. Using pkg-config instead")
|
|
||||||
|
|
||||||
env.ParseConfig("pkg-config monosgen-2 --libs")
|
|
||||||
env_mono.ParseConfig("pkg-config monosgen-2 --cflags")
|
|
||||||
|
|
||||||
tmpenv = Environment()
|
|
||||||
tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
|
|
||||||
tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
|
|
||||||
|
|
||||||
for hint_dir in tmpenv["LIBPATH"]:
|
|
||||||
file_found = find_file_in_dir(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
|
|
||||||
if file_found:
|
|
||||||
mono_lib_path = hint_dir
|
|
||||||
mono_so_file = file_found
|
|
||||||
break
|
|
||||||
|
|
||||||
if not mono_so_file:
|
|
||||||
raise RuntimeError("Could not find mono shared library in: " + str(tmpenv["LIBPATH"]))
|
|
||||||
|
|
||||||
if not mono_static:
|
|
||||||
libs_output_dir = get_android_out_dir(env) if is_android else "#bin"
|
|
||||||
copy_file(mono_lib_path, libs_output_dir, mono_so_file)
|
|
||||||
|
|
||||||
if not tools_enabled:
|
|
||||||
if is_desktop(env["platform"]):
|
|
||||||
if not mono_root:
|
|
||||||
mono_root = (
|
|
||||||
subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
make_template_dir(env, mono_root)
|
|
||||||
elif is_android:
|
|
||||||
# Compress Android Mono Config
|
|
||||||
from . import make_android_mono_config
|
|
||||||
|
|
||||||
module_dir = os.getcwd()
|
|
||||||
config_file_path = os.path.join(module_dir, "build_scripts", "mono_android_config.xml")
|
|
||||||
make_android_mono_config.generate_compressed_config(config_file_path, "mono_gd/")
|
|
||||||
|
|
||||||
# Copy the required shared libraries
|
|
||||||
copy_mono_shared_libs(env, mono_root, None)
|
|
||||||
elif is_javascript:
|
|
||||||
pass # No data directory for this platform
|
|
||||||
elif is_ios:
|
|
||||||
pass # No data directory for this platform
|
|
||||||
|
|
||||||
if copy_mono_root:
|
|
||||||
if not mono_root:
|
|
||||||
mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
|
|
||||||
|
|
||||||
if tools_enabled:
|
|
||||||
# Only supported for editor builds.
|
|
||||||
copy_mono_root_files(env, mono_root, mono_bcl)
|
|
||||||
|
|
||||||
|
|
||||||
def make_template_dir(env, mono_root):
|
def determine_runtime_identifier(env):
|
||||||
from shutil import rmtree
|
names_map = {
|
||||||
|
"windows": "win",
|
||||||
|
"osx": "osx",
|
||||||
|
"linuxbsd": "linux",
|
||||||
|
"server": "linux", # FIXME: Is server linux only, or also macos?
|
||||||
|
}
|
||||||
|
|
||||||
platform = env["platform"]
|
# architectures names: x86, x64, arm, or arm64
|
||||||
target = env["target"]
|
|
||||||
|
|
||||||
template_dir_name = ""
|
|
||||||
|
|
||||||
assert is_desktop(platform)
|
|
||||||
|
|
||||||
template_dir_name = "data.mono.%s.%s.%s" % (platform, env["bits"], target)
|
|
||||||
|
|
||||||
output_dir = Dir("#bin").abspath
|
|
||||||
template_dir = os.path.join(output_dir, template_dir_name)
|
|
||||||
|
|
||||||
template_mono_root_dir = os.path.join(template_dir, "Mono")
|
|
||||||
|
|
||||||
if os.path.isdir(template_mono_root_dir):
|
|
||||||
rmtree(template_mono_root_dir) # Clean first
|
|
||||||
|
|
||||||
# Copy etc/mono/
|
|
||||||
|
|
||||||
template_mono_config_dir = os.path.join(template_mono_root_dir, "etc", "mono")
|
|
||||||
copy_mono_etc_dir(mono_root, template_mono_config_dir, platform)
|
|
||||||
|
|
||||||
# Copy the required shared libraries
|
|
||||||
|
|
||||||
copy_mono_shared_libs(env, mono_root, template_mono_root_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def copy_mono_root_files(env, mono_root, mono_bcl):
|
|
||||||
from glob import glob
|
|
||||||
from shutil import copy
|
|
||||||
from shutil import rmtree
|
|
||||||
|
|
||||||
if not mono_root:
|
|
||||||
raise RuntimeError("Mono installation directory not found")
|
|
||||||
|
|
||||||
output_dir = Dir("#bin").abspath
|
|
||||||
editor_mono_root_dir = os.path.join(output_dir, "GodotSharp", "Mono")
|
|
||||||
|
|
||||||
if os.path.isdir(editor_mono_root_dir):
|
|
||||||
rmtree(editor_mono_root_dir) # Clean first
|
|
||||||
|
|
||||||
# Copy etc/mono/
|
|
||||||
|
|
||||||
editor_mono_config_dir = os.path.join(editor_mono_root_dir, "etc", "mono")
|
|
||||||
copy_mono_etc_dir(mono_root, editor_mono_config_dir, env["platform"])
|
|
||||||
|
|
||||||
# Copy the required shared libraries
|
|
||||||
|
|
||||||
copy_mono_shared_libs(env, mono_root, editor_mono_root_dir)
|
|
||||||
|
|
||||||
# Copy framework assemblies
|
|
||||||
|
|
||||||
mono_framework_dir = mono_bcl or os.path.join(mono_root, "lib", "mono", "4.5")
|
|
||||||
mono_framework_facades_dir = os.path.join(mono_framework_dir, "Facades")
|
|
||||||
|
|
||||||
editor_mono_framework_dir = os.path.join(editor_mono_root_dir, "lib", "mono", "4.5")
|
|
||||||
editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, "Facades")
|
|
||||||
|
|
||||||
if not os.path.isdir(editor_mono_framework_dir):
|
|
||||||
os.makedirs(editor_mono_framework_dir)
|
|
||||||
if not os.path.isdir(editor_mono_framework_facades_dir):
|
|
||||||
os.makedirs(editor_mono_framework_facades_dir)
|
|
||||||
|
|
||||||
for assembly in glob(os.path.join(mono_framework_dir, "*.dll")):
|
|
||||||
copy(assembly, editor_mono_framework_dir)
|
|
||||||
for assembly in glob(os.path.join(mono_framework_facades_dir, "*.dll")):
|
|
||||||
copy(assembly, editor_mono_framework_facades_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
|
|
||||||
from distutils.dir_util import copy_tree
|
|
||||||
from glob import glob
|
|
||||||
from shutil import copy
|
|
||||||
|
|
||||||
if not os.path.isdir(target_mono_config_dir):
|
|
||||||
os.makedirs(target_mono_config_dir)
|
|
||||||
|
|
||||||
mono_etc_dir = os.path.join(mono_root, "etc", "mono")
|
|
||||||
if not os.path.isdir(mono_etc_dir):
|
|
||||||
mono_etc_dir = ""
|
|
||||||
etc_hint_dirs = []
|
|
||||||
if platform != "windows":
|
|
||||||
etc_hint_dirs += ["/etc/mono", "/usr/local/etc/mono"]
|
|
||||||
if "MONO_CFG_DIR" in os.environ:
|
|
||||||
etc_hint_dirs += [os.path.join(os.environ["MONO_CFG_DIR"], "mono")]
|
|
||||||
for etc_hint_dir in etc_hint_dirs:
|
|
||||||
if os.path.isdir(etc_hint_dir):
|
|
||||||
mono_etc_dir = etc_hint_dir
|
|
||||||
break
|
|
||||||
if not mono_etc_dir:
|
|
||||||
raise RuntimeError("Mono installation etc directory not found")
|
|
||||||
|
|
||||||
copy_tree(os.path.join(mono_etc_dir, "2.0"), os.path.join(target_mono_config_dir, "2.0"))
|
|
||||||
copy_tree(os.path.join(mono_etc_dir, "4.0"), os.path.join(target_mono_config_dir, "4.0"))
|
|
||||||
copy_tree(os.path.join(mono_etc_dir, "4.5"), os.path.join(target_mono_config_dir, "4.5"))
|
|
||||||
if os.path.isdir(os.path.join(mono_etc_dir, "mconfig")):
|
|
||||||
copy_tree(os.path.join(mono_etc_dir, "mconfig"), os.path.join(target_mono_config_dir, "mconfig"))
|
|
||||||
|
|
||||||
for file in glob(os.path.join(mono_etc_dir, "*")):
|
|
||||||
if os.path.isfile(file):
|
|
||||||
copy(file, target_mono_config_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
|
|
||||||
from shutil import copy
|
|
||||||
|
|
||||||
def copy_if_exists(src, dst):
|
|
||||||
if os.path.isfile(src):
|
|
||||||
copy(src, dst)
|
|
||||||
|
|
||||||
platform = env["platform"]
|
platform = env["platform"]
|
||||||
|
|
||||||
if platform == "windows":
|
if is_desktop(platform):
|
||||||
src_mono_bin_dir = os.path.join(mono_root, "bin")
|
bits = env["bits"]
|
||||||
target_mono_bin_dir = os.path.join(target_mono_root_dir, "bin")
|
bit_arch_map = {"64": "x64", "32": "x86"}
|
||||||
|
return "%s-%s" % (names_map[platform], bit_arch_map[bits])
|
||||||
if not os.path.isdir(target_mono_bin_dir):
|
|
||||||
os.makedirs(target_mono_bin_dir)
|
|
||||||
|
|
||||||
mono_posix_helper_file = find_file_in_dir(
|
|
||||||
src_mono_bin_dir, ["MonoPosixHelper"], prefixes=["", "lib"], extensions=[".dll"]
|
|
||||||
)
|
|
||||||
copy(
|
|
||||||
os.path.join(src_mono_bin_dir, mono_posix_helper_file),
|
|
||||||
os.path.join(target_mono_bin_dir, "MonoPosixHelper.dll"),
|
|
||||||
)
|
|
||||||
|
|
||||||
# For newer versions
|
|
||||||
btls_dll_path = os.path.join(src_mono_bin_dir, "libmono-btls-shared.dll")
|
|
||||||
if os.path.isfile(btls_dll_path):
|
|
||||||
copy(btls_dll_path, target_mono_bin_dir)
|
|
||||||
else:
|
else:
|
||||||
target_mono_lib_dir = (
|
raise NotImplementedError()
|
||||||
get_android_out_dir(env) if platform == "android" else os.path.join(target_mono_root_dir, "lib")
|
|
||||||
)
|
|
||||||
|
|
||||||
if not os.path.isdir(target_mono_lib_dir):
|
|
||||||
os.makedirs(target_mono_lib_dir)
|
|
||||||
|
|
||||||
lib_file_names = []
|
|
||||||
if platform == "osx":
|
|
||||||
lib_file_names = [
|
|
||||||
lib_name + ".dylib"
|
|
||||||
for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"]
|
|
||||||
]
|
|
||||||
elif is_unix_like(platform):
|
|
||||||
lib_file_names = [
|
|
||||||
lib_name + ".so"
|
|
||||||
for lib_name in [
|
|
||||||
"libmono-btls-shared",
|
|
||||||
"libmono-ee-interp",
|
|
||||||
"libmono-native",
|
|
||||||
"libMonoPosixHelper",
|
|
||||||
"libmono-profiler-aot",
|
|
||||||
"libmono-profiler-coverage",
|
|
||||||
"libmono-profiler-log",
|
|
||||||
"libMonoSupportW",
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
for lib_file_name in lib_file_names:
|
|
||||||
copy_if_exists(os.path.join(mono_root, "lib", lib_file_name), target_mono_lib_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
|
def find_app_host_version(dotnet_cmd, search_version):
|
||||||
tmpenv = Environment()
|
import subprocess
|
||||||
tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
|
|
||||||
tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
|
try:
|
||||||
for hint_dir in tmpenv["LIBPATH"]:
|
lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"]).splitlines()
|
||||||
name_found = find_name_in_dir_files(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
|
|
||||||
if name_found and os.path.isdir(os.path.join(hint_dir, "..", "include", "mono-2.0")):
|
for line_bytes in lines:
|
||||||
return os.path.join(hint_dir, "..")
|
line = line_bytes.decode("utf-8")
|
||||||
|
if not line.startswith("Microsoft.NETCore.App "):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split(" ")
|
||||||
|
if len(parts) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
version = parts[1]
|
||||||
|
|
||||||
|
# Look for 6.0.0 or 6.0.0-*
|
||||||
|
if version.startswith(search_version + "."):
|
||||||
|
return version
|
||||||
|
except (subprocess.CalledProcessError, OSError):
|
||||||
|
pass
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
ENV_PATH_SEP = ";" if os.name == "nt" else ":"
|
||||||
|
|
||||||
|
|
||||||
|
def find_executable(name):
|
||||||
|
is_windows = os.name == "nt"
|
||||||
|
windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None
|
||||||
|
path_dirs = os.environ["PATH"].split(ENV_PATH_SEP)
|
||||||
|
|
||||||
|
search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list
|
||||||
|
|
||||||
|
for dir in search_dirs:
|
||||||
|
path = os.path.join(dir, name)
|
||||||
|
|
||||||
|
if is_windows:
|
||||||
|
for extension in windows_exts:
|
||||||
|
path_with_ext = path + extension
|
||||||
|
|
||||||
|
if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK):
|
||||||
|
return path_with_ext
|
||||||
|
else:
|
||||||
|
if os.path.isfile(path) and os.access(path, os.X_OK):
|
||||||
|
return path
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
import sys
|
|
||||||
import winreg
|
|
||||||
|
|
||||||
|
|
||||||
def _reg_open_key(key, subkey):
|
|
||||||
try:
|
|
||||||
return winreg.OpenKey(key, subkey)
|
|
||||||
except OSError:
|
|
||||||
if platform.architecture()[0] == "32bit":
|
|
||||||
bitness_sam = winreg.KEY_WOW64_64KEY
|
|
||||||
else:
|
|
||||||
bitness_sam = winreg.KEY_WOW64_32KEY
|
|
||||||
return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
|
|
||||||
|
|
||||||
|
|
||||||
def _reg_open_key_bits(key, subkey, bits):
|
|
||||||
sam = winreg.KEY_READ
|
|
||||||
|
|
||||||
if platform.architecture()[0] == "32bit":
|
|
||||||
if bits == "64":
|
|
||||||
# Force 32bit process to search in 64bit registry
|
|
||||||
sam |= winreg.KEY_WOW64_64KEY
|
|
||||||
else:
|
|
||||||
if bits == "32":
|
|
||||||
# Force 64bit process to search in 32bit registry
|
|
||||||
sam |= winreg.KEY_WOW64_32KEY
|
|
||||||
|
|
||||||
return winreg.OpenKey(key, subkey, 0, sam)
|
|
||||||
|
|
||||||
|
|
||||||
def _find_mono_in_reg(subkey, bits):
|
|
||||||
try:
|
|
||||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
|
||||||
value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0]
|
|
||||||
return value
|
|
||||||
except OSError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _find_mono_in_reg_old(subkey, bits):
|
|
||||||
try:
|
|
||||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
|
||||||
default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0]
|
|
||||||
if default_clr:
|
|
||||||
return _find_mono_in_reg(subkey + "\\" + default_clr, bits)
|
|
||||||
return None
|
|
||||||
except OSError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def find_mono_root_dir(bits):
|
|
||||||
root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits)
|
|
||||||
if root_dir is not None:
|
|
||||||
return str(root_dir)
|
|
||||||
root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits)
|
|
||||||
if root_dir is not None:
|
|
||||||
return str(root_dir)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def find_msbuild_tools_path_reg():
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
vswhere = os.getenv("PROGRAMFILES(X86)")
|
|
||||||
if not vswhere:
|
|
||||||
vswhere = os.getenv("PROGRAMFILES")
|
|
||||||
vswhere += r"\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
||||||
|
|
||||||
vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
|
|
||||||
|
|
||||||
try:
|
|
||||||
lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
parts = line.decode("utf-8").split(":", 1)
|
|
||||||
|
|
||||||
if len(parts) < 2 or parts[0] != "installationPath":
|
|
||||||
continue
|
|
||||||
|
|
||||||
val = parts[1].strip()
|
|
||||||
|
|
||||||
if not val:
|
|
||||||
raise ValueError("Value of `installationPath` entry is empty")
|
|
||||||
|
|
||||||
# Since VS2019, the directory is simply named "Current"
|
|
||||||
msbuild_dir = os.path.join(val, "MSBuild\\Current\\Bin")
|
|
||||||
if os.path.isdir(msbuild_dir):
|
|
||||||
return msbuild_dir
|
|
||||||
|
|
||||||
# Directory name "15.0" is used in VS 2017
|
|
||||||
return os.path.join(val, "MSBuild\\15.0\\Bin")
|
|
||||||
|
|
||||||
raise ValueError("Cannot find `installationPath` entry")
|
|
||||||
except ValueError as e:
|
|
||||||
print("Error reading output from vswhere: " + e.message)
|
|
||||||
except OSError:
|
|
||||||
pass # Fine, vswhere not found
|
|
||||||
except (subprocess.CalledProcessError, OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Try to find 14.0 in the Registry
|
|
||||||
|
|
||||||
try:
|
|
||||||
subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"
|
|
||||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
|
|
||||||
value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0]
|
|
||||||
return value
|
|
||||||
except OSError:
|
|
||||||
return ""
|
|
|
@ -1,145 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
verbose = False
|
|
||||||
|
|
||||||
|
|
||||||
def find_dotnet_cli():
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
|
||||||
hint_dir = hint_dir.strip('"')
|
|
||||||
hint_path = os.path.join(hint_dir, "dotnet")
|
|
||||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
|
||||||
return hint_path
|
|
||||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
|
||||||
return hint_path + ".exe"
|
|
||||||
else:
|
|
||||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
|
||||||
hint_dir = hint_dir.strip('"')
|
|
||||||
hint_path = os.path.join(hint_dir, "dotnet")
|
|
||||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
|
||||||
return hint_path
|
|
||||||
|
|
||||||
|
|
||||||
def find_msbuild_unix():
|
|
||||||
import os.path
|
|
||||||
import sys
|
|
||||||
|
|
||||||
hint_dirs = []
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
hint_dirs[:0] = [
|
|
||||||
"/Library/Frameworks/Mono.framework/Versions/Current/bin",
|
|
||||||
"/usr/local/var/homebrew/linked/mono/bin",
|
|
||||||
]
|
|
||||||
|
|
||||||
for hint_dir in hint_dirs:
|
|
||||||
hint_path = os.path.join(hint_dir, "msbuild")
|
|
||||||
if os.path.isfile(hint_path):
|
|
||||||
return hint_path
|
|
||||||
elif os.path.isfile(hint_path + ".exe"):
|
|
||||||
return hint_path + ".exe"
|
|
||||||
|
|
||||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
|
||||||
hint_dir = hint_dir.strip('"')
|
|
||||||
hint_path = os.path.join(hint_dir, "msbuild")
|
|
||||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
|
||||||
return hint_path
|
|
||||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
|
||||||
return hint_path + ".exe"
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def find_msbuild_windows(env):
|
|
||||||
from .mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg
|
|
||||||
|
|
||||||
mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"])
|
|
||||||
|
|
||||||
if not mono_root:
|
|
||||||
raise RuntimeError("Cannot find mono root directory")
|
|
||||||
|
|
||||||
mono_bin_dir = os.path.join(mono_root, "bin")
|
|
||||||
msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat")
|
|
||||||
|
|
||||||
msbuild_tools_path = find_msbuild_tools_path_reg()
|
|
||||||
|
|
||||||
if msbuild_tools_path:
|
|
||||||
return (os.path.join(msbuild_tools_path, "MSBuild.exe"), {})
|
|
||||||
|
|
||||||
if os.path.isfile(msbuild_mono):
|
|
||||||
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
|
|
||||||
# building with Mono's MSBuild. They must point to the batch files
|
|
||||||
# in Mono's bin directory to make sure they are executed with Mono.
|
|
||||||
mono_msbuild_env = {
|
|
||||||
"CscToolExe": os.path.join(mono_bin_dir, "csc.bat"),
|
|
||||||
"VbcToolExe": os.path.join(mono_bin_dir, "vbc.bat"),
|
|
||||||
"FscToolExe": os.path.join(mono_bin_dir, "fsharpc.bat"),
|
|
||||||
}
|
|
||||||
return (msbuild_mono, mono_msbuild_env)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def run_command(command, args, env_override=None, name=None):
|
|
||||||
def cmd_args_to_str(cmd_args):
|
|
||||||
return " ".join([arg if not " " in arg else '"%s"' % arg for arg in cmd_args])
|
|
||||||
|
|
||||||
args = [command] + args
|
|
||||||
|
|
||||||
if name is None:
|
|
||||||
name = os.path.basename(command)
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print("Running '%s': %s" % (name, cmd_args_to_str(args)))
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
try:
|
|
||||||
if env_override is None:
|
|
||||||
subprocess.check_call(args)
|
|
||||||
else:
|
|
||||||
subprocess.check_call(args, env=env_override)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode))
|
|
||||||
|
|
||||||
|
|
||||||
def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
|
|
||||||
global verbose
|
|
||||||
verbose = env["verbose"]
|
|
||||||
|
|
||||||
msbuild_env = os.environ.copy()
|
|
||||||
|
|
||||||
# Needed when running from Developer Command Prompt for VS
|
|
||||||
if "PLATFORM" in msbuild_env:
|
|
||||||
del msbuild_env["PLATFORM"]
|
|
||||||
|
|
||||||
msbuild_args = []
|
|
||||||
|
|
||||||
dotnet_cli = find_dotnet_cli()
|
|
||||||
|
|
||||||
if dotnet_cli:
|
|
||||||
msbuild_path = dotnet_cli
|
|
||||||
msbuild_args += ["msbuild"] # `dotnet msbuild` command
|
|
||||||
else:
|
|
||||||
# Find MSBuild
|
|
||||||
if os.name == "nt":
|
|
||||||
msbuild_info = find_msbuild_windows(env)
|
|
||||||
if msbuild_info is None:
|
|
||||||
raise RuntimeError("Cannot find MSBuild executable")
|
|
||||||
msbuild_path = msbuild_info[0]
|
|
||||||
msbuild_env.update(msbuild_info[1])
|
|
||||||
else:
|
|
||||||
msbuild_path = find_msbuild_unix()
|
|
||||||
if msbuild_path is None:
|
|
||||||
raise RuntimeError("Cannot find MSBuild executable")
|
|
||||||
|
|
||||||
print("MSBuild path: " + msbuild_path)
|
|
||||||
|
|
||||||
# Build solution
|
|
||||||
|
|
||||||
msbuild_args += [solution_path, "/restore", "/t:Build", "/p:Configuration=" + build_config]
|
|
||||||
msbuild_args += extra_msbuild_args
|
|
||||||
|
|
||||||
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")
|
|
|
@ -1,8 +1,10 @@
|
||||||
supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"]
|
# Prior to .NET Core, we supported these: ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"]
|
||||||
|
# Eventually support for each them should be added back (except Haiku if not supported by .NET Core)
|
||||||
|
supported_platforms = ["windows", "osx", "linuxbsd", "server"]
|
||||||
|
|
||||||
|
|
||||||
def can_build(env, platform):
|
def can_build(env, platform):
|
||||||
return True
|
return env["module_gdnative_enabled"]
|
||||||
|
|
||||||
|
|
||||||
def configure(env):
|
def configure(env):
|
||||||
|
@ -13,52 +15,21 @@ def configure(env):
|
||||||
|
|
||||||
env.add_module_version_string("mono")
|
env.add_module_version_string("mono")
|
||||||
|
|
||||||
from SCons.Script import BoolVariable, PathVariable, Variables, Help
|
from SCons.Script import PathVariable, Variables, Help
|
||||||
|
|
||||||
default_mono_static = platform in ["iphone", "javascript"]
|
|
||||||
default_mono_bundles_zlib = platform in ["javascript"]
|
|
||||||
|
|
||||||
envvars = Variables()
|
envvars = Variables()
|
||||||
envvars.Add(
|
envvars.Add(
|
||||||
PathVariable(
|
PathVariable(
|
||||||
"mono_prefix",
|
"dotnet_root",
|
||||||
"Path to the Mono installation directory for the target platform and architecture",
|
"Path to the .NET Sdk installation directory for the target platform and architecture",
|
||||||
"",
|
"",
|
||||||
PathVariable.PathAccept,
|
PathVariable.PathAccept,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
envvars.Add(
|
|
||||||
PathVariable(
|
|
||||||
"mono_bcl",
|
|
||||||
"Path to a custom Mono BCL (Base Class Library) directory for the target platform",
|
|
||||||
"",
|
|
||||||
PathVariable.PathAccept,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static))
|
|
||||||
envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True))
|
|
||||||
envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
|
|
||||||
envvars.Add(
|
|
||||||
BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True)
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: It would be great if this could be detected automatically instead
|
|
||||||
envvars.Add(
|
|
||||||
BoolVariable(
|
|
||||||
"mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
envvars.Update(env)
|
envvars.Update(env)
|
||||||
Help(envvars.GenerateHelpText(env))
|
Help(envvars.GenerateHelpText(env))
|
||||||
|
|
||||||
if env["mono_bundles_zlib"]:
|
|
||||||
# Mono may come with zlib bundled for WASM or on newer version when built with MinGW.
|
|
||||||
print("This Mono runtime comes with zlib bundled. Disabling 'builtin_zlib'...")
|
|
||||||
env["builtin_zlib"] = False
|
|
||||||
thirdparty_zlib_dir = "#thirdparty/zlib/"
|
|
||||||
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
|
||||||
|
|
||||||
|
|
||||||
def get_doc_classes():
|
def get_doc_classes():
|
||||||
return [
|
return [
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,8 +39,6 @@
|
||||||
|
|
||||||
#include "mono_gc_handle.h"
|
#include "mono_gc_handle.h"
|
||||||
#include "mono_gd/gd_mono.h"
|
#include "mono_gd/gd_mono.h"
|
||||||
#include "mono_gd/gd_mono_header.h"
|
|
||||||
#include "mono_gd/gd_mono_internals.h"
|
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
#include "editor/editor_plugin.h"
|
#include "editor/editor_plugin.h"
|
||||||
|
@ -66,18 +64,6 @@ TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
|
||||||
|
|
||||||
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
|
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
|
||||||
|
|
||||||
struct DotNetScriptLookupInfo {
|
|
||||||
String class_namespace;
|
|
||||||
String class_name;
|
|
||||||
GDMonoClass *script_class = nullptr;
|
|
||||||
|
|
||||||
DotNetScriptLookupInfo() {} // Required by HashMap...
|
|
||||||
|
|
||||||
DotNetScriptLookupInfo(const String &p_class_namespace, const String &p_class_name, GDMonoClass *p_script_class) :
|
|
||||||
class_namespace(p_class_namespace), class_name(p_class_name), script_class(p_script_class) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CSharpScript : public Script {
|
class CSharpScript : public Script {
|
||||||
GDCLASS(CSharpScript, Script);
|
GDCLASS(CSharpScript, Script);
|
||||||
|
|
||||||
|
@ -88,26 +74,13 @@ public:
|
||||||
bool nil_is_variant = false;
|
bool nil_is_variant = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventSignal {
|
|
||||||
GDMonoField *field = nullptr;
|
|
||||||
GDMonoMethod *invoke_method = nullptr;
|
|
||||||
Vector<SignalParameter> parameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class CSharpInstance;
|
friend class CSharpInstance;
|
||||||
friend class CSharpLanguage;
|
friend class CSharpLanguage;
|
||||||
friend struct CSharpScriptDepSort;
|
|
||||||
|
|
||||||
bool tool = false;
|
bool tool = false;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
bool builtin;
|
|
||||||
|
|
||||||
GDMonoClass *base = nullptr;
|
|
||||||
GDMonoClass *native = nullptr;
|
|
||||||
GDMonoClass *script_class = nullptr;
|
|
||||||
|
|
||||||
Ref<CSharpScript> base_cache; // TODO what's this for?
|
Ref<CSharpScript> base_cache; // TODO what's this for?
|
||||||
|
|
||||||
Set<Object *> instances;
|
Set<Object *> instances;
|
||||||
|
@ -128,14 +101,9 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String source;
|
String source;
|
||||||
StringName name;
|
|
||||||
|
|
||||||
SelfList<CSharpScript> script_list = this;
|
SelfList<CSharpScript> script_list = this;
|
||||||
|
|
||||||
Map<StringName, Vector<SignalParameter>> _signals;
|
|
||||||
Map<StringName, EventSignal> event_signals;
|
|
||||||
bool signals_invalidated = true;
|
|
||||||
|
|
||||||
Vector<MultiplayerAPI::RPCConfig> rpc_functions;
|
Vector<MultiplayerAPI::RPCConfig> rpc_functions;
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
@ -158,34 +126,26 @@ private:
|
||||||
|
|
||||||
void _clear();
|
void _clear();
|
||||||
|
|
||||||
void _update_name();
|
|
||||||
|
|
||||||
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
|
|
||||||
bool _get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_invoke, Vector<SignalParameter> ¶ms);
|
|
||||||
|
|
||||||
bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
|
bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
|
||||||
|
|
||||||
|
#warning TODO
|
||||||
|
#if 0
|
||||||
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
|
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);
|
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
|
CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
|
||||||
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||||
|
|
||||||
// Do not use unless you know what you are doing
|
// Do not use unless you know what you are doing
|
||||||
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
|
|
||||||
static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
|
|
||||||
static void update_script_class_info(Ref<CSharpScript> p_script);
|
static void update_script_class_info(Ref<CSharpScript> p_script);
|
||||||
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
|
static void initialize_for_managed_type(Ref<CSharpScript> p_script);
|
||||||
|
|
||||||
MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
|
||||||
void _resource_path_changed() override;
|
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
void _get_property_list(List<PropertyInfo> *p_properties) const;
|
void _get_property_list(List<PropertyInfo> *p_properties) const;
|
||||||
|
@ -270,22 +230,21 @@ class CSharpInstance : public ScriptInstance {
|
||||||
bool _unreference_owner_unsafe();
|
bool _unreference_owner_unsafe();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If nullptr is returned, the caller must destroy the script instance by removing it from its owner.
|
* If false is returned, the caller must destroy the script instance by removing it from its owner.
|
||||||
*/
|
*/
|
||||||
MonoObject *_internal_new_managed();
|
bool _internal_new_managed();
|
||||||
|
|
||||||
// Do not use unless you know what you are doing
|
// Do not use unless you know what you are doing
|
||||||
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
|
|
||||||
static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle);
|
static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle);
|
||||||
|
|
||||||
void get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state);
|
void get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state);
|
||||||
void get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state);
|
void get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MonoObject *get_mono_object() const;
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool is_destructing_script_instance() { return destructing_script_instance; }
|
_FORCE_INLINE_ bool is_destructing_script_instance() { return destructing_script_instance; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ GCHandleIntPtr get_gchandle_intptr() { return gchandle.get_intptr(); }
|
||||||
|
|
||||||
Object *get_owner() override;
|
Object *get_owner() override;
|
||||||
|
|
||||||
bool set(const StringName &p_name, const Variant &p_value) override;
|
bool set(const StringName &p_name, const Variant &p_value) override;
|
||||||
|
@ -297,15 +256,15 @@ public:
|
||||||
bool has_method(const StringName &p_method) const override;
|
bool has_method(const StringName &p_method) const override;
|
||||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||||
|
|
||||||
void mono_object_disposed(MonoObject *p_obj);
|
void mono_object_disposed();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, if
|
* If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, if
|
||||||
* 'r_remove_script_instance' is set to true, the caller must destroy the script instance by removing it from its owner.
|
* 'r_remove_script_instance' is set to true, the caller must destroy the script instance by removing it from its owner.
|
||||||
*/
|
*/
|
||||||
void mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);
|
void mono_object_disposed_baseref(bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);
|
||||||
|
|
||||||
void connect_event_signals();
|
void connect_event_signal(const StringName &p_event_signal);
|
||||||
void disconnect_event_signals();
|
void disconnect_event_signals();
|
||||||
|
|
||||||
void refcount_incremented() override;
|
void refcount_incremented() override;
|
||||||
|
@ -329,7 +288,6 @@ public:
|
||||||
struct CSharpScriptBinding {
|
struct CSharpScriptBinding {
|
||||||
bool inited = false;
|
bool inited = false;
|
||||||
StringName type_name;
|
StringName type_name;
|
||||||
GDMonoClass *wrapper_class = nullptr;
|
|
||||||
MonoGCHandleData gchandle;
|
MonoGCHandleData gchandle;
|
||||||
Object *owner = nullptr;
|
Object *owner = nullptr;
|
||||||
|
|
||||||
|
@ -367,33 +325,22 @@ class CSharpLanguage : public ScriptLanguage {
|
||||||
ManagedCallableMiddleman *managed_callable_middleman = memnew(ManagedCallableMiddleman);
|
ManagedCallableMiddleman *managed_callable_middleman = memnew(ManagedCallableMiddleman);
|
||||||
|
|
||||||
struct StringNameCache {
|
struct StringNameCache {
|
||||||
StringName _signal_callback;
|
|
||||||
StringName _set;
|
|
||||||
StringName _get;
|
|
||||||
StringName _get_property_list;
|
|
||||||
StringName _notification;
|
|
||||||
StringName _script_source;
|
StringName _script_source;
|
||||||
StringName dotctor; // .ctor
|
|
||||||
StringName on_before_serialize; // OnBeforeSerialize
|
StringName on_before_serialize; // OnBeforeSerialize
|
||||||
StringName on_after_deserialize; // OnAfterDeserialize
|
StringName on_after_deserialize; // OnAfterDeserialize
|
||||||
StringName delegate_invoke_method_name;
|
|
||||||
|
|
||||||
StringNameCache();
|
StringNameCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
int lang_idx = -1;
|
int lang_idx = -1;
|
||||||
|
|
||||||
HashMap<String, DotNetScriptLookupInfo> dotnet_script_lookup_map;
|
|
||||||
|
|
||||||
void lookup_script_for_class(GDMonoClass *p_class);
|
|
||||||
|
|
||||||
// For debug_break and debug_break_parse
|
// For debug_break and debug_break_parse
|
||||||
int _debug_parse_err_line = -1;
|
int _debug_parse_err_line = -1;
|
||||||
String _debug_parse_err_file;
|
String _debug_parse_err_file;
|
||||||
String _debug_error;
|
String _debug_error;
|
||||||
|
|
||||||
friend class GDMono;
|
friend class GDMono;
|
||||||
void _on_scripts_domain_unloaded();
|
void _on_scripts_domain_about_to_unload();
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
EditorPlugin *godotsharp_editor = nullptr;
|
EditorPlugin *godotsharp_editor = nullptr;
|
||||||
|
@ -416,6 +363,7 @@ public:
|
||||||
StringNameCache string_names;
|
StringNameCache string_names;
|
||||||
|
|
||||||
const Mutex &get_language_bind_mutex() { return language_bind_mutex; }
|
const Mutex &get_language_bind_mutex() { return language_bind_mutex; }
|
||||||
|
const Mutex &get_script_instances_mutex() { return script_instances_mutex; }
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_language_index() { return lang_idx; }
|
_FORCE_INLINE_ int get_language_index() { return lang_idx; }
|
||||||
void set_language_index(int p_idx);
|
void set_language_index(int p_idx);
|
||||||
|
@ -429,7 +377,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void release_script_gchandle(MonoGCHandleData &p_gchandle);
|
static void release_script_gchandle(MonoGCHandleData &p_gchandle);
|
||||||
static void release_script_gchandle(MonoObject *p_expected_obj, MonoGCHandleData &p_gchandle);
|
static void release_script_gchandle(void *p_expected_mono_obj_unused, MonoGCHandleData &p_gchandle);
|
||||||
|
|
||||||
bool debug_break(const String &p_error, bool p_allow_continue = true);
|
bool debug_break(const String &p_error, bool p_allow_continue = true);
|
||||||
bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
|
bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
|
||||||
|
@ -441,12 +389,6 @@ public:
|
||||||
|
|
||||||
_FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
|
_FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
|
||||||
|
|
||||||
void lookup_scripts_in_assembly(GDMonoAssembly *p_assembly);
|
|
||||||
|
|
||||||
const DotNetScriptLookupInfo *lookup_dotnet_script(const String &p_script_path) const {
|
|
||||||
return dotnet_script_lookup_map.getptr(p_script_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
String get_name() const override;
|
String get_name() const override;
|
||||||
|
|
||||||
/* LANGUAGE FUNCTIONS */
|
/* LANGUAGE FUNCTIONS */
|
||||||
|
@ -514,15 +456,18 @@ public:
|
||||||
bool overrides_external_editor() override;
|
bool overrides_external_editor() override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* THREAD ATTACHING */
|
|
||||||
void thread_enter() override;
|
|
||||||
void thread_exit() override;
|
|
||||||
|
|
||||||
Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
|
Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
|
||||||
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
|
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
|
||||||
|
|
||||||
|
static void tie_native_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, const StringName *p_native_name, bool p_ref_counted);
|
||||||
|
static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, CSharpScript *p_script, bool p_ref_counted);
|
||||||
|
static void tie_managed_to_unmanaged_with_pre_setup(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged);
|
||||||
|
|
||||||
|
#warning TODO
|
||||||
|
#if 0
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
|
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void post_unsafe_reference(Object *p_obj);
|
void post_unsafe_reference(Object *p_obj);
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
</tutorials>
|
</tutorials>
|
||||||
<methods>
|
<methods>
|
||||||
<method name="new" qualifiers="vararg">
|
<method name="new" qualifiers="vararg">
|
||||||
<return type="Variant">
|
<return type="Variant" />
|
||||||
</return>
|
|
||||||
<description>
|
<description>
|
||||||
Returns a new instance of the script.
|
Returns a new instance of the script.
|
||||||
</description>
|
</description>
|
||||||
|
|
|
@ -10,64 +10,10 @@
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
<methods>
|
<methods>
|
||||||
<method name="attach_thread">
|
|
||||||
<return type="void">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Attaches the current thread to the Mono runtime.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="detach_thread">
|
|
||||||
<return type="void">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Detaches the current thread from the Mono runtime.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="get_domain_id">
|
|
||||||
<return type="int">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Returns the current MonoDomain ID.
|
|
||||||
[b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="get_scripts_domain_id">
|
|
||||||
<return type="int">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Returns the scripts MonoDomain's ID. This will be the same MonoDomain ID as [method get_domain_id], unless the scripts domain isn't loaded.
|
|
||||||
[b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="is_domain_finalizing_for_unload">
|
|
||||||
<return type="bool">
|
|
||||||
</return>
|
|
||||||
<argument index="0" name="domain_id" type="int">
|
|
||||||
</argument>
|
|
||||||
<description>
|
|
||||||
Returns [code]true[/code] if the domain is being finalized, [code]false[/code] otherwise.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="is_runtime_initialized">
|
<method name="is_runtime_initialized">
|
||||||
<return type="bool">
|
<return type="bool" />
|
||||||
</return>
|
|
||||||
<description>
|
<description>
|
||||||
Returns [code]true[/code] if the Mono runtime is initialized, [code]false[/code] otherwise.
|
Returns [code]true[/code] if the .NET runtime is initialized, [code]false[/code] otherwise.
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="is_runtime_shutting_down">
|
|
||||||
<return type="bool">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Returns [code]true[/code] if the Mono runtime is shutting down, [code]false[/code] otherwise.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="is_scripts_domain_loaded">
|
|
||||||
<return type="bool">
|
|
||||||
</return>
|
|
||||||
<description>
|
|
||||||
Returns [code]true[/code] if the scripts domain is loaded, [code]false[/code] otherwise.
|
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Build.Framework" Version="16.5.0" />
|
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" ExcludeAssets="runtime" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
|
<ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid>
|
<ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid>
|
<ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
|
|
@ -1,32 +1,16 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
|
<ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<LangVersion>7.2</LangVersion>
|
<LangVersion>7.2</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Build" Version="16.5.0" />
|
<PackageReference Include="Microsoft.Build" Version="15.1.548" ExcludeAssets="runtime" />
|
||||||
|
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
||||||
<ProjectReference Include="..\GodotTools.Shared\GodotTools.Shared.csproj" />
|
<ProjectReference Include="..\GodotTools.Shared\GodotTools.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!--
|
|
||||||
The Microsoft.Build.Runtime package is too problematic so we create a MSBuild.exe stub. The workaround described
|
|
||||||
here doesn't work with Microsoft.NETFramework.ReferenceAssemblies: https://github.com/microsoft/msbuild/issues/3486
|
|
||||||
We need a MSBuild.exe file as there's an issue in Microsoft.Build where it executes platform dependent code when
|
|
||||||
searching for MSBuild.exe before the fallback to not using it. A stub is fine as it should never be executed.
|
|
||||||
-->
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="MSBuild.exe" CopyToOutputDirectory="Always" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Target Name="CopyMSBuildStubWindows" AfterTargets="Build" Condition=" '$(GodotPlatform)' == 'windows' Or ( '$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT' ) ">
|
|
||||||
<PropertyGroup>
|
|
||||||
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
|
|
||||||
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<!-- Need to copy it here as well on Windows -->
|
|
||||||
<Copy SourceFiles="MSBuild.exe" DestinationFiles="$(GodotOutputDataDir)\Mono\lib\mono\v4.0\MSBuild.exe" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -21,7 +21,8 @@ namespace GodotTools.ProjectEditor
|
||||||
root.Sdk = GodotSdkAttrValue;
|
root.Sdk = GodotSdkAttrValue;
|
||||||
|
|
||||||
var mainGroup = root.AddPropertyGroup();
|
var mainGroup = root.AddPropertyGroup();
|
||||||
mainGroup.AddProperty("TargetFramework", "netstandard2.1");
|
mainGroup.AddProperty("TargetFramework", "net5.0");
|
||||||
|
mainGroup.AddProperty("EnableDynamicLoading", "true");
|
||||||
|
|
||||||
string sanitizedName = IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true);
|
string sanitizedName = IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ namespace GodotTools.ProjectEditor
|
||||||
|
|
||||||
public static class ProjectUtils
|
public static class ProjectUtils
|
||||||
{
|
{
|
||||||
|
public static void MSBuildLocatorRegisterDefaults()
|
||||||
|
=> Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
|
||||||
|
|
||||||
public static MSBuildProject Open(string path)
|
public static MSBuildProject Open(string path)
|
||||||
{
|
{
|
||||||
var root = ProjectRootElement.Open(path);
|
var root = ProjectRootElement.Open(path);
|
||||||
|
@ -42,7 +45,8 @@ namespace GodotTools.ProjectEditor
|
||||||
var root = project.Root;
|
var root = project.Root;
|
||||||
string godotSdkAttrValue = ProjectGenerator.GodotSdkAttrValue;
|
string godotSdkAttrValue = ProjectGenerator.GodotSdkAttrValue;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(root.Sdk) && root.Sdk.Trim().Equals(godotSdkAttrValue, StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrEmpty(root.Sdk) &&
|
||||||
|
root.Sdk.Trim().Equals(godotSdkAttrValue, StringComparison.OrdinalIgnoreCase))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
root.Sdk = godotSdkAttrValue;
|
root.Sdk = godotSdkAttrValue;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="GenerateGodotNupkgsVersions.targets" />
|
<Import Project="GenerateGodotNupkgsVersions.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2012
|
# Visual Studio 2012
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GodotTools.Ides.Rider;
|
using GodotTools.Ides.Rider;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using static GodotTools.Internals.Globals;
|
using static GodotTools.Internals.Globals;
|
||||||
using File = GodotTools.Utils.File;
|
using File = GodotTools.Utils.File;
|
||||||
using OS = GodotTools.Utils.OS;
|
using OS = GodotTools.Utils.OS;
|
||||||
|
@ -159,7 +159,7 @@ namespace GodotTools.Build
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool BuildProjectBlocking(string config, [CanBeNull] string[] targets = null, [CanBeNull] string platform = null)
|
public static bool BuildProjectBlocking(string config, [MaybeNull] string[] targets = null, [MaybeNull] string platform = null)
|
||||||
{
|
{
|
||||||
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets ?? new[] {"Build"}, config, restore: true);
|
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets ?? new[] {"Build"}, config, restore: true);
|
||||||
|
|
||||||
|
@ -178,17 +178,6 @@ namespace GodotTools.Build
|
||||||
if (!File.Exists(buildInfo.Solution))
|
if (!File.Exists(buildInfo.Solution))
|
||||||
return true; // No solution to build
|
return true; // No solution to build
|
||||||
|
|
||||||
// Make sure the API assemblies are up to date before building the project.
|
|
||||||
// We may not have had the chance to update the release API assemblies, and the debug ones
|
|
||||||
// may have been deleted by the user at some point after they were loaded by the Godot editor.
|
|
||||||
string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(buildInfo.Configuration == "ExportRelease" ? "Release" : "Debug");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(apiAssembliesUpdateError))
|
|
||||||
{
|
|
||||||
ShowBuildErrorDialog("Failed to update the Godot API assemblies");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var pr = new EditorProgress("mono_project_debug_build", "Building project solution...", 1))
|
using (var pr = new EditorProgress("mono_project_debug_build", "Building project solution...", 1))
|
||||||
{
|
{
|
||||||
pr.Step("Building project solution", 0);
|
pr.Step("Building project solution", 0);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using File = GodotTools.Utils.File;
|
using File = GodotTools.Utils.File;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using Godot;
|
using Godot;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using static GodotTools.Internals.Globals;
|
using static GodotTools.Internals.Globals;
|
||||||
using File = GodotTools.Utils.File;
|
using File = GodotTools.Utils.File;
|
||||||
|
|
||||||
|
@ -28,7 +27,6 @@ namespace GodotTools.Build
|
||||||
BuildOutputView.UpdateIssuesList();
|
BuildOutputView.UpdateIssuesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[UsedImplicitly]
|
|
||||||
public void BuildSolution()
|
public void BuildSolution()
|
||||||
{
|
{
|
||||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||||
|
@ -57,7 +55,6 @@ namespace GodotTools.Build
|
||||||
Internal.ReloadAssemblies(softReload: false);
|
Internal.ReloadAssemblies(softReload: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UsedImplicitly]
|
|
||||||
private void RebuildSolution()
|
private void RebuildSolution()
|
||||||
{
|
{
|
||||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||||
|
@ -86,7 +83,6 @@ namespace GodotTools.Build
|
||||||
Internal.ReloadAssemblies(softReload: false);
|
Internal.ReloadAssemblies(softReload: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UsedImplicitly]
|
|
||||||
private void CleanSolution()
|
private void CleanSolution()
|
||||||
{
|
{
|
||||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using GodotTools.Build;
|
using GodotTools.Build;
|
||||||
using GodotTools.Core;
|
using GodotTools.Core;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using static GodotTools.Internals.Globals;
|
using static GodotTools.Internals.Globals;
|
||||||
using Directory = GodotTools.Utils.Directory;
|
using Directory = GodotTools.Utils.Directory;
|
||||||
using File = GodotTools.Utils.File;
|
using File = GodotTools.Utils.File;
|
||||||
|
@ -100,7 +101,9 @@ namespace GodotTools.Export
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Path.GetExtension(path) != Internal.CSharpLanguageExtension)
|
if (Path.GetExtension(path) != Internal.CSharpLanguageExtension)
|
||||||
throw new ArgumentException($"Resource of type {Internal.CSharpLanguageType} has an invalid file extension: {path}", nameof(path));
|
throw new ArgumentException(
|
||||||
|
$"Resource of type {Internal.CSharpLanguageType} has an invalid file extension: {path}",
|
||||||
|
nameof(path));
|
||||||
|
|
||||||
// TODO What if the source file is not part of the game's C# project
|
// TODO What if the source file is not part of the game's C# project
|
||||||
|
|
||||||
|
@ -194,7 +197,8 @@ namespace GodotTools.Export
|
||||||
{
|
{
|
||||||
string thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName + ".dll");
|
string thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName + ".dll");
|
||||||
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
||||||
throw new FileNotFoundException($"Assembly not found: '{thisWasmFrameworkAssemblyName}'", thisWasmFrameworkAssemblyPath);
|
throw new FileNotFoundException($"Assembly not found: '{thisWasmFrameworkAssemblyName}'",
|
||||||
|
thisWasmFrameworkAssemblyPath);
|
||||||
assemblies[thisWasmFrameworkAssemblyName] = thisWasmFrameworkAssemblyPath;
|
assemblies[thisWasmFrameworkAssemblyName] = thisWasmFrameworkAssemblyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,17 +210,20 @@ namespace GodotTools.Export
|
||||||
|
|
||||||
foreach (var thisWasmFrameworkAssemblyName in wasmFrameworkAssembliesOneOf)
|
foreach (var thisWasmFrameworkAssemblyName in wasmFrameworkAssembliesOneOf)
|
||||||
{
|
{
|
||||||
string thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName.newName + ".dll");
|
string thisWasmFrameworkAssemblyPath =
|
||||||
|
Path.Combine(bclDir, thisWasmFrameworkAssemblyName.newName + ".dll");
|
||||||
if (File.Exists(thisWasmFrameworkAssemblyPath))
|
if (File.Exists(thisWasmFrameworkAssemblyPath))
|
||||||
{
|
{
|
||||||
assemblies[thisWasmFrameworkAssemblyName.newName] = thisWasmFrameworkAssemblyPath;
|
assemblies[thisWasmFrameworkAssemblyName.newName] = thisWasmFrameworkAssemblyPath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName.oldName + ".dll");
|
thisWasmFrameworkAssemblyPath =
|
||||||
|
Path.Combine(bclDir, thisWasmFrameworkAssemblyName.oldName + ".dll");
|
||||||
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
||||||
{
|
{
|
||||||
throw new FileNotFoundException("Expected one of the following assemblies but none were found: " +
|
throw new FileNotFoundException(
|
||||||
|
"Expected one of the following assemblies but none were found: " +
|
||||||
$"'{thisWasmFrameworkAssemblyName.newName}' / '{thisWasmFrameworkAssemblyName.oldName}'",
|
$"'{thisWasmFrameworkAssemblyName.newName}' / '{thisWasmFrameworkAssemblyName.oldName}'",
|
||||||
thisWasmFrameworkAssemblyPath);
|
thisWasmFrameworkAssemblyPath);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +234,13 @@ namespace GodotTools.Export
|
||||||
}
|
}
|
||||||
|
|
||||||
var initialAssemblies = assemblies.Duplicate();
|
var initialAssemblies = assemblies.Duplicate();
|
||||||
internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
|
godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue;
|
||||||
|
using godot_string buildConfigAux = Marshaling.mono_string_to_godot(buildConfig);
|
||||||
|
using godot_string bclDirAux = Marshaling.mono_string_to_godot(bclDir);
|
||||||
|
godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue;
|
||||||
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
//internal_GetExportedAssemblyDependencies(initialAssembliesAux, buildConfigAux, bclDirAux, ref assembliesAux);
|
||||||
|
|
||||||
AddI18NAssemblies(assemblies, bclDir);
|
AddI18NAssemblies(assemblies, bclDir);
|
||||||
|
|
||||||
|
@ -237,9 +250,12 @@ namespace GodotTools.Export
|
||||||
outputDataDir = ExportDataDirectory(features, platform, isDebug, outputDir);
|
outputDataDir = ExportDataDirectory(features, platform, isDebug, outputDir);
|
||||||
|
|
||||||
string apiConfig = isDebug ? "Debug" : "Release";
|
string apiConfig = isDebug ? "Debug" : "Release";
|
||||||
string resAssembliesDir = Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, apiConfig);
|
// TODO
|
||||||
|
throw new NotImplementedException();
|
||||||
|
string resAssembliesDir = null; // Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, apiConfig);
|
||||||
|
|
||||||
bool assembliesInsidePck = (bool)ProjectSettings.GetSetting("mono/export/export_assemblies_inside_pck") || outputDataDir == null;
|
bool assembliesInsidePck = (bool)ProjectSettings.GetSetting("mono/export/export_assemblies_inside_pck") ||
|
||||||
|
outputDataDir == null;
|
||||||
|
|
||||||
if (!assembliesInsidePck)
|
if (!assembliesInsidePck)
|
||||||
{
|
{
|
||||||
|
@ -277,7 +293,8 @@ namespace GodotTools.Export
|
||||||
}
|
}
|
||||||
|
|
||||||
// AOT compilation
|
// AOT compilation
|
||||||
bool aotEnabled = platform == OS.Platforms.iOS || (bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
|
bool aotEnabled = platform == OS.Platforms.iOS ||
|
||||||
|
(bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
|
||||||
|
|
||||||
if (aotEnabled)
|
if (aotEnabled)
|
||||||
{
|
{
|
||||||
|
@ -296,14 +313,19 @@ namespace GodotTools.Export
|
||||||
LLVMOnly = false,
|
LLVMOnly = false,
|
||||||
LLVMPath = "",
|
LLVMPath = "",
|
||||||
LLVMOutputPath = "",
|
LLVMOutputPath = "",
|
||||||
FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
|
FullAot = platform == OS.Platforms.iOS ||
|
||||||
|
(bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
|
||||||
UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
|
UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
|
||||||
ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? Array.Empty<string>(),
|
ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ??
|
||||||
ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? Array.Empty<string>(),
|
Array.Empty<string>(),
|
||||||
|
ExtraOptimizerOptions =
|
||||||
|
(string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ??
|
||||||
|
Array.Empty<string>(),
|
||||||
ToolchainPath = aotToolchainPath
|
ToolchainPath = aotToolchainPath
|
||||||
};
|
};
|
||||||
|
|
||||||
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
|
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir,
|
||||||
|
outputDataDir, assemblies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +339,9 @@ namespace GodotTools.Export
|
||||||
Directory.Delete(aotTempDir, recursive: true);
|
Directory.Delete(aotTempDir, recursive: true);
|
||||||
|
|
||||||
// TODO: Just a workaround until the export plugins can be made to abort with errors
|
// TODO: Just a workaround until the export plugins can be made to abort with errors
|
||||||
if (!string.IsNullOrEmpty(maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
|
if (
|
||||||
|
!string.IsNullOrEmpty(
|
||||||
|
maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
|
||||||
{
|
{
|
||||||
string lastExportError = maybeLastExportError;
|
string lastExportError = maybeLastExportError;
|
||||||
maybeLastExportError = null;
|
maybeLastExportError = null;
|
||||||
|
@ -326,7 +350,7 @@ namespace GodotTools.Export
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NotNull]
|
[return: NotNull]
|
||||||
private static string ExportDataDirectory(string[] features, string platform, bool isDebug, string outputDir)
|
private static string ExportDataDirectory(string[] features, string platform, bool isDebug, string outputDir)
|
||||||
{
|
{
|
||||||
string target = isDebug ? "release_debug" : "release";
|
string target = isDebug ? "release_debug" : "release";
|
||||||
|
@ -381,7 +405,8 @@ namespace GodotTools.Export
|
||||||
private static bool PlatformHasTemplateDir(string platform)
|
private static bool PlatformHasTemplateDir(string platform)
|
||||||
{
|
{
|
||||||
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
|
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
|
||||||
return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
|
return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }
|
||||||
|
.Contains(platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
|
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
|
||||||
|
@ -474,9 +499,5 @@ namespace GodotTools.Export
|
||||||
string appNameSafe = appName.ToSafeDirName();
|
string appNameSafe = appName.ToSafeDirName();
|
||||||
return $"data_{appNameSafe}";
|
return $"data_{appNameSafe}";
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
|
|
||||||
string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,10 @@ namespace GodotTools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
private bool CreateProjectSolution()
|
private bool CreateProjectSolution()
|
||||||
{
|
{
|
||||||
using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 3))
|
using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2))
|
||||||
{
|
{
|
||||||
pr.Step("Generating C# project...".TTR());
|
pr.Step("Generating C# project...".TTR());
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ namespace GodotTools
|
||||||
{
|
{
|
||||||
Guid = guid,
|
Guid = guid,
|
||||||
PathRelativeToSolution = name + ".csproj",
|
PathRelativeToSolution = name + ".csproj",
|
||||||
Configs = new List<string> {"Debug", "ExportDebug", "ExportRelease"}
|
Configs = new List<string> { "Debug", "ExportDebug", "ExportRelease" }
|
||||||
};
|
};
|
||||||
|
|
||||||
solution.AddNewProject(name, projectInfo);
|
solution.AddNewProject(name, projectInfo);
|
||||||
|
@ -89,24 +90,6 @@ namespace GodotTools
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr.Step("Updating Godot API assemblies...".TTR());
|
|
||||||
|
|
||||||
string debugApiAssembliesError = Internal.UpdateApiAssembliesFromPrebuilt("Debug");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(debugApiAssembliesError))
|
|
||||||
{
|
|
||||||
ShowErrorDialog("Failed to update the Godot API assemblies: " + debugApiAssembliesError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string releaseApiAssembliesError = Internal.UpdateApiAssembliesFromPrebuilt("Release");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(releaseApiAssembliesError))
|
|
||||||
{
|
|
||||||
ShowErrorDialog("Failed to update the Godot API assemblies: " + releaseApiAssembliesError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr.Step("Done".TTR());
|
pr.Step("Done".TTR());
|
||||||
|
|
||||||
// Here, after all calls to progress_task_step
|
// Here, after all calls to progress_task_step
|
||||||
|
@ -140,7 +123,8 @@ namespace GodotTools
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string fallbackFolder = NuGetUtils.GodotFallbackFolderPath;
|
string fallbackFolder = NuGetUtils.GodotFallbackFolderPath;
|
||||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, fallbackFolder);
|
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName,
|
||||||
|
fallbackFolder);
|
||||||
NuGetUtils.AddBundledPackagesToFallbackFolder(fallbackFolder);
|
NuGetUtils.AddBundledPackagesToFallbackFolder(fallbackFolder);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -218,13 +202,15 @@ namespace GodotTools
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Godot.OS.IsStdoutVerbose())
|
if (Godot.OS.IsStdoutVerbose())
|
||||||
Console.WriteLine($"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}");
|
Console.WriteLine(
|
||||||
|
$"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}");
|
||||||
|
|
||||||
OS.RunProcess(command, args);
|
OS.RunProcess(command, args);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
GD.PushError($"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'");
|
GD.PushError(
|
||||||
|
$"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -395,6 +381,8 @@ namespace GodotTools
|
||||||
{
|
{
|
||||||
base._EnablePlugin();
|
base._EnablePlugin();
|
||||||
|
|
||||||
|
ProjectUtils.MSBuildLocatorRegisterDefaults();
|
||||||
|
|
||||||
if (Instance != null)
|
if (Instance != null)
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
@ -410,7 +398,7 @@ namespace GodotTools
|
||||||
MSBuildPanel = new MSBuildPanel();
|
MSBuildPanel = new MSBuildPanel();
|
||||||
bottomPanelBtn = AddControlToBottomPanel(MSBuildPanel, "MSBuild".TTR());
|
bottomPanelBtn = AddControlToBottomPanel(MSBuildPanel, "MSBuild".TTR());
|
||||||
|
|
||||||
AddChild(new HotReloadAssemblyWatcher {Name = "HotReloadAssemblyWatcher"});
|
AddChild(new HotReloadAssemblyWatcher { Name = "HotReloadAssemblyWatcher" });
|
||||||
|
|
||||||
menuPopup = new PopupMenu();
|
menuPopup = new PopupMenu();
|
||||||
menuPopup.Hide();
|
menuPopup.Hide();
|
||||||
|
@ -482,7 +470,8 @@ namespace GodotTools
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// At startup we make sure NuGet.Config files have our Godot NuGet fallback folder included
|
// At startup we make sure NuGet.Config files have our Godot NuGet fallback folder included
|
||||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, NuGetUtils.GodotFallbackFolderPath);
|
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName,
|
||||||
|
NuGetUtils.GodotFallbackFolderPath);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -528,8 +517,9 @@ namespace GodotTools
|
||||||
public static GodotSharpEditor Instance { get; private set; }
|
public static GodotSharpEditor Instance { get; private set; }
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
private GodotSharpEditor()
|
private static IntPtr InternalCreateInstance()
|
||||||
{
|
{
|
||||||
|
return new GodotSharpEditor().NativeInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
|
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<LangVersion>7.2</LangVersion>
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
|
<LangVersion>8</LangVersion>
|
||||||
<!-- The Godot editor uses the Debug Godot API assemblies -->
|
<!-- The Godot editor uses the Debug Godot API assemblies -->
|
||||||
<GodotApiConfiguration>Debug</GodotApiConfiguration>
|
<GodotApiConfiguration>Debug</GodotApiConfiguration>
|
||||||
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
|
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
|
||||||
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
|
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
|
||||||
<GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
|
<GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') ">
|
<PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') ">
|
||||||
<!-- The project is part of the Godot source tree -->
|
<!-- The project is part of the Godot source tree -->
|
||||||
|
@ -20,6 +22,8 @@
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
<!-- For RiderPathLocator -->
|
||||||
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
<Reference Include="GodotSharp">
|
<Reference Include="GodotSharp">
|
||||||
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using static GodotTools.Internals.Globals;
|
using static GodotTools.Internals.Globals;
|
||||||
|
|
||||||
namespace GodotTools
|
namespace GodotTools
|
||||||
|
@ -25,6 +26,7 @@ namespace GodotTools
|
||||||
Internal.ReloadAssemblies(softReload: false);
|
Internal.ReloadAssemblies(softReload: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
public void RestartTimer()
|
public void RestartTimer()
|
||||||
{
|
{
|
||||||
watchTimer.Stop();
|
watchTimer.Stop();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
using Godot;
|
using Godot;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Directory = System.IO.Directory;
|
using Directory = System.IO.Directory;
|
||||||
|
@ -112,6 +113,7 @@ namespace GodotTools.Ides.Rider
|
||||||
return installInfos.ToArray();
|
return installInfos.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
private static RiderInfo[] CollectRiderInfosWindows()
|
private static RiderInfo[] CollectRiderInfosWindows()
|
||||||
{
|
{
|
||||||
var installInfos = new List<RiderInfo>();
|
var installInfos = new List<RiderInfo>();
|
||||||
|
@ -216,6 +218,7 @@ namespace GodotTools.Ides.Rider
|
||||||
throw new Exception("Unknown OS.");
|
throw new Exception("Unknown OS.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
|
private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
|
||||||
{
|
{
|
||||||
using (var key = Registry.CurrentUser.OpenSubKey(registryKey))
|
using (var key = Registry.CurrentUser.OpenSubKey(registryKey))
|
||||||
|
@ -228,6 +231,7 @@ namespace GodotTools.Ides.Rider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
private static void CollectPathsFromRegistry(List<string> installPaths, RegistryKey key)
|
private static void CollectPathsFromRegistry(List<string> installPaths, RegistryKey key)
|
||||||
{
|
{
|
||||||
if (key == null) return;
|
if (key == null) return;
|
||||||
|
@ -323,7 +327,7 @@ namespace GodotTools.Ides.Rider
|
||||||
{
|
{
|
||||||
public string install_location;
|
public string install_location;
|
||||||
|
|
||||||
[CanBeNull]
|
[return: MaybeNull]
|
||||||
public static string GetInstallLocationFromJson(string json)
|
public static string GetInstallLocationFromJson(string json)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -377,7 +381,7 @@ namespace GodotTools.Ides.Rider
|
||||||
public string version;
|
public string version;
|
||||||
public string versionSuffix;
|
public string versionSuffix;
|
||||||
|
|
||||||
[CanBeNull]
|
[return: MaybeNull]
|
||||||
internal static ProductInfo GetProductInfo(string json)
|
internal static ProductInfo GetProductInfo(string json)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -401,7 +405,7 @@ namespace GodotTools.Ides.Rider
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ActiveApplication active_application;
|
public ActiveApplication active_application;
|
||||||
|
|
||||||
[CanBeNull]
|
[return: MaybeNull]
|
||||||
public static string GetLatestBuildFromJson(string json)
|
public static string GetLatestBuildFromJson(string json)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace GodotTools.Internals
|
namespace GodotTools.Internals
|
||||||
{
|
{
|
||||||
|
@ -8,19 +9,12 @@ namespace GodotTools.Internals
|
||||||
{
|
{
|
||||||
public string Task { get; }
|
public string Task { get; }
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern void internal_Create(string task, string label, int amount, bool canCancel);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern void internal_Dispose(string task);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern bool internal_Step(string task, string state, int step, bool forceRefresh);
|
|
||||||
|
|
||||||
public EditorProgress(string task, string label, int amount, bool canCancel = false)
|
public EditorProgress(string task, string label, int amount, bool canCancel = false)
|
||||||
{
|
{
|
||||||
Task = task;
|
Task = task;
|
||||||
internal_Create(task, label, amount, canCancel);
|
using godot_string taskIn = Marshaling.mono_string_to_godot(task);
|
||||||
|
using godot_string labelIn = Marshaling.mono_string_to_godot(label);
|
||||||
|
Internal.godot_icall_EditorProgress_Create(taskIn, labelIn, amount, canCancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
~EditorProgress()
|
~EditorProgress()
|
||||||
|
@ -33,18 +27,23 @@ namespace GodotTools.Internals
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
internal_Dispose(Task);
|
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||||
|
Internal.godot_icall_EditorProgress_Dispose(taskIn);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Step(string state, int step = -1, bool forceRefresh = true)
|
public void Step(string state, int step = -1, bool forceRefresh = true)
|
||||||
{
|
{
|
||||||
internal_Step(Task, state, step, forceRefresh);
|
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||||
|
using godot_string stateIn = Marshaling.mono_string_to_godot(state);
|
||||||
|
Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryStep(string state, int step = -1, bool forceRefresh = true)
|
public bool TryStep(string state, int step = -1, bool forceRefresh = true)
|
||||||
{
|
{
|
||||||
return internal_Step(Task, state, step, forceRefresh);
|
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||||
|
using godot_string stateIn = Marshaling.mono_string_to_godot(state);
|
||||||
|
return Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Godot.NativeInterop;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
@ -5,29 +6,33 @@ namespace GodotTools.Internals
|
||||||
{
|
{
|
||||||
public static class Globals
|
public static class Globals
|
||||||
{
|
{
|
||||||
public static float EditorScale => internal_EditorScale();
|
public static float EditorScale => Internal.godot_icall_Globals_EditorScale();
|
||||||
|
|
||||||
public static object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false) =>
|
public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
|
||||||
internal_GlobalDef(setting, defaultValue, restartIfChanged);
|
{
|
||||||
|
using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
|
||||||
|
using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
|
||||||
|
Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
|
||||||
|
using (result)
|
||||||
|
return Marshaling.variant_to_mono_object(&result);
|
||||||
|
}
|
||||||
|
|
||||||
public static object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) =>
|
public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
|
||||||
internal_EditorDef(setting, defaultValue, restartIfChanged);
|
{
|
||||||
|
using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
|
||||||
|
using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
|
||||||
|
Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
|
||||||
|
using (result)
|
||||||
|
return Marshaling.variant_to_mono_object(&result);
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||||
public static string TTR(this string text) => internal_TTR(text);
|
public static string TTR(this string text)
|
||||||
|
{
|
||||||
// Internal Calls
|
using godot_string textIn = Marshaling.mono_string_to_godot(text);
|
||||||
|
Internal.godot_icall_Globals_TTR(textIn, out godot_string dest);
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
using (dest)
|
||||||
private static extern float internal_EditorScale();
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern object internal_GlobalDef(string setting, object defaultValue, bool restartIfChanged);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern object internal_EditorDef(string setting, object defaultValue, bool restartIfChanged);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_TTR(string text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +1,78 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace GodotTools.Internals
|
namespace GodotTools.Internals
|
||||||
{
|
{
|
||||||
public static class GodotSharpDirs
|
public static class GodotSharpDirs
|
||||||
{
|
{
|
||||||
public static string ResDataDir => internal_ResDataDir();
|
public static string ResMetadataDir
|
||||||
public static string ResMetadataDir => internal_ResMetadataDir();
|
{
|
||||||
public static string ResAssembliesBaseDir => internal_ResAssembliesBaseDir();
|
get
|
||||||
public static string ResAssembliesDir => internal_ResAssembliesDir();
|
{
|
||||||
public static string ResConfigDir => internal_ResConfigDir();
|
Internal.godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string dest);
|
||||||
public static string ResTempDir => internal_ResTempDir();
|
using (dest)
|
||||||
public static string ResTempAssembliesBaseDir => internal_ResTempAssembliesBaseDir();
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
public static string ResTempAssembliesDir => internal_ResTempAssembliesDir();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string MonoUserDir => internal_MonoUserDir();
|
public static string ResTempAssembliesBaseDir
|
||||||
public static string MonoLogsDir => internal_MonoLogsDir();
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Tools-only
|
public static string MonoUserDir
|
||||||
public static string MonoSolutionsDir => internal_MonoSolutionsDir();
|
{
|
||||||
public static string BuildLogsDirs => internal_BuildLogsDirs();
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_MonoUserDir(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string ProjectSlnPath => internal_ProjectSlnPath();
|
public static string BuildLogsDirs
|
||||||
public static string ProjectCsProjPath => internal_ProjectCsProjPath();
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string DataEditorToolsDir => internal_DataEditorToolsDir();
|
public static string ProjectSlnPath
|
||||||
public static string DataEditorPrebuiltApiDir => internal_DataEditorPrebuiltApiDir();
|
{
|
||||||
#endregion
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string DataMonoEtcDir => internal_DataMonoEtcDir();
|
public static string ProjectCsProjPath
|
||||||
public static string DataMonoLibDir => internal_DataMonoLibDir();
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Windows-only
|
public static string DataEditorToolsDir
|
||||||
public static string DataMonoBinDir => internal_DataMonoBinDir();
|
{
|
||||||
#endregion
|
get
|
||||||
|
{
|
||||||
|
Internal.godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string dest);
|
||||||
#region Internal
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
}
|
||||||
private static extern string internal_ResDataDir();
|
}
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResMetadataDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResAssembliesBaseDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResAssembliesDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResConfigDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResTempDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResTempAssembliesBaseDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ResTempAssembliesDir();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_MonoUserDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_MonoLogsDir();
|
|
||||||
|
|
||||||
#region Tools-only
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_MonoSolutionsDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_BuildLogsDirs();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ProjectSlnPath();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_ProjectCsProjPath();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_DataEditorToolsDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_DataEditorPrebuiltApiDir();
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_DataMonoEtcDir();
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_DataMonoLibDir();
|
|
||||||
|
|
||||||
#region Windows-only
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string internal_DataMonoBinDir();
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,114 +1,189 @@
|
||||||
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
using GodotTools.IdeMessaging.Requests;
|
using GodotTools.IdeMessaging.Requests;
|
||||||
|
|
||||||
namespace GodotTools.Internals
|
namespace GodotTools.Internals
|
||||||
{
|
{
|
||||||
public static class Internal
|
internal static class Internal
|
||||||
{
|
{
|
||||||
public const string CSharpLanguageType = "CSharpScript";
|
public const string CSharpLanguageType = "CSharpScript";
|
||||||
public const string CSharpLanguageExtension = ".cs";
|
public const string CSharpLanguageExtension = ".cs";
|
||||||
|
|
||||||
public static string UpdateApiAssembliesFromPrebuilt(string config) =>
|
public static string FullTemplatesDir
|
||||||
internal_UpdateApiAssembliesFromPrebuilt(config);
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
godot_icall_Internal_FullTemplatesDir(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string FullTemplatesDir =>
|
public static string SimplifyGodotPath(this string path)
|
||||||
internal_FullTemplatesDir();
|
{
|
||||||
|
using godot_string pathIn = Marshaling.mono_string_to_godot(path);
|
||||||
|
godot_icall_Internal_SimplifyGodotPath(pathIn, out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
|
||||||
public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path);
|
public static bool IsOsxAppBundleInstalled(string bundleId)
|
||||||
|
{
|
||||||
|
using godot_string bundleIdIn = Marshaling.mono_string_to_godot(bundleId);
|
||||||
|
return godot_icall_Internal_IsOsxAppBundleInstalled(bundleIdIn);
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId);
|
public static bool GodotIs32Bits() => godot_icall_Internal_GodotIs32Bits();
|
||||||
|
|
||||||
public static bool GodotIs32Bits() => internal_GodotIs32Bits();
|
public static bool GodotIsRealTDouble() => godot_icall_Internal_GodotIsRealTDouble();
|
||||||
|
|
||||||
public static bool GodotIsRealTDouble() => internal_GodotIsRealTDouble();
|
public static void GodotMainIteration() => godot_icall_Internal_GodotMainIteration();
|
||||||
|
|
||||||
public static void GodotMainIteration() => internal_GodotMainIteration();
|
public static bool IsAssembliesReloadingNeeded() => godot_icall_Internal_IsAssembliesReloadingNeeded();
|
||||||
|
|
||||||
public static ulong GetCoreApiHash() => internal_GetCoreApiHash();
|
public static void ReloadAssemblies(bool softReload) => godot_icall_Internal_ReloadAssemblies(softReload);
|
||||||
|
|
||||||
public static ulong GetEditorApiHash() => internal_GetEditorApiHash();
|
public static void EditorDebuggerNodeReloadScripts() => godot_icall_Internal_EditorDebuggerNodeReloadScripts();
|
||||||
|
|
||||||
public static bool IsAssembliesReloadingNeeded() => internal_IsAssembliesReloadingNeeded();
|
|
||||||
|
|
||||||
public static void ReloadAssemblies(bool softReload) => internal_ReloadAssemblies(softReload);
|
|
||||||
|
|
||||||
public static void EditorDebuggerNodeReloadScripts() => internal_EditorDebuggerNodeReloadScripts();
|
|
||||||
|
|
||||||
public static bool ScriptEditorEdit(Resource resource, int line, int col, bool grabFocus = true) =>
|
public static bool ScriptEditorEdit(Resource resource, int line, int col, bool grabFocus = true) =>
|
||||||
internal_ScriptEditorEdit(resource, line, col, grabFocus);
|
godot_icall_Internal_ScriptEditorEdit(resource.NativeInstance, line, col, grabFocus);
|
||||||
|
|
||||||
public static void EditorNodeShowScriptScreen() => internal_EditorNodeShowScriptScreen();
|
public static void EditorNodeShowScriptScreen() => godot_icall_Internal_EditorNodeShowScriptScreen();
|
||||||
|
|
||||||
public static string MonoWindowsInstallRoot => internal_MonoWindowsInstallRoot();
|
public static string MonoWindowsInstallRoot
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void EditorRunPlay() => internal_EditorRunPlay();
|
public static void EditorRunPlay() => godot_icall_Internal_EditorRunPlay();
|
||||||
|
|
||||||
public static void EditorRunStop() => internal_EditorRunStop();
|
public static void EditorRunStop() => godot_icall_Internal_EditorRunStop();
|
||||||
|
|
||||||
public static void ScriptEditorDebugger_ReloadScripts() => internal_ScriptEditorDebugger_ReloadScripts();
|
public static void ScriptEditorDebugger_ReloadScripts() =>
|
||||||
|
godot_icall_Internal_ScriptEditorDebugger_ReloadScripts();
|
||||||
|
|
||||||
public static string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind, string scriptFile) =>
|
public static unsafe string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind,
|
||||||
internal_CodeCompletionRequest((int)kind, scriptFile);
|
string scriptFile)
|
||||||
|
{
|
||||||
|
using godot_string scriptFileIn = Marshaling.mono_string_to_godot(scriptFile);
|
||||||
|
godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res);
|
||||||
|
using (res)
|
||||||
|
return Marshaling.PackedStringArray_to_mono_array(&res);
|
||||||
|
}
|
||||||
|
|
||||||
#region Internal
|
#region Internal
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
private const string GodotDllName = "__Internal";
|
||||||
private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern string internal_FullTemplatesDir();
|
public static extern void godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern string internal_SimplifyGodotPath(this string path);
|
public static extern void godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern bool internal_IsOsxAppBundleInstalled(string bundleId);
|
public static extern void godot_icall_GodotSharpDirs_MonoUserDir(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern bool internal_GodotIs32Bits();
|
public static extern void godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern bool internal_GodotIsRealTDouble();
|
public static extern void godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_GodotMainIteration();
|
public static extern void godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern ulong internal_GetCoreApiHash();
|
public static extern void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern ulong internal_GetEditorApiHash();
|
public static extern void godot_icall_EditorProgress_Create(in godot_string task, in godot_string label,
|
||||||
|
int amount, bool canCancel);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern bool internal_IsAssembliesReloadingNeeded();
|
public static extern void godot_icall_EditorProgress_Dispose(in godot_string task);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_ReloadAssemblies(bool softReload);
|
public static extern bool godot_icall_EditorProgress_Step(in godot_string task, in godot_string state, int step,
|
||||||
|
bool forceRefresh);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_EditorDebuggerNodeReloadScripts();
|
private static extern void godot_icall_Internal_FullTemplatesDir(out godot_string dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern bool internal_ScriptEditorEdit(Resource resource, int line, int col, bool grabFocus);
|
private static extern void godot_icall_Internal_SimplifyGodotPath(in godot_string path, out godot_string dest);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_EditorNodeShowScriptScreen();
|
private static extern bool godot_icall_Internal_IsOsxAppBundleInstalled(in godot_string bundleId);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern string internal_MonoWindowsInstallRoot();
|
private static extern bool godot_icall_Internal_GodotIs32Bits();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_EditorRunPlay();
|
private static extern bool godot_icall_Internal_GodotIsRealTDouble();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_EditorRunStop();
|
private static extern void godot_icall_Internal_GodotMainIteration();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern void internal_ScriptEditorDebugger_ReloadScripts();
|
private static extern bool godot_icall_Internal_IsAssembliesReloadingNeeded();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[DllImport(GodotDllName)]
|
||||||
private static extern string[] internal_CodeCompletionRequest(int kind, string scriptFile);
|
private static extern void godot_icall_Internal_ReloadAssemblies(bool softReload);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_EditorDebuggerNodeReloadScripts();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern bool godot_icall_Internal_ScriptEditorEdit(IntPtr resource, int line, int col,
|
||||||
|
bool grabFocus);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_EditorNodeShowScriptScreen();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_EditorRunPlay();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_EditorRunStop();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
private static extern void godot_icall_Internal_CodeCompletionRequest(int kind, in godot_string scriptFile,
|
||||||
|
out godot_packed_string_array res);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern float godot_icall_Globals_EditorScale();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godot_icall_Globals_GlobalDef(in godot_string setting, in godot_variant defaultValue,
|
||||||
|
bool restartIfChanged, out godot_variant result);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godot_icall_Globals_EditorDef(in godot_string setting, in godot_variant defaultValue,
|
||||||
|
bool restartIfChanged, out godot_variant result);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godot_icall_Globals_TTR(in godot_string text, out godot_string dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern bool godot_icall_Utils_OS_UnixFileHasExecutableAccess(in godot_string filePath);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Godot;
|
using Godot;
|
||||||
using GodotTools.Core;
|
using GodotTools.Core;
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace GodotTools.Utils
|
namespace GodotTools.Utils
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ namespace GodotTools.Utils
|
||||||
return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm);
|
return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm);
|
||||||
}
|
}
|
||||||
|
|
||||||
[CanBeNull]
|
[return: MaybeNull]
|
||||||
public static string LocalizePathWithCaseChecked(string path)
|
public static string LocalizePathWithCaseChecked(string path)
|
||||||
{
|
{
|
||||||
string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar;
|
string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Godot.NativeInterop;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -5,19 +6,13 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using JetBrains.Annotations;
|
using GodotTools.Internals;
|
||||||
|
|
||||||
namespace GodotTools.Utils
|
namespace GodotTools.Utils
|
||||||
{
|
{
|
||||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||||
public static class OS
|
public static class OS
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
static extern string GetPlatformName();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
static extern bool UnixFileHasExecutableAccess(string filePath);
|
|
||||||
|
|
||||||
public static class Names
|
public static class Names
|
||||||
{
|
{
|
||||||
public const string Windows = "Windows";
|
public const string Windows = "Windows";
|
||||||
|
@ -63,14 +58,24 @@ namespace GodotTools.Utils
|
||||||
[Names.HTML5] = Platforms.HTML5
|
[Names.HTML5] = Platforms.HTML5
|
||||||
};
|
};
|
||||||
|
|
||||||
private static bool IsOS(string name)
|
private static unsafe bool IsOS(string name)
|
||||||
{
|
{
|
||||||
return name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
|
Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
{
|
||||||
|
string platformName = Marshaling.mono_string_from_godot(dest);
|
||||||
|
return name.Equals(platformName, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsAnyOS(IEnumerable<string> names)
|
private static unsafe bool IsAnyOS(IEnumerable<string> names)
|
||||||
{
|
{
|
||||||
return names.Any(p => p.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase));
|
Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||||
|
using (dest)
|
||||||
|
{
|
||||||
|
string platformName = Marshaling.mono_string_from_godot(dest);
|
||||||
|
return names.Any(p => p.Equals(platformName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly IEnumerable<string> LinuxBSDPlatforms =
|
private static readonly IEnumerable<string> LinuxBSDPlatforms =
|
||||||
|
@ -91,14 +96,23 @@ namespace GodotTools.Utils
|
||||||
private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5));
|
private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5));
|
||||||
private static readonly Lazy<bool> _isUnixLike = new Lazy<bool>(() => IsAnyOS(UnixLikePlatforms));
|
private static readonly Lazy<bool> _isUnixLike = new Lazy<bool>(() => IsAnyOS(UnixLikePlatforms));
|
||||||
|
|
||||||
|
// TODO SupportedOSPlatformGuard once we target .NET 6
|
||||||
|
// [SupportedOSPlatformGuard("windows")]
|
||||||
public static bool IsWindows => _isWindows.Value || IsUWP;
|
public static bool IsWindows => _isWindows.Value || IsUWP;
|
||||||
|
// [SupportedOSPlatformGuard("osx")]
|
||||||
public static bool IsMacOS => _isMacOS.Value;
|
public static bool IsMacOS => _isMacOS.Value;
|
||||||
|
// [SupportedOSPlatformGuard("linux")]
|
||||||
public static bool IsLinuxBSD => _isLinuxBSD.Value;
|
public static bool IsLinuxBSD => _isLinuxBSD.Value;
|
||||||
|
// [SupportedOSPlatformGuard("linux")]
|
||||||
public static bool IsServer => _isServer.Value;
|
public static bool IsServer => _isServer.Value;
|
||||||
|
// [SupportedOSPlatformGuard("windows")]
|
||||||
public static bool IsUWP => _isUWP.Value;
|
public static bool IsUWP => _isUWP.Value;
|
||||||
public static bool IsHaiku => _isHaiku.Value;
|
public static bool IsHaiku => _isHaiku.Value;
|
||||||
|
// [SupportedOSPlatformGuard("android")]
|
||||||
public static bool IsAndroid => _isAndroid.Value;
|
public static bool IsAndroid => _isAndroid.Value;
|
||||||
|
// [SupportedOSPlatformGuard("ios")]
|
||||||
public static bool IsiOS => _isiOS.Value;
|
public static bool IsiOS => _isiOS.Value;
|
||||||
|
// [SupportedOSPlatformGuard("browser")]
|
||||||
public static bool IsHTML5 => _isHTML5.Value;
|
public static bool IsHTML5 => _isHTML5.Value;
|
||||||
public static bool IsUnixLike => _isUnixLike.Value;
|
public static bool IsUnixLike => _isUnixLike.Value;
|
||||||
|
|
||||||
|
@ -111,7 +125,8 @@ namespace GodotTools.Utils
|
||||||
|
|
||||||
private static string PathWhichWindows([NotNull] string name)
|
private static string PathWhichWindows([NotNull] string name)
|
||||||
{
|
{
|
||||||
string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
|
string[] windowsExts =
|
||||||
|
Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
|
||||||
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
|
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
|
||||||
char[] invalidPathChars = Path.GetInvalidPathChars();
|
char[] invalidPathChars = Path.GetInvalidPathChars();
|
||||||
|
|
||||||
|
@ -129,7 +144,8 @@ namespace GodotTools.Utils
|
||||||
}
|
}
|
||||||
|
|
||||||
string nameExt = Path.GetExtension(name);
|
string nameExt = Path.GetExtension(name);
|
||||||
bool hasPathExt = !string.IsNullOrEmpty(nameExt) && windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
|
bool hasPathExt = !string.IsNullOrEmpty(nameExt) &&
|
||||||
|
windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
||||||
|
|
||||||
|
@ -164,7 +180,11 @@ namespace GodotTools.Utils
|
||||||
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
||||||
|
|
||||||
return searchDirs.Select(dir => Path.Combine(dir, name))
|
return searchDirs.Select(dir => Path.Combine(dir, name))
|
||||||
.FirstOrDefault(path => File.Exists(path) && UnixFileHasExecutableAccess(path));
|
.FirstOrDefault(path =>
|
||||||
|
{
|
||||||
|
using godot_string pathIn = Marshaling.mono_string_to_godot(path);
|
||||||
|
return File.Exists(path) && Internal.godot_icall_Utils_OS_UnixFileHasExecutableAccess(pathIn);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RunProcess(string command, IEnumerable<string> arguments)
|
public static void RunProcess(string command, IEnumerable<string> arguments)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -218,6 +218,11 @@ class BindingsGenerator {
|
||||||
bool is_singleton = false;
|
bool is_singleton = false;
|
||||||
bool is_ref_counted = false;
|
bool is_ref_counted = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the
|
||||||
|
*/
|
||||||
|
bool c_type_is_disposable_struct = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used only by Object-derived types.
|
* Used only by Object-derived types.
|
||||||
* Determines if this type is not abstract (incomplete).
|
* Determines if this type is not abstract (incomplete).
|
||||||
|
@ -232,32 +237,35 @@ class BindingsGenerator {
|
||||||
*/
|
*/
|
||||||
bool memory_own = false;
|
bool memory_own = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* This must be set to true for any struct bigger than 32-bits. Those cannot be passed/returned by value
|
|
||||||
* with internal calls, so we must use pointers instead. Returns must be replace with out parameters.
|
|
||||||
* In this case, [c_out] and [cs_out] must have a different format, explained below.
|
|
||||||
* The Mono IL interpreter icall trampolines don't support passing structs bigger than 32-bits by value (at least not on WASM).
|
|
||||||
*/
|
|
||||||
bool ret_as_byref_arg = false;
|
|
||||||
|
|
||||||
// !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
|
// !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
|
||||||
// !! When renaming those fields, make sure to rename their references in the comments
|
// !! When renaming those fields, make sure to rename their references in the comments
|
||||||
|
|
||||||
// --- C INTERFACE ---
|
// --- C INTERFACE ---
|
||||||
|
|
||||||
static const char *DEFAULT_VARARG_C_IN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
|
* One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
|
||||||
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
||||||
* the name of that local must be specified with [c_arg_in].
|
* the name of that local must be specified with [c_arg_in].
|
||||||
* For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
|
|
||||||
* Formatting elements:
|
* Formatting elements:
|
||||||
* %0: [c_type] of the parameter
|
* %0: [c_type] of the parameter
|
||||||
* %1: name of the parameter
|
* %1: name of the parameter
|
||||||
|
* %2-4: reserved
|
||||||
|
* %5: indentation text
|
||||||
*/
|
*/
|
||||||
String c_in;
|
String c_in;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more statements that manipulate the parameter before being passed as argument of a vararg call.
|
||||||
|
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
||||||
|
* the name of that local must be specified with [c_arg_in].
|
||||||
|
* Formatting elements:
|
||||||
|
* %0: [c_type] of the parameter
|
||||||
|
* %1: name of the parameter
|
||||||
|
* %2-4: reserved
|
||||||
|
* %5: indentation text
|
||||||
|
*/
|
||||||
|
String c_in_vararg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the expression that will be passed as argument to ptrcall.
|
* Determines the expression that will be passed as argument to ptrcall.
|
||||||
* By default the value equals the name of the parameter,
|
* By default the value equals the name of the parameter,
|
||||||
|
@ -281,7 +289,8 @@ class BindingsGenerator {
|
||||||
* %0: [c_type_out] of the return type
|
* %0: [c_type_out] of the return type
|
||||||
* %1: name of the variable to be returned
|
* %1: name of the variable to be returned
|
||||||
* %2: [name] of the return type
|
* %2: [name] of the return type
|
||||||
* %3: name of the parameter that must be assigned the return value
|
* %3-4: reserved
|
||||||
|
* %5: indentation text
|
||||||
*/
|
*/
|
||||||
String c_out;
|
String c_out;
|
||||||
|
|
||||||
|
@ -320,6 +329,7 @@ class BindingsGenerator {
|
||||||
* %0 or %s: name of the parameter
|
* %0 or %s: name of the parameter
|
||||||
*/
|
*/
|
||||||
String cs_in;
|
String cs_in;
|
||||||
|
bool cs_in_is_unsafe = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One or more statements that determine how a variable of this type is returned from a method.
|
* One or more statements that determine how a variable of this type is returned from a method.
|
||||||
|
@ -328,7 +338,9 @@ class BindingsGenerator {
|
||||||
* %0: internal method name
|
* %0: internal method name
|
||||||
* %1: internal method call arguments without surrounding parenthesis
|
* %1: internal method call arguments without surrounding parenthesis
|
||||||
* %2: [cs_type] of the return type
|
* %2: [cs_type] of the return type
|
||||||
* %3: [im_type_out] of the return type
|
* %3: [c_type_out] of the return type
|
||||||
|
* %4: reserved
|
||||||
|
* %5: indentation text
|
||||||
*/
|
*/
|
||||||
String cs_out;
|
String cs_out;
|
||||||
|
|
||||||
|
@ -338,16 +350,6 @@ class BindingsGenerator {
|
||||||
*/
|
*/
|
||||||
String cs_type;
|
String cs_type;
|
||||||
|
|
||||||
/**
|
|
||||||
* Type used for parameters of internal call methods.
|
|
||||||
*/
|
|
||||||
String im_type_in;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type used for the return type of internal call methods.
|
|
||||||
*/
|
|
||||||
String im_type_out;
|
|
||||||
|
|
||||||
const DocData::ClassDoc *class_doc = nullptr;
|
const DocData::ClassDoc *class_doc = nullptr;
|
||||||
|
|
||||||
List<ConstantInterface> constants;
|
List<ConstantInterface> constants;
|
||||||
|
@ -356,6 +358,8 @@ class BindingsGenerator {
|
||||||
List<MethodInterface> methods;
|
List<MethodInterface> methods;
|
||||||
List<SignalInterface> signals_;
|
List<SignalInterface> signals_;
|
||||||
|
|
||||||
|
bool has_virtual_methods = false;
|
||||||
|
|
||||||
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
|
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
|
||||||
for (const MethodInterface &E : methods) {
|
for (const MethodInterface &E : methods) {
|
||||||
if (E.cname == p_cname) {
|
if (E.cname == p_cname) {
|
||||||
|
@ -402,8 +406,8 @@ class BindingsGenerator {
|
||||||
|
|
||||||
itype.c_type = itype.name;
|
itype.c_type = itype.name;
|
||||||
itype.cs_type = itype.proxy_name;
|
itype.cs_type = itype.proxy_name;
|
||||||
itype.im_type_in = "ref " + itype.proxy_name;
|
itype.c_type_in = itype.proxy_name + "*";
|
||||||
itype.im_type_out = itype.proxy_name;
|
itype.c_type_out = itype.proxy_name;
|
||||||
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
|
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,65 +441,26 @@ class BindingsGenerator {
|
||||||
return itype;
|
return itype;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
|
static void postsetup_enum_type(TypeInterface &r_enum_itype);
|
||||||
r_itype.name = p_cname;
|
|
||||||
r_itype.cname = p_cname;
|
|
||||||
r_itype.proxy_name = r_itype.name;
|
|
||||||
|
|
||||||
r_itype.c_type = r_itype.name;
|
|
||||||
r_itype.c_type_in = "MonoObject*";
|
|
||||||
r_itype.c_type_out = "MonoObject*";
|
|
||||||
r_itype.cs_type = r_itype.proxy_name;
|
|
||||||
r_itype.im_type_in = r_itype.proxy_name;
|
|
||||||
r_itype.im_type_out = r_itype.proxy_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void postsetup_enum_type(TypeInterface &r_enum_itype) {
|
|
||||||
// C interface for enums is the same as that of 'uint32_t'. Remember to apply
|
|
||||||
// any of the changes done here to the 'uint32_t' type interface as well.
|
|
||||||
|
|
||||||
r_enum_itype.c_arg_in = "&%s_in";
|
|
||||||
{
|
|
||||||
// The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
|
|
||||||
r_enum_itype.c_in = "\t%0 %1_in = (%0)%1;\n";
|
|
||||||
r_enum_itype.c_out = "\treturn (%0)%1;\n";
|
|
||||||
r_enum_itype.c_type = "int64_t";
|
|
||||||
}
|
|
||||||
r_enum_itype.c_type_in = "int32_t";
|
|
||||||
r_enum_itype.c_type_out = r_enum_itype.c_type_in;
|
|
||||||
|
|
||||||
r_enum_itype.cs_type = r_enum_itype.proxy_name;
|
|
||||||
r_enum_itype.cs_in = "(int)%s";
|
|
||||||
r_enum_itype.cs_out = "return (%2)%0(%1);";
|
|
||||||
r_enum_itype.im_type_in = "int";
|
|
||||||
r_enum_itype.im_type_out = "int";
|
|
||||||
r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name];
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeInterface() {}
|
TypeInterface() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InternalCall {
|
struct InternalCall {
|
||||||
String name;
|
String name;
|
||||||
String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
|
|
||||||
String im_sig; // Signature for the C# method declaration
|
|
||||||
String unique_sig; // Unique signature to avoid duplicates in containers
|
String unique_sig; // Unique signature to avoid duplicates in containers
|
||||||
bool editor_only = false;
|
bool editor_only = false;
|
||||||
|
|
||||||
|
bool is_vararg;
|
||||||
|
TypeReference return_type;
|
||||||
|
List<TypeReference> argument_types;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int get_arguments_count() const { return argument_types.size(); }
|
||||||
|
|
||||||
InternalCall() {}
|
InternalCall() {}
|
||||||
|
|
||||||
InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_unique_sig = String()) {
|
||||||
name = p_name;
|
name = p_name;
|
||||||
im_type_out = p_im_type_out;
|
|
||||||
im_sig = p_im_sig;
|
|
||||||
unique_sig = p_unique_sig;
|
|
||||||
editor_only = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
|
||||||
name = p_name;
|
|
||||||
im_type_out = p_im_type_out;
|
|
||||||
im_sig = p_im_sig;
|
|
||||||
unique_sig = p_unique_sig;
|
unique_sig = p_unique_sig;
|
||||||
editor_only = api_type == ClassDB::API_EDITOR;
|
editor_only = api_type == ClassDB::API_EDITOR;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +475,6 @@ class BindingsGenerator {
|
||||||
|
|
||||||
OrderedHashMap<StringName, TypeInterface> obj_types;
|
OrderedHashMap<StringName, TypeInterface> obj_types;
|
||||||
|
|
||||||
Map<StringName, TypeInterface> placeholder_types;
|
|
||||||
Map<StringName, TypeInterface> builtin_types;
|
Map<StringName, TypeInterface> builtin_types;
|
||||||
Map<StringName, TypeInterface> enum_types;
|
Map<StringName, TypeInterface> enum_types;
|
||||||
|
|
||||||
|
@ -518,13 +482,9 @@ class BindingsGenerator {
|
||||||
List<ConstantInterface> global_constants;
|
List<ConstantInterface> global_constants;
|
||||||
|
|
||||||
List<InternalCall> method_icalls;
|
List<InternalCall> method_icalls;
|
||||||
|
/// Stores the unique internal calls from [method_icalls] that are assigned to each method.
|
||||||
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
|
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
|
||||||
|
|
||||||
List<const InternalCall *> generated_icall_funcs;
|
|
||||||
|
|
||||||
List<InternalCall> core_custom_icalls;
|
|
||||||
List<InternalCall> editor_custom_icalls;
|
|
||||||
|
|
||||||
Map<StringName, List<StringName>> blacklisted_methods;
|
Map<StringName, List<StringName>> blacklisted_methods;
|
||||||
|
|
||||||
void _initialize_blacklisted_methods();
|
void _initialize_blacklisted_methods();
|
||||||
|
@ -536,6 +496,8 @@ class BindingsGenerator {
|
||||||
StringName type_Object = StaticCString::create("Object");
|
StringName type_Object = StaticCString::create("Object");
|
||||||
StringName type_RefCounted = StaticCString::create("RefCounted");
|
StringName type_RefCounted = StaticCString::create("RefCounted");
|
||||||
StringName type_RID = StaticCString::create("RID");
|
StringName type_RID = StaticCString::create("RID");
|
||||||
|
StringName type_Callable = StaticCString::create("Callable");
|
||||||
|
StringName type_Signal = StaticCString::create("Signal");
|
||||||
StringName type_String = StaticCString::create("String");
|
StringName type_String = StaticCString::create("String");
|
||||||
StringName type_StringName = StaticCString::create("StringName");
|
StringName type_StringName = StaticCString::create("StringName");
|
||||||
StringName type_NodePath = StaticCString::create("NodePath");
|
StringName type_NodePath = StaticCString::create("NodePath");
|
||||||
|
@ -601,17 +563,6 @@ class BindingsGenerator {
|
||||||
|
|
||||||
NameCache name_cache;
|
NameCache name_cache;
|
||||||
|
|
||||||
const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
|
|
||||||
const List<InternalCall>::Element *it = p_list.front();
|
|
||||||
while (it) {
|
|
||||||
if (it->get().name == p_name) {
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
it = it->next();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
|
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
|
||||||
for (const ConstantInterface &E : p_constants) {
|
for (const ConstantInterface &E : p_constants) {
|
||||||
if (E.name == p_name) {
|
if (E.name == p_name) {
|
||||||
|
@ -622,10 +573,9 @@ class BindingsGenerator {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String get_unique_sig(const TypeInterface &p_type) {
|
inline String get_arg_unique_sig(const TypeInterface &p_type) {
|
||||||
if (p_type.is_ref_counted) {
|
// For parameters, we treat reference and non-reference derived types the same.
|
||||||
return "Ref";
|
if (p_type.is_object_type) {
|
||||||
} else if (p_type.is_object_type) {
|
|
||||||
return "Obj";
|
return "Obj";
|
||||||
} else if (p_type.is_enum) {
|
} else if (p_type.is_enum) {
|
||||||
return "int";
|
return "int";
|
||||||
|
@ -634,15 +584,27 @@ class BindingsGenerator {
|
||||||
return p_type.name;
|
return p_type.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline String get_ret_unique_sig(const TypeInterface *p_type) {
|
||||||
|
// Reference derived return types are treated differently.
|
||||||
|
if (p_type->is_ref_counted) {
|
||||||
|
return "Ref";
|
||||||
|
} else if (p_type->is_object_type) {
|
||||||
|
return "Obj";
|
||||||
|
} else if (p_type->is_enum) {
|
||||||
|
return "int";
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_type->name;
|
||||||
|
}
|
||||||
|
|
||||||
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
|
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
|
||||||
|
|
||||||
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
||||||
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
||||||
|
|
||||||
void _generate_method_icalls(const TypeInterface &p_itype);
|
Error _populate_method_icalls_table(const TypeInterface &p_itype);
|
||||||
|
|
||||||
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
|
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
|
||||||
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
|
|
||||||
|
|
||||||
StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
||||||
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
||||||
|
@ -661,11 +623,11 @@ class BindingsGenerator {
|
||||||
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
|
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
|
||||||
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
|
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
|
||||||
|
|
||||||
|
Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output);
|
||||||
|
|
||||||
void _generate_array_extensions(StringBuilder &p_output);
|
void _generate_array_extensions(StringBuilder &p_output);
|
||||||
void _generate_global_constants(StringBuilder &p_output);
|
void _generate_global_constants(StringBuilder &p_output);
|
||||||
|
|
||||||
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, StringBuilder &p_output);
|
|
||||||
|
|
||||||
Error _save_file(const String &p_path, const StringBuilder &p_content);
|
Error _save_file(const String &p_path, const StringBuilder &p_content);
|
||||||
|
|
||||||
void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
|
void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
|
||||||
|
@ -676,15 +638,12 @@ public:
|
||||||
Error generate_cs_core_project(const String &p_proj_dir);
|
Error generate_cs_core_project(const String &p_proj_dir);
|
||||||
Error generate_cs_editor_project(const String &p_proj_dir);
|
Error generate_cs_editor_project(const String &p_proj_dir);
|
||||||
Error generate_cs_api(const String &p_output_dir);
|
Error generate_cs_api(const String &p_output_dir);
|
||||||
Error generate_glue(const String &p_output_dir);
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool is_log_print_enabled() { return log_print_enabled; }
|
_FORCE_INLINE_ bool is_log_print_enabled() { return log_print_enabled; }
|
||||||
_FORCE_INLINE_ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; }
|
_FORCE_INLINE_ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; }
|
||||||
|
|
||||||
_FORCE_INLINE_ bool is_initialized() { return initialized; }
|
_FORCE_INLINE_ bool is_initialized() { return initialized; }
|
||||||
|
|
||||||
static uint32_t get_version();
|
|
||||||
|
|
||||||
static void handle_cmdline_args(const List<String> &p_cmdline_args);
|
static void handle_cmdline_args(const List<String> &p_cmdline_args);
|
||||||
|
|
||||||
BindingsGenerator() {
|
BindingsGenerator() {
|
||||||
|
|
|
@ -43,179 +43,120 @@
|
||||||
#include "main/main.h"
|
#include "main/main.h"
|
||||||
|
|
||||||
#include "../csharp_script.h"
|
#include "../csharp_script.h"
|
||||||
#include "../glue/cs_glue_version.gen.h"
|
|
||||||
#include "../godotsharp_dirs.h"
|
#include "../godotsharp_dirs.h"
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
#include "../utils/osx_utils.h"
|
#include "../utils/osx_utils.h"
|
||||||
#include "code_completion.h"
|
#include "code_completion.h"
|
||||||
#include "godotsharp_export.h"
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResDataDir() {
|
#include <gdnative/gdnative.h>
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_data_dir());
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define MAYBE_UNUSED [[maybe_unused]]
|
||||||
|
#else
|
||||||
|
#define MAYBE_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define GD_PINVOKE_EXPORT MAYBE_UNUSED __attribute__((visibility("default")))
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#define GD_PINVOKE_EXPORT MAYBE_UNUSED __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define GD_PINVOKE_EXPORT MAYBE_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void godot_icall_GodotSharpDirs_ResMetadataDir(godot_string *r_dest) {
|
||||||
|
memnew_placement(r_dest, String(GodotSharpDirs::get_res_metadata_dir()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResMetadataDir() {
|
void godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(godot_string *r_dest) {
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_metadata_dir());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_res_temp_assemblies_base_dir()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResAssembliesBaseDir() {
|
void godot_icall_GodotSharpDirs_MonoUserDir(godot_string *r_dest) {
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_assemblies_base_dir());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_mono_user_dir()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResAssembliesDir() {
|
void godot_icall_GodotSharpDirs_BuildLogsDirs(godot_string *r_dest) {
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_assemblies_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResConfigDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_config_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResTempDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_assemblies_base_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ResTempAssembliesDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_assemblies_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_MonoUserDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_user_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_MonoLogsDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_logs_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_MonoSolutionsDir() {
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_solutions_dir());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_build_logs_dir()));
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_BuildLogsDirs() {
|
void godot_icall_GodotSharpDirs_ProjectSlnPath(godot_string *r_dest) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_build_logs_dir());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_project_sln_path()));
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ProjectSlnPath() {
|
void godot_icall_GodotSharpDirs_ProjectCsProjPath(godot_string *r_dest) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_sln_path());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_project_csproj_path()));
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_ProjectCsProjPath() {
|
void godot_icall_GodotSharpDirs_DataEditorToolsDir(godot_string *r_dest) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_csproj_path());
|
memnew_placement(r_dest, String(GodotSharpDirs::get_data_editor_tools_dir()));
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_DataEditorToolsDir() {
|
void godot_icall_EditorProgress_Create(const godot_string *p_task, const godot_string *p_label, int32_t p_amount, bool p_can_cancel) {
|
||||||
#ifdef TOOLS_ENABLED
|
String task = *reinterpret_cast<const String *>(p_task);
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_tools_dir());
|
String label = *reinterpret_cast<const String *>(p_label);
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_DataEditorPrebuiltApiDir() {
|
|
||||||
#ifdef TOOLS_ENABLED
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_prebuilt_api_dir());
|
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_DataMonoEtcDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_etc_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_DataMonoLibDir() {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_lib_dir());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GodotSharpDirs_DataMonoBinDir() {
|
|
||||||
#ifdef WINDOWS_ENABLED
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_bin_dir());
|
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_EditorProgress_Create(MonoString *p_task, MonoString *p_label, int32_t p_amount, MonoBoolean p_can_cancel) {
|
|
||||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
|
||||||
String label = GDMonoMarshal::mono_string_to_godot(p_label);
|
|
||||||
EditorNode::progress_add_task(task, label, p_amount, (bool)p_can_cancel);
|
EditorNode::progress_add_task(task, label, p_amount, (bool)p_can_cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void godot_icall_EditorProgress_Dispose(MonoString *p_task) {
|
void godot_icall_EditorProgress_Dispose(const godot_string *p_task) {
|
||||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
String task = *reinterpret_cast<const String *>(p_task);
|
||||||
EditorNode::progress_end_task(task);
|
EditorNode::progress_end_task(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_EditorProgress_Step(MonoString *p_task, MonoString *p_state, int32_t p_step, MonoBoolean p_force_refresh) {
|
bool godot_icall_EditorProgress_Step(const godot_string *p_task, const godot_string *p_state, int32_t p_step, bool p_force_refresh) {
|
||||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
String task = *reinterpret_cast<const String *>(p_task);
|
||||||
String state = GDMonoMarshal::mono_string_to_godot(p_state);
|
String state = *reinterpret_cast<const String *>(p_state);
|
||||||
return EditorNode::progress_task_step(task, state, p_step, (bool)p_force_refresh);
|
return EditorNode::progress_task_step(task, state, p_step, (bool)p_force_refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
|
void godot_icall_Internal_FullTemplatesDir(godot_string *r_dest) {
|
||||||
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 assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
|
|
||||||
|
|
||||||
return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {
|
|
||||||
String config = GDMonoMarshal::mono_string_to_godot(p_config);
|
|
||||||
String error_str = GDMono::get_singleton()->update_api_assemblies_from_prebuilt(config);
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(error_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_Internal_FullTemplatesDir() {
|
|
||||||
String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
|
String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
|
||||||
return GDMonoMarshal::mono_string_from_godot(full_templates_dir);
|
memnew_placement(r_dest, String(full_templates_dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) {
|
void godot_icall_Internal_SimplifyGodotPath(const godot_string *p_path, godot_string *r_dest) {
|
||||||
String path = GDMonoMarshal::mono_string_to_godot(p_path);
|
String path = *reinterpret_cast<const String *>(p_path);
|
||||||
return GDMonoMarshal::mono_string_from_godot(path.simplify_path());
|
memnew_placement(r_dest, String(path.simplify_path()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) {
|
bool godot_icall_Internal_IsOsxAppBundleInstalled(const godot_string *p_bundle_id) {
|
||||||
#ifdef OSX_ENABLED
|
#ifdef OSX_ENABLED
|
||||||
String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id);
|
String bundle_id = *reinterpret_cast<const String *>(p_bundle_id);
|
||||||
return (MonoBoolean)osx_is_app_bundle_installed(bundle_id);
|
return (bool)osx_is_app_bundle_installed(bundle_id);
|
||||||
#else
|
#else
|
||||||
(void)p_bundle_id; // UNUSED
|
(void)p_bundle_id; // UNUSED
|
||||||
return (MonoBoolean) false;
|
return (bool)false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_Internal_GodotIs32Bits() {
|
bool godot_icall_Internal_GodotIs32Bits() {
|
||||||
return sizeof(void *) == 4;
|
return sizeof(void *) == 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_Internal_GodotIsRealTDouble() {
|
bool godot_icall_Internal_GodotIsRealTDouble() {
|
||||||
#ifdef REAL_T_IS_DOUBLE
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
return (MonoBoolean) true;
|
return (bool)true;
|
||||||
#else
|
#else
|
||||||
return (MonoBoolean) false;
|
return (bool)false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,23 +164,15 @@ void godot_icall_Internal_GodotMainIteration() {
|
||||||
Main::iteration();
|
Main::iteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t godot_icall_Internal_GetCoreApiHash() {
|
bool godot_icall_Internal_IsAssembliesReloadingNeeded() {
|
||||||
return ClassDB::get_api_hash(ClassDB::API_CORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t godot_icall_Internal_GetEditorApiHash() {
|
|
||||||
return ClassDB::get_api_hash(ClassDB::API_EDITOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Internal_IsAssembliesReloadingNeeded() {
|
|
||||||
#ifdef GD_MONO_HOT_RELOAD
|
#ifdef GD_MONO_HOT_RELOAD
|
||||||
return (MonoBoolean)CSharpLanguage::get_singleton()->is_assembly_reloading_needed();
|
return (bool)CSharpLanguage::get_singleton()->is_assembly_reloading_needed();
|
||||||
#else
|
#else
|
||||||
return (MonoBoolean) false;
|
return (bool)false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void godot_icall_Internal_ReloadAssemblies(MonoBoolean p_soft_reload) {
|
void godot_icall_Internal_ReloadAssemblies(bool p_soft_reload) {
|
||||||
#ifdef GD_MONO_HOT_RELOAD
|
#ifdef GD_MONO_HOT_RELOAD
|
||||||
mono_bind::GodotSharp::get_singleton()->call_deferred(SNAME("_reload_assemblies"), (bool)p_soft_reload);
|
mono_bind::GodotSharp::get_singleton()->call_deferred(SNAME("_reload_assemblies"), (bool)p_soft_reload);
|
||||||
#endif
|
#endif
|
||||||
|
@ -249,21 +182,22 @@ void godot_icall_Internal_EditorDebuggerNodeReloadScripts() {
|
||||||
EditorDebuggerNode::get_singleton()->reload_scripts();
|
EditorDebuggerNode::get_singleton()->reload_scripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_Internal_ScriptEditorEdit(MonoObject *p_resource, int32_t p_line, int32_t p_col, MonoBoolean p_grab_focus) {
|
bool godot_icall_Internal_ScriptEditorEdit(Resource *p_resource, int32_t p_line, int32_t p_col, bool p_grab_focus) {
|
||||||
Ref<Resource> resource = GDMonoMarshal::mono_object_to_variant(p_resource);
|
Ref<Resource> resource = p_resource;
|
||||||
return (MonoBoolean)ScriptEditor::get_singleton()->edit(resource, p_line, p_col, (bool)p_grab_focus);
|
return (bool)ScriptEditor::get_singleton()->edit(resource, p_line, p_col, (bool)p_grab_focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void godot_icall_Internal_EditorNodeShowScriptScreen() {
|
void godot_icall_Internal_EditorNodeShowScriptScreen() {
|
||||||
EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
|
EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_Internal_MonoWindowsInstallRoot() {
|
void godot_icall_Internal_MonoWindowsInstallRoot(godot_string *r_dest) {
|
||||||
#ifdef WINDOWS_ENABLED
|
#ifdef WINDOWS_ENABLED
|
||||||
String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir;
|
String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir;
|
||||||
return GDMonoMarshal::mono_string_from_godot(install_root_dir);
|
memnew_placement(r_dest, String(install_root_dir));
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
memnew_placement(r_dest, String);
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,107 +216,84 @@ void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoArray *godot_icall_Internal_CodeCompletionRequest(int32_t p_kind, MonoString *p_script_file) {
|
void godot_icall_Internal_CodeCompletionRequest(int32_t p_kind, const godot_string *p_script_file, godot_packed_string_array *r_ret) {
|
||||||
String script_file = GDMonoMarshal::mono_string_to_godot(p_script_file);
|
String script_file = *reinterpret_cast<const String *>(p_script_file);
|
||||||
PackedStringArray suggestions = gdmono::get_code_completion((gdmono::CompletionKind)p_kind, script_file);
|
PackedStringArray suggestions = gdmono::get_code_completion((gdmono::CompletionKind)p_kind, script_file);
|
||||||
return GDMonoMarshal::PackedStringArray_to_mono_array(suggestions);
|
memnew_placement(r_ret, PackedStringArray(suggestions));
|
||||||
}
|
}
|
||||||
|
|
||||||
float godot_icall_Globals_EditorScale() {
|
float godot_icall_Globals_EditorScale() {
|
||||||
return EDSCALE;
|
return EDSCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *godot_icall_Globals_GlobalDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
|
void godot_icall_Globals_GlobalDef(const godot_string *p_setting, const godot_variant *p_default_value, bool p_restart_if_changed, godot_variant *r_result) {
|
||||||
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
|
String setting = *reinterpret_cast<const String *>(p_setting);
|
||||||
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
|
Variant default_value = *reinterpret_cast<const Variant *>(p_default_value);
|
||||||
Variant result = _GLOBAL_DEF(setting, default_value, (bool)p_restart_if_changed);
|
Variant result = _GLOBAL_DEF(setting, default_value, (bool)p_restart_if_changed);
|
||||||
return GDMonoMarshal::variant_to_mono_object(result);
|
memnew_placement(r_result, Variant(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *godot_icall_Globals_EditorDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
|
void godot_icall_Globals_EditorDef(const godot_string *p_setting, const godot_variant *p_default_value, bool p_restart_if_changed, godot_variant *r_result) {
|
||||||
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
|
String setting = *reinterpret_cast<const String *>(p_setting);
|
||||||
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
|
Variant default_value = *reinterpret_cast<const Variant *>(p_default_value);
|
||||||
Variant result = _EDITOR_DEF(setting, default_value, (bool)p_restart_if_changed);
|
Variant result = _EDITOR_DEF(setting, default_value, (bool)p_restart_if_changed);
|
||||||
return GDMonoMarshal::variant_to_mono_object(result);
|
memnew_placement(r_result, Variant(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_Globals_TTR(MonoString *p_text) {
|
void godot_icall_Globals_TTR(const godot_string *p_text, godot_string *r_dest) {
|
||||||
String text = GDMonoMarshal::mono_string_to_godot(p_text);
|
String text = *reinterpret_cast<const String *>(p_text);
|
||||||
return GDMonoMarshal::mono_string_from_godot(TTR(text));
|
memnew_placement(r_dest, String(TTR(text)));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *godot_icall_Utils_OS_GetPlatformName() {
|
void godot_icall_Utils_OS_GetPlatformName(godot_string *r_dest) {
|
||||||
String os_name = OS::get_singleton()->get_name();
|
String os_name = OS::get_singleton()->get_name();
|
||||||
return GDMonoMarshal::mono_string_from_godot(os_name);
|
memnew_placement(r_dest, String(os_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoBoolean godot_icall_Utils_OS_UnixFileHasExecutableAccess(MonoString *p_file_path) {
|
bool godot_icall_Utils_OS_UnixFileHasExecutableAccess(const godot_string *p_file_path) {
|
||||||
#ifdef UNIX_ENABLED
|
#ifdef UNIX_ENABLED
|
||||||
String file_path = GDMonoMarshal::mono_string_to_godot(p_file_path);
|
String file_path = *reinterpret_cast<const String *>(p_file_path);
|
||||||
return access(file_path.utf8().get_data(), X_OK) == 0;
|
return access(file_path.utf8().get_data(), X_OK) == 0;
|
||||||
#else
|
#else
|
||||||
ERR_FAIL_V(false);
|
ERR_FAIL_V(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_editor_internal_calls() {
|
#ifdef __cplusplus
|
||||||
// GodotSharpDirs
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResDataDir", godot_icall_GodotSharpDirs_ResDataDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResMetadataDir", godot_icall_GodotSharpDirs_ResMetadataDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResAssembliesBaseDir", godot_icall_GodotSharpDirs_ResAssembliesBaseDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResAssembliesDir", godot_icall_GodotSharpDirs_ResAssembliesDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResConfigDir", godot_icall_GodotSharpDirs_ResConfigDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempDir", godot_icall_GodotSharpDirs_ResTempDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempAssembliesBaseDir", godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempAssembliesDir", godot_icall_GodotSharpDirs_ResTempAssembliesDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoUserDir", godot_icall_GodotSharpDirs_MonoUserDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoLogsDir", godot_icall_GodotSharpDirs_MonoLogsDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoSolutionsDir", godot_icall_GodotSharpDirs_MonoSolutionsDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_BuildLogsDirs", godot_icall_GodotSharpDirs_BuildLogsDirs);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ProjectSlnPath", godot_icall_GodotSharpDirs_ProjectSlnPath);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ProjectCsProjPath", godot_icall_GodotSharpDirs_ProjectCsProjPath);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataEditorToolsDir", godot_icall_GodotSharpDirs_DataEditorToolsDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataEditorPrebuiltApiDir", godot_icall_GodotSharpDirs_DataEditorPrebuiltApiDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoEtcDir", godot_icall_GodotSharpDirs_DataMonoEtcDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoLibDir", godot_icall_GodotSharpDirs_DataMonoLibDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoBinDir", godot_icall_GodotSharpDirs_DataMonoBinDir);
|
|
||||||
|
|
||||||
// EditorProgress
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Create", godot_icall_EditorProgress_Create);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Dispose", godot_icall_EditorProgress_Dispose);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Step", godot_icall_EditorProgress_Step);
|
|
||||||
|
|
||||||
// ExportPlugin
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Export.ExportPlugin::internal_GetExportedAssemblyDependencies", godot_icall_ExportPlugin_GetExportedAssemblyDependencies);
|
|
||||||
|
|
||||||
// Internals
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetCoreApiHash", godot_icall_Internal_GetCoreApiHash);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetEditorApiHash", godot_icall_Internal_GetEditorApiHash);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsAssembliesReloadingNeeded", godot_icall_Internal_IsAssembliesReloadingNeeded);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ReloadAssemblies", godot_icall_Internal_ReloadAssemblies);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorDebuggerNodeReloadScripts", godot_icall_Internal_EditorDebuggerNodeReloadScripts);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorEdit", godot_icall_Internal_ScriptEditorEdit);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorNodeShowScriptScreen", godot_icall_Internal_EditorNodeShowScriptScreen);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_MonoWindowsInstallRoot", godot_icall_Internal_MonoWindowsInstallRoot);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunPlay", godot_icall_Internal_EditorRunPlay);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunStop", godot_icall_Internal_EditorRunStop);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorDebugger_ReloadScripts", godot_icall_Internal_ScriptEditorDebugger_ReloadScripts);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_CodeCompletionRequest", godot_icall_Internal_CodeCompletionRequest);
|
|
||||||
|
|
||||||
// Globals
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorScale", godot_icall_Globals_EditorScale);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_GlobalDef", godot_icall_Globals_GlobalDef);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorDef", godot_icall_Globals_EditorDef);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_TTR", godot_icall_Globals_TTR);
|
|
||||||
|
|
||||||
// Utils.OS
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Utils.OS::GetPlatformName", godot_icall_Utils_OS_GetPlatformName);
|
|
||||||
GDMonoUtils::add_internal_call("GodotTools.Utils.OS::UnixFileHasExecutableAccess", godot_icall_Utils_OS_UnixFileHasExecutableAccess);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *godotsharp_editor_pinvoke_funcs[32] = {
|
||||||
|
(void *)godot_icall_GodotSharpDirs_ResMetadataDir,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_MonoUserDir,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_BuildLogsDirs,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_ProjectSlnPath,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_ProjectCsProjPath,
|
||||||
|
(void *)godot_icall_GodotSharpDirs_DataEditorToolsDir,
|
||||||
|
(void *)godot_icall_EditorProgress_Create,
|
||||||
|
(void *)godot_icall_EditorProgress_Dispose,
|
||||||
|
(void *)godot_icall_EditorProgress_Step,
|
||||||
|
(void *)godot_icall_Internal_FullTemplatesDir,
|
||||||
|
(void *)godot_icall_Internal_SimplifyGodotPath,
|
||||||
|
(void *)godot_icall_Internal_IsOsxAppBundleInstalled,
|
||||||
|
(void *)godot_icall_Internal_GodotIs32Bits,
|
||||||
|
(void *)godot_icall_Internal_GodotIsRealTDouble,
|
||||||
|
(void *)godot_icall_Internal_GodotMainIteration,
|
||||||
|
(void *)godot_icall_Internal_IsAssembliesReloadingNeeded,
|
||||||
|
(void *)godot_icall_Internal_ReloadAssemblies,
|
||||||
|
(void *)godot_icall_Internal_EditorDebuggerNodeReloadScripts,
|
||||||
|
(void *)godot_icall_Internal_ScriptEditorEdit,
|
||||||
|
(void *)godot_icall_Internal_EditorNodeShowScriptScreen,
|
||||||
|
(void *)godot_icall_Internal_MonoWindowsInstallRoot,
|
||||||
|
(void *)godot_icall_Internal_EditorRunPlay,
|
||||||
|
(void *)godot_icall_Internal_EditorRunStop,
|
||||||
|
(void *)godot_icall_Internal_ScriptEditorDebugger_ReloadScripts,
|
||||||
|
(void *)godot_icall_Internal_CodeCompletionRequest,
|
||||||
|
(void *)godot_icall_Globals_EditorScale,
|
||||||
|
(void *)godot_icall_Globals_GlobalDef,
|
||||||
|
(void *)godot_icall_Globals_EditorDef,
|
||||||
|
(void *)godot_icall_Globals_TTR,
|
||||||
|
(void *)godot_icall_Utils_OS_GetPlatformName,
|
||||||
|
(void *)godot_icall_Utils_OS_UnixFileHasExecutableAccess,
|
||||||
|
};
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* godotsharp_export.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#include "godotsharp_export.h"
|
|
||||||
|
|
||||||
#include <mono/metadata/image.h>
|
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
|
||||||
#include "core/io/file_access_pack.h"
|
|
||||||
#include "core/os/os.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono.h"
|
|
||||||
#include "../mono_gd/gd_mono_assembly.h"
|
|
||||||
#include "../mono_gd/gd_mono_cache.h"
|
|
||||||
#include "../utils/macros.h"
|
|
||||||
|
|
||||||
namespace GodotSharpExport {
|
|
||||||
|
|
||||||
MonoAssemblyName *new_mono_assembly_name() {
|
|
||||||
// Mono has no public API to create an empty MonoAssemblyName and the struct is private.
|
|
||||||
// As such the only way to create it is with a stub name and then clear it.
|
|
||||||
|
|
||||||
MonoAssemblyName *aname = mono_assembly_name_new("stub");
|
|
||||||
CRASH_COND(aname == nullptr);
|
|
||||||
mono_assembly_name_free(aname); // Frees the string fields, not the struct
|
|
||||||
return aname;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AssemblyRefInfo {
|
|
||||||
String name;
|
|
||||||
uint16_t major = 0;
|
|
||||||
uint16_t minor = 0;
|
|
||||||
uint16_t build = 0;
|
|
||||||
uint16_t revision = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
AssemblyRefInfo get_assemblyref_name(MonoImage *p_image, int index) {
|
|
||||||
const MonoTableInfo *table_info = mono_image_get_table_info(p_image, MONO_TABLE_ASSEMBLYREF);
|
|
||||||
|
|
||||||
uint32_t cols[MONO_ASSEMBLYREF_SIZE];
|
|
||||||
|
|
||||||
mono_metadata_decode_row(table_info, index, cols, MONO_ASSEMBLYREF_SIZE);
|
|
||||||
|
|
||||||
return {
|
|
||||||
String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME])),
|
|
||||||
(uint16_t)cols[MONO_ASSEMBLYREF_MAJOR_VERSION],
|
|
||||||
(uint16_t)cols[MONO_ASSEMBLYREF_MINOR_VERSION],
|
|
||||||
(uint16_t)cols[MONO_ASSEMBLYREF_BUILD_NUMBER],
|
|
||||||
(uint16_t)cols[MONO_ASSEMBLYREF_REV_NUMBER]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, MonoAssemblyName *reusable_aname, 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++) {
|
|
||||||
AssemblyRefInfo ref_info = get_assemblyref_name(image, i);
|
|
||||||
|
|
||||||
const String &ref_name = ref_info.name;
|
|
||||||
|
|
||||||
if (r_assembly_dependencies.has(ref_name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mono_assembly_get_assemblyref(image, i, reusable_aname);
|
|
||||||
|
|
||||||
GDMonoAssembly *ref_assembly = nullptr;
|
|
||||||
if (!GDMono::get_singleton()->load_assembly(ref_name, reusable_aname, &ref_assembly, /* refonly: */ true, p_search_dirs)) {
|
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
r_assembly_dependencies[ref_name] = ref_assembly->get_path();
|
|
||||||
|
|
||||||
Error err = get_assembly_dependencies(ref_assembly, reusable_aname, 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_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);
|
|
||||||
|
|
||||||
_GDMONO_SCOPE_DOMAIN_(export_domain);
|
|
||||||
|
|
||||||
Vector<String> search_dirs;
|
|
||||||
GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
|
|
||||||
|
|
||||||
if (p_custom_bcl_dir.length()) {
|
|
||||||
// Only one mscorlib can be loaded. We need this workaround to make sure we get it from the right BCL directory.
|
|
||||||
r_assembly_dependencies["mscorlib"] = p_custom_bcl_dir.plus_file("mscorlib.dll").simplify_path();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
|
|
||||||
String assembly_name = *key;
|
|
||||||
String assembly_path = p_initial_assemblies[*key];
|
|
||||||
|
|
||||||
GDMonoAssembly *assembly = nullptr;
|
|
||||||
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 + "'.");
|
|
||||||
|
|
||||||
MonoAssemblyName *reusable_aname = new_mono_assembly_name();
|
|
||||||
SCOPE_EXIT { mono_free(reusable_aname); };
|
|
||||||
|
|
||||||
Error err = get_assembly_dependencies(assembly, reusable_aname, search_dirs, r_assembly_dependencies);
|
|
||||||
if (err != OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
} // namespace GodotSharpExport
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* godotsharp_export.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef GODOTSHARP_EXPORT_H
|
|
||||||
#define GODOTSHARP_EXPORT_H
|
|
||||||
|
|
||||||
#include "core/error/error_list.h"
|
|
||||||
#include "core/string/ustring.h"
|
|
||||||
#include "core/variant/dictionary.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_header.h"
|
|
||||||
|
|
||||||
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_assemblies,
|
|
||||||
const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
|
|
||||||
} // namespace GodotSharpExport
|
|
||||||
|
|
||||||
#endif // GODOTSHARP_EXPORT_H
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
|
||||||
|
<!-- To generate the .runtimeconfig.json file-->
|
||||||
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GodotSharp\GodotSharp.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
195
modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
Normal file
195
modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
namespace GodotPlugins
|
||||||
|
{
|
||||||
|
public static class Main
|
||||||
|
{
|
||||||
|
private static readonly List<AssemblyName> SharedAssemblies = new();
|
||||||
|
private static readonly Assembly CoreApiAssembly = typeof(Godot.Object).Assembly;
|
||||||
|
private static Assembly? _editorApiAssembly;
|
||||||
|
|
||||||
|
private static readonly AssemblyLoadContext MainLoadContext =
|
||||||
|
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ??
|
||||||
|
AssemblyLoadContext.Default;
|
||||||
|
|
||||||
|
// Right now we do it this way for simplicity as hot-reload is disabled. It will need to be changed later.
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool Initialize(godot_bool editorHint,
|
||||||
|
PluginsCallbacks* pluginsCallbacks, Godot.Bridge.ManagedCallbacks* managedCallbacks)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SharedAssemblies.Add(CoreApiAssembly.GetName());
|
||||||
|
|
||||||
|
if (editorHint.ToBool())
|
||||||
|
{
|
||||||
|
_editorApiAssembly = Assembly.Load("GodotSharpEditor");
|
||||||
|
SharedAssemblies.Add(_editorApiAssembly.GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeLibrary.SetDllImportResolver(CoreApiAssembly, OnResolveDllImport);
|
||||||
|
|
||||||
|
*pluginsCallbacks = new()
|
||||||
|
{
|
||||||
|
LoadProjectAssemblyCallback = &LoadProjectAssembly,
|
||||||
|
LoadToolsAssemblyCallback = &LoadToolsAssembly,
|
||||||
|
};
|
||||||
|
|
||||||
|
*managedCallbacks = Godot.Bridge.ManagedCallbacks.Create();
|
||||||
|
|
||||||
|
return godot_bool.True;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e);
|
||||||
|
*pluginsCallbacks = default;
|
||||||
|
*managedCallbacks = default;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct PluginsCallbacks
|
||||||
|
{
|
||||||
|
public unsafe delegate* unmanaged<char*, godot_bool> LoadProjectAssemblyCallback;
|
||||||
|
public unsafe delegate* unmanaged<char*, IntPtr> LoadToolsAssemblyCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool LoadProjectAssembly(char* nAssemblyPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string assemblyPath = new(nAssemblyPath);
|
||||||
|
|
||||||
|
var assembly = LoadPlugin(assemblyPath);
|
||||||
|
|
||||||
|
var method = CoreApiAssembly.GetType("Godot.Bridge.ScriptManagerBridge")?
|
||||||
|
.GetMethod("LookupScriptsInAssembly",
|
||||||
|
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (method == null)
|
||||||
|
{
|
||||||
|
throw new MissingMethodException("Godot.Bridge.ScriptManagerBridge",
|
||||||
|
"LookupScriptsInAssembly");
|
||||||
|
}
|
||||||
|
|
||||||
|
method.Invoke(null, new object[] { assembly });
|
||||||
|
|
||||||
|
return godot_bool.True;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe IntPtr LoadToolsAssembly(char* nAssemblyPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string assemblyPath = new(nAssemblyPath);
|
||||||
|
|
||||||
|
if (_editorApiAssembly == null)
|
||||||
|
throw new InvalidOperationException("The Godot editor API assembly is not loaded");
|
||||||
|
|
||||||
|
var assembly = LoadPlugin(assemblyPath);
|
||||||
|
|
||||||
|
NativeLibrary.SetDllImportResolver(assembly, OnResolveDllImport);
|
||||||
|
|
||||||
|
var method = assembly.GetType("GodotTools.GodotSharpEditor")?
|
||||||
|
.GetMethod("InternalCreateInstance",
|
||||||
|
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (method == null)
|
||||||
|
{
|
||||||
|
throw new MissingMethodException("GodotTools.GodotSharpEditor",
|
||||||
|
"InternalCreateInstance");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IntPtr?)method.Invoke(null, null) ?? IntPtr.Zero;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e);
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Assembly LoadPlugin(string assemblyPath)
|
||||||
|
{
|
||||||
|
string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
|
||||||
|
|
||||||
|
var sharedAssemblies = new List<string>();
|
||||||
|
|
||||||
|
foreach (var sharedAssembly in SharedAssemblies)
|
||||||
|
{
|
||||||
|
string? sharedAssemblyName = sharedAssembly.Name;
|
||||||
|
if (sharedAssemblyName != null)
|
||||||
|
sharedAssemblies.Add(sharedAssemblyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var loadContext = new PluginLoadContext(assemblyPath, sharedAssemblies, MainLoadContext);
|
||||||
|
return loadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
|
||||||
|
{
|
||||||
|
if (libraryName == "__Internal")
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return Win32.GetModuleHandle(null);
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
return Linux.dlopen(null, Linux.RTLD_LAZY);
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||||
|
{
|
||||||
|
return MacOS.dlopen(null, MacOS.RTLD_LAZY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
private static class MacOS
|
||||||
|
{
|
||||||
|
private const string SystemLibrary = "/usr/lib/libSystem.dylib";
|
||||||
|
|
||||||
|
public const int RTLD_LAZY = 1;
|
||||||
|
|
||||||
|
[DllImport(SystemLibrary)]
|
||||||
|
public static extern IntPtr dlopen(string? path, int mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Linux
|
||||||
|
{
|
||||||
|
private const string SystemLibrary = "dl";
|
||||||
|
|
||||||
|
public const int RTLD_LAZY = 1;
|
||||||
|
|
||||||
|
[DllImport(SystemLibrary)]
|
||||||
|
public static extern IntPtr dlopen(string? path, int mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Win32
|
||||||
|
{
|
||||||
|
private const string SystemLibrary = "Kernel32.dll";
|
||||||
|
|
||||||
|
[DllImport(SystemLibrary)]
|
||||||
|
public static extern IntPtr GetModuleHandle(string? lpModuleName);
|
||||||
|
}
|
||||||
|
// ReSharper restore InconsistentNaming
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
|
||||||
|
namespace GodotPlugins
|
||||||
|
{
|
||||||
|
public class PluginLoadContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private readonly AssemblyDependencyResolver _resolver;
|
||||||
|
private readonly ICollection<string> _sharedAssemblies;
|
||||||
|
private readonly AssemblyLoadContext _mainLoadContext;
|
||||||
|
|
||||||
|
public PluginLoadContext(string pluginPath, ICollection<string> sharedAssemblies,
|
||||||
|
AssemblyLoadContext mainLoadContext)
|
||||||
|
{
|
||||||
|
Console.WriteLine(pluginPath);
|
||||||
|
Console.Out.Flush();
|
||||||
|
_resolver = new AssemblyDependencyResolver(pluginPath);
|
||||||
|
_sharedAssemblies = sharedAssemblies;
|
||||||
|
_mainLoadContext = mainLoadContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Assembly? Load(AssemblyName assemblyName)
|
||||||
|
{
|
||||||
|
if (assemblyName.Name == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (_sharedAssemblies.Contains(assemblyName.Name))
|
||||||
|
return _mainLoadContext.LoadFromAssemblyName(assemblyName);
|
||||||
|
|
||||||
|
string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||||
|
if (assemblyPath != null)
|
||||||
|
{
|
||||||
|
// Load in memory to prevent locking the file
|
||||||
|
using var assemblyFile = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
string pdbPath = Path.ChangeExtension(assemblyPath, ".pdb");
|
||||||
|
|
||||||
|
if (File.Exists(pdbPath))
|
||||||
|
{
|
||||||
|
using var pdbFile = File.Open(pdbPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
return LoadFromStream(assemblyFile, pdbFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromStream(assemblyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
|
||||||
|
{
|
||||||
|
string? libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
|
||||||
|
if (libraryPath != null)
|
||||||
|
return LoadUnmanagedDllFromPath(libraryPath);
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "GodotSharp\Go
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpEditor", "GodotSharpEditor\GodotSharpEditor.csproj", "{8FBEC238-D944-4074-8548-B3B524305905}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpEditor", "GodotSharpEditor\GodotSharpEditor.csproj", "{8FBEC238-D944-4074-8548-B3B524305905}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotPlugins", "GodotPlugins\GodotPlugins.csproj", "{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -18,5 +20,9 @@ Global
|
||||||
{8FBEC238-D944-4074-8548-B3B524305905}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8FBEC238-D944-4074-8548-B3B524305905}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
7
modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
Normal file
7
modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=vcall/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -1,47 +1,27 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot.Collections
|
namespace Godot.Collections
|
||||||
{
|
{
|
||||||
class ArraySafeHandle : SafeHandle
|
|
||||||
{
|
|
||||||
public ArraySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
|
|
||||||
{
|
|
||||||
this.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsInvalid
|
|
||||||
{
|
|
||||||
get { return handle == IntPtr.Zero; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
|
||||||
{
|
|
||||||
Array.godot_icall_Array_Dtor(handle);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper around Godot's Array class, an array of Variant
|
/// Wrapper around Godot's Array class, an array of Variant
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
/// typed elements allocated in the engine in C++. Useful when
|
||||||
/// interfacing with the engine. Otherwise prefer .NET collections
|
/// interfacing with the engine. Otherwise prefer .NET collections
|
||||||
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
|
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Array : IList, IDisposable
|
public sealed class Array : IList, IDisposable
|
||||||
{
|
{
|
||||||
ArraySafeHandle safeHandle;
|
public godot_array NativeValue;
|
||||||
bool disposed = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Array"/>.
|
/// Constructs a new empty <see cref="Array"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Array()
|
public Array()
|
||||||
{
|
{
|
||||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
|
NativeValue = NativeFuncs.godotsharp_array_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -58,6 +38,7 @@ namespace Godot.Collections
|
||||||
Add(element);
|
Add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This must be removed. Lots of silent mistakes as it takes pretty much anything.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new <see cref="Array"/> from the given objects.
|
/// Constructs a new <see cref="Array"/> from the given objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -66,28 +47,44 @@ namespace Godot.Collections
|
||||||
public Array(params object[] array) : this()
|
public Array(params object[] array) : this()
|
||||||
{
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
{
|
|
||||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||||
}
|
|
||||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
|
NativeValue = NativeFuncs.godotsharp_array_new();
|
||||||
|
int length = array.Length;
|
||||||
|
|
||||||
|
Resize(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
this[i] = array[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Array(ArraySafeHandle handle)
|
private Array(godot_array nativeValueToOwn)
|
||||||
{
|
{
|
||||||
safeHandle = handle;
|
NativeValue = nativeValueToOwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Array(IntPtr handle)
|
// Explicit name to make it very clear
|
||||||
|
internal static Array CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
|
||||||
|
=> new Array(nativeValueToOwn);
|
||||||
|
|
||||||
|
~Array()
|
||||||
{
|
{
|
||||||
safeHandle = new ArraySafeHandle(handle);
|
Dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IntPtr GetPtr()
|
/// <summary>
|
||||||
|
/// Disposes of this <see cref="Array"/>.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (disposed)
|
Dispose(true);
|
||||||
throw new ObjectDisposedException(GetType().FullName);
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
return safeHandle.DangerousGetHandle();
|
public void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
// Always dispose `NativeValue` even if disposing is true
|
||||||
|
NativeValue.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -97,7 +94,9 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Array.</returns>
|
/// <returns>A new Godot Array.</returns>
|
||||||
public Array Duplicate(bool deep = false)
|
public Array Duplicate(bool deep = false)
|
||||||
{
|
{
|
||||||
return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
|
godot_array newArray;
|
||||||
|
NativeFuncs.godotsharp_array_duplicate(ref NativeValue, deep.ToGodotBool(), out newArray);
|
||||||
|
return CreateTakingOwnershipOfDisposableValue(newArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -105,18 +104,12 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newSize">The new size of the array.</param>
|
/// <param name="newSize">The new size of the array.</param>
|
||||||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
||||||
public Error Resize(int newSize)
|
public Error Resize(int newSize) => NativeFuncs.godotsharp_array_resize(ref NativeValue, newSize);
|
||||||
{
|
|
||||||
return godot_icall_Array_Resize(GetPtr(), newSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shuffles the contents of this <see cref="Array"/> into a random order.
|
/// Shuffles the contents of this <see cref="Array"/> into a random order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Shuffle()
|
public void Shuffle() => NativeFuncs.godotsharp_array_shuffle(ref NativeValue);
|
||||||
{
|
|
||||||
godot_icall_Array_Shuffle(GetPtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Concatenates these two <see cref="Array"/>s.
|
/// Concatenates these two <see cref="Array"/>s.
|
||||||
|
@ -126,26 +119,16 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
||||||
public static Array operator +(Array left, Array right)
|
public static Array operator +(Array left, Array right)
|
||||||
{
|
{
|
||||||
return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr()));
|
int leftCount = left.Count;
|
||||||
}
|
int rightCount = right.Count;
|
||||||
|
|
||||||
// IDisposable
|
Array newArray = left.Duplicate(deep: false);
|
||||||
|
newArray.Resize(leftCount + rightCount);
|
||||||
|
|
||||||
/// <summary>
|
for (int i = 0; i < rightCount; i++)
|
||||||
/// Disposes of this <see cref="Array"/>.
|
newArray[i + leftCount] = right[i];
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (safeHandle != null)
|
return newArray;
|
||||||
{
|
|
||||||
safeHandle.Dispose();
|
|
||||||
safeHandle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
disposed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IList
|
// IList
|
||||||
|
@ -158,10 +141,20 @@ namespace Godot.Collections
|
||||||
/// Returns the object at the given index.
|
/// Returns the object at the given index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The object at the given index.</value>
|
/// <value>The object at the given index.</value>
|
||||||
public object this[int index]
|
public unsafe object this[int index]
|
||||||
{
|
{
|
||||||
get => godot_icall_Array_At(GetPtr(), index);
|
get
|
||||||
set => godot_icall_Array_SetAt(GetPtr(), index, value);
|
{
|
||||||
|
GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
||||||
|
return Marshaling.variant_to_mono_object(&borrowElem);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= Count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref NativeValue);
|
||||||
|
ptrw[index] = Marshaling.mono_object_to_variant(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -170,19 +163,23 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The object to add.</param>
|
/// <param name="value">The object to add.</param>
|
||||||
/// <returns>The new size after adding the object.</returns>
|
/// <returns>The new size after adding the object.</returns>
|
||||||
public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
|
public unsafe int Add(object value)
|
||||||
|
{
|
||||||
|
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||||
|
return NativeFuncs.godotsharp_array_add(ref NativeValue, &variantValue);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if this <see cref="Array"/> contains the given object.
|
/// Checks if this <see cref="Array"/> contains the given object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The item to look for.</param>
|
/// <param name="value">The item to look for.</param>
|
||||||
/// <returns>Whether or not this array contains the given object.</returns>
|
/// <returns>Whether or not this array contains the given object.</returns>
|
||||||
public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
|
public bool Contains(object value) => IndexOf(value) != -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Erases all items from this <see cref="Array"/>.
|
/// Erases all items from this <see cref="Array"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear() => godot_icall_Array_Clear(GetPtr());
|
public void Clear() => Resize(0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches this <see cref="Array"/> for an object
|
/// Searches this <see cref="Array"/> for an object
|
||||||
|
@ -190,7 +187,11 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The object to search for.</param>
|
/// <param name="value">The object to search for.</param>
|
||||||
/// <returns>The index of the object, or -1 if not found.</returns>
|
/// <returns>The index of the object, or -1 if not found.</returns>
|
||||||
public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
|
public unsafe int IndexOf(object value)
|
||||||
|
{
|
||||||
|
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||||
|
return NativeFuncs.godotsharp_array_index_of(ref NativeValue, &variantValue);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inserts a new object at a given position in the array.
|
/// Inserts a new object at a given position in the array.
|
||||||
|
@ -200,20 +201,38 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The index to insert at.</param>
|
/// <param name="index">The index to insert at.</param>
|
||||||
/// <param name="value">The object to insert.</param>
|
/// <param name="value">The object to insert.</param>
|
||||||
public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
|
public unsafe void Insert(int index, object value)
|
||||||
|
{
|
||||||
|
if (index < 0 || index > Count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||||
|
NativeFuncs.godotsharp_array_insert(ref NativeValue, index, &variantValue);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the first occurrence of the specified value
|
/// Removes the first occurrence of the specified value
|
||||||
/// from this <see cref="Array"/>.
|
/// from this <see cref="Array"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value to remove.</param>
|
/// <param name="value">The value to remove.</param>
|
||||||
public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
|
public void Remove(object value)
|
||||||
|
{
|
||||||
|
int index = IndexOf(value);
|
||||||
|
if (index >= 0)
|
||||||
|
RemoveAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an element from this <see cref="Array"/> by index.
|
/// Removes an element from this <see cref="Array"/> by index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The index of the element to remove.</param>
|
/// <param name="index">The index of the element to remove.</param>
|
||||||
public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
|
public void RemoveAt(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index > Count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
NativeFuncs.godotsharp_array_remove_at(ref NativeValue, index);
|
||||||
|
}
|
||||||
|
|
||||||
// ICollection
|
// ICollection
|
||||||
|
|
||||||
|
@ -222,7 +241,7 @@ namespace Godot.Collections
|
||||||
/// This is also known as the size or length of the array.
|
/// This is also known as the size or length of the array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The number of elements.</returns>
|
/// <returns>The number of elements.</returns>
|
||||||
public int Count => godot_icall_Array_Count(GetPtr());
|
public int Count => NativeValue.Size;
|
||||||
|
|
||||||
object ICollection.SyncRoot => this;
|
object ICollection.SyncRoot => this;
|
||||||
|
|
||||||
|
@ -233,17 +252,35 @@ namespace Godot.Collections
|
||||||
/// untyped C# array, starting at the given index.
|
/// untyped C# array, starting at the given index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="array">The array to copy to.</param>
|
/// <param name="array">The array to copy to.</param>
|
||||||
/// <param name="index">The index to start at.</param>
|
/// <param name="destIndex">The index to start at.</param>
|
||||||
public void CopyTo(System.Array array, int index)
|
public void CopyTo(System.Array array, int destIndex)
|
||||||
{
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
|
||||||
if (index < 0)
|
if (destIndex < 0)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(destIndex),
|
||||||
|
"Number was less than the array's lower bound in the first dimension.");
|
||||||
|
}
|
||||||
|
|
||||||
// Internal call may throw ArgumentException
|
int count = Count;
|
||||||
godot_icall_Array_CopyTo(GetPtr(), array, index);
|
|
||||||
|
if (array.Length < (destIndex + count))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
object obj = Marshaling.variant_to_mono_object(&(*NativeValue._p)._arrayVector._ptr[i]);
|
||||||
|
array.SetValue(obj, destIndex);
|
||||||
|
destIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IEnumerable
|
// IEnumerable
|
||||||
|
@ -266,75 +303,39 @@ namespace Godot.Collections
|
||||||
/// Converts this <see cref="Array"/> to a string.
|
/// Converts this <see cref="Array"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string representation of this array.</returns>
|
/// <returns>A string representation of this array.</returns>
|
||||||
public override string ToString()
|
public override unsafe string ToString()
|
||||||
{
|
{
|
||||||
return godot_icall_Array_ToString(GetPtr());
|
using godot_string str = default;
|
||||||
|
NativeFuncs.godotsharp_array_to_string(ref NativeValue, &str);
|
||||||
|
return Marshaling.mono_string_from_godot(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
/// <summary>
|
||||||
internal extern static IntPtr godot_icall_Array_Ctor();
|
/// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed.
|
||||||
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
internal void GetVariantBorrowElementAt(int index, out godot_variant elem)
|
||||||
internal extern static IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
|
{
|
||||||
|
if (index < 0 || index >= Count)
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
throw new IndexOutOfRangeException();
|
||||||
internal extern static void godot_icall_Array_Dtor(IntPtr ptr);
|
GetVariantBorrowElementAtUnchecked(index, out elem);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_Array_Count(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_Array_Add(IntPtr ptr, object item);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_Clear(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static Error godot_icall_Array_Resize(IntPtr ptr, int newSize);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static Error godot_icall_Array_Shuffle(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_Array_ToString(IntPtr ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed.
|
||||||
|
/// </summary>
|
||||||
|
internal unsafe void GetVariantBorrowElementAtUnchecked(int index, out godot_variant elem)
|
||||||
|
{
|
||||||
|
elem = (*NativeValue._p)._arrayVector._ptr[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface IGenericGodotArray
|
||||||
|
{
|
||||||
|
Array UnderlyingArray { get; }
|
||||||
|
Type TypeOfElements { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Now we should be able to avoid boxing
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Typed wrapper around Godot's Array class, an array of Variant
|
/// Typed wrapper around Godot's Array class, an array of Variant
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
/// typed elements allocated in the engine in C++. Useful when
|
||||||
|
@ -342,24 +343,27 @@ namespace Godot.Collections
|
||||||
/// such as arrays or <see cref="List{T}"/>.
|
/// such as arrays or <see cref="List{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of the array.</typeparam>
|
/// <typeparam name="T">The type of the array.</typeparam>
|
||||||
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
|
[SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
|
||||||
|
public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
|
||||||
{
|
{
|
||||||
Array objectArray;
|
private readonly Array _underlyingArray;
|
||||||
|
|
||||||
internal static int elemTypeEncoding;
|
// ReSharper disable StaticMemberInGenericType
|
||||||
internal static IntPtr elemTypeClass;
|
// Warning is about unique static fields being created for each generic type combination:
|
||||||
|
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
||||||
|
// In our case this is exactly what we want.
|
||||||
|
private static readonly Type TypeOfElements = typeof(T);
|
||||||
|
// ReSharper restore StaticMemberInGenericType
|
||||||
|
|
||||||
static Array()
|
Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
|
||||||
{
|
Type IGenericGodotArray.TypeOfElements => TypeOfElements;
|
||||||
Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Array{T}"/>.
|
/// Constructs a new empty <see cref="Array{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Array()
|
public Array()
|
||||||
{
|
{
|
||||||
objectArray = new Array();
|
_underlyingArray = new Array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -372,7 +376,7 @@ namespace Godot.Collections
|
||||||
if (collection == null)
|
if (collection == null)
|
||||||
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
|
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
|
||||||
|
|
||||||
objectArray = new Array(collection);
|
_underlyingArray = new Array(collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -386,7 +390,8 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||||
}
|
}
|
||||||
objectArray = new Array(array);
|
|
||||||
|
_underlyingArray = new Array(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -395,23 +400,12 @@ namespace Godot.Collections
|
||||||
/// <param name="array">The untyped array to construct from.</param>
|
/// <param name="array">The untyped array to construct from.</param>
|
||||||
public Array(Array array)
|
public Array(Array array)
|
||||||
{
|
{
|
||||||
objectArray = array;
|
_underlyingArray = array;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Array(IntPtr handle)
|
// Explicit name to make it very clear
|
||||||
{
|
internal static Array<T> CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
|
||||||
objectArray = new Array(handle);
|
=> new Array<T>(Array.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
||||||
}
|
|
||||||
|
|
||||||
internal Array(ArraySafeHandle handle)
|
|
||||||
{
|
|
||||||
objectArray = new Array(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IntPtr GetPtr()
|
|
||||||
{
|
|
||||||
return objectArray.GetPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
|
/// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
|
||||||
|
@ -419,7 +413,7 @@ namespace Godot.Collections
|
||||||
/// <param name="from">The typed array to convert.</param>
|
/// <param name="from">The typed array to convert.</param>
|
||||||
public static explicit operator Array(Array<T> from)
|
public static explicit operator Array(Array<T> from)
|
||||||
{
|
{
|
||||||
return from.objectArray;
|
return from._underlyingArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -429,7 +423,7 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Array.</returns>
|
/// <returns>A new Godot Array.</returns>
|
||||||
public Array<T> Duplicate(bool deep = false)
|
public Array<T> Duplicate(bool deep = false)
|
||||||
{
|
{
|
||||||
return new Array<T>(objectArray.Duplicate(deep));
|
return new Array<T>(_underlyingArray.Duplicate(deep));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -439,7 +433,7 @@ namespace Godot.Collections
|
||||||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
||||||
public Error Resize(int newSize)
|
public Error Resize(int newSize)
|
||||||
{
|
{
|
||||||
return objectArray.Resize(newSize);
|
return _underlyingArray.Resize(newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -447,7 +441,7 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Shuffle()
|
public void Shuffle()
|
||||||
{
|
{
|
||||||
objectArray.Shuffle();
|
_underlyingArray.Shuffle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -458,7 +452,7 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
||||||
public static Array<T> operator +(Array<T> left, Array<T> right)
|
public static Array<T> operator +(Array<T> left, Array<T> right)
|
||||||
{
|
{
|
||||||
return new Array<T>(left.objectArray + right.objectArray);
|
return new Array<T>(left._underlyingArray + right._underlyingArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IList<T>
|
// IList<T>
|
||||||
|
@ -469,8 +463,15 @@ namespace Godot.Collections
|
||||||
/// <value>The value at the given index.</value>
|
/// <value>The value at the given index.</value>
|
||||||
public T this[int index]
|
public T this[int index]
|
||||||
{
|
{
|
||||||
get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
|
get
|
||||||
set { objectArray[index] = value; }
|
{
|
||||||
|
_underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
return (T)Marshaling.variant_to_mono_object_of_type(&borrowElem, TypeOfElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set => _underlyingArray[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -481,7 +482,7 @@ namespace Godot.Collections
|
||||||
/// <returns>The index of the item, or -1 if not found.</returns>
|
/// <returns>The index of the item, or -1 if not found.</returns>
|
||||||
public int IndexOf(T item)
|
public int IndexOf(T item)
|
||||||
{
|
{
|
||||||
return objectArray.IndexOf(item);
|
return _underlyingArray.IndexOf(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -494,7 +495,7 @@ namespace Godot.Collections
|
||||||
/// <param name="item">The item to insert.</param>
|
/// <param name="item">The item to insert.</param>
|
||||||
public void Insert(int index, T item)
|
public void Insert(int index, T item)
|
||||||
{
|
{
|
||||||
objectArray.Insert(index, item);
|
_underlyingArray.Insert(index, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -503,7 +504,7 @@ namespace Godot.Collections
|
||||||
/// <param name="index">The index of the element to remove.</param>
|
/// <param name="index">The index of the element to remove.</param>
|
||||||
public void RemoveAt(int index)
|
public void RemoveAt(int index)
|
||||||
{
|
{
|
||||||
objectArray.RemoveAt(index);
|
_underlyingArray.RemoveAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICollection<T>
|
// ICollection<T>
|
||||||
|
@ -513,10 +514,7 @@ namespace Godot.Collections
|
||||||
/// This is also known as the size or length of the array.
|
/// This is also known as the size or length of the array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The number of elements.</returns>
|
/// <returns>The number of elements.</returns>
|
||||||
public int Count
|
public int Count => _underlyingArray.Count;
|
||||||
{
|
|
||||||
get { return objectArray.Count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<T>.IsReadOnly => false;
|
bool ICollection<T>.IsReadOnly => false;
|
||||||
|
|
||||||
|
@ -528,7 +526,7 @@ namespace Godot.Collections
|
||||||
/// <returns>The new size after adding the item.</returns>
|
/// <returns>The new size after adding the item.</returns>
|
||||||
public void Add(T item)
|
public void Add(T item)
|
||||||
{
|
{
|
||||||
objectArray.Add(item);
|
_underlyingArray.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -536,7 +534,7 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
objectArray.Clear();
|
_underlyingArray.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -546,7 +544,7 @@ namespace Godot.Collections
|
||||||
/// <returns>Whether or not this array contains the given item.</returns>
|
/// <returns>Whether or not this array contains the given item.</returns>
|
||||||
public bool Contains(T item)
|
public bool Contains(T item)
|
||||||
{
|
{
|
||||||
return objectArray.Contains(item);
|
return _underlyingArray.Contains(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -561,19 +559,18 @@ namespace Godot.Collections
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
|
||||||
if (arrayIndex < 0)
|
if (arrayIndex < 0)
|
||||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
|
throw new ArgumentOutOfRangeException(nameof(arrayIndex),
|
||||||
|
"Number was less than the array's lower bound in the first dimension.");
|
||||||
|
|
||||||
// TODO This may be quite slow because every element access is an internal call.
|
int count = _underlyingArray.Count;
|
||||||
// It could be moved entirely to an internal call if we find out how to do the cast there.
|
|
||||||
|
|
||||||
int count = objectArray.Count;
|
|
||||||
|
|
||||||
if (array.Length < (arrayIndex + count))
|
if (array.Length < (arrayIndex + count))
|
||||||
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
throw new ArgumentException(
|
||||||
|
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
array[arrayIndex] = (T)this[i];
|
array[arrayIndex] = this[i];
|
||||||
arrayIndex++;
|
arrayIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,7 +583,14 @@ namespace Godot.Collections
|
||||||
/// <returns>A bool indicating success or failure.</returns>
|
/// <returns>A bool indicating success or failure.</returns>
|
||||||
public bool Remove(T item)
|
public bool Remove(T item)
|
||||||
{
|
{
|
||||||
return Array.godot_icall_Array_Remove(GetPtr(), item);
|
int index = IndexOf(item);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
RemoveAt(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IEnumerable<T>
|
// IEnumerable<T>
|
||||||
|
@ -597,23 +601,20 @@ namespace Godot.Collections
|
||||||
/// <returns>An enumerator.</returns>
|
/// <returns>An enumerator.</returns>
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
int count = objectArray.Count;
|
int count = _underlyingArray.Count;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
yield return (T)this[i];
|
yield return this[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this <see cref="Array{T}"/> to a string.
|
/// Converts this <see cref="Array{T}"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string representation of this array.</returns>
|
/// <returns>A string representation of this array.</returns>
|
||||||
public override string ToString() => objectArray.ToString();
|
public override string ToString() => _underlyingArray.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Assembly)]
|
[AttributeUsage(AttributeTargets.Assembly)]
|
||||||
public class AssemblyHasScriptsAttribute : Attribute
|
public class AssemblyHasScriptsAttribute : Attribute
|
||||||
{
|
{
|
||||||
private readonly bool requiresLookup;
|
public bool RequiresLookup { get; private set; }
|
||||||
private readonly System.Type[] scriptTypes;
|
public Type[]? ScriptTypes { get; private set; }
|
||||||
|
|
||||||
public AssemblyHasScriptsAttribute()
|
public AssemblyHasScriptsAttribute()
|
||||||
{
|
{
|
||||||
requiresLookup = true;
|
RequiresLookup = true;
|
||||||
|
ScriptTypes = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssemblyHasScriptsAttribute(System.Type[] scriptTypes)
|
public AssemblyHasScriptsAttribute(Type[] scriptTypes)
|
||||||
{
|
{
|
||||||
requiresLookup = false;
|
RequiresLookup = false;
|
||||||
this.scriptTypes = scriptTypes;
|
ScriptTypes = scriptTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#nullable restore
|
||||||
|
|
|
@ -5,11 +5,11 @@ namespace Godot
|
||||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||||
public class ScriptPathAttribute : Attribute
|
public class ScriptPathAttribute : Attribute
|
||||||
{
|
{
|
||||||
private string path;
|
public string Path { get; private set; }
|
||||||
|
|
||||||
public ScriptPathAttribute(string path)
|
public ScriptPathAttribute(string path)
|
||||||
{
|
{
|
||||||
this.path = path;
|
Path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -727,7 +727,7 @@ namespace Godot
|
||||||
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
|
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
|
||||||
/// given in the vector format as (X angle, Y angle, Z angle).
|
/// given in the vector format as (X angle, Y angle, Z angle).
|
||||||
///
|
///
|
||||||
/// Consider using the <see cref="Basis(Quaternion)"/> constructor instead, which
|
/// Consider using the <see cref="Basis(Godot.Quaternion)"/> constructor instead, which
|
||||||
/// uses a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
|
/// uses a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
|
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
namespace Godot.Bridge
|
||||||
|
{
|
||||||
|
internal static class CSharpInstanceBridge
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool Call(IntPtr godotObjectGCHandle, godot_string_name* method,
|
||||||
|
godot_variant** args, int argCount, godot_variant_call_error* refCallError, godot_variant* ret)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||||
|
|
||||||
|
if (godotObject == null)
|
||||||
|
{
|
||||||
|
*ret = default;
|
||||||
|
(*refCallError).error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
using godot_string dest = default;
|
||||||
|
NativeFuncs.godotsharp_string_name_as_string(&dest, method);
|
||||||
|
string methodStr = Marshaling.mono_string_from_godot(dest);
|
||||||
|
|
||||||
|
_ = godotObject.InternalGodotScriptCall(methodStr, args, argCount, out godot_variant retValue);
|
||||||
|
*ret = retValue;
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
*ret = default;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool Set(IntPtr godotObjectGCHandle, godot_string_name* name, godot_variant* value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||||
|
|
||||||
|
if (godotObject == null)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_string_name_new_copy(name));
|
||||||
|
|
||||||
|
if (godotObject.InternalGodotScriptSetFieldOrPropViaReflection(nameManaged.ToString(), value))
|
||||||
|
return true.ToGodotBool();
|
||||||
|
|
||||||
|
object valueManaged = Marshaling.variant_to_mono_object(value);
|
||||||
|
|
||||||
|
return godotObject._Set(nameManaged, valueManaged).ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool Get(IntPtr godotObjectGCHandle, godot_string_name* name,
|
||||||
|
godot_variant* outRet)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||||
|
|
||||||
|
if (godotObject == null)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_string_name_new_copy(name));
|
||||||
|
|
||||||
|
if (godotObject.InternalGodotScriptGetFieldOrPropViaReflection(nameManaged.ToString(),
|
||||||
|
out godot_variant outRetValue))
|
||||||
|
{
|
||||||
|
*outRet = outRetValue;
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
object ret = godotObject._Get(nameManaged);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
{
|
||||||
|
*outRet = default;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
*outRet = Marshaling.mono_object_to_variant(ret);
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
*outRet = default;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void CallDispose(IntPtr godotObjectGCHandle, godot_bool okIfNull)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||||
|
|
||||||
|
if (okIfNull.ToBool())
|
||||||
|
godotObject?.Dispose();
|
||||||
|
else
|
||||||
|
godotObject!.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void CallToString(IntPtr godotObjectGCHandle, godot_string* outRes, godot_bool* outValid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var self = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||||
|
|
||||||
|
if (self == null)
|
||||||
|
{
|
||||||
|
*outRes = default;
|
||||||
|
*outValid = false.ToGodotBool();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultStr = self.ToString();
|
||||||
|
|
||||||
|
if (resultStr == null)
|
||||||
|
{
|
||||||
|
*outRes = default;
|
||||||
|
*outValid = false.ToGodotBool();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outRes = Marshaling.mono_string_to_godot(resultStr);
|
||||||
|
*outValid = true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
*outRes = default;
|
||||||
|
*outValid = false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
namespace Godot.Bridge
|
||||||
|
{
|
||||||
|
internal static class GCHandleBridge
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void FreeGCHandle(IntPtr gcHandlePtr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GCHandle.FromIntPtr(gcHandlePtr).Free();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
namespace Godot.Bridge
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe struct ManagedCallbacks
|
||||||
|
{
|
||||||
|
// @formatter:off
|
||||||
|
public delegate* unmanaged<IntPtr, godot_variant**, int, godot_bool*, void> SignalAwaiter_SignalCallback;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_variant**, uint, godot_variant*, void> DelegateUtils_InvokeWithVariantArgs;
|
||||||
|
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> DelegateUtils_DelegateEquals;
|
||||||
|
public delegate* unmanaged<void> ScriptManagerBridge_FrameCallback;
|
||||||
|
public delegate* unmanaged<godot_string_name*, IntPtr, IntPtr> ScriptManagerBridge_CreateManagedForGodotObjectBinding;
|
||||||
|
public delegate* unmanaged<IntPtr, IntPtr, godot_variant**, int, godot_bool> ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string_name*, void> ScriptManagerBridge_GetScriptNativeName;
|
||||||
|
public delegate* unmanaged<IntPtr, IntPtr, void> ScriptManagerBridge_SetGodotObjectPtr;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_bool*, void> ScriptManagerBridge_RaiseEventSignal;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_dictionary*, void> ScriptManagerBridge_GetScriptSignalList;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string*, godot_bool> ScriptManagerBridge_HasScriptSignal;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string*, godot_bool, godot_bool> ScriptManagerBridge_HasMethodUnknownParams;
|
||||||
|
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> ScriptManagerBridge_ScriptIsOrInherits;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string*, godot_bool> ScriptManagerBridge_AddScriptBridge;
|
||||||
|
public delegate* unmanaged<IntPtr, void> ScriptManagerBridge_RemoveScriptBridge;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_bool*, godot_dictionary*, void> ScriptManagerBridge_UpdateScriptClassInfo;
|
||||||
|
public delegate* unmanaged<IntPtr, IntPtr*, godot_bool, godot_bool> ScriptManagerBridge_SwapGCHandleForType;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> CSharpInstanceBridge_Call;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Set;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Get;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_bool, void> CSharpInstanceBridge_CallDispose;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_string*, godot_bool*, void> CSharpInstanceBridge_CallToString;
|
||||||
|
public delegate* unmanaged<IntPtr, void> GCHandleBridge_FreeGCHandle;
|
||||||
|
public delegate* unmanaged<void> DebuggingUtils_InstallTraceListener;
|
||||||
|
public delegate* unmanaged<void> Dispatcher_InitializeDefaultGodotTaskScheduler;
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
public static ManagedCallbacks Create()
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
// @formatter:off
|
||||||
|
SignalAwaiter_SignalCallback = &SignalAwaiter.SignalCallback,
|
||||||
|
DelegateUtils_InvokeWithVariantArgs = &DelegateUtils.InvokeWithVariantArgs,
|
||||||
|
DelegateUtils_DelegateEquals = &DelegateUtils.DelegateEquals,
|
||||||
|
ScriptManagerBridge_FrameCallback = &ScriptManagerBridge.FrameCallback,
|
||||||
|
ScriptManagerBridge_CreateManagedForGodotObjectBinding = &ScriptManagerBridge.CreateManagedForGodotObjectBinding,
|
||||||
|
ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance = &ScriptManagerBridge.CreateManagedForGodotObjectScriptInstance,
|
||||||
|
ScriptManagerBridge_GetScriptNativeName = &ScriptManagerBridge.GetScriptNativeName,
|
||||||
|
ScriptManagerBridge_SetGodotObjectPtr = &ScriptManagerBridge.SetGodotObjectPtr,
|
||||||
|
ScriptManagerBridge_RaiseEventSignal = &ScriptManagerBridge.RaiseEventSignal,
|
||||||
|
ScriptManagerBridge_GetScriptSignalList = &ScriptManagerBridge.GetScriptSignalList,
|
||||||
|
ScriptManagerBridge_HasScriptSignal = &ScriptManagerBridge.HasScriptSignal,
|
||||||
|
ScriptManagerBridge_HasMethodUnknownParams = &ScriptManagerBridge.HasMethodUnknownParams,
|
||||||
|
ScriptManagerBridge_ScriptIsOrInherits = &ScriptManagerBridge.ScriptIsOrInherits,
|
||||||
|
ScriptManagerBridge_AddScriptBridge = &ScriptManagerBridge.AddScriptBridge,
|
||||||
|
ScriptManagerBridge_RemoveScriptBridge = &ScriptManagerBridge.RemoveScriptBridge,
|
||||||
|
ScriptManagerBridge_UpdateScriptClassInfo = &ScriptManagerBridge.UpdateScriptClassInfo,
|
||||||
|
ScriptManagerBridge_SwapGCHandleForType = &ScriptManagerBridge.SwapGCHandleForType,
|
||||||
|
CSharpInstanceBridge_Call = &CSharpInstanceBridge.Call,
|
||||||
|
CSharpInstanceBridge_Set = &CSharpInstanceBridge.Set,
|
||||||
|
CSharpInstanceBridge_Get = &CSharpInstanceBridge.Get,
|
||||||
|
CSharpInstanceBridge_CallDispose = &CSharpInstanceBridge.CallDispose,
|
||||||
|
CSharpInstanceBridge_CallToString = &CSharpInstanceBridge.CallToString,
|
||||||
|
GCHandleBridge_FreeGCHandle = &GCHandleBridge.FreeGCHandle,
|
||||||
|
DebuggingUtils_InstallTraceListener = &DebuggingUtils.InstallTraceListener,
|
||||||
|
Dispatcher_InitializeDefaultGodotTaskScheduler = &Dispatcher.InitializeDefaultGodotTaskScheduler,
|
||||||
|
// @formatter:on
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,668 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Godot.Collections;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
namespace Godot.Bridge
|
||||||
|
{
|
||||||
|
internal static class ScriptManagerBridge
|
||||||
|
{
|
||||||
|
private static System.Collections.Generic.Dictionary<string, ScriptLookupInfo> _scriptLookupMap = new();
|
||||||
|
private static System.Collections.Generic.Dictionary<IntPtr, Type> _scriptBridgeMap = new();
|
||||||
|
|
||||||
|
private struct ScriptLookupInfo
|
||||||
|
{
|
||||||
|
public string ClassNamespace { get; private set; }
|
||||||
|
public string ClassName { get; private set; }
|
||||||
|
public Type ScriptType { get; private set; }
|
||||||
|
|
||||||
|
public ScriptLookupInfo(string classNamespace, string className, Type scriptType)
|
||||||
|
{
|
||||||
|
ClassNamespace = classNamespace;
|
||||||
|
ClassName = className;
|
||||||
|
ScriptType = scriptType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void FrameCallback()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dispatcher.DefaultGodotTaskScheduler?.Activate();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
|
||||||
|
IntPtr godotObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type nativeType = TypeGetProxyClass(nativeTypeName);
|
||||||
|
var obj = (Object)FormatterServices.GetUninitializedObject(nativeType);
|
||||||
|
|
||||||
|
obj.NativePtr = godotObject;
|
||||||
|
|
||||||
|
var ctor = nativeType.GetConstructor(
|
||||||
|
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||||
|
null, Type.EmptyTypes, null);
|
||||||
|
_ = ctor!.Invoke(obj, null);
|
||||||
|
|
||||||
|
return GCHandle.ToIntPtr(GCHandle.Alloc(obj));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool CreateManagedForGodotObjectScriptInstance(IntPtr scriptPtr,
|
||||||
|
IntPtr godotObject,
|
||||||
|
godot_variant** args, int argCount)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
Type scriptType = _scriptBridgeMap[scriptPtr];
|
||||||
|
var obj = (Object)FormatterServices.GetUninitializedObject(scriptType);
|
||||||
|
|
||||||
|
obj.NativePtr = godotObject;
|
||||||
|
|
||||||
|
var ctor = scriptType
|
||||||
|
.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
.Where(c => c.GetParameters().Length == argCount)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (ctor == null)
|
||||||
|
{
|
||||||
|
if (argCount == 0)
|
||||||
|
{
|
||||||
|
throw new MissingMemberException(
|
||||||
|
$"Cannot create script instance. The class '{scriptType.FullName}' does not define a parameterless constructor.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new MissingMemberException(
|
||||||
|
$"The class '{scriptType.FullName}' does not define a constructor that takes x parameters.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parameters = ctor.GetParameters();
|
||||||
|
int paramCount = parameters.Length;
|
||||||
|
|
||||||
|
object[] invokeParams = new object[paramCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < paramCount; i++)
|
||||||
|
{
|
||||||
|
invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
|
||||||
|
args[i], parameters[i].ParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctor.Invoke(obj, invokeParams);
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void GetScriptNativeName(IntPtr scriptPtr, godot_string_name* outRes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||||
|
{
|
||||||
|
*outRes = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var native = Object.InternalGetClassNativeBase(scriptType);
|
||||||
|
|
||||||
|
var field = native?.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||||
|
BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
if (field == null)
|
||||||
|
{
|
||||||
|
*outRes = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nativeName = (StringName)field.GetValue(null);
|
||||||
|
|
||||||
|
if (nativeName == null)
|
||||||
|
{
|
||||||
|
*outRes = default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outRes = NativeFuncs.godotsharp_string_name_new_copy(nativeName.NativeValue);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
*outRes = default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void SetGodotObjectPtr(IntPtr gcHandlePtr, IntPtr newPtr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var target = (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
|
||||||
|
if (target != null)
|
||||||
|
target.NativePtr = newPtr;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static unsafe Type TypeGetProxyClass(godot_string_name* nativeTypeName)
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with a generated dictionary.
|
||||||
|
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_string_name_new_copy(nativeTypeName));
|
||||||
|
string nativeTypeNameStr = stringName.ToString();
|
||||||
|
|
||||||
|
if (nativeTypeNameStr[0] == '_')
|
||||||
|
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
|
||||||
|
|
||||||
|
Type wrapperType = typeof(Object).Assembly.GetType("Godot." + nativeTypeNameStr);
|
||||||
|
|
||||||
|
if (wrapperType == null)
|
||||||
|
{
|
||||||
|
wrapperType = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.First(a => a.GetName().Name == "GodotSharpEditor")
|
||||||
|
.GetType("Godot." + nativeTypeNameStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
|
||||||
|
|
||||||
|
if (wrapperType != null && IsStatic(wrapperType))
|
||||||
|
{
|
||||||
|
// A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
|
||||||
|
return typeof(Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapperType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from GodotPlugins
|
||||||
|
// ReSharper disable once UnusedMember.Local
|
||||||
|
private static void LookupScriptsInAssembly(Assembly assembly)
|
||||||
|
{
|
||||||
|
static void LookupScriptForClass(Type type)
|
||||||
|
{
|
||||||
|
var scriptPathAttr = type.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<ScriptPathAttribute>()
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (scriptPathAttr == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_scriptLookupMap[scriptPathAttr.Path] = new ScriptLookupInfo(type.Namespace, type.Name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
var assemblyHasScriptsAttr = assembly.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<AssemblyHasScriptsAttribute>()
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (assemblyHasScriptsAttr == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (assemblyHasScriptsAttr.RequiresLookup)
|
||||||
|
{
|
||||||
|
// This is supported for scenarios where specifying all types would be cumbersome,
|
||||||
|
// such as when disabling C# source generators (for whatever reason) or when using a
|
||||||
|
// language other than C# that has nothing similar to source generators to automate it.
|
||||||
|
|
||||||
|
var typeOfGodotObject = typeof(Object);
|
||||||
|
|
||||||
|
foreach (var type in assembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (type.IsNested)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!typeOfGodotObject.IsAssignableFrom(type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LookupScriptForClass(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is the most likely scenario as we use C# source generators
|
||||||
|
|
||||||
|
var scriptTypes = assemblyHasScriptsAttr.ScriptTypes;
|
||||||
|
|
||||||
|
if (scriptTypes != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < scriptTypes.Length; i++)
|
||||||
|
{
|
||||||
|
LookupScriptForClass(scriptTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void RaiseEventSignal(IntPtr ownerGCHandlePtr,
|
||||||
|
godot_string_name* eventSignalName, godot_variant** args, int argCount, godot_bool* outOwnerIsNull)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var owner = (Object)GCHandle.FromIntPtr(ownerGCHandlePtr).Target;
|
||||||
|
|
||||||
|
if (owner == null)
|
||||||
|
{
|
||||||
|
*outOwnerIsNull = true.ToGodotBool();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outOwnerIsNull = false.ToGodotBool();
|
||||||
|
|
||||||
|
owner.InternalRaiseEventSignal(eventSignalName, args, argCount);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
*outOwnerIsNull = false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void GetScriptSignalList(IntPtr scriptPtr, godot_dictionary* outRetSignals)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
using var signals = new Dictionary();
|
||||||
|
|
||||||
|
Type top = _scriptBridgeMap[scriptPtr];
|
||||||
|
Type native = Object.InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
// Legacy signals
|
||||||
|
|
||||||
|
foreach (var signalDelegate in top
|
||||||
|
.GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
|
||||||
|
.Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any()))
|
||||||
|
{
|
||||||
|
var invokeMethod = signalDelegate.GetMethod("Invoke");
|
||||||
|
|
||||||
|
if (invokeMethod == null)
|
||||||
|
throw new MissingMethodException(signalDelegate.FullName, "Invoke");
|
||||||
|
|
||||||
|
var signalParams = new Collections.Array();
|
||||||
|
|
||||||
|
foreach (var parameters in invokeMethod.GetParameters())
|
||||||
|
{
|
||||||
|
var paramType = Marshaling.managed_to_variant_type(
|
||||||
|
parameters.ParameterType, out bool nilIsVariant);
|
||||||
|
signalParams.Add(new Dictionary()
|
||||||
|
{
|
||||||
|
{ "name", parameters.Name },
|
||||||
|
{ "type", paramType },
|
||||||
|
{ "nil_is_variant", nilIsVariant }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
signals.Add(signalDelegate.Name, signalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event signals
|
||||||
|
|
||||||
|
var foundEventSignals = top.GetEvents(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||||
|
.Select(ev => ev.Name);
|
||||||
|
|
||||||
|
var fields = top.GetFields(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
foreach (var eventSignalField in fields
|
||||||
|
.Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
|
||||||
|
.Where(f => foundEventSignals.Contains(f.Name)))
|
||||||
|
{
|
||||||
|
var delegateType = eventSignalField.FieldType;
|
||||||
|
var invokeMethod = delegateType.GetMethod("Invoke");
|
||||||
|
|
||||||
|
if (invokeMethod == null)
|
||||||
|
throw new MissingMethodException(delegateType.FullName, "Invoke");
|
||||||
|
|
||||||
|
var signalParams = new Collections.Array();
|
||||||
|
|
||||||
|
foreach (var parameters in invokeMethod.GetParameters())
|
||||||
|
{
|
||||||
|
var paramType = Marshaling.managed_to_variant_type(
|
||||||
|
parameters.ParameterType, out bool nilIsVariant);
|
||||||
|
signalParams.Add(new Dictionary()
|
||||||
|
{
|
||||||
|
{ "name", parameters.Name },
|
||||||
|
{ "type", paramType },
|
||||||
|
{ "nil_is_variant", nilIsVariant }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
signals.Add(eventSignalField.Name, signalParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outRetSignals = NativeFuncs.godotsharp_dictionary_new_copy(signals.NativeValue);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
*outRetSignals = NativeFuncs.godotsharp_dictionary_new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool HasScriptSignal(IntPtr scriptPtr, godot_string* signalName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
using var signals = new Dictionary();
|
||||||
|
|
||||||
|
string signalNameStr = Marshaling.mono_string_from_godot(*signalName);
|
||||||
|
|
||||||
|
Type top = _scriptBridgeMap[scriptPtr];
|
||||||
|
Type native = Object.InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
// Legacy signals
|
||||||
|
|
||||||
|
if (top
|
||||||
|
.GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
|
||||||
|
.Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||||
|
.Any(signalDelegate => signalDelegate.Name == signalNameStr)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event signals
|
||||||
|
|
||||||
|
if (top.GetEvents(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||||
|
.Any(eventSignal => eventSignal.Name == signalNameStr)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool HasMethodUnknownParams(IntPtr scriptPtr, godot_string* method,
|
||||||
|
godot_bool deep)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||||
|
return false.ToGodotBool();
|
||||||
|
|
||||||
|
string methodStr = Marshaling.mono_string_from_godot(*method);
|
||||||
|
|
||||||
|
if (deep.ToBool())
|
||||||
|
{
|
||||||
|
Type top = scriptType;
|
||||||
|
Type native = Object.InternalGetClassNativeBase(scriptType);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
var methodInfo = top.GetMethod(methodStr,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (methodInfo != null)
|
||||||
|
return true.ToGodotBool();
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
top = native;
|
||||||
|
Type typeOfSystemObject = typeof(System.Object);
|
||||||
|
while (top != null && top != typeOfSystemObject)
|
||||||
|
{
|
||||||
|
bool found = top.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(m => m.GetCustomAttributes(false).OfType<GodotMethodAttribute>()
|
||||||
|
.Where(a => a.MethodName == methodStr)
|
||||||
|
.Any())
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
return true.ToGodotBool();
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var methodInfo = scriptType.GetMethod(methodStr, BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
return (methodInfo != null).ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static godot_bool ScriptIsOrInherits(IntPtr scriptPtr, IntPtr scriptPtrMaybeBase)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||||
|
return false.ToGodotBool();
|
||||||
|
|
||||||
|
if (!_scriptBridgeMap.TryGetValue(scriptPtrMaybeBase, out var maybeBaseType))
|
||||||
|
return false.ToGodotBool();
|
||||||
|
|
||||||
|
return (scriptType == maybeBaseType || maybeBaseType.IsAssignableFrom(scriptType)).ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool AddScriptBridge(IntPtr scriptPtr, godot_string* scriptPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string scriptPathStr = Marshaling.mono_string_from_godot(*scriptPath);
|
||||||
|
|
||||||
|
if (!_scriptLookupMap.TryGetValue(scriptPathStr, out var lookupInfo))
|
||||||
|
return false.ToGodotBool();
|
||||||
|
|
||||||
|
_scriptBridgeMap.Add(scriptPtr, lookupInfo.ScriptType);
|
||||||
|
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AddScriptBridgeWithType(IntPtr scriptPtr, Type scriptType)
|
||||||
|
=> _scriptBridgeMap.Add(scriptPtr, scriptType);
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void RemoveScriptBridge(IntPtr scriptPtr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_scriptBridgeMap.Remove(scriptPtr);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void UpdateScriptClassInfo(IntPtr scriptPtr, godot_bool* outTool,
|
||||||
|
godot_dictionary* outRpcFunctionsDest)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
var scriptType = _scriptBridgeMap[scriptPtr];
|
||||||
|
|
||||||
|
*outTool = scriptType.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<ToolAttribute>()
|
||||||
|
.Any().ToGodotBool();
|
||||||
|
|
||||||
|
if (!(*outTool).ToBool() && scriptType.IsNested)
|
||||||
|
{
|
||||||
|
*outTool = (scriptType.DeclaringType?.GetCustomAttributes(inherit: false)
|
||||||
|
.OfType<ToolAttribute>()
|
||||||
|
.Any() ?? false).ToGodotBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*outTool).ToBool() && scriptType.Assembly.GetName().Name == "GodotTools")
|
||||||
|
*outTool = true.ToGodotBool();
|
||||||
|
|
||||||
|
// RPC functions
|
||||||
|
|
||||||
|
static MultiplayerAPI.RPCMode MemberGetRpcMode(MemberInfo memberInfo)
|
||||||
|
{
|
||||||
|
if (memberInfo.GetCustomAttributes(inherit: false).OfType<RemoteAttribute>().Any())
|
||||||
|
return MultiplayerAPI.RPCMode.Remote;
|
||||||
|
|
||||||
|
if (memberInfo.GetCustomAttributes(inherit: false).OfType<MasterAttribute>().Any())
|
||||||
|
return MultiplayerAPI.RPCMode.Master;
|
||||||
|
|
||||||
|
if (memberInfo.GetCustomAttributes(inherit: false).OfType<PuppetAttribute>().Any())
|
||||||
|
return MultiplayerAPI.RPCMode.Puppet;
|
||||||
|
|
||||||
|
return MultiplayerAPI.RPCMode.Disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, Dictionary> rpcFunctions = new();
|
||||||
|
|
||||||
|
Type top = _scriptBridgeMap[scriptPtr];
|
||||||
|
Type native = Object.InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
foreach (var method in top.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
|
{
|
||||||
|
if (method.IsStatic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string methodName = method.Name;
|
||||||
|
|
||||||
|
if (rpcFunctions.ContainsKey(methodName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var rpcMode = MemberGetRpcMode(method);
|
||||||
|
|
||||||
|
if (rpcMode == MultiplayerAPI.RPCMode.Disabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var rpcConfig = new Dictionary();
|
||||||
|
rpcConfig["rpc_mode"] = (int)rpcMode;
|
||||||
|
// TODO Transfer mode, channel
|
||||||
|
rpcConfig["transfer_mode"] = (int)MultiplayerPeer.TransferModeEnum.Reliable;
|
||||||
|
rpcConfig["channel"] = 0;
|
||||||
|
|
||||||
|
rpcFunctions.Add(methodName, rpcConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outRpcFunctionsDest =
|
||||||
|
NativeFuncs.godotsharp_dictionary_new_copy(((Dictionary)rpcFunctions).NativeValue);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
*outTool = false.ToGodotBool();
|
||||||
|
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe godot_bool SwapGCHandleForType(IntPtr oldGCHandlePtr, IntPtr* outNewGCHandlePtr,
|
||||||
|
godot_bool createWeak)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var oldGCHandle = GCHandle.FromIntPtr(oldGCHandlePtr);
|
||||||
|
|
||||||
|
object target = oldGCHandle.Target;
|
||||||
|
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
*outNewGCHandlePtr = IntPtr.Zero;
|
||||||
|
return false.ToGodotBool(); // Called after the managed side was collected, so nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the current weak handle and replace it with a strong handle.
|
||||||
|
var newGCHandle = GCHandle.Alloc(target,
|
||||||
|
createWeak.ToBool() ? GCHandleType.Weak : GCHandleType.Normal);
|
||||||
|
*outNewGCHandlePtr = GCHandle.ToIntPtr(newGCHandle);
|
||||||
|
|
||||||
|
return true.ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
*outNewGCHandlePtr = IntPtr.Zero;
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
|
@ -19,13 +21,23 @@ namespace Godot
|
||||||
sb.Append(" ");
|
sb.Append(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InstallTraceListener()
|
[UnmanagedCallersOnly]
|
||||||
|
internal static void InstallTraceListener()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Trace.Listeners.Clear();
|
Trace.Listeners.Clear();
|
||||||
Trace.Listeners.Add(new GodotTraceListener());
|
Trace.Listeners.Add(new GodotTraceListener());
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
ExceptionUtils.PushError("Failed to install 'System.Diagnostics.Trace' listener.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl)
|
public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber,
|
||||||
|
out string methodDecl)
|
||||||
{
|
{
|
||||||
fileName = frame.GetFileName();
|
fileName = frame.GetFileName();
|
||||||
fileLineNumber = frame.GetFileLineNumber();
|
fileLineNumber = frame.GetFileLineNumber();
|
||||||
|
|
|
@ -4,11 +4,67 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
internal static class DelegateUtils
|
internal static class DelegateUtils
|
||||||
{
|
{
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static godot_bool DelegateEquals(IntPtr delegateGCHandleA, IntPtr delegateGCHandleB)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var @delegateA = (Delegate)GCHandle.FromIntPtr(delegateGCHandleA).Target;
|
||||||
|
var @delegateB = (Delegate)GCHandle.FromIntPtr(delegateGCHandleB).Target;
|
||||||
|
return (@delegateA == @delegateB).ToGodotBool();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
return false.ToGodotBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, godot_variant** args, uint argc,
|
||||||
|
godot_variant* outRet)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: Optimize
|
||||||
|
var @delegate = (Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target;
|
||||||
|
var managedArgs = new object[argc];
|
||||||
|
|
||||||
|
var parameterInfos = @delegate!.Method.GetParameters();
|
||||||
|
var paramsLength = parameterInfos.Length;
|
||||||
|
|
||||||
|
if (argc != paramsLength)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"The delegate expects {paramsLength} arguments, but received {argc}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
|
||||||
|
args[i], parameterInfos[i].ParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
object invokeRet = @delegate.DynamicInvoke(managedArgs);
|
||||||
|
|
||||||
|
*outRet = Marshaling.mono_object_to_variant(invokeRet);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
|
*outRet = default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check if we should be using BindingFlags.DeclaredOnly (would give better reflection performance).
|
||||||
|
|
||||||
private enum TargetKind : uint
|
private enum TargetKind : uint
|
||||||
{
|
{
|
||||||
Static,
|
Static,
|
||||||
|
@ -16,7 +72,10 @@ namespace Godot
|
||||||
CompilerGenerated
|
CompilerGenerated
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
|
internal static bool TrySerializeDelegateWithGCHandle(IntPtr delegateGCHandle, Collections.Array serializedData)
|
||||||
|
=> TrySerializeDelegate((Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target, serializedData);
|
||||||
|
|
||||||
|
private static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
|
||||||
{
|
{
|
||||||
if (@delegate is MulticastDelegate multicastDelegate)
|
if (@delegate is MulticastDelegate multicastDelegate)
|
||||||
{
|
{
|
||||||
|
@ -72,12 +131,14 @@ namespace Godot
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ReSharper disable once RedundantNameQualifier
|
||||||
case Godot.Object godotObject:
|
case Godot.Object godotObject:
|
||||||
{
|
{
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
using (var writer = new BinaryWriter(stream))
|
using (var writer = new BinaryWriter(stream))
|
||||||
{
|
{
|
||||||
writer.Write((ulong)TargetKind.GodotObject);
|
writer.Write((ulong)TargetKind.GodotObject);
|
||||||
|
// ReSharper disable once RedundantCast
|
||||||
writer.Write((ulong)godotObject.GetInstanceId());
|
writer.Write((ulong)godotObject.GetInstanceId());
|
||||||
|
|
||||||
SerializeType(writer, @delegate.GetType());
|
SerializeType(writer, @delegate.GetType());
|
||||||
|
@ -93,7 +154,7 @@ namespace Godot
|
||||||
{
|
{
|
||||||
Type targetType = target.GetType();
|
Type targetType = target.GetType();
|
||||||
|
|
||||||
if (targetType.GetCustomAttribute(typeof(CompilerGeneratedAttribute), true) != null)
|
if (targetType.IsDefined(typeof(CompilerGeneratedAttribute), true))
|
||||||
{
|
{
|
||||||
// Compiler generated. Probably a closure. Try to serialize it.
|
// Compiler generated. Probably a closure. Try to serialize it.
|
||||||
|
|
||||||
|
@ -213,6 +274,14 @@ namespace Godot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TryDeserializeDelegateWithGCHandle(Collections.Array serializedData,
|
||||||
|
out IntPtr delegateGCHandle)
|
||||||
|
{
|
||||||
|
bool res = TryDeserializeDelegate(serializedData, out Delegate @delegate);
|
||||||
|
delegateGCHandle = GCHandle.ToIntPtr(GCHandle.Alloc(@delegate));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TryDeserializeDelegate(Collections.Array serializedData, out Delegate @delegate)
|
private static bool TryDeserializeDelegate(Collections.Array serializedData, out Delegate @delegate)
|
||||||
{
|
{
|
||||||
if (serializedData.Count == 1)
|
if (serializedData.Count == 1)
|
||||||
|
@ -276,6 +345,7 @@ namespace Godot
|
||||||
case TargetKind.GodotObject:
|
case TargetKind.GodotObject:
|
||||||
{
|
{
|
||||||
ulong objectId = reader.ReadUInt64();
|
ulong objectId = reader.ReadUInt64();
|
||||||
|
// ReSharper disable once RedundantNameQualifier
|
||||||
Godot.Object godotObject = GD.InstanceFromId(objectId);
|
Godot.Object godotObject = GD.InstanceFromId(objectId);
|
||||||
if (godotObject == null)
|
if (godotObject == null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -313,7 +383,8 @@ namespace Godot
|
||||||
int valueBufferLength = reader.ReadInt32();
|
int valueBufferLength = reader.ReadInt32();
|
||||||
byte[] valueBuffer = reader.ReadBytes(valueBufferLength);
|
byte[] valueBuffer = reader.ReadBytes(valueBufferLength);
|
||||||
|
|
||||||
FieldInfo fieldInfo = targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
|
FieldInfo fieldInfo =
|
||||||
|
targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
|
||||||
fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer));
|
fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,28 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Runtime.CompilerServices;
|
using Godot.NativeInterop;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace Godot.Collections
|
namespace Godot.Collections
|
||||||
{
|
{
|
||||||
class DictionarySafeHandle : SafeHandle
|
|
||||||
{
|
|
||||||
public DictionarySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
|
|
||||||
{
|
|
||||||
this.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsInvalid
|
|
||||||
{
|
|
||||||
get { return handle == IntPtr.Zero; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
|
||||||
{
|
|
||||||
Dictionary.godot_icall_Dictionary_Dtor(handle);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper around Godot's Dictionary class, a dictionary of Variant
|
/// Wrapper around Godot's Dictionary class, a dictionary of Variant
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
/// typed elements allocated in the engine in C++. Useful when
|
||||||
/// interfacing with the engine.
|
/// interfacing with the engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Dictionary :
|
public sealed class Dictionary :
|
||||||
IDictionary,
|
IDictionary,
|
||||||
IDisposable
|
IDisposable
|
||||||
{
|
{
|
||||||
DictionarySafeHandle safeHandle;
|
public godot_dictionary NativeValue;
|
||||||
bool disposed = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Dictionary"/>.
|
/// Constructs a new empty <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary()
|
public Dictionary()
|
||||||
{
|
{
|
||||||
safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
|
NativeValue = NativeFuncs.godotsharp_dictionary_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -60,22 +39,18 @@ namespace Godot.Collections
|
||||||
Add(entry.Key, entry.Value);
|
Add(entry.Key, entry.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Dictionary(DictionarySafeHandle handle)
|
private Dictionary(godot_dictionary nativeValueToOwn)
|
||||||
{
|
{
|
||||||
safeHandle = handle;
|
NativeValue = nativeValueToOwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Dictionary(IntPtr handle)
|
// Explicit name to make it very clear
|
||||||
{
|
internal static Dictionary CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn)
|
||||||
safeHandle = new DictionarySafeHandle(handle);
|
=> new Dictionary(nativeValueToOwn);
|
||||||
}
|
|
||||||
|
|
||||||
internal IntPtr GetPtr()
|
~Dictionary()
|
||||||
{
|
{
|
||||||
if (disposed)
|
Dispose(false);
|
||||||
throw new ObjectDisposedException(GetType().FullName);
|
|
||||||
|
|
||||||
return safeHandle.DangerousGetHandle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -83,16 +58,14 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (disposed)
|
Dispose(true);
|
||||||
return;
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
if (safeHandle != null)
|
|
||||||
{
|
|
||||||
safeHandle.Dispose();
|
|
||||||
safeHandle = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = true;
|
public void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
// Always dispose `NativeValue` even if disposing is true
|
||||||
|
NativeValue.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -102,7 +75,9 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
/// <returns>A new Godot Dictionary.</returns>
|
||||||
public Dictionary Duplicate(bool deep = false)
|
public Dictionary Duplicate(bool deep = false)
|
||||||
{
|
{
|
||||||
return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep));
|
godot_dictionary newDictionary;
|
||||||
|
NativeFuncs.godotsharp_dictionary_duplicate(ref NativeValue, deep.ToGodotBool(), out newDictionary);
|
||||||
|
return CreateTakingOwnershipOfDisposableValue(newDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDictionary
|
// IDictionary
|
||||||
|
@ -114,8 +89,9 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
IntPtr handle = godot_icall_Dictionary_Keys(GetPtr());
|
godot_array keysArray;
|
||||||
return new Array(new ArraySafeHandle(handle));
|
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
|
||||||
|
return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,16 +102,24 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
IntPtr handle = godot_icall_Dictionary_Values(GetPtr());
|
godot_array valuesArray;
|
||||||
return new Array(new ArraySafeHandle(handle));
|
NativeFuncs.godotsharp_dictionary_values(ref NativeValue, out valuesArray);
|
||||||
|
return Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private (Array keys, Array values, int count) GetKeyValuePairs()
|
private (Array keys, Array values, int count) GetKeyValuePairs()
|
||||||
{
|
{
|
||||||
int count = godot_icall_Dictionary_KeyValuePairs(GetPtr(), out IntPtr keysHandle, out IntPtr valuesHandle);
|
godot_array keysArray;
|
||||||
Array keys = new Array(new ArraySafeHandle(keysHandle));
|
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
|
||||||
Array values = new Array(new ArraySafeHandle(valuesHandle));
|
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||||
|
|
||||||
|
godot_array valuesArray;
|
||||||
|
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out valuesArray);
|
||||||
|
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||||
|
|
||||||
|
int count = NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
|
||||||
|
|
||||||
return (keys, values, count);
|
return (keys, values, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +131,28 @@ namespace Godot.Collections
|
||||||
/// Returns the object at the given <paramref name="key"/>.
|
/// Returns the object at the given <paramref name="key"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The object at the given <paramref name="key"/>.</value>
|
/// <value>The object at the given <paramref name="key"/>.</value>
|
||||||
public object this[object key]
|
public unsafe object this[object key]
|
||||||
{
|
{
|
||||||
get => godot_icall_Dictionary_GetValue(GetPtr(), key);
|
get
|
||||||
set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref NativeValue, &variantKey,
|
||||||
|
out godot_variant value).ToBool())
|
||||||
|
{
|
||||||
|
using (value)
|
||||||
|
return Marshaling.variant_to_mono_object(&value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||||
|
NativeFuncs.godotsharp_dictionary_set_value(ref NativeValue, &variantKey, &variantValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -159,19 +161,32 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key at which to add the object.</param>
|
/// <param name="key">The key at which to add the object.</param>
|
||||||
/// <param name="value">The object to add.</param>
|
/// <param name="value">The object to add.</param>
|
||||||
public void Add(object key, object value) => godot_icall_Dictionary_Add(GetPtr(), key, value);
|
public unsafe void Add(object key, object value)
|
||||||
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
|
||||||
|
if (NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool())
|
||||||
|
throw new ArgumentException("An element with the same key already exists", nameof(key));
|
||||||
|
|
||||||
|
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||||
|
NativeFuncs.godotsharp_dictionary_add(ref NativeValue, &variantKey, &variantValue);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Erases all items from this <see cref="Dictionary"/>.
|
/// Erases all items from this <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
|
public void Clear() => NativeFuncs.godotsharp_dictionary_clear(ref NativeValue);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if this <see cref="Dictionary"/> contains the given key.
|
/// Checks if this <see cref="Dictionary"/> contains the given key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key to look for.</param>
|
/// <param name="key">The key to look for.</param>
|
||||||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
||||||
public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(GetPtr(), key);
|
public unsafe bool Contains(object key)
|
||||||
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
return NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
||||||
|
@ -183,7 +198,11 @@ namespace Godot.Collections
|
||||||
/// Removes an element from this <see cref="Dictionary"/> by key.
|
/// Removes an element from this <see cref="Dictionary"/> by key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key of the element to remove.</param>
|
/// <param name="key">The key of the element to remove.</param>
|
||||||
public void Remove(object key) => godot_icall_Dictionary_RemoveKey(GetPtr(), key);
|
public unsafe void Remove(object key)
|
||||||
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
NativeFuncs.godotsharp_dictionary_remove_key(ref NativeValue, &variantKey);
|
||||||
|
}
|
||||||
|
|
||||||
// ICollection
|
// ICollection
|
||||||
|
|
||||||
|
@ -196,7 +215,7 @@ namespace Godot.Collections
|
||||||
/// This is also known as the size or length of the dictionary.
|
/// This is also known as the size or length of the dictionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The number of elements.</returns>
|
/// <returns>The number of elements.</returns>
|
||||||
public int Count => godot_icall_Dictionary_Count(GetPtr());
|
public int Count => NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies the elements of this <see cref="Dictionary"/> to the given
|
/// Copies the elements of this <see cref="Dictionary"/> to the given
|
||||||
|
@ -210,12 +229,14 @@ namespace Godot.Collections
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
|
throw new ArgumentOutOfRangeException(nameof(index),
|
||||||
|
"Number was less than the array's lower bound in the first dimension.");
|
||||||
|
|
||||||
var (keys, values, count) = GetKeyValuePairs();
|
var (keys, values, count) = GetKeyValuePairs();
|
||||||
|
|
||||||
if (array.Length < (index + count))
|
if (array.Length < (index + count))
|
||||||
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
throw new ArgumentException(
|
||||||
|
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -253,15 +274,23 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
UpdateEntry();
|
UpdateEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateEntry()
|
private unsafe void UpdateEntry()
|
||||||
{
|
{
|
||||||
dirty = false;
|
dirty = false;
|
||||||
godot_icall_Dictionary_KeyValuePairAt(dictionary.GetPtr(), index, out object key, out object value);
|
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref dictionary.NativeValue, index,
|
||||||
entry = new DictionaryEntry(key, value);
|
out godot_variant key,
|
||||||
|
out godot_variant value);
|
||||||
|
using (key)
|
||||||
|
using (value)
|
||||||
|
{
|
||||||
|
entry = new DictionaryEntry(Marshaling.variant_to_mono_object(&key),
|
||||||
|
Marshaling.variant_to_mono_object(&value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Key => Entry.Key;
|
public object Key => Entry.Key;
|
||||||
|
@ -286,75 +315,23 @@ namespace Godot.Collections
|
||||||
/// Converts this <see cref="Dictionary"/> to a string.
|
/// Converts this <see cref="Dictionary"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string representation of this dictionary.</returns>
|
/// <returns>A string representation of this dictionary.</returns>
|
||||||
public override string ToString()
|
public override unsafe string ToString()
|
||||||
{
|
{
|
||||||
return godot_icall_Dictionary_ToString(GetPtr());
|
using godot_string str = default;
|
||||||
|
NativeFuncs.godotsharp_dictionary_to_string(ref NativeValue, &str);
|
||||||
|
return Marshaling.mono_string_from_godot(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
internal interface IGenericGodotDictionary
|
||||||
internal extern static IntPtr godot_icall_Dictionary_Ctor();
|
{
|
||||||
|
Dictionary UnderlyingDictionary { get; }
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
Type TypeOfKeys { get; }
|
||||||
internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr);
|
Type TypeOfValues { get; }
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_Dictionary_Count(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_Dictionary_ToString(IntPtr ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Now we should be able to avoid boxing
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
|
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
/// typed elements allocated in the engine in C++. Useful when
|
||||||
|
@ -363,25 +340,30 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
|
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
|
||||||
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
||||||
public class Dictionary<TKey, TValue> :
|
public sealed class Dictionary<TKey, TValue> :
|
||||||
IDictionary<TKey, TValue>
|
IDictionary<TKey, TValue>, IGenericGodotDictionary
|
||||||
{
|
{
|
||||||
private readonly Dictionary objectDict;
|
private readonly Dictionary _underlyingDict;
|
||||||
|
|
||||||
internal static int valTypeEncoding;
|
// ReSharper disable StaticMemberInGenericType
|
||||||
internal static IntPtr valTypeClass;
|
// Warning is about unique static fields being created for each generic type combination:
|
||||||
|
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
||||||
|
// In our case this is exactly what we want.
|
||||||
|
private static readonly Type TypeOfKeys = typeof(TKey);
|
||||||
|
|
||||||
static Dictionary()
|
private static readonly Type TypeOfValues = typeof(TValue);
|
||||||
{
|
// ReSharper restore StaticMemberInGenericType
|
||||||
Dictionary.godot_icall_Dictionary_Generic_GetValueTypeInfo(typeof(TValue), out valTypeEncoding, out valTypeClass);
|
|
||||||
}
|
Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
|
||||||
|
Type IGenericGodotDictionary.TypeOfKeys => TypeOfKeys;
|
||||||
|
Type IGenericGodotDictionary.TypeOfValues => TypeOfValues;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
|
/// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary()
|
public Dictionary()
|
||||||
{
|
{
|
||||||
objectDict = new Dictionary();
|
_underlyingDict = new Dictionary();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -391,19 +373,13 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
/// <returns>A new Godot Dictionary.</returns>
|
||||||
public Dictionary(IDictionary<TKey, TValue> dictionary)
|
public Dictionary(IDictionary<TKey, TValue> dictionary)
|
||||||
{
|
{
|
||||||
objectDict = new Dictionary();
|
_underlyingDict = new Dictionary();
|
||||||
|
|
||||||
if (dictionary == null)
|
if (dictionary == null)
|
||||||
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
|
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
|
||||||
|
|
||||||
// TODO: Can be optimized
|
|
||||||
|
|
||||||
IntPtr godotDictionaryPtr = GetPtr();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
|
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
|
||||||
{
|
Add(entry.Key, entry.Value);
|
||||||
Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -413,18 +389,13 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
/// <returns>A new Godot Dictionary.</returns>
|
||||||
public Dictionary(Dictionary dictionary)
|
public Dictionary(Dictionary dictionary)
|
||||||
{
|
{
|
||||||
objectDict = dictionary;
|
_underlyingDict = dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Dictionary(IntPtr handle)
|
// Explicit name to make it very clear
|
||||||
{
|
internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(
|
||||||
objectDict = new Dictionary(handle);
|
godot_dictionary nativeValueToOwn)
|
||||||
}
|
=> new Dictionary<TKey, TValue>(Dictionary.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
||||||
|
|
||||||
internal Dictionary(DictionarySafeHandle handle)
|
|
||||||
{
|
|
||||||
objectDict = new Dictionary(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
|
/// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
|
||||||
|
@ -432,12 +403,7 @@ namespace Godot.Collections
|
||||||
/// <param name="from">The typed dictionary to convert.</param>
|
/// <param name="from">The typed dictionary to convert.</param>
|
||||||
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
|
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
|
||||||
{
|
{
|
||||||
return from.objectDict;
|
return from._underlyingDict;
|
||||||
}
|
|
||||||
|
|
||||||
internal IntPtr GetPtr()
|
|
||||||
{
|
|
||||||
return objectDict.GetPtr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -447,7 +413,7 @@ namespace Godot.Collections
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
/// <returns>A new Godot Dictionary.</returns>
|
||||||
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
|
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
|
||||||
{
|
{
|
||||||
return new Dictionary<TKey, TValue>(objectDict.Duplicate(deep));
|
return new Dictionary<TKey, TValue>(_underlyingDict.Duplicate(deep));
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDictionary<TKey, TValue>
|
// IDictionary<TKey, TValue>
|
||||||
|
@ -458,8 +424,24 @@ namespace Godot.Collections
|
||||||
/// <value>The value at the given <paramref name="key"/>.</value>
|
/// <value>The value at the given <paramref name="key"/>.</value>
|
||||||
public TValue this[TKey key]
|
public TValue this[TKey key]
|
||||||
{
|
{
|
||||||
get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
|
get
|
||||||
set { objectDict[key] = value; }
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||||
|
&variantKey, out godot_variant value).ToBool())
|
||||||
|
{
|
||||||
|
using (value)
|
||||||
|
return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set => _underlyingDict[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -469,8 +451,9 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(objectDict.GetPtr());
|
godot_array keyArray;
|
||||||
return new Array<TKey>(new ArraySafeHandle(handle));
|
NativeFuncs.godotsharp_dictionary_keys(ref _underlyingDict.NativeValue, out keyArray);
|
||||||
|
return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,15 +464,23 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Values(objectDict.GetPtr());
|
godot_array valuesArray;
|
||||||
return new Array<TValue>(new ArraySafeHandle(handle));
|
NativeFuncs.godotsharp_dictionary_values(ref _underlyingDict.NativeValue, out valuesArray);
|
||||||
|
return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
||||||
{
|
{
|
||||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value);
|
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _underlyingDict.NativeValue, index,
|
||||||
return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
|
out godot_variant key,
|
||||||
|
out godot_variant value);
|
||||||
|
using (key)
|
||||||
|
using (value)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<TKey, TValue>((TKey)Marshaling.variant_to_mono_object(&key),
|
||||||
|
(TValue)Marshaling.variant_to_mono_object(&value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -500,7 +491,7 @@ namespace Godot.Collections
|
||||||
/// <param name="value">The object to add.</param>
|
/// <param name="value">The object to add.</param>
|
||||||
public void Add(TKey key, TValue value)
|
public void Add(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
objectDict.Add(key, value);
|
_underlyingDict.Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -510,16 +501,17 @@ namespace Godot.Collections
|
||||||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
||||||
public bool ContainsKey(TKey key)
|
public bool ContainsKey(TKey key)
|
||||||
{
|
{
|
||||||
return objectDict.Contains(key);
|
return _underlyingDict.Contains(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
|
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key of the element to remove.</param>
|
/// <param name="key">The key of the element to remove.</param>
|
||||||
public bool Remove(TKey key)
|
public unsafe bool Remove(TKey key)
|
||||||
{
|
{
|
||||||
return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
|
return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -528,10 +520,19 @@ namespace Godot.Collections
|
||||||
/// <param name="key">The key of the element to get.</param>
|
/// <param name="key">The key of the element to get.</param>
|
||||||
/// <param name="value">The value at the given <paramref name="key"/>.</param>
|
/// <param name="value">The value at the given <paramref name="key"/>.</param>
|
||||||
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
|
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
|
||||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||||
{
|
{
|
||||||
bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out object retValue, valTypeEncoding, valTypeClass);
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||||
value = found ? (TValue)retValue : default;
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||||
|
&variantKey, out godot_variant retValue).ToBool();
|
||||||
|
|
||||||
|
using (retValue)
|
||||||
|
{
|
||||||
|
value = found ?
|
||||||
|
(TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) :
|
||||||
|
default;
|
||||||
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,16 +543,13 @@ namespace Godot.Collections
|
||||||
/// This is also known as the size or length of the dictionary.
|
/// This is also known as the size or length of the dictionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The number of elements.</returns>
|
/// <returns>The number of elements.</returns>
|
||||||
public int Count
|
public int Count => _underlyingDict.Count;
|
||||||
{
|
|
||||||
get { return objectDict.Count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
||||||
|
|
||||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
objectDict.Add(item.Key, item.Value);
|
_underlyingDict.Add(item.Key, item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -559,12 +557,22 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
objectDict.Clear();
|
_underlyingDict.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
|
||||||
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||||
|
&variantKey, out godot_variant retValue).ToBool();
|
||||||
|
|
||||||
|
using (retValue)
|
||||||
|
{
|
||||||
|
if (!found)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue).ToBool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -579,12 +587,14 @@ namespace Godot.Collections
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
|
||||||
if (arrayIndex < 0)
|
if (arrayIndex < 0)
|
||||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
|
throw new ArgumentOutOfRangeException(nameof(arrayIndex),
|
||||||
|
"Number was less than the array's lower bound in the first dimension.");
|
||||||
|
|
||||||
int count = Count;
|
int count = Count;
|
||||||
|
|
||||||
if (array.Length < (arrayIndex + count))
|
if (array.Length < (arrayIndex + count))
|
||||||
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
throw new ArgumentException(
|
||||||
|
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -593,10 +603,25 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||||
{
|
{
|
||||||
return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
|
using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
|
||||||
;
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||||
|
&variantKey, out godot_variant retValue).ToBool();
|
||||||
|
|
||||||
|
using (retValue)
|
||||||
|
{
|
||||||
|
if (!found)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue).ToBool())
|
||||||
|
{
|
||||||
|
return NativeFuncs.godotsharp_dictionary_remove_key(
|
||||||
|
ref _underlyingDict.NativeValue, &variantKey).ToBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IEnumerable<KeyValuePair<TKey, TValue>>
|
// IEnumerable<KeyValuePair<TKey, TValue>>
|
||||||
|
@ -613,15 +638,12 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
|
/// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string representation of this dictionary.</returns>
|
/// <returns>A string representation of this dictionary.</returns>
|
||||||
public override string ToString() => objectDict.ToString();
|
public override string ToString() => _underlyingDict.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public static class Dispatcher
|
public static class Dispatcher
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
internal static GodotTaskScheduler DefaultGodotTaskScheduler;
|
||||||
private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler();
|
|
||||||
|
|
||||||
public static GodotSynchronizationContext SynchronizationContext =>
|
[UnmanagedCallersOnly]
|
||||||
godot_icall_DefaultGodotTaskScheduler().Context;
|
internal static void InitializeDefaultGodotTaskScheduler()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DefaultGodotTaskScheduler = new GodotTaskScheduler();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.DebugUnhandledException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,212 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Dynamic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Godot
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an <see cref="Godot.Object"/> whose members can be dynamically accessed at runtime through the Variant API.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// The <see cref="Godot.DynamicGodotObject"/> class enables access to the Variant
|
|
||||||
/// members of a <see cref="Godot.Object"/> instance at runtime.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// This allows accessing the class members using their original names in the engine as well as the members from the
|
|
||||||
/// script attached to the <see cref="Godot.Object"/>, regardless of the scripting language it was written in.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
/// <example>
|
|
||||||
/// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>.
|
|
||||||
/// <code>
|
|
||||||
/// dynamic sprite = GetNode("Sprite2D").DynamicGodotObject;
|
|
||||||
/// sprite.add_child(this);
|
|
||||||
///
|
|
||||||
/// if ((sprite.hframes * sprite.vframes) > 0)
|
|
||||||
/// sprite.frame = 0;
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
/// <example>
|
|
||||||
/// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Godot.Object"/>.
|
|
||||||
/// <code>
|
|
||||||
/// dynamic childNode = GetNode("ChildNode").DynamicGodotObject;
|
|
||||||
///
|
|
||||||
/// if (childNode.print_allowed)
|
|
||||||
/// {
|
|
||||||
/// childNode.message = "Hello from C#";
|
|
||||||
/// childNode.print_message(3);
|
|
||||||
/// }
|
|
||||||
/// </code>
|
|
||||||
/// The <c>ChildNode</c> node has the following GDScript script attached:
|
|
||||||
/// <code>
|
|
||||||
/// // # ChildNode.gd
|
|
||||||
/// // var print_allowed = true
|
|
||||||
/// // var message = ""
|
|
||||||
/// //
|
|
||||||
/// // func print_message(times):
|
|
||||||
/// // for i in times:
|
|
||||||
/// // print(message)
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
public class DynamicGodotObject : DynamicObject
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the <see cref="Godot.Object"/> associated with this <see cref="Godot.DynamicGodotObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
public Object Value { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="Godot.DynamicGodotObject"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="godotObject">
|
|
||||||
/// The <see cref="Godot.Object"/> that will be associated with this <see cref="Godot.DynamicGodotObject"/>.
|
|
||||||
/// </param>
|
|
||||||
/// <exception cref="System.ArgumentNullException">
|
|
||||||
/// Thrown when the <paramref name="godotObject"/> parameter is null.
|
|
||||||
/// </exception>
|
|
||||||
public DynamicGodotObject(Object godotObject)
|
|
||||||
{
|
|
||||||
if (godotObject == null)
|
|
||||||
throw new ArgumentNullException(nameof(godotObject));
|
|
||||||
|
|
||||||
this.Value = godotObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<string> GetDynamicMemberNames()
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_SetMemberList(Object.GetPtr(Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
|
|
||||||
{
|
|
||||||
switch (binder.Operation)
|
|
||||||
{
|
|
||||||
case ExpressionType.Equal:
|
|
||||||
case ExpressionType.NotEqual:
|
|
||||||
if (binder.ReturnType == typeof(bool) || binder.ReturnType.IsAssignableFrom(typeof(bool)))
|
|
||||||
{
|
|
||||||
if (arg == null)
|
|
||||||
{
|
|
||||||
bool boolResult = Object.IsInstanceValid(Value);
|
|
||||||
|
|
||||||
if (binder.Operation == ExpressionType.Equal)
|
|
||||||
boolResult = !boolResult;
|
|
||||||
|
|
||||||
result = boolResult;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg is Object other)
|
|
||||||
{
|
|
||||||
bool boolResult = (Value == other);
|
|
||||||
|
|
||||||
if (binder.Operation == ExpressionType.NotEqual)
|
|
||||||
boolResult = !boolResult;
|
|
||||||
|
|
||||||
result = boolResult;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// We're not implementing operators <, <=, >, and >= (LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual).
|
|
||||||
// These are used on the actual pointers in variant_op.cpp. It's better to let the user do that explicitly.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.TryBinaryOperation(binder, arg, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryConvert(ConvertBinder binder, out object result)
|
|
||||||
{
|
|
||||||
if (binder.Type == typeof(Object))
|
|
||||||
{
|
|
||||||
result = Value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(Object).IsAssignableFrom(binder.Type))
|
|
||||||
{
|
|
||||||
// Throws InvalidCastException when the cast fails
|
|
||||||
result = Convert.ChangeType(Value, binder.Type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.TryConvert(binder, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
|
|
||||||
{
|
|
||||||
if (indexes.Length == 1)
|
|
||||||
{
|
|
||||||
if (indexes[0] is string name)
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), name, out result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.TryGetIndex(binder, indexes, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), binder.Name, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_InvokeMember(Object.GetPtr(Value), binder.Name, args, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
|
|
||||||
{
|
|
||||||
if (indexes.Length == 1)
|
|
||||||
{
|
|
||||||
if (indexes[0] is string name)
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.TrySetIndex(binder, indexes, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
|
||||||
{
|
|
||||||
return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), binder.Name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
|
|
||||||
|
|
||||||
#region We don't override these methods
|
|
||||||
|
|
||||||
// Looks like this is not usable from C#
|
|
||||||
//public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
|
|
||||||
|
|
||||||
// Object members cannot be deleted
|
|
||||||
//public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
|
|
||||||
//public override bool TryDeleteMember(DeleteMemberBinder binder);
|
|
||||||
|
|
||||||
// Invocation on the object itself, e.g.: obj(param)
|
|
||||||
//public override bool TryInvoke(InvokeBinder binder, object[] args, out object result);
|
|
||||||
|
|
||||||
// No unnary operations to handle
|
|
||||||
//public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
|
@ -12,10 +12,20 @@ namespace Godot
|
||||||
|
|
||||||
public static WeakRef WeakRef(Object obj)
|
public static WeakRef WeakRef(Object obj)
|
||||||
{
|
{
|
||||||
return godot_icall_Object_weakref(Object.GetPtr(obj));
|
if (!IsInstanceValid(obj))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
using godot_ref weakRef = default;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
NativeFuncs.godotsharp_weakref(GetPtr(obj), &weakRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
if (weakRef.IsNull)
|
||||||
internal extern static WeakRef godot_icall_Object_weakref(IntPtr obj);
|
return null;
|
||||||
|
|
||||||
|
return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef._reference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,64 @@
|
||||||
using System;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public partial class SceneTree
|
public partial class SceneTree
|
||||||
{
|
{
|
||||||
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
|
public unsafe Array<T> GetNodesInGroup<T>(StringName group) where T : class
|
||||||
{
|
{
|
||||||
return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(Object.GetPtr(this), StringName.GetPtr(group), typeof(T)));
|
var array = GetNodesInGroup(group);
|
||||||
|
|
||||||
|
if (array.Count == 0)
|
||||||
|
return new Array<T>(array);
|
||||||
|
|
||||||
|
var typeOfT = typeof(T);
|
||||||
|
bool nativeBase = InternalIsClassNativeBase(typeOfT);
|
||||||
|
|
||||||
|
if (nativeBase)
|
||||||
|
{
|
||||||
|
// Native type
|
||||||
|
var field = typeOfT.GetField("NativeName",
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||||
|
BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
var nativeName = (StringName)field!.GetValue(null);
|
||||||
|
godot_string_name nativeNameAux = nativeName.NativeValue;
|
||||||
|
godot_array inputAux = array.NativeValue;
|
||||||
|
godot_array filteredArray;
|
||||||
|
NativeFuncs.godotsharp_array_filter_godot_objects_by_native(
|
||||||
|
&nativeNameAux, &inputAux, &filteredArray);
|
||||||
|
return Array<T>.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Custom derived type
|
||||||
|
godot_array inputAux = array.NativeValue;
|
||||||
|
godot_array filteredArray;
|
||||||
|
NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(&inputAux, &filteredArray);
|
||||||
|
|
||||||
|
var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
||||||
|
|
||||||
|
// Re-use first array as its size is the same or greater than the filtered one
|
||||||
|
var resWrapped = new Array<T>(array);
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < filteredArrayWrapped.Count; i++)
|
||||||
|
{
|
||||||
|
if (filteredArrayWrapped[i] is T t)
|
||||||
|
{
|
||||||
|
resWrapped[j] = t;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
// Remove trailing elements, since this was re-used
|
||||||
internal extern static IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
|
resWrapped.Resize(j);
|
||||||
|
|
||||||
|
return resWrapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using real_t = System.Single;
|
||||||
#endif
|
#endif
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
// TODO: Add comments describing what this class does. It is not obvious.
|
// TODO: Add comments describing what this class does. It is not obvious.
|
||||||
|
|
||||||
|
@ -13,14 +13,20 @@ namespace Godot
|
||||||
{
|
{
|
||||||
public static partial class GD
|
public static partial class GD
|
||||||
{
|
{
|
||||||
public static object Bytes2Var(byte[] bytes, bool allowObjects = false)
|
public static unsafe object Bytes2Var(byte[] bytes, bool allowObjects = false)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_bytes2var(bytes, allowObjects);
|
using var varBytes = Marshaling.mono_array_to_PackedByteArray(bytes);
|
||||||
|
using godot_variant ret = default;
|
||||||
|
NativeFuncs.godotsharp_bytes2var(&varBytes, allowObjects.ToGodotBool(), &ret);
|
||||||
|
return Marshaling.variant_to_mono_object(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object Convert(object what, Variant.Type type)
|
public static unsafe object Convert(object what, Variant.Type type)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_convert(what, type);
|
using var whatVariant = Marshaling.mono_object_to_variant(what);
|
||||||
|
using godot_variant ret = default;
|
||||||
|
NativeFuncs.godotsharp_convert(&whatVariant, type, &ret);
|
||||||
|
return Marshaling.variant_to_mono_object(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static real_t Db2Linear(real_t db)
|
public static real_t Db2Linear(real_t db)
|
||||||
|
@ -28,7 +34,7 @@ namespace Godot
|
||||||
return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
|
return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object[] GetPrintParams(object[] parameters)
|
private static string[] GetPrintParams(object[] parameters)
|
||||||
{
|
{
|
||||||
if (parameters == null)
|
if (parameters == null)
|
||||||
{
|
{
|
||||||
|
@ -38,14 +44,15 @@ namespace Godot
|
||||||
return Array.ConvertAll(parameters, x => x?.ToString() ?? "null");
|
return Array.ConvertAll(parameters, x => x?.ToString() ?? "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Hash(object var)
|
public static unsafe int Hash(object var)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_hash(var);
|
using var variant = Marshaling.mono_object_to_variant(var);
|
||||||
|
return NativeFuncs.godotsharp_hash(&variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object InstanceFromId(ulong instanceId)
|
public static Object InstanceFromId(ulong instanceId)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_instance_from_id(instanceId);
|
return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static real_t Linear2Db(real_t linear)
|
public static real_t Linear2Db(real_t linear)
|
||||||
|
@ -63,19 +70,23 @@ namespace Godot
|
||||||
return ResourceLoader.Load<T>(path);
|
return ResourceLoader.Load<T>(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PushError(string message)
|
public static unsafe void PushError(string message)
|
||||||
{
|
{
|
||||||
godot_icall_GD_pusherror(message);
|
using var godotStr = Marshaling.mono_string_to_godot(message);
|
||||||
|
NativeFuncs.godotsharp_pusherror(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PushWarning(string message)
|
public static unsafe void PushWarning(string message)
|
||||||
{
|
{
|
||||||
godot_icall_GD_pushwarning(message);
|
using var godotStr = Marshaling.mono_string_to_godot(message);
|
||||||
|
NativeFuncs.godotsharp_pushwarning(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Print(params object[] what)
|
public static unsafe void Print(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_print(GetPrintParams(what));
|
string str = string.Concat(GetPrintParams(what));
|
||||||
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
NativeFuncs.godotsharp_print(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintStack()
|
public static void PrintStack()
|
||||||
|
@ -83,54 +94,62 @@ namespace Godot
|
||||||
Print(System.Environment.StackTrace);
|
Print(System.Environment.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintErr(params object[] what)
|
public static unsafe void PrintErr(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_printerr(GetPrintParams(what));
|
string str = string.Concat(GetPrintParams(what));
|
||||||
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
NativeFuncs.godotsharp_printerr(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintRaw(params object[] what)
|
public static unsafe void PrintRaw(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_printraw(GetPrintParams(what));
|
string str = string.Concat(GetPrintParams(what));
|
||||||
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
NativeFuncs.godotsharp_printraw(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintS(params object[] what)
|
public static unsafe void PrintS(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_prints(GetPrintParams(what));
|
string str = string.Join(' ', GetPrintParams(what));
|
||||||
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
NativeFuncs.godotsharp_prints(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintT(params object[] what)
|
public static unsafe void PrintT(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_printt(GetPrintParams(what));
|
string str = string.Join('\t', GetPrintParams(what));
|
||||||
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
NativeFuncs.godotsharp_printt(&godotStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Randf()
|
public static float Randf()
|
||||||
{
|
{
|
||||||
return godot_icall_GD_randf();
|
return NativeFuncs.godotsharp_randf();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint Randi()
|
public static uint Randi()
|
||||||
{
|
{
|
||||||
return godot_icall_GD_randi();
|
return NativeFuncs.godotsharp_randi();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Randomize()
|
public static void Randomize()
|
||||||
{
|
{
|
||||||
godot_icall_GD_randomize();
|
NativeFuncs.godotsharp_randomize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double RandRange(double from, double to)
|
public static double RandRange(double from, double to)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_randf_range(from, to);
|
return NativeFuncs.godotsharp_randf_range(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int RandRange(int from, int to)
|
public static int RandRange(int from, int to)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_randi_range(from, to);
|
return NativeFuncs.godotsharp_randi_range(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint RandFromSeed(ref ulong seed)
|
public static uint RandFromSeed(ref ulong seed)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_rand_seed(seed, out seed);
|
return NativeFuncs.godotsharp_rand_from_seed(seed, out seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<int> Range(int end)
|
public static IEnumerable<int> Range(int end)
|
||||||
|
@ -165,109 +184,45 @@ namespace Godot
|
||||||
|
|
||||||
public static void Seed(ulong seed)
|
public static void Seed(ulong seed)
|
||||||
{
|
{
|
||||||
godot_icall_GD_seed(seed);
|
NativeFuncs.godotsharp_seed(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Str(params object[] what)
|
public static unsafe string Str(params object[] what)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_str(what);
|
using var whatGodotArray = Marshaling.mono_array_to_Array(what);
|
||||||
|
using godot_string ret = default;
|
||||||
|
NativeFuncs.godotsharp_str(&whatGodotArray, &ret);
|
||||||
|
return Marshaling.mono_string_from_godot(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object Str2Var(string str)
|
public static unsafe object Str2Var(string str)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_str2var(str);
|
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||||
|
using godot_variant ret = default;
|
||||||
|
NativeFuncs.godotsharp_str2var(&godotStr, &ret);
|
||||||
|
return Marshaling.variant_to_mono_object(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TypeExists(StringName type)
|
public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_type_exists(StringName.GetPtr(type));
|
using var variant = Marshaling.mono_object_to_variant(var);
|
||||||
|
using godot_packed_byte_array varBytes = default;
|
||||||
|
NativeFuncs.godotsharp_var2bytes(&variant, fullObjects.ToGodotBool(), &varBytes);
|
||||||
|
using (varBytes)
|
||||||
|
return Marshaling.PackedByteArray_to_mono_array(&varBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] Var2Bytes(object var, bool fullObjects = false)
|
public static unsafe string Var2Str(object var)
|
||||||
{
|
{
|
||||||
return godot_icall_GD_var2bytes(var, fullObjects);
|
using var variant = Marshaling.mono_object_to_variant(var);
|
||||||
}
|
using godot_string ret = default;
|
||||||
|
NativeFuncs.godotsharp_var2str(&variant, &ret);
|
||||||
public static string Var2Str(object var)
|
return Marshaling.mono_string_from_godot(ret);
|
||||||
{
|
|
||||||
return godot_icall_GD_var2str(var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Variant.Type TypeToVariantType(Type type)
|
public static Variant.Type TypeToVariantType(Type type)
|
||||||
{
|
{
|
||||||
return godot_icall_TypeToVariantType(type);
|
return Marshaling.managed_to_variant_type(type, out bool _);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_GD_hash(object var);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static Object godot_icall_GD_instance_from_id(ulong instanceId);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_print(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_printerr(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_printraw(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_prints(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_printt(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static float godot_icall_GD_randf();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static uint godot_icall_GD_randi();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_randomize();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static double godot_icall_GD_randf_range(double from, double to);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_GD_randi_range(int from, int to);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_seed(ulong seed);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_GD_str(object[] what);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static object godot_icall_GD_str2var(string str);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static bool godot_icall_GD_type_exists(IntPtr type);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_GD_var2str(object var);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_pusherror(string type);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_GD_pushwarning(string type);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern Variant.Type godot_icall_TypeToVariantType(Type type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,7 @@ namespace Godot
|
||||||
public override void Fail(string message, string detailMessage)
|
public override void Fail(string message, string detailMessage)
|
||||||
{
|
{
|
||||||
GD.PrintErr("Assertion failed: ", message);
|
GD.PrintErr("Assertion failed: ", message);
|
||||||
if (detailMessage != null)
|
|
||||||
{
|
|
||||||
GD.PrintErr(" Details: ", detailMessage);
|
GD.PrintErr(" Details: ", detailMessage);
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Godot
|
|
||||||
{
|
|
||||||
static class MarshalUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
|
|
||||||
/// is <see cref="Godot.Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <exception cref="System.InvalidOperationException">
|
|
||||||
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
|
|
||||||
/// </exception>
|
|
||||||
static bool TypeIsGenericArray(Type type) =>
|
|
||||||
type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
|
|
||||||
/// is <see cref="Godot.Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <exception cref="System.InvalidOperationException">
|
|
||||||
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
|
|
||||||
/// </exception>
|
|
||||||
static bool TypeIsGenericDictionary(Type type) =>
|
|
||||||
type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
|
|
||||||
|
|
||||||
static bool TypeIsSystemGenericList(Type type) =>
|
|
||||||
type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>);
|
|
||||||
|
|
||||||
static bool TypeIsSystemGenericDictionary(Type type) =>
|
|
||||||
type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>);
|
|
||||||
|
|
||||||
static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
|
|
||||||
|
|
||||||
static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
|
|
||||||
|
|
||||||
static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
|
|
||||||
|
|
||||||
static void ArrayGetElementType(Type arrayType, out Type elementType)
|
|
||||||
{
|
|
||||||
elementType = arrayType.GetGenericArguments()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
|
|
||||||
{
|
|
||||||
var genericArgs = dictionaryType.GetGenericArguments();
|
|
||||||
keyType = genericArgs[0];
|
|
||||||
valueType = genericArgs[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type MakeGenericArrayType(Type elemType)
|
|
||||||
{
|
|
||||||
return typeof(Godot.Collections.Array<>).MakeGenericType(elemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type MakeGenericDictionaryType(Type keyType, Type valueType)
|
|
||||||
{
|
|
||||||
return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
internal static class ExceptionUtils
|
||||||
|
{
|
||||||
|
public static void PushError(string message)
|
||||||
|
{
|
||||||
|
GD.PushError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnExceptionLoggerException(Exception loggerException, Exception exceptionToLog)
|
||||||
|
{
|
||||||
|
// This better not throw
|
||||||
|
PushError("Exception thrown when trying to log another exception...");
|
||||||
|
PushError("Exception:");
|
||||||
|
PushError(exceptionToLog.ToString());
|
||||||
|
PushError("Logger exception:");
|
||||||
|
PushError(loggerException.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DebugPrintUnhandledException(Exception e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO Not implemented (debug_print_unhandled_exception)
|
||||||
|
GD.PushError(e.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception unexpected)
|
||||||
|
{
|
||||||
|
OnExceptionLoggerException(unexpected, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DebugSendUnhandledExceptionError(Exception e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO Not implemented (debug_send_unhandled_exception_error)
|
||||||
|
GD.PushError(e.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception unexpected)
|
||||||
|
{
|
||||||
|
OnExceptionLoggerException(unexpected, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DebugUnhandledException(Exception e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO Not implemented (debug_unhandled_exception)
|
||||||
|
GD.PushError(e.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception unexpected)
|
||||||
|
{
|
||||||
|
OnExceptionLoggerException(unexpected, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintUnhandledException(Exception e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO Not implemented (print_unhandled_exception)
|
||||||
|
GD.PushError(e.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception unexpected)
|
||||||
|
{
|
||||||
|
OnExceptionLoggerException(unexpected, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,481 @@
|
||||||
|
#if REAL_T_IS_DOUBLE
|
||||||
|
using real_t = System.Double;
|
||||||
|
#else
|
||||||
|
using real_t = System.Single;
|
||||||
|
#endif
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
internal static class GodotBoolExtensions
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_bool ToGodotBool(this bool @bool)
|
||||||
|
{
|
||||||
|
return *(godot_bool*)&@bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe bool ToBool(this godot_bool godotBool)
|
||||||
|
{
|
||||||
|
return *(bool*)&godotBool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apparently a struct with a byte is not blittable? It crashes when calling a UnmanagedCallersOnly function ptr.
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public enum godot_bool : byte
|
||||||
|
{
|
||||||
|
True = 1,
|
||||||
|
False = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_ref : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _reference;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_reference == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_ref_destroy(ref this);
|
||||||
|
_reference = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsNull => _reference == IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||||
|
public enum godot_variant_call_error_error
|
||||||
|
{
|
||||||
|
GODOT_CALL_ERROR_CALL_OK = 0,
|
||||||
|
GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD,
|
||||||
|
GODOT_CALL_ERROR_CALL_ERROR_INVALID_ARGUMENT,
|
||||||
|
GODOT_CALL_ERROR_CALL_ERROR_TOO_MANY_ARGUMENTS,
|
||||||
|
GODOT_CALL_ERROR_CALL_ERROR_TOO_FEW_ARGUMENTS,
|
||||||
|
GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_variant_call_error
|
||||||
|
{
|
||||||
|
public godot_variant_call_error_error error;
|
||||||
|
public int argument;
|
||||||
|
public Godot.Variant.Type expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_variant : IDisposable
|
||||||
|
{
|
||||||
|
[FieldOffset(0)] public Godot.Variant.Type _type;
|
||||||
|
|
||||||
|
// There's padding here
|
||||||
|
|
||||||
|
[FieldOffset(8)] internal godot_variant_data _data;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
internal unsafe struct godot_variant_data
|
||||||
|
{
|
||||||
|
[FieldOffset(0)] public godot_bool _bool;
|
||||||
|
[FieldOffset(0)] public long _int;
|
||||||
|
[FieldOffset(0)] public double _float;
|
||||||
|
[FieldOffset(0)] public Transform2D* _transform2d;
|
||||||
|
[FieldOffset(0)] public AABB* _aabb;
|
||||||
|
[FieldOffset(0)] public Basis* _basis;
|
||||||
|
[FieldOffset(0)] public Transform3D* _transform3d;
|
||||||
|
[FieldOffset(0)] private godot_variant_data_mem _mem;
|
||||||
|
|
||||||
|
// The following fields are not in the C++ union, but this is how they're stored in _mem.
|
||||||
|
[FieldOffset(0)] public godot_string_name _m_string_name;
|
||||||
|
[FieldOffset(0)] public godot_string _m_string;
|
||||||
|
[FieldOffset(0)] public Vector3 _m_vector3;
|
||||||
|
[FieldOffset(0)] public Vector3i _m_vector3i;
|
||||||
|
[FieldOffset(0)] public Vector2 _m_vector2;
|
||||||
|
[FieldOffset(0)] public Vector2i _m_vector2i;
|
||||||
|
[FieldOffset(0)] public Rect2 _m_rect2;
|
||||||
|
[FieldOffset(0)] public Rect2i _m_rect2i;
|
||||||
|
[FieldOffset(0)] public Plane _m_plane;
|
||||||
|
[FieldOffset(0)] public Quaternion _m_quaternion;
|
||||||
|
[FieldOffset(0)] public Color _m_color;
|
||||||
|
[FieldOffset(0)] public godot_node_path _m_node_path;
|
||||||
|
[FieldOffset(0)] public RID _m_rid;
|
||||||
|
[FieldOffset(0)] public godot_variant_obj_data _m_obj_data;
|
||||||
|
[FieldOffset(0)] public godot_callable _m_callable;
|
||||||
|
[FieldOffset(0)] public godot_signal _m_signal;
|
||||||
|
[FieldOffset(0)] public godot_dictionary _m_dictionary;
|
||||||
|
[FieldOffset(0)] public godot_array _m_array;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
internal struct godot_variant_obj_data
|
||||||
|
{
|
||||||
|
public UInt64 id;
|
||||||
|
public IntPtr obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
private struct godot_variant_data_mem
|
||||||
|
{
|
||||||
|
#pragma warning disable 169
|
||||||
|
private real_t _mem0;
|
||||||
|
private real_t _mem1;
|
||||||
|
private real_t _mem2;
|
||||||
|
private real_t _mem3;
|
||||||
|
#pragma warning restore 169
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
switch (_type)
|
||||||
|
{
|
||||||
|
case Variant.Type.Nil:
|
||||||
|
case Variant.Type.Bool:
|
||||||
|
case Variant.Type.Int:
|
||||||
|
case Variant.Type.Float:
|
||||||
|
case Variant.Type.Vector2:
|
||||||
|
case Variant.Type.Vector2i:
|
||||||
|
case Variant.Type.Rect2:
|
||||||
|
case Variant.Type.Rect2i:
|
||||||
|
case Variant.Type.Vector3:
|
||||||
|
case Variant.Type.Vector3i:
|
||||||
|
case Variant.Type.Plane:
|
||||||
|
case Variant.Type.Quaternion:
|
||||||
|
case Variant.Type.Color:
|
||||||
|
case Variant.Type.Rid:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeFuncs.godotsharp_variant_destroy(ref this);
|
||||||
|
_type = Variant.Type.Nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_string : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _ptr;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_string_destroy(ref this);
|
||||||
|
_ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size including the null termination character
|
||||||
|
public unsafe int Size => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_string_name : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _data;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_data == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_string_name_destroy(ref this);
|
||||||
|
_data = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An static method because an instance method could result in a hidden copy if called on an `in` parameter.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool IsEmpty(in godot_string_name name) =>
|
||||||
|
// This is all that's needed to check if it's empty. Equivalent to `== StringName()` in C++.
|
||||||
|
name._data == IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_node_path : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _data;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_data == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_node_path_destroy(ref this);
|
||||||
|
_data = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An static method because an instance method could result in a hidden copy if called on an `in` parameter.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool IsEmpty(in godot_node_path nodePath) =>
|
||||||
|
// This is all that's needed to check if it's empty. It's what the `is_empty()` C++ method does.
|
||||||
|
nodePath._data == IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_signal : IDisposable
|
||||||
|
{
|
||||||
|
[FieldOffset(0)] public godot_string_name _name;
|
||||||
|
|
||||||
|
// There's padding here on 32-bit
|
||||||
|
|
||||||
|
[FieldOffset(8)] public UInt64 _objectId;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_name._data == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_signal_destroy(ref this);
|
||||||
|
_name._data = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_callable : IDisposable
|
||||||
|
{
|
||||||
|
[FieldOffset(0)] public godot_string_name _method;
|
||||||
|
|
||||||
|
// There's padding here on 32-bit
|
||||||
|
|
||||||
|
[FieldOffset(8)] public UInt64 _objectId;
|
||||||
|
[FieldOffset(8)] public IntPtr _custom;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_method._data == IntPtr.Zero && _custom == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_callable_destroy(ref this);
|
||||||
|
_method._data = IntPtr.Zero;
|
||||||
|
_custom = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
||||||
|
// Don't pass a C# default constructed `godot_array` to native code, unless it's going to
|
||||||
|
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_array : IDisposable
|
||||||
|
{
|
||||||
|
internal unsafe ArrayPrivate* _p;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct ArrayPrivate
|
||||||
|
{
|
||||||
|
private uint _safeRefCount;
|
||||||
|
|
||||||
|
internal VariantVector _arrayVector;
|
||||||
|
// There's more here, but we don't care as we never store this in C#
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct VariantVector
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe godot_variant* _ptr;
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _p != null ? _p->_arrayVector.Size : 0;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_p == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_array_destroy(ref this);
|
||||||
|
_p = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPORTANT:
|
||||||
|
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
||||||
|
// Don't pass a C# default constructed `godot_dictionary` to native code, unless it's going to
|
||||||
|
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_dictionary : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _p;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_p == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_dictionary_destroy(ref this);
|
||||||
|
_p = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_byte_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe byte* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_byte_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_int32_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe int* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_int32_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *(_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_int64_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe long* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_int64_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_float32_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe float* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_float32_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_float64_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe double* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_float64_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_string_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe godot_string* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_string_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_vector2_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe Vector2* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_vector2_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_vector3_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe Vector3* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_vector3_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct godot_packed_color_array : IDisposable
|
||||||
|
{
|
||||||
|
internal IntPtr _writeProxy;
|
||||||
|
internal unsafe Color* _ptr;
|
||||||
|
|
||||||
|
public unsafe void Dispose()
|
||||||
|
{
|
||||||
|
if (_ptr == null)
|
||||||
|
return;
|
||||||
|
NativeFuncs.godotsharp_packed_color_array_destroy(ref this);
|
||||||
|
_ptr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.Bridge;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
internal static class InteropUtils
|
||||||
|
{
|
||||||
|
public static Object UnmanagedGetManaged(IntPtr unmanaged)
|
||||||
|
{
|
||||||
|
// The native pointer may be null
|
||||||
|
if (unmanaged == IntPtr.Zero)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
IntPtr gcHandlePtr;
|
||||||
|
godot_bool has_cs_script_instance = false.ToGodotBool();
|
||||||
|
|
||||||
|
// First try to get the tied managed instance from a CSharpInstance script instance
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_script_instance_managed(
|
||||||
|
unmanaged, &has_cs_script_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gcHandlePtr != IntPtr.Zero)
|
||||||
|
return (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
|
||||||
|
|
||||||
|
// Otherwise, if the object has a CSharpInstance script instance, return null
|
||||||
|
|
||||||
|
if (has_cs_script_instance.ToBool())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// If it doesn't have a CSharpInstance script instance, try with native instance bindings
|
||||||
|
|
||||||
|
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_instance_binding_managed(unmanaged);
|
||||||
|
|
||||||
|
object target = gcHandlePtr != IntPtr.Zero ? GCHandle.FromIntPtr(gcHandlePtr).Target : null;
|
||||||
|
|
||||||
|
if (target != null)
|
||||||
|
return (Object)target;
|
||||||
|
|
||||||
|
// If the native instance binding GC handle target was collected, create a new one
|
||||||
|
|
||||||
|
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_instance_binding_create_managed(
|
||||||
|
unmanaged, gcHandlePtr);
|
||||||
|
|
||||||
|
return gcHandlePtr != IntPtr.Zero ? (Object)GCHandle.FromIntPtr(gcHandlePtr).Target : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TieManagedToUnmanaged(Object managed, IntPtr unmanaged,
|
||||||
|
StringName nativeName, bool refCounted, Type type, Type nativeType)
|
||||||
|
{
|
||||||
|
var gcHandle = GCHandle.Alloc(managed, refCounted ? GCHandleType.Weak : GCHandleType.Normal);
|
||||||
|
|
||||||
|
if (type == nativeType)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
godot_string_name nativeNameAux = nativeName.NativeValue;
|
||||||
|
NativeFuncs.godotsharp_internal_tie_native_managed_to_unmanaged(
|
||||||
|
GCHandle.ToIntPtr(gcHandle), unmanaged, &nativeNameAux, refCounted.ToGodotBool());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IntPtr scriptPtr = NativeFuncs.godotsharp_internal_new_csharp_script();
|
||||||
|
|
||||||
|
ScriptManagerBridge.AddScriptBridgeWithType(scriptPtr, type);
|
||||||
|
|
||||||
|
// IMPORTANT: This must be called after AddScriptWithTypeBridge
|
||||||
|
NativeFuncs.godotsharp_internal_tie_user_managed_to_unmanaged(
|
||||||
|
GCHandle.ToIntPtr(gcHandle), unmanaged, scriptPtr, refCounted.ToGodotBool());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TieManagedToUnmanagedWithPreSetup(Object managed, IntPtr unmanaged)
|
||||||
|
{
|
||||||
|
var strongGCHandle = GCHandle.Alloc(managed, GCHandleType.Normal);
|
||||||
|
NativeFuncs.godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
|
||||||
|
GCHandle.ToIntPtr(strongGCHandle), unmanaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe Object EngineGetSingleton(string name)
|
||||||
|
{
|
||||||
|
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||||
|
return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(&src));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,608 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
#if !NET
|
||||||
|
// This improves P/Invoke performance.
|
||||||
|
// The attribute is not available with .NET Core and it's not needed there.
|
||||||
|
[System.Security.SuppressUnmanagedCodeSecurity]
|
||||||
|
#endif
|
||||||
|
public static unsafe partial class NativeFuncs
|
||||||
|
{
|
||||||
|
private const string GodotDllName = "__Internal";
|
||||||
|
|
||||||
|
// Custom functions
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname,
|
||||||
|
char* p_methodname);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
|
||||||
|
ref godot_string_name p_classname);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_engine_get_singleton(godot_string* p_name);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
internal static extern void godotsharp_internal_object_disposed(IntPtr ptr);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
internal static extern void godotsharp_internal_refcounted_disposed(IntPtr ptr, godot_bool isFinalizer);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
internal static extern void godotsharp_internal_object_connect_event_signal(IntPtr obj,
|
||||||
|
godot_string_name* eventSignal);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
internal static extern Error godotsharp_internal_signal_awaiter_connect(IntPtr source,
|
||||||
|
ref godot_string_name signal,
|
||||||
|
IntPtr target, IntPtr awaiterHandlePtr);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_internal_tie_native_managed_to_unmanaged(IntPtr gcHandleIntPtr,
|
||||||
|
IntPtr unmanaged, godot_string_name* nativeName, godot_bool refCounted);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_internal_tie_user_managed_to_unmanaged(IntPtr gcHandleIntPtr,
|
||||||
|
IntPtr unmanaged, IntPtr scriptPtr, godot_bool refCounted);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
|
||||||
|
IntPtr gcHandleIntPtr, IntPtr unmanaged);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_internal_unmanaged_get_script_instance_managed(IntPtr p_unmanaged,
|
||||||
|
godot_bool* r_has_cs_script_instance);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_internal_unmanaged_get_instance_binding_managed(IntPtr p_unmanaged);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_internal_unmanaged_instance_binding_create_managed(IntPtr p_unmanaged,
|
||||||
|
IntPtr oldGCHandlePtr);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_internal_new_csharp_script();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_filter_godot_objects_by_native(godot_string_name* p_native_name,
|
||||||
|
godot_array* p_input, godot_array* r_output);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_filter_godot_objects_by_non_native(godot_array* p_input,
|
||||||
|
godot_array* r_output);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_name_new_from_string(godot_string_name* dest, godot_string* name);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_new_from_string(godot_node_path* dest, godot_string* name);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_name_as_string(godot_string* r_dest, godot_string_name* p_name);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_as_string(godot_string* r_dest, godot_node_path* p_np);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(int* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(long* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(float* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(double* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(Vector2* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src,
|
||||||
|
int p_length);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest,
|
||||||
|
godot_string* p_element);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle,
|
||||||
|
godot_callable* r_callable);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable,
|
||||||
|
IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name);
|
||||||
|
|
||||||
|
// GDNative functions
|
||||||
|
|
||||||
|
// gdnative.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_method_bind_ptrcall(IntPtr p_method_bind, IntPtr p_instance, void** p_args,
|
||||||
|
void* p_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance,
|
||||||
|
godot_variant** p_args, int p_arg_count, godot_variant_call_error* p_call_error);
|
||||||
|
|
||||||
|
// variant.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_string_name(godot_variant* r_dest, godot_string_name* p_s);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_node_path(godot_variant* r_dest, godot_node_path* p_np);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_object(godot_variant* r_dest, IntPtr p_obj);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_transform2d(godot_variant* r_dest, Transform2D* p_t2d);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_basis(godot_variant* r_dest, Basis* p_basis);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_transform3d(godot_variant* r_dest, Transform3D* p_trans);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_aabb(godot_variant* r_dest, AABB* p_aabb);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_dictionary(godot_variant* r_dest, godot_dictionary* p_dict);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_array(godot_variant* r_dest, godot_array* p_arr);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest,
|
||||||
|
godot_packed_byte_array* p_pba);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest,
|
||||||
|
godot_packed_int32_array* p_pia);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest,
|
||||||
|
godot_packed_int64_array* p_pia);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest,
|
||||||
|
godot_packed_float32_array* p_pra);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest,
|
||||||
|
godot_packed_float64_array* p_pra);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest,
|
||||||
|
godot_packed_string_array* p_psa);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest,
|
||||||
|
godot_packed_vector2_array* p_pv2a);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest,
|
||||||
|
godot_packed_vector3_array* p_pv3a);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest,
|
||||||
|
godot_packed_color_array* p_pca);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_variant_as_bool(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Int64 godotsharp_variant_as_int(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern double godotsharp_variant_as_float(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_string godotsharp_variant_as_string(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Vector2 godotsharp_variant_as_vector2(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Vector2i godotsharp_variant_as_vector2i(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Rect2 godotsharp_variant_as_rect2(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Rect2i godotsharp_variant_as_rect2i(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Vector3 godotsharp_variant_as_vector3(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Vector3i godotsharp_variant_as_vector3i(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Transform2D godotsharp_variant_as_transform2d(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Plane godotsharp_variant_as_plane(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Quaternion godotsharp_variant_as_quaternion(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern AABB godotsharp_variant_as_aabb(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Basis godotsharp_variant_as_basis(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Transform3D godotsharp_variant_as_transform3d(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Color godotsharp_variant_as_color(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_string_name godotsharp_variant_as_string_name(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_node_path godotsharp_variant_as_node_path(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern RID godotsharp_variant_as_rid(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_callable godotsharp_variant_as_callable(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_signal godotsharp_variant_as_signal(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_dictionary godotsharp_variant_as_dictionary(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_array godotsharp_variant_as_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_byte_array godotsharp_variant_as_packed_byte_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_int32_array godotsharp_variant_as_packed_int32_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(
|
||||||
|
godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(
|
||||||
|
godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(
|
||||||
|
godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(
|
||||||
|
godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(godot_variant* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_variant_equals(godot_variant* p_a, godot_variant* p_b);
|
||||||
|
|
||||||
|
// string.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_new_with_utf16_chars(godot_string* r_dest, char* p_contents);
|
||||||
|
|
||||||
|
// string_name.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_name_new_copy(godot_string_name* r_dest, godot_string_name* p_src);
|
||||||
|
|
||||||
|
// node_path.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_new_copy(godot_node_path* r_dest, godot_node_path* p_src);
|
||||||
|
|
||||||
|
// array.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_new(godot_array* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
|
||||||
|
|
||||||
|
// dictionary.h
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_new(godot_dictionary* p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_new_copy(godot_dictionary* r_dest, godot_dictionary* p_src);
|
||||||
|
|
||||||
|
// destroy functions
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_byte_array_destroy(ref godot_packed_byte_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_int32_array_destroy(ref godot_packed_int32_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_int64_array_destroy(ref godot_packed_int64_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_float32_array_destroy(ref godot_packed_float32_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_float64_array_destroy(ref godot_packed_float64_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_string_array_destroy(ref godot_packed_string_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_vector2_array_destroy(ref godot_packed_vector2_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_vector3_array_destroy(ref godot_packed_vector3_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_packed_color_array_destroy(ref godot_packed_color_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_variant_destroy(ref godot_variant p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_destroy(ref godot_string p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_name_destroy(ref godot_string_name p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_destroy(ref godot_node_path p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_signal_destroy(ref godot_signal p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_callable_destroy(ref godot_callable p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_destroy(ref godot_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_destroy(ref godot_dictionary p_self);
|
||||||
|
|
||||||
|
// Array
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_array_add(ref godot_array p_self, godot_variant* p_item);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void
|
||||||
|
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_array_index_of(ref godot_array p_self, godot_variant* p_item);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_insert(ref godot_array p_self, int p_index, godot_variant* p_item);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Error godotsharp_array_resize(ref godot_array p_self, int p_new_size);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern Error godotsharp_array_shuffle(ref godot_array p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_array_to_string(ref godot_array p_self, godot_string* r_str);
|
||||||
|
|
||||||
|
// Dictionary
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
|
||||||
|
godot_variant* p_key,
|
||||||
|
out godot_variant r_value);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_set_value(ref godot_dictionary p_self, godot_variant* p_key,
|
||||||
|
godot_variant* p_value);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_values(ref godot_dictionary p_self, out godot_array r_dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_dictionary_count(ref godot_dictionary p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_key_value_pair_at(ref godot_dictionary p_self, int p_index,
|
||||||
|
out godot_variant r_key, out godot_variant r_value);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_add(ref godot_dictionary p_self, godot_variant* p_key,
|
||||||
|
godot_variant* p_value);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_clear(ref godot_dictionary p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
|
||||||
|
godot_variant* p_key);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
|
||||||
|
out godot_dictionary r_dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self,
|
||||||
|
godot_variant* p_key);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_dictionary_to_string(ref godot_dictionary p_self, godot_string* r_str);
|
||||||
|
|
||||||
|
// StringExtensions
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_md5_buffer(godot_string* p_self,
|
||||||
|
godot_packed_byte_array* r_md5_buffer);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_md5_text(godot_string* p_self, godot_string* r_md5_text);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_string_rfind(godot_string* p_self, godot_string* p_what, int p_from);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_string_rfindn(godot_string* p_self, godot_string* p_what, int p_from);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_sha256_buffer(godot_string* p_self,
|
||||||
|
godot_packed_byte_array* r_sha256_buffer);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_string_sha256_text(godot_string* p_self, godot_string* r_sha256_text);
|
||||||
|
|
||||||
|
// NodePath
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_get_as_property_path(ref godot_node_path p_self,
|
||||||
|
ref godot_node_path r_dest);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_get_concatenated_subnames(ref godot_node_path p_self,
|
||||||
|
godot_string* r_subnames);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_get_name(ref godot_node_path p_self, int p_idx,
|
||||||
|
godot_string* r_name);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_node_path_get_name_count(ref godot_node_path p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_node_path_get_subname(ref godot_node_path p_self, int p_idx,
|
||||||
|
godot_string* r_subname);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_node_path_get_subname_count(ref godot_node_path p_self);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern godot_bool godotsharp_node_path_is_absolute(ref godot_node_path p_self);
|
||||||
|
|
||||||
|
// GD, etc
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_bytes2var(godot_packed_byte_array* p_bytes, godot_bool p_allow_objects,
|
||||||
|
godot_variant* r_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_convert(godot_variant* p_what, Variant.Type p_type, godot_variant* r_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_hash(godot_variant* var);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern IntPtr godotsharp_instance_from_id(ulong instanceId);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_print(godot_string* p_what);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_printerr(godot_string* p_what);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_printraw(godot_string* p_what);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_prints(godot_string* p_what);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_printt(godot_string* p_what);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern float godotsharp_randf();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern uint godotsharp_randi();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_randomize();
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern double godotsharp_randf_range(double from, double to);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern int godotsharp_randi_range(int from, int to);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern uint godotsharp_rand_from_seed(ulong seed, out ulong newSeed);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_seed(ulong seed);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_weakref(IntPtr obj, godot_ref* r_weak_ref);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern string godotsharp_str(godot_array* p_what, godot_string* r_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_str2var(godot_string* p_str, godot_variant* r_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_var2bytes(godot_variant* what, godot_bool fullObjects,
|
||||||
|
godot_packed_byte_array* bytes);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_var2str(godot_variant* var, godot_string* r_ret);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_pusherror(godot_string* type);
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern void godotsharp_pushwarning(godot_string* type);
|
||||||
|
|
||||||
|
// Object
|
||||||
|
|
||||||
|
[DllImport(GodotDllName)]
|
||||||
|
public static extern string godotsharp_object_to_string(IntPtr ptr, godot_string* r_str);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
public static unsafe partial class NativeFuncs
|
||||||
|
{
|
||||||
|
public static godot_string_name godotsharp_string_name_new_copy(godot_string_name* src)
|
||||||
|
{
|
||||||
|
godot_string_name ret;
|
||||||
|
godotsharp_string_name_new_copy(&ret, src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static godot_string_name godotsharp_string_name_new_copy(godot_string_name src)
|
||||||
|
=> godotsharp_string_name_new_copy(&src);
|
||||||
|
|
||||||
|
public static godot_node_path godotsharp_node_path_new_copy(godot_node_path* src)
|
||||||
|
{
|
||||||
|
godot_node_path ret;
|
||||||
|
godotsharp_node_path_new_copy(&ret, src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static godot_node_path godotsharp_node_path_new_copy(godot_node_path src)
|
||||||
|
=> godotsharp_node_path_new_copy(&src);
|
||||||
|
|
||||||
|
public static godot_array godotsharp_array_new()
|
||||||
|
{
|
||||||
|
godot_array ret;
|
||||||
|
godotsharp_array_new(&ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static godot_array godotsharp_array_new_copy(godot_array* src)
|
||||||
|
{
|
||||||
|
godot_array ret;
|
||||||
|
godotsharp_array_new_copy(&ret, src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static godot_array godotsharp_array_new_copy(godot_array src)
|
||||||
|
=> godotsharp_array_new_copy(&src);
|
||||||
|
|
||||||
|
public static godot_dictionary godotsharp_dictionary_new()
|
||||||
|
{
|
||||||
|
godot_dictionary ret;
|
||||||
|
godotsharp_dictionary_new(&ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary* src)
|
||||||
|
{
|
||||||
|
godot_dictionary ret;
|
||||||
|
godotsharp_dictionary_new_copy(&ret, src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary src)
|
||||||
|
=> godotsharp_dictionary_new_copy(&src);
|
||||||
|
|
||||||
|
public static godot_string_name godotsharp_string_name_new_from_string(string name)
|
||||||
|
{
|
||||||
|
godot_string_name ret;
|
||||||
|
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||||
|
godotsharp_string_name_new_from_string(&ret, &src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static godot_node_path godotsharp_node_path_new_from_string(string name)
|
||||||
|
{
|
||||||
|
godot_node_path ret;
|
||||||
|
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||||
|
godotsharp_node_path_new_from_string(&ret, &src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
internal ref struct VariantSpanDisposer
|
||||||
|
{
|
||||||
|
private readonly Span<godot_variant> _variantSpan;
|
||||||
|
|
||||||
|
// IMPORTANT: The span element must be default initialized.
|
||||||
|
// Make sure call Clear() on the span if it was created with stackalloc.
|
||||||
|
public VariantSpanDisposer(Span<godot_variant> variantSpan)
|
||||||
|
{
|
||||||
|
_variantSpan = variantSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _variantSpan.Length; i++)
|
||||||
|
_variantSpan[i].Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class VariantSpanExtensions
|
||||||
|
{
|
||||||
|
// Used to make sure we always initialize the span values to the default,
|
||||||
|
// as we need that in order to safely dispose all elements after.
|
||||||
|
public static Span<godot_variant> Cleared(this Span<godot_variant> span)
|
||||||
|
{
|
||||||
|
span.Clear();
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,355 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop
|
||||||
|
{
|
||||||
|
public static class VariantUtils
|
||||||
|
{
|
||||||
|
public static godot_variant CreateFromRID(RID from)
|
||||||
|
=> new() { _type = Variant.Type.Rid, _data = { _m_rid = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromBool(bool from)
|
||||||
|
=> new() { _type = Variant.Type.Bool, _data = { _bool = from.ToGodotBool() } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromInt(long from)
|
||||||
|
=> new() { _type = Variant.Type.Int, _data = { _int = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromInt(ulong from)
|
||||||
|
=> new() { _type = Variant.Type.Int, _data = { _int = (long)from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromFloat(double from)
|
||||||
|
=> new() { _type = Variant.Type.Float, _data = { _float = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromVector2(Vector2 from)
|
||||||
|
=> new() { _type = Variant.Type.Vector2, _data = { _m_vector2 = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromVector2i(Vector2i from)
|
||||||
|
=> new() { _type = Variant.Type.Vector2i, _data = { _m_vector2i = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromVector3(Vector3 from)
|
||||||
|
=> new() { _type = Variant.Type.Vector3, _data = { _m_vector3 = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromVector3i(Vector3i from)
|
||||||
|
=> new() { _type = Variant.Type.Vector3i, _data = { _m_vector3i = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromRect2(Rect2 from)
|
||||||
|
=> new() { _type = Variant.Type.Rect2, _data = { _m_rect2 = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromRect2i(Rect2i from)
|
||||||
|
=> new() { _type = Variant.Type.Rect2i, _data = { _m_rect2i = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromQuaternion(Quaternion from)
|
||||||
|
=> new() { _type = Variant.Type.Quaternion, _data = { _m_quaternion = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromColor(Color from)
|
||||||
|
=> new() { _type = Variant.Type.Color, _data = { _m_color = from } };
|
||||||
|
|
||||||
|
public static godot_variant CreateFromPlane(Plane from)
|
||||||
|
=> new() { _type = Variant.Type.Plane, _data = { _m_plane = from } };
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromTransform2D(Transform2D from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_transform2d(&ret, &from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromBasis(Basis from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_basis(&ret, &from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromTransform3D(Transform3D from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_transform3d(&ret, &from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromAABB(AABB from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_aabb(&ret, &from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicit name to make it very clear
|
||||||
|
public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
|
||||||
|
=> new() { _type = Variant.Type.Callable, _data = { _m_callable = from } };
|
||||||
|
|
||||||
|
// Explicit name to make it very clear
|
||||||
|
public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
|
||||||
|
=> new() { _type = Variant.Type.Signal, _data = { _m_signal = from } };
|
||||||
|
|
||||||
|
// Explicit name to make it very clear
|
||||||
|
public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
|
||||||
|
=> new() { _type = Variant.Type.String, _data = { _m_string = from } };
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedByteArray(godot_packed_byte_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_byte_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedInt32Array(godot_packed_int32_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_int32_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedInt64Array(godot_packed_int64_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_int64_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedFloat32Array(godot_packed_float32_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_float32_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedFloat64Array(godot_packed_float64_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_float64_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedStringArray(godot_packed_string_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_string_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedVector2Array(godot_packed_vector2_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_vector2_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedVector3Array(godot_packed_vector3_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_vector3_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromPackedColorArray(godot_packed_color_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_packed_color_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromArray(godot_array* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_array(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant CreateFromArray(godot_array from)
|
||||||
|
=> CreateFromArray(&from);
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromDictionary(godot_dictionary* from)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_dictionary(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant CreateFromDictionary(godot_dictionary from)
|
||||||
|
=> CreateFromDictionary(&from);
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromStringName(ref godot_string_name arg1)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
godot_string_name src = arg1;
|
||||||
|
NativeFuncs.godotsharp_variant_new_string_name(&ret, &src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromNodePath(ref godot_node_path arg1)
|
||||||
|
{
|
||||||
|
godot_variant ret;
|
||||||
|
godot_node_path src = arg1;
|
||||||
|
NativeFuncs.godotsharp_variant_new_node_path(&ret, &src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe godot_variant CreateFromGodotObject(IntPtr from)
|
||||||
|
{
|
||||||
|
if (from == IntPtr.Zero)
|
||||||
|
return new godot_variant();
|
||||||
|
godot_variant ret;
|
||||||
|
NativeFuncs.godotsharp_variant_new_object(&ret, from);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We avoid the internal call if the stored type is the same we want.
|
||||||
|
|
||||||
|
public static unsafe bool ConvertToBool(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Bool ?
|
||||||
|
(*p_var)._data._bool.ToBool() :
|
||||||
|
NativeFuncs.godotsharp_variant_as_bool(p_var).ToBool();
|
||||||
|
|
||||||
|
public static unsafe char ConvertToChar(godot_variant* p_var)
|
||||||
|
=> (char)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe sbyte ConvertToInt8(godot_variant* p_var)
|
||||||
|
=> (sbyte)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe Int16 ConvertToInt16(godot_variant* p_var)
|
||||||
|
=> (Int16)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe Int32 ConvertToInt32(godot_variant* p_var)
|
||||||
|
=> (Int32)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe Int64 ConvertToInt64(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var);
|
||||||
|
|
||||||
|
public static unsafe byte ConvertToUInt8(godot_variant* p_var)
|
||||||
|
=> (byte)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe UInt16 ConvertToUInt16(godot_variant* p_var)
|
||||||
|
=> (UInt16)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe UInt32 ConvertToUInt32(godot_variant* p_var)
|
||||||
|
=> (UInt32)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe UInt64 ConvertToUInt64(godot_variant* p_var)
|
||||||
|
=> (UInt64)((*p_var)._type == Variant.Type.Int ?
|
||||||
|
(*p_var)._data._int :
|
||||||
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
public static unsafe float ConvertToFloat32(godot_variant* p_var)
|
||||||
|
=> (float)((*p_var)._type == Variant.Type.Float ?
|
||||||
|
(*p_var)._data._float :
|
||||||
|
NativeFuncs.godotsharp_variant_as_float(p_var));
|
||||||
|
|
||||||
|
public static unsafe double ConvertToFloat64(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Float ?
|
||||||
|
(*p_var)._data._float :
|
||||||
|
NativeFuncs.godotsharp_variant_as_float(p_var);
|
||||||
|
|
||||||
|
public static unsafe Vector2 ConvertToVector2(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Vector2 ?
|
||||||
|
(*p_var)._data._m_vector2 :
|
||||||
|
NativeFuncs.godotsharp_variant_as_vector2(p_var);
|
||||||
|
|
||||||
|
public static unsafe Vector2i ConvertToVector2i(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Vector2i ?
|
||||||
|
(*p_var)._data._m_vector2i :
|
||||||
|
NativeFuncs.godotsharp_variant_as_vector2i(p_var);
|
||||||
|
|
||||||
|
public static unsafe Rect2 ConvertToRect2(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Rect2 ?
|
||||||
|
(*p_var)._data._m_rect2 :
|
||||||
|
NativeFuncs.godotsharp_variant_as_rect2(p_var);
|
||||||
|
|
||||||
|
public static unsafe Rect2i ConvertToRect2i(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Rect2i ?
|
||||||
|
(*p_var)._data._m_rect2i :
|
||||||
|
NativeFuncs.godotsharp_variant_as_rect2i(p_var);
|
||||||
|
|
||||||
|
public static unsafe Transform2D ConvertToTransform2D(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Transform2d ?
|
||||||
|
*(*p_var)._data._transform2d :
|
||||||
|
NativeFuncs.godotsharp_variant_as_transform2d(p_var);
|
||||||
|
|
||||||
|
public static unsafe Vector3 ConvertToVector3(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Vector3 ?
|
||||||
|
(*p_var)._data._m_vector3 :
|
||||||
|
NativeFuncs.godotsharp_variant_as_vector3(p_var);
|
||||||
|
|
||||||
|
public static unsafe Vector3i ConvertToVector3i(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Vector3i ?
|
||||||
|
(*p_var)._data._m_vector3i :
|
||||||
|
NativeFuncs.godotsharp_variant_as_vector3i(p_var);
|
||||||
|
|
||||||
|
public static unsafe Basis ConvertToBasis(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Basis ?
|
||||||
|
*(*p_var)._data._basis :
|
||||||
|
NativeFuncs.godotsharp_variant_as_basis(p_var);
|
||||||
|
|
||||||
|
public static unsafe Quaternion ConvertToQuaternion(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Quaternion ?
|
||||||
|
(*p_var)._data._m_quaternion :
|
||||||
|
NativeFuncs.godotsharp_variant_as_quaternion(p_var);
|
||||||
|
|
||||||
|
public static unsafe Transform3D ConvertToTransform3D(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Transform3d ?
|
||||||
|
*(*p_var)._data._transform3d :
|
||||||
|
NativeFuncs.godotsharp_variant_as_transform3d(p_var);
|
||||||
|
|
||||||
|
public static unsafe AABB ConvertToAABB(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Aabb ?
|
||||||
|
*(*p_var)._data._aabb :
|
||||||
|
NativeFuncs.godotsharp_variant_as_aabb(p_var);
|
||||||
|
|
||||||
|
public static unsafe Color ConvertToColor(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Color ?
|
||||||
|
(*p_var)._data._m_color :
|
||||||
|
NativeFuncs.godotsharp_variant_as_color(p_var);
|
||||||
|
|
||||||
|
public static unsafe Plane ConvertToPlane(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Plane ?
|
||||||
|
(*p_var)._data._m_plane :
|
||||||
|
NativeFuncs.godotsharp_variant_as_plane(p_var);
|
||||||
|
|
||||||
|
public static unsafe IntPtr ConvertToGodotObject(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Object ? (*p_var)._data._m_obj_data.obj : IntPtr.Zero;
|
||||||
|
|
||||||
|
public static unsafe RID ConvertToRID(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Rid ?
|
||||||
|
(*p_var)._data._m_rid :
|
||||||
|
NativeFuncs.godotsharp_variant_as_rid(p_var);
|
||||||
|
|
||||||
|
public static unsafe godot_string_name ConvertToStringName(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.StringName ?
|
||||||
|
NativeFuncs.godotsharp_string_name_new_copy(&(*p_var)._data._m_string_name) :
|
||||||
|
NativeFuncs.godotsharp_variant_as_string_name(p_var);
|
||||||
|
|
||||||
|
public static unsafe godot_node_path ConvertToNodePath(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.NodePath ?
|
||||||
|
NativeFuncs.godotsharp_node_path_new_copy(&(*p_var)._data._m_node_path) :
|
||||||
|
NativeFuncs.godotsharp_variant_as_node_path(p_var);
|
||||||
|
|
||||||
|
public static unsafe godot_array ConvertToArray(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Array ?
|
||||||
|
NativeFuncs.godotsharp_array_new_copy(&(*p_var)._data._m_array) :
|
||||||
|
NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||||
|
|
||||||
|
public static unsafe godot_dictionary ConvertToDictionary(godot_variant* p_var)
|
||||||
|
=> (*p_var)._type == Variant.Type.Dictionary ?
|
||||||
|
NativeFuncs.godotsharp_dictionary_new_copy(&(*p_var)._data._m_dictionary) :
|
||||||
|
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public sealed partial class NodePath : IDisposable
|
public sealed class NodePath : IDisposable
|
||||||
{
|
{
|
||||||
private bool disposed = false;
|
public godot_node_path NativeValue;
|
||||||
|
|
||||||
private IntPtr ptr;
|
|
||||||
|
|
||||||
internal static IntPtr GetPtr(NodePath instance)
|
|
||||||
{
|
|
||||||
if (instance == null)
|
|
||||||
throw new NullReferenceException($"The instance of type {nameof(NodePath)} is null.");
|
|
||||||
|
|
||||||
if (instance.disposed)
|
|
||||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
|
||||||
|
|
||||||
return instance.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~NodePath()
|
~NodePath()
|
||||||
{
|
{
|
||||||
|
@ -31,112 +19,90 @@ namespace Godot
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
public void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposed)
|
// Always dispose `NativeValue` even if disposing is true
|
||||||
return;
|
NativeValue.Dispose();
|
||||||
|
|
||||||
if (ptr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
godot_icall_NodePath_Dtor(ptr);
|
|
||||||
ptr = IntPtr.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = true;
|
private NodePath(godot_node_path nativeValueToOwn)
|
||||||
}
|
|
||||||
|
|
||||||
internal NodePath(IntPtr ptr)
|
|
||||||
{
|
{
|
||||||
this.ptr = ptr;
|
NativeValue = nativeValueToOwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodePath() : this(string.Empty) {}
|
// Explicit name to make it very clear
|
||||||
|
internal static NodePath CreateTakingOwnershipOfDisposableValue(godot_node_path nativeValueToOwn)
|
||||||
|
=> new NodePath(nativeValueToOwn);
|
||||||
|
|
||||||
|
public NodePath()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public NodePath(string path)
|
public NodePath(string path)
|
||||||
{
|
{
|
||||||
ptr = godot_icall_NodePath_Ctor(path);
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
NativeValue = NativeFuncs.godotsharp_node_path_new_from_string(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator NodePath(string from) => new NodePath(from);
|
public static implicit operator NodePath(string from) => new NodePath(from);
|
||||||
|
|
||||||
public static implicit operator string(NodePath from) => from.ToString();
|
public static implicit operator string(NodePath from) => from.ToString();
|
||||||
|
|
||||||
public override string ToString()
|
public override unsafe string ToString()
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_operator_String(GetPtr(this));
|
if (IsEmpty)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
godot_string dest;
|
||||||
|
godot_node_path src = NativeValue;
|
||||||
|
NativeFuncs.godotsharp_node_path_as_string(&dest, &src);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodePath GetAsPropertyPath()
|
public NodePath GetAsPropertyPath()
|
||||||
{
|
{
|
||||||
return new NodePath(godot_icall_NodePath_get_as_property_path(GetPtr(this)));
|
godot_node_path propertyPath = default;
|
||||||
|
NativeFuncs.godotsharp_node_path_get_as_property_path(ref NativeValue, ref propertyPath);
|
||||||
|
return CreateTakingOwnershipOfDisposableValue(propertyPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetConcatenatedSubnames()
|
public unsafe string GetConcatenatedSubNames()
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this));
|
using godot_string subNames = default;
|
||||||
|
NativeFuncs.godotsharp_node_path_get_concatenated_subnames(ref NativeValue, &subNames);
|
||||||
|
return Marshaling.mono_string_from_godot(subNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetName(int idx)
|
public unsafe string GetName(int idx)
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_get_name(GetPtr(this), idx);
|
using godot_string name = default;
|
||||||
|
NativeFuncs.godotsharp_node_path_get_name(ref NativeValue, idx, &name);
|
||||||
|
return Marshaling.mono_string_from_godot(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetNameCount()
|
public int GetNameCount()
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_get_name_count(GetPtr(this));
|
return NativeFuncs.godotsharp_node_path_get_name_count(ref NativeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetSubname(int idx)
|
public unsafe string GetSubName(int idx)
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_get_subname(GetPtr(this), idx);
|
using godot_string subName = default;
|
||||||
|
NativeFuncs.godotsharp_node_path_get_subname(ref NativeValue, idx, &subName);
|
||||||
|
return Marshaling.mono_string_from_godot(subName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetSubnameCount()
|
public int GetSubNameCount()
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_get_subname_count(GetPtr(this));
|
return NativeFuncs.godotsharp_node_path_get_subname_count(ref NativeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAbsolute()
|
public bool IsAbsolute()
|
||||||
{
|
{
|
||||||
return godot_icall_NodePath_is_absolute(GetPtr(this));
|
return NativeFuncs.godotsharp_node_path_is_absolute(ref NativeValue).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty()
|
public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue);
|
||||||
{
|
|
||||||
return godot_icall_NodePath_is_empty(GetPtr(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern IntPtr godot_icall_NodePath_Ctor(string path);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern void godot_icall_NodePath_Dtor(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string godot_icall_NodePath_operator_String(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string godot_icall_NodePath_get_name(IntPtr ptr, int arg1);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern int godot_icall_NodePath_get_name_count(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern int godot_icall_NodePath_get_subname_count(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern bool godot_icall_NodePath_is_absolute(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern bool godot_icall_NodePath_is_empty(IntPtr ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,80 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public partial class Object : IDisposable
|
public partial class Object : IDisposable
|
||||||
{
|
{
|
||||||
private bool disposed = false;
|
private bool _disposed = false;
|
||||||
|
private Type _cachedType = typeof(Object);
|
||||||
|
|
||||||
private static StringName nativeName = "Object";
|
internal IntPtr NativePtr;
|
||||||
|
internal bool MemoryOwn;
|
||||||
internal IntPtr ptr;
|
|
||||||
internal bool memoryOwn;
|
|
||||||
|
|
||||||
public Object() : this(false)
|
public Object() : this(false)
|
||||||
{
|
{
|
||||||
if (ptr == IntPtr.Zero)
|
if (NativePtr == IntPtr.Zero)
|
||||||
ptr = godot_icall_Object_Ctor(this);
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
NativePtr = NativeCtor();
|
||||||
|
}
|
||||||
|
|
||||||
|
InteropUtils.TieManagedToUnmanaged(this, NativePtr,
|
||||||
|
NativeName, refCounted: false, GetType(), _cachedType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InteropUtils.TieManagedToUnmanagedWithPreSetup(this, NativePtr);
|
||||||
|
}
|
||||||
|
|
||||||
_InitializeGodotScriptInstanceInternals();
|
_InitializeGodotScriptInstanceInternals();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void _InitializeGodotScriptInstanceInternals()
|
internal void _InitializeGodotScriptInstanceInternals()
|
||||||
{
|
{
|
||||||
godot_icall_Object_ConnectEventSignals(ptr);
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
Type top = GetType();
|
||||||
|
Type native = InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
foreach (var eventSignal in top.GetEvents(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any()))
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
using var eventSignalName = new StringName(eventSignal.Name);
|
||||||
|
godot_string_name eventSignalNameAux = eventSignalName.NativeValue;
|
||||||
|
NativeFuncs.godotsharp_internal_object_connect_event_signal(NativePtr, &eventSignalNameAux);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Object(bool memoryOwn)
|
internal Object(bool memoryOwn)
|
||||||
{
|
{
|
||||||
this.memoryOwn = memoryOwn;
|
MemoryOwn = memoryOwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntPtr NativeInstance
|
public IntPtr NativeInstance => NativePtr;
|
||||||
{
|
|
||||||
get { return ptr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static IntPtr GetPtr(Object instance)
|
internal static IntPtr GetPtr(Object instance)
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
if (instance.disposed)
|
if (instance._disposed)
|
||||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||||
|
|
||||||
return instance.ptr;
|
return instance.NativePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Object()
|
~Object()
|
||||||
|
@ -58,30 +90,32 @@ namespace Godot
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposed)
|
if (_disposed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ptr != IntPtr.Zero)
|
if (NativePtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (memoryOwn)
|
if (MemoryOwn)
|
||||||
{
|
{
|
||||||
memoryOwn = false;
|
MemoryOwn = false;
|
||||||
godot_icall_RefCounted_Disposed(this, ptr, !disposing);
|
NativeFuncs.godotsharp_internal_refcounted_disposed(NativePtr, (!disposing).ToGodotBool());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
godot_icall_Object_Disposed(this, ptr);
|
NativeFuncs.godotsharp_internal_object_disposed(NativePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ptr = IntPtr.Zero;
|
NativePtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override unsafe string ToString()
|
||||||
{
|
{
|
||||||
return godot_icall_Object_ToString(GetPtr(this));
|
using godot_string str = default;
|
||||||
|
NativeFuncs.godotsharp_object_to_string(GetPtr(this), &str);
|
||||||
|
return Marshaling.mono_string_from_godot(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -112,33 +146,236 @@ namespace Godot
|
||||||
return new SignalAwaiter(source, signal, this);
|
return new SignalAwaiter(source, signal, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal static Type InternalGetClassNativeBase(Type t)
|
||||||
/// Gets a new <see cref="Godot.DynamicGodotObject"/> associated with this instance.
|
|
||||||
/// </summary>
|
|
||||||
public dynamic DynamicObject => new DynamicGodotObject(this);
|
|
||||||
|
|
||||||
internal static IntPtr __ClassDB_get_method(StringName type, string method)
|
|
||||||
{
|
{
|
||||||
return godot_icall_Object_ClassDB_get_method(StringName.GetPtr(type), method);
|
do
|
||||||
|
{
|
||||||
|
var assemblyName = t.Assembly.GetName();
|
||||||
|
|
||||||
|
if (assemblyName.Name == "GodotSharp")
|
||||||
|
return t;
|
||||||
|
|
||||||
|
if (assemblyName.Name == "GodotSharpEditor")
|
||||||
|
return t;
|
||||||
|
} while ((t = t.BaseType) != null);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
internal static bool InternalIsClassNativeBase(Type t)
|
||||||
internal static extern IntPtr godot_icall_Object_Ctor(Object obj);
|
{
|
||||||
|
var assemblyName = t.Assembly.GetName();
|
||||||
|
return assemblyName.Name == "GodotSharp" || assemblyName.Name == "GodotSharpEditor";
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
internal unsafe bool InternalGodotScriptCallViaReflection(string method, godot_variant** args, int argCount,
|
||||||
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
|
out godot_variant ret)
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
Type top = GetType();
|
||||||
|
Type native = InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
while (top != null && top != native)
|
||||||
internal static extern void godot_icall_RefCounted_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
|
{
|
||||||
|
var methodInfo = top.GetMethod(method,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
if (methodInfo != null)
|
||||||
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
|
{
|
||||||
|
var parameters = methodInfo.GetParameters();
|
||||||
|
int paramCount = parameters.Length;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
if (argCount == paramCount)
|
||||||
internal static extern string godot_icall_Object_ToString(IntPtr ptr);
|
{
|
||||||
|
object[] invokeParams = new object[paramCount];
|
||||||
|
|
||||||
// Used by the generated API
|
for (int i = 0; i < paramCount; i++)
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
{
|
||||||
internal static extern IntPtr godot_icall_Object_ClassDB_get_method(IntPtr type, string method);
|
invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
|
||||||
|
args[i], parameters[i].ParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
object retObj = methodInfo.Invoke(this, invokeParams);
|
||||||
|
|
||||||
|
ret = Marshaling.mono_object_to_variant(retObj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal unsafe bool InternalGodotScriptSetFieldOrPropViaReflection(string name, godot_variant* value)
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
Type top = GetType();
|
||||||
|
Type native = InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
var fieldInfo = top.GetField(name,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (fieldInfo != null)
|
||||||
|
{
|
||||||
|
object valueManaged = Marshaling.variant_to_mono_object_of_type(value, fieldInfo.FieldType);
|
||||||
|
fieldInfo.SetValue(this, valueManaged);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyInfo = top.GetProperty(name,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (propertyInfo != null)
|
||||||
|
{
|
||||||
|
object valueManaged = Marshaling.variant_to_mono_object_of_type(value, propertyInfo.PropertyType);
|
||||||
|
propertyInfo.SetValue(this, valueManaged);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool InternalGodotScriptGetFieldOrPropViaReflection(string name, out godot_variant value)
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
Type top = GetType();
|
||||||
|
Type native = InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
var fieldInfo = top.GetField(name,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (fieldInfo != null)
|
||||||
|
{
|
||||||
|
object valueManaged = fieldInfo.GetValue(this);
|
||||||
|
value = Marshaling.mono_object_to_variant(valueManaged);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyInfo = top.GetProperty(name,
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
if (propertyInfo != null)
|
||||||
|
{
|
||||||
|
object valueManaged = propertyInfo.GetValue(this);
|
||||||
|
value = Marshaling.mono_object_to_variant(valueManaged);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal unsafe void InternalRaiseEventSignal(godot_string_name* eventSignalName, godot_variant** args,
|
||||||
|
int argc)
|
||||||
|
{
|
||||||
|
// Performance is not critical here as this will be replaced with source generators.
|
||||||
|
|
||||||
|
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_string_name_new_copy(eventSignalName));
|
||||||
|
string eventSignalNameStr = stringName.ToString();
|
||||||
|
|
||||||
|
Type top = GetType();
|
||||||
|
Type native = InternalGetClassNativeBase(top);
|
||||||
|
|
||||||
|
while (top != null && top != native)
|
||||||
|
{
|
||||||
|
var foundEventSignals = top.GetEvents(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public)
|
||||||
|
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||||
|
.Select(ev => ev.Name);
|
||||||
|
|
||||||
|
var fields = top.GetFields(
|
||||||
|
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
||||||
|
var eventSignalField = fields
|
||||||
|
.Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
|
||||||
|
.Where(f => foundEventSignals.Contains(f.Name))
|
||||||
|
.FirstOrDefault(f => f.Name == eventSignalNameStr);
|
||||||
|
|
||||||
|
if (eventSignalField != null)
|
||||||
|
{
|
||||||
|
var @delegate = (Delegate)eventSignalField.GetValue(this);
|
||||||
|
|
||||||
|
if (@delegate == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var delegateType = eventSignalField.FieldType;
|
||||||
|
|
||||||
|
var invokeMethod = delegateType.GetMethod("Invoke");
|
||||||
|
|
||||||
|
if (invokeMethod == null)
|
||||||
|
throw new MissingMethodException(delegateType.FullName, "Invoke");
|
||||||
|
|
||||||
|
var parameterInfos = invokeMethod.GetParameters();
|
||||||
|
var paramsLength = parameterInfos.Length;
|
||||||
|
|
||||||
|
if (argc != paramsLength)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"The event delegate expects {paramsLength} arguments, but received {argc}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var managedArgs = new object[argc];
|
||||||
|
|
||||||
|
for (uint i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
|
||||||
|
args[i], parameterInfos[i].ParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeMethod.Invoke(@delegate, managedArgs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top.BaseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static unsafe IntPtr ClassDB_get_method(StringName type, string method)
|
||||||
|
{
|
||||||
|
IntPtr methodBind;
|
||||||
|
fixed (char* methodChars = method)
|
||||||
|
{
|
||||||
|
methodBind = NativeFuncs.godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodBind == IntPtr.Zero)
|
||||||
|
throw new NativeMethodBindNotFoundException(type + "." + method);
|
||||||
|
|
||||||
|
return methodBind;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
|
||||||
|
{
|
||||||
|
// for some reason the '??' operator doesn't support 'delegate*'
|
||||||
|
var nativeConstructor = NativeFuncs.godotsharp_get_class_constructor(ref type.NativeValue);
|
||||||
|
|
||||||
|
if (nativeConstructor == null)
|
||||||
|
throw new NativeConstructorNotFoundException(type);
|
||||||
|
|
||||||
|
return nativeConstructor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace Godot
|
||||||
|
{
|
||||||
|
public partial class Object
|
||||||
|
{
|
||||||
|
public class NativeMemberNotFoundException : Exception
|
||||||
|
{
|
||||||
|
public NativeMemberNotFoundException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMemberNotFoundException(string? message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMemberNotFoundException(string? message, Exception? innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NativeConstructorNotFoundException : NativeMemberNotFoundException
|
||||||
|
{
|
||||||
|
private readonly string? _nativeClassName;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
private const string Arg_NativeConstructorNotFoundException = "Unable to find the native constructor.";
|
||||||
|
|
||||||
|
public NativeConstructorNotFoundException()
|
||||||
|
: base(Arg_NativeConstructorNotFoundException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeConstructorNotFoundException(string? nativeClassName)
|
||||||
|
: this(Arg_NativeConstructorNotFoundException, nativeClassName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeConstructorNotFoundException(string? message, Exception? innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeConstructorNotFoundException(string? message, string? nativeClassName)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
_nativeClassName = nativeClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeConstructorNotFoundException(string? message, string? nativeClassName, Exception? innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
_nativeClassName = nativeClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string s = base.Message;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
{
|
||||||
|
s = Arg_NativeConstructorNotFoundException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_nativeClassName))
|
||||||
|
{
|
||||||
|
s += " " + string.Format("(Class '{0}')", _nativeClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NativeMethodBindNotFoundException : NativeMemberNotFoundException
|
||||||
|
{
|
||||||
|
private readonly string? _nativeMethodName;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
private const string Arg_NativeMethodBindNotFoundException = "Unable to find the native method bind.";
|
||||||
|
|
||||||
|
public NativeMethodBindNotFoundException()
|
||||||
|
: base(Arg_NativeMethodBindNotFoundException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMethodBindNotFoundException(string? nativeMethodName)
|
||||||
|
: this(Arg_NativeMethodBindNotFoundException, nativeMethodName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMethodBindNotFoundException(string? message, Exception? innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMethodBindNotFoundException(string? message, string? nativeMethodName)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
_nativeMethodName = nativeMethodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeMethodBindNotFoundException(string? message, string? nativeMethodName, Exception? innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
_nativeMethodName = nativeMethodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string s = base.Message;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
{
|
||||||
|
s = Arg_NativeMethodBindNotFoundException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_nativeMethodName))
|
||||||
|
{
|
||||||
|
s += " " + string.Format("(Method '{0}')", _nativeMethodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,84 +1,25 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public sealed partial class RID : IDisposable
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct RID
|
||||||
{
|
{
|
||||||
private bool disposed = false;
|
private ulong _id; // Default is 0
|
||||||
|
|
||||||
internal IntPtr ptr;
|
internal RID(ulong id)
|
||||||
|
|
||||||
internal static IntPtr GetPtr(RID instance)
|
|
||||||
{
|
{
|
||||||
if (instance == null)
|
_id = id;
|
||||||
throw new NullReferenceException($"The instance of type {nameof(RID)} is null.");
|
|
||||||
|
|
||||||
if (instance.disposed)
|
|
||||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
|
||||||
|
|
||||||
return instance.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~RID()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ptr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
godot_icall_RID_Dtor(ptr);
|
|
||||||
ptr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal RID(IntPtr ptr)
|
|
||||||
{
|
|
||||||
this.ptr = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntPtr NativeInstance
|
|
||||||
{
|
|
||||||
get { return ptr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal RID()
|
|
||||||
{
|
|
||||||
this.ptr = IntPtr.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RID(Object from)
|
public RID(Object from)
|
||||||
{
|
=> _id = from is Resource res ? res.GetRid()._id : default;
|
||||||
this.ptr = godot_icall_RID_Ctor(Object.GetPtr(from));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetId()
|
public ulong Id => _id;
|
||||||
{
|
|
||||||
return godot_icall_RID_get_id(RID.GetPtr(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => "[RID]";
|
public override string ToString() => $"RID({Id})";
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static void godot_icall_RID_Dtor(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_RID_get_id(IntPtr ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,66 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
|
public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
|
||||||
{
|
{
|
||||||
private bool completed;
|
private bool _completed;
|
||||||
private object[] result;
|
private object[] _result;
|
||||||
private Action action;
|
private Action _action;
|
||||||
|
|
||||||
public SignalAwaiter(Object source, StringName signal, Object target)
|
public SignalAwaiter(Object source, StringName signal, Object target)
|
||||||
{
|
{
|
||||||
godot_icall_SignalAwaiter_connect(Object.GetPtr(source), StringName.GetPtr(signal), Object.GetPtr(target), this);
|
NativeFuncs.godotsharp_internal_signal_awaiter_connect(Object.GetPtr(source), ref signal.NativeValue,
|
||||||
|
Object.GetPtr(target), GCHandle.ToIntPtr(GCHandle.Alloc(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
public bool IsCompleted => _completed;
|
||||||
internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter);
|
|
||||||
|
|
||||||
public bool IsCompleted
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return completed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action action)
|
public void OnCompleted(Action action)
|
||||||
{
|
{
|
||||||
this.action = action;
|
this._action = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[] GetResult()
|
public object[] GetResult() => _result;
|
||||||
|
|
||||||
|
public IAwaiter<object[]> GetAwaiter() => this;
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe void SignalCallback(IntPtr awaiterGCHandlePtr, godot_variant** args, int argCount,
|
||||||
|
godot_bool* outAwaiterIsNull)
|
||||||
{
|
{
|
||||||
return result;
|
try
|
||||||
|
{
|
||||||
|
var awaiter = (SignalAwaiter)GCHandle.FromIntPtr(awaiterGCHandlePtr).Target;
|
||||||
|
|
||||||
|
if (awaiter == null)
|
||||||
|
{
|
||||||
|
*outAwaiterIsNull = true.ToGodotBool();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAwaiter<object[]> GetAwaiter()
|
*outAwaiterIsNull = false.ToGodotBool();
|
||||||
|
|
||||||
|
awaiter._completed = true;
|
||||||
|
|
||||||
|
object[] signalArgs = new object[argCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < argCount; i++)
|
||||||
|
signalArgs[i] = Marshaling.variant_to_mono_object(args[i]);
|
||||||
|
|
||||||
|
awaiter._result = signalArgs;
|
||||||
|
|
||||||
|
if (awaiter._action != null)
|
||||||
{
|
{
|
||||||
return this;
|
awaiter._action();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
internal void SignalCallback(object[] args)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
completed = true;
|
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||||
result = args;
|
*outAwaiterIsNull = false.ToGodotBool();
|
||||||
|
|
||||||
if (action != null)
|
|
||||||
{
|
|
||||||
action();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
|
@ -157,6 +158,7 @@ namespace Godot
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from == 0 && to == len)
|
if (from == 0 && to == len)
|
||||||
{
|
{
|
||||||
str = instance;
|
str = instance;
|
||||||
|
@ -192,7 +194,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string CEscape(this string instance)
|
public static string CEscape(this string instance)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(string.Copy(instance));
|
var sb = new StringBuilder(instance);
|
||||||
|
|
||||||
sb.Replace("\\", "\\\\");
|
sb.Replace("\\", "\\\\");
|
||||||
sb.Replace("\a", "\\a");
|
sb.Replace("\a", "\\a");
|
||||||
|
@ -215,7 +217,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string CUnescape(this string instance)
|
public static string CUnescape(this string instance)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(string.Copy(instance));
|
var sb = new StringBuilder(instance);
|
||||||
|
|
||||||
sb.Replace("\\a", "\a");
|
sb.Replace("\\a", "\a");
|
||||||
sb.Replace("\\b", "\b");
|
sb.Replace("\\b", "\b");
|
||||||
|
@ -355,7 +357,8 @@ namespace Godot
|
||||||
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
||||||
public static int Find(this string instance, string what, int from = 0, bool caseSensitive = true)
|
public static int Find(this string instance, string what, int from = 0, bool caseSensitive = true)
|
||||||
{
|
{
|
||||||
return instance.IndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
return instance.IndexOf(what, from,
|
||||||
|
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -366,7 +369,8 @@ namespace Godot
|
||||||
{
|
{
|
||||||
// TODO: Could be more efficient if we get a char version of `IndexOf`.
|
// TODO: Could be more efficient if we get a char version of `IndexOf`.
|
||||||
// See https://github.com/dotnet/runtime/issues/44116
|
// See https://github.com/dotnet/runtime/issues/44116
|
||||||
return instance.IndexOf(what.ToString(), from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
return instance.IndexOf(what.ToString(), from,
|
||||||
|
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Find the last occurrence of a substring.</summary>
|
/// <summary>Find the last occurrence of a substring.</summary>
|
||||||
|
@ -380,7 +384,8 @@ namespace Godot
|
||||||
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
||||||
public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
|
public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
|
||||||
{
|
{
|
||||||
return instance.LastIndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
return instance.LastIndexOf(what, from,
|
||||||
|
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -623,6 +628,7 @@ namespace Godot
|
||||||
{
|
{
|
||||||
match = instance[source] == text[target];
|
match = instance[source] == text[target];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
source++;
|
source++;
|
||||||
|
@ -732,7 +738,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string JSONEscape(this string instance)
|
public static string JSONEscape(this string instance)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(string.Copy(instance));
|
var sb = new StringBuilder(instance);
|
||||||
|
|
||||||
sb.Replace("\\", "\\\\");
|
sb.Replace("\\", "\\\\");
|
||||||
sb.Replace("\b", "\\b");
|
sb.Replace("\b", "\\b");
|
||||||
|
@ -808,15 +814,18 @@ namespace Godot
|
||||||
switch (expr[0])
|
switch (expr[0])
|
||||||
{
|
{
|
||||||
case '*':
|
case '*':
|
||||||
return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && ExprMatch(instance.Substring(1), expr, caseSensitive));
|
return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 &&
|
||||||
|
ExprMatch(instance.Substring(1), expr, caseSensitive));
|
||||||
case '?':
|
case '?':
|
||||||
return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
return instance.Length > 0 && instance[0] != '.' &&
|
||||||
|
ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||||
default:
|
default:
|
||||||
if (instance.Length == 0)
|
if (instance.Length == 0)
|
||||||
return false;
|
return false;
|
||||||
if (caseSensitive)
|
if (caseSensitive)
|
||||||
return instance[0] == expr[0];
|
return instance[0] == expr[0];
|
||||||
return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) &&
|
||||||
|
ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,25 +856,25 @@ namespace Godot
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the MD5 hash of the string as an array of bytes.
|
/// Return the MD5 hash of the string as an array of bytes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static byte[] MD5Buffer(this string instance)
|
public static unsafe byte[] MD5Buffer(this string instance)
|
||||||
{
|
{
|
||||||
return godot_icall_String_md5_buffer(instance);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_packed_byte_array md5Buffer = default;
|
||||||
|
NativeFuncs.godotsharp_string_md5_buffer(&instanceStr, &md5Buffer);
|
||||||
|
return Marshaling.PackedByteArray_to_mono_array(&md5Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static byte[] godot_icall_String_md5_buffer(string str);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the MD5 hash of the string as a string.
|
/// Return the MD5 hash of the string as a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string MD5Text(this string instance)
|
public static unsafe string MD5Text(this string instance)
|
||||||
{
|
{
|
||||||
return godot_icall_String_md5_text(instance);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_string md5Text = default;
|
||||||
|
NativeFuncs.godotsharp_string_md5_text(&instanceStr, &md5Text);
|
||||||
|
return Marshaling.mono_string_from_godot(md5Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_String_md5_text(string str);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
|
/// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -981,26 +990,24 @@ namespace Godot
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int RFind(this string instance, string what, int from = -1)
|
public static unsafe int RFind(this string instance, string what, int from = -1)
|
||||||
{
|
{
|
||||||
return godot_icall_String_rfind(instance, what, from);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
return NativeFuncs.godotsharp_string_rfind(&instanceStr, &whatStr, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_String_rfind(string str, string what, int from);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
||||||
/// Also search case-insensitive.
|
/// Also search case-insensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int RFindN(this string instance, string what, int from = -1)
|
public static unsafe int RFindN(this string instance, string what, int from = -1)
|
||||||
{
|
{
|
||||||
return godot_icall_String_rfindn(instance, what, from);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
return NativeFuncs.godotsharp_string_rfindn(&instanceStr, &whatStr, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static int godot_icall_String_rfindn(string str, string what, int from);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the right side of the string from a given position.
|
/// Return the right side of the string from a given position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1042,25 +1049,25 @@ namespace Godot
|
||||||
return instance.Substr(0, end + 1);
|
return instance.Substr(0, end + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] SHA256Buffer(this string instance)
|
public static unsafe byte[] SHA256Buffer(this string instance)
|
||||||
{
|
{
|
||||||
return godot_icall_String_sha256_buffer(instance);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_packed_byte_array sha256Buffer = default;
|
||||||
|
NativeFuncs.godotsharp_string_sha256_buffer(&instanceStr, &sha256Buffer);
|
||||||
|
return Marshaling.PackedByteArray_to_mono_array(&sha256Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static byte[] godot_icall_String_sha256_buffer(string str);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the SHA-256 hash of the string as a string.
|
/// Return the SHA-256 hash of the string as a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string SHA256Text(this string instance)
|
public static unsafe string SHA256Text(this string instance)
|
||||||
{
|
{
|
||||||
return godot_icall_String_sha256_text(instance);
|
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||||
|
using godot_string sha256Text = default;
|
||||||
|
NativeFuncs.godotsharp_string_sha256_text(&instanceStr, &sha256Text);
|
||||||
|
return Marshaling.mono_string_from_godot(sha256Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal extern static string godot_icall_String_sha256_text(string str);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the similarity index of the text compared to this string.
|
/// Return the similarity index of the text compared to this string.
|
||||||
/// 1 means totally similar and 0 means totally dissimilar.
|
/// 1 means totally similar and 0 means totally dissimilar.
|
||||||
|
@ -1072,6 +1079,7 @@ namespace Godot
|
||||||
// Equal strings are totally similar
|
// Equal strings are totally similar
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance.Length < 2 || text.Length < 2)
|
if (instance.Length < 2 || text.Length < 2)
|
||||||
{
|
{
|
||||||
// No way to calculate similarity without a single bigram
|
// No way to calculate similarity without a single bigram
|
||||||
|
@ -1108,7 +1116,8 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
|
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
|
||||||
{
|
{
|
||||||
return instance.Split(new[] { divisor }, allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
|
return instance.Split(new[] { divisor },
|
||||||
|
allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1137,7 +1146,8 @@ namespace Godot
|
||||||
return ret.ToArray();
|
return ret.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly char[] _nonPrintable = {
|
private static readonly char[] _nonPrintable =
|
||||||
|
{
|
||||||
(char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
|
(char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
|
||||||
(char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
|
(char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
|
||||||
(char)12, (char)13, (char)14, (char)15, (char)16, (char)17,
|
(char)12, (char)13, (char)14, (char)15, (char)16, (char)17,
|
||||||
|
|
|
@ -1,22 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public sealed partial class StringName : IDisposable
|
public sealed class StringName : IDisposable
|
||||||
{
|
{
|
||||||
private IntPtr ptr;
|
public godot_string_name NativeValue;
|
||||||
|
|
||||||
internal static IntPtr GetPtr(StringName instance)
|
|
||||||
{
|
|
||||||
if (instance == null)
|
|
||||||
throw new NullReferenceException($"The instance of type {nameof(StringName)} is null.");
|
|
||||||
|
|
||||||
if (instance.ptr == IntPtr.Zero)
|
|
||||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
|
||||||
|
|
||||||
return instance.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~StringName()
|
~StringName()
|
||||||
{
|
{
|
||||||
|
@ -29,54 +19,47 @@ namespace Godot
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
public void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (ptr != IntPtr.Zero)
|
// Always dispose `NativeValue` even if disposing is true
|
||||||
{
|
NativeValue.Dispose();
|
||||||
godot_icall_StringName_Dtor(ptr);
|
|
||||||
ptr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal StringName(IntPtr ptr)
|
private StringName(godot_string_name nativeValueToOwn)
|
||||||
{
|
{
|
||||||
this.ptr = ptr;
|
NativeValue = nativeValueToOwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Explicit name to make it very clear
|
||||||
|
internal static StringName CreateTakingOwnershipOfDisposableValue(godot_string_name nativeValueToOwn)
|
||||||
|
=> new StringName(nativeValueToOwn);
|
||||||
|
|
||||||
public StringName()
|
public StringName()
|
||||||
{
|
{
|
||||||
ptr = IntPtr.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringName(string path)
|
public StringName(string name)
|
||||||
{
|
{
|
||||||
ptr = path == null ? IntPtr.Zero : godot_icall_StringName_Ctor(path);
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
NativeValue = NativeFuncs.godotsharp_string_name_new_from_string(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator StringName(string from) => new StringName(from);
|
public static implicit operator StringName(string from) => new StringName(from);
|
||||||
|
|
||||||
public static implicit operator string(StringName from) => from.ToString();
|
public static implicit operator string(StringName from) => from.ToString();
|
||||||
|
|
||||||
public override string ToString()
|
public override unsafe string ToString()
|
||||||
{
|
{
|
||||||
return ptr == IntPtr.Zero ? string.Empty : godot_icall_StringName_operator_String(GetPtr(this));
|
if (IsEmpty)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
godot_string dest;
|
||||||
|
godot_string_name src = NativeValue;
|
||||||
|
NativeFuncs.godotsharp_string_name_as_string(&dest, &src);
|
||||||
|
using (dest)
|
||||||
|
return Marshaling.mono_string_from_godot(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty()
|
public bool IsEmpty => godot_string_name.IsEmpty(in NativeValue);
|
||||||
{
|
|
||||||
return ptr == IntPtr.Zero || godot_icall_StringName_is_empty(GetPtr(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern IntPtr godot_icall_StringName_Ctor(string path);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern void godot_icall_StringName_Dtor(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern string godot_icall_StringName_operator_String(IntPtr ptr);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
private static extern bool godot_icall_StringName_is_empty(IntPtr ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,22 @@
|
||||||
<OutputPath>bin/$(Configuration)</OutputPath>
|
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<RootNamespace>Godot</RootNamespace>
|
<RootNamespace>Godot</RootNamespace>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||||
<EnableDefaultItems>false</EnableDefaultItems>
|
<EnableDefaultItems>false</EnableDefaultItems>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
|
||||||
|
<!-- Disabled temporarily as it pollutes the warnings, but we need to document public APIs. -->
|
||||||
|
<NoWarn>CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
|
||||||
|
<!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Core\AABB.cs" />
|
<Compile Include="Core\AABB.cs" />
|
||||||
<Compile Include="Core\Array.cs" />
|
<Compile Include="Core\Array.cs" />
|
||||||
|
@ -23,6 +32,10 @@
|
||||||
<Compile Include="Core\Attributes\SignalAttribute.cs" />
|
<Compile Include="Core\Attributes\SignalAttribute.cs" />
|
||||||
<Compile Include="Core\Attributes\ToolAttribute.cs" />
|
<Compile Include="Core\Attributes\ToolAttribute.cs" />
|
||||||
<Compile Include="Core\Basis.cs" />
|
<Compile Include="Core\Basis.cs" />
|
||||||
|
<Compile Include="Core\Bridge\CSharpInstanceBridge.cs" />
|
||||||
|
<Compile Include="Core\Bridge\GCHandleBridge.cs" />
|
||||||
|
<Compile Include="Core\Bridge\ManagedCallbacks.cs" />
|
||||||
|
<Compile Include="Core\Bridge\ScriptManagerBridge.cs" />
|
||||||
<Compile Include="Core\Callable.cs" />
|
<Compile Include="Core\Callable.cs" />
|
||||||
<Compile Include="Core\Color.cs" />
|
<Compile Include="Core\Color.cs" />
|
||||||
<Compile Include="Core\Colors.cs" />
|
<Compile Include="Core\Colors.cs" />
|
||||||
|
@ -30,7 +43,6 @@
|
||||||
<Compile Include="Core\DelegateUtils.cs" />
|
<Compile Include="Core\DelegateUtils.cs" />
|
||||||
<Compile Include="Core\Dictionary.cs" />
|
<Compile Include="Core\Dictionary.cs" />
|
||||||
<Compile Include="Core\Dispatcher.cs" />
|
<Compile Include="Core\Dispatcher.cs" />
|
||||||
<Compile Include="Core\DynamicObject.cs" />
|
|
||||||
<Compile Include="Core\Extensions\NodeExtensions.cs" />
|
<Compile Include="Core\Extensions\NodeExtensions.cs" />
|
||||||
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
|
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
|
||||||
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
|
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
|
||||||
|
@ -44,16 +56,24 @@
|
||||||
<Compile Include="Core\Interfaces\IAwaitable.cs" />
|
<Compile Include="Core\Interfaces\IAwaitable.cs" />
|
||||||
<Compile Include="Core\Interfaces\IAwaiter.cs" />
|
<Compile Include="Core\Interfaces\IAwaiter.cs" />
|
||||||
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
|
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
|
||||||
<Compile Include="Core\MarshalUtils.cs" />
|
|
||||||
<Compile Include="Core\Mathf.cs" />
|
<Compile Include="Core\Mathf.cs" />
|
||||||
<Compile Include="Core\MathfEx.cs" />
|
<Compile Include="Core\MathfEx.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\VariantUtils.cs" />
|
||||||
<Compile Include="Core\NodePath.cs" />
|
<Compile Include="Core\NodePath.cs" />
|
||||||
<Compile Include="Core\Object.base.cs" />
|
<Compile Include="Core\Object.base.cs" />
|
||||||
|
<Compile Include="Core\Object.exceptions.cs" />
|
||||||
<Compile Include="Core\Plane.cs" />
|
<Compile Include="Core\Plane.cs" />
|
||||||
<Compile Include="Core\Quaternion.cs" />
|
<Compile Include="Core\Quaternion.cs" />
|
||||||
<Compile Include="Core\Rect2.cs" />
|
<Compile Include="Core\Rect2.cs" />
|
||||||
<Compile Include="Core\Rect2i.cs" />
|
<Compile Include="Core\Rect2i.cs" />
|
||||||
<Compile Include="Core\RID.cs" />
|
<Compile Include="Core\RID.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\NativeFuncs.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\InteropStructs.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\Marshaling.cs" />
|
||||||
<Compile Include="Core\SignalInfo.cs" />
|
<Compile Include="Core\SignalInfo.cs" />
|
||||||
<Compile Include="Core\SignalAwaiter.cs" />
|
<Compile Include="Core\SignalAwaiter.cs" />
|
||||||
<Compile Include="Core\StringExtensions.cs" />
|
<Compile Include="Core\StringExtensions.cs" />
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
</wpf:ResourceDictionary>
|
|
@ -1,3 +1,4 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("GodotSharpEditor")]
|
[assembly: InternalsVisibleTo("GodotSharpEditor")]
|
||||||
|
[assembly: InternalsVisibleTo("GodotPlugins")]
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
<OutputPath>bin/$(Configuration)</OutputPath>
|
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<RootNamespace>Godot</RootNamespace>
|
<RootNamespace>Godot</RootNamespace>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||||
<EnableDefaultItems>false</EnableDefaultItems>
|
<EnableDefaultItems>false</EnableDefaultItems>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
</wpf:ResourceDictionary>
|
|
@ -1,67 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* arguments_vector.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef ARGUMENTS_VECTOR_H
|
|
||||||
#define ARGUMENTS_VECTOR_H
|
|
||||||
|
|
||||||
#include "core/os/memory.h"
|
|
||||||
|
|
||||||
template <typename T, int POOL_SIZE = 5>
|
|
||||||
struct ArgumentsVector {
|
|
||||||
private:
|
|
||||||
T pool[POOL_SIZE];
|
|
||||||
T *_ptr;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
ArgumentsVector() = delete;
|
|
||||||
ArgumentsVector(const ArgumentsVector &) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
T *ptr() { return _ptr; }
|
|
||||||
T &get(int p_idx) { return _ptr[p_idx]; }
|
|
||||||
void set(int p_idx, const T &p_value) { _ptr[p_idx] = p_value; }
|
|
||||||
|
|
||||||
explicit ArgumentsVector(int p_size) :
|
|
||||||
size(p_size) {
|
|
||||||
if (p_size <= POOL_SIZE) {
|
|
||||||
_ptr = pool;
|
|
||||||
} else {
|
|
||||||
_ptr = memnew_arr(T, p_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~ArgumentsVector() {
|
|
||||||
if (size > POOL_SIZE) {
|
|
||||||
memdelete_arr(_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ARGUMENTS_VECTOR_H
|
|
|
@ -1,257 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* base_object_glue.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include "core/object/class_db.h"
|
|
||||||
#include "core/object/ref_counted.h"
|
|
||||||
#include "core/string/string_name.h"
|
|
||||||
|
|
||||||
#include "../csharp_script.h"
|
|
||||||
#include "../mono_gd/gd_mono_cache.h"
|
|
||||||
#include "../mono_gd/gd_mono_class.h"
|
|
||||||
#include "../mono_gd/gd_mono_internals.h"
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
#include "../mono_gd/gd_mono_utils.h"
|
|
||||||
#include "../signal_awaiter_utils.h"
|
|
||||||
#include "arguments_vector.h"
|
|
||||||
|
|
||||||
Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
|
|
||||||
Object *instance = memnew(Object);
|
|
||||||
GDMonoInternals::tie_managed_to_unmanaged(p_obj, instance);
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
CRASH_COND(p_ptr == nullptr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p_ptr->get_script_instance()) {
|
|
||||||
CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance());
|
|
||||||
if (cs_instance) {
|
|
||||||
if (!cs_instance->is_destructing_script_instance()) {
|
|
||||||
cs_instance->mono_object_disposed(p_obj);
|
|
||||||
p_ptr->set_script_instance(nullptr);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *data = CSharpLanguage::get_existing_instance_binding(p_ptr);
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
|
|
||||||
if (script_binding.inited) {
|
|
||||||
MonoGCHandleData &gchandle = script_binding.gchandle;
|
|
||||||
if (!gchandle.is_released()) {
|
|
||||||
CSharpLanguage::release_script_gchandle(p_obj, gchandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
CRASH_COND(p_ptr == nullptr);
|
|
||||||
// This is only called with RefCounted derived classes
|
|
||||||
CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RefCounted *rc = static_cast<RefCounted *>(p_ptr);
|
|
||||||
|
|
||||||
if (rc->get_script_instance()) {
|
|
||||||
CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(rc->get_script_instance());
|
|
||||||
if (cs_instance) {
|
|
||||||
if (!cs_instance->is_destructing_script_instance()) {
|
|
||||||
bool delete_owner;
|
|
||||||
bool remove_script_instance;
|
|
||||||
|
|
||||||
cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);
|
|
||||||
|
|
||||||
if (delete_owner) {
|
|
||||||
memdelete(rc);
|
|
||||||
} else if (remove_script_instance) {
|
|
||||||
rc->set_script_instance(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsafe refcount decrement. The managed instance also counts as a reference.
|
|
||||||
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
|
|
||||||
CSharpLanguage::get_singleton()->pre_unsafe_unreference(rc);
|
|
||||||
if (rc->unreference()) {
|
|
||||||
memdelete(rc);
|
|
||||||
} else {
|
|
||||||
void *data = CSharpLanguage::get_existing_instance_binding(rc);
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
|
|
||||||
if (script_binding.inited) {
|
|
||||||
MonoGCHandleData &gchandle = script_binding.gchandle;
|
|
||||||
if (!gchandle.is_released()) {
|
|
||||||
CSharpLanguage::release_script_gchandle(p_obj, gchandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
|
|
||||||
CSharpInstance *csharp_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance());
|
|
||||||
if (csharp_instance) {
|
|
||||||
csharp_instance->connect_event_signals();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodBind *godot_icall_Object_ClassDB_get_method(StringName *p_type, MonoString *p_method) {
|
|
||||||
StringName type = p_type ? *p_type : StringName();
|
|
||||||
StringName method(GDMonoMarshal::mono_string_to_godot(p_method));
|
|
||||||
return ClassDB::get_method(type, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
|
|
||||||
if (!p_ptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<WeakRef> wref;
|
|
||||||
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
REF r = rc;
|
|
||||||
if (!r.is_valid()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
wref.instantiate();
|
|
||||||
wref->set_ref(r);
|
|
||||||
} else {
|
|
||||||
wref.instantiate();
|
|
||||||
wref->set_obj(p_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GDMonoUtils::unmanaged_get_managed(wref.ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_SignalAwaiter_connect(Object *p_source, StringName *p_signal, Object *p_target, MonoObject *p_awaiter) {
|
|
||||||
StringName signal = p_signal ? *p_signal : StringName();
|
|
||||||
return (int32_t)gd_mono_connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
|
|
||||||
List<PropertyInfo> property_list;
|
|
||||||
p_ptr->get_property_list(&property_list);
|
|
||||||
|
|
||||||
MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (const PropertyInfo &E : property_list) {
|
|
||||||
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E.name);
|
|
||||||
mono_array_setref(result, i, boxed);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result) {
|
|
||||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
|
||||||
|
|
||||||
int argc = mono_array_length(p_args);
|
|
||||||
|
|
||||||
ArgumentsVector<Variant> arg_store(argc);
|
|
||||||
ArgumentsVector<const Variant *> args(argc);
|
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_args, MonoObject *, i);
|
|
||||||
arg_store.set(i, GDMonoMarshal::mono_object_to_variant(elem));
|
|
||||||
args.set(i, &arg_store.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
Callable::CallError error;
|
|
||||||
Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
|
|
||||||
|
|
||||||
*r_result = GDMonoMarshal::variant_to_mono_object(result);
|
|
||||||
|
|
||||||
return error.error == Callable::CallError::CALL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
|
|
||||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
|
||||||
|
|
||||||
bool valid;
|
|
||||||
Variant value = p_ptr->get(StringName(name), &valid);
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
*r_result = GDMonoMarshal::variant_to_mono_object(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value) {
|
|
||||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
|
||||||
Variant value = GDMonoMarshal::mono_object_to_variant(p_value);
|
|
||||||
|
|
||||||
bool valid;
|
|
||||||
p_ptr->set(StringName(name), value, &valid);
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_Object_ToString(Object *p_ptr) {
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
// Cannot happen in C#; would get an ObjectDisposedException instead.
|
|
||||||
CRASH_COND(p_ptr == nullptr);
|
|
||||||
#endif
|
|
||||||
// Can't call 'Object::to_string()' here, as that can end up calling 'ToString' again resulting in an endless circular loop.
|
|
||||||
String result = "[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]";
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_register_object_icalls() {
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Ctor", godot_icall_Object_Ctor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Disposed", godot_icall_Object_Disposed);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_RefCounted_Disposed", godot_icall_RefCounted_Disposed);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ConnectEventSignals", godot_icall_Object_ConnectEventSignals);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", godot_icall_Object_ClassDB_get_method);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ToString", godot_icall_Object_ToString);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_weakref", godot_icall_Object_weakref);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", godot_icall_SignalAwaiter_connect);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", godot_icall_DynamicGodotObject_SetMemberList);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_InvokeMember", godot_icall_DynamicGodotObject_InvokeMember);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", godot_icall_DynamicGodotObject_GetMember);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", godot_icall_DynamicGodotObject_SetMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
|
@ -1,369 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* collections_glue.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include <mono/metadata/exception.h>
|
|
||||||
|
|
||||||
#include "core/variant/array.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_cache.h"
|
|
||||||
#include "../mono_gd/gd_mono_class.h"
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
#include "../mono_gd/gd_mono_utils.h"
|
|
||||||
|
|
||||||
Array *godot_icall_Array_Ctor() {
|
|
||||||
return memnew(Array);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_Dtor(Array *ptr) {
|
|
||||||
memdelete(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_Array_At(Array *ptr, int32_t index) {
|
|
||||||
if (index < 0 || index >= ptr->size()) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_Array_At_Generic(Array *ptr, int32_t index, uint32_t type_encoding, GDMonoClass *type_class) {
|
|
||||||
if (index < 0 || index >= ptr->size()) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) {
|
|
||||||
if (index < 0 || index >= ptr->size()) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr->operator[](index) = GDMonoMarshal::mono_object_to_variant(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Array_Count(Array *ptr) {
|
|
||||||
return ptr->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Array_Add(Array *ptr, MonoObject *item) {
|
|
||||||
ptr->append(GDMonoMarshal::mono_object_to_variant(item));
|
|
||||||
return ptr->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_Clear(Array *ptr) {
|
|
||||||
ptr->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
|
|
||||||
return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index) {
|
|
||||||
unsigned int count = ptr->size();
|
|
||||||
|
|
||||||
if (mono_array_length(array) < (array_index + count)) {
|
|
||||||
MonoException *exc = mono_get_exception_argument("", "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
|
||||||
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(ptr->operator[](i));
|
|
||||||
mono_array_setref(array, array_index, boxed);
|
|
||||||
array_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) {
|
|
||||||
Array *godot_array = memnew(Array);
|
|
||||||
unsigned int count = mono_array_length(mono_array);
|
|
||||||
godot_array->resize(count);
|
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
|
||||||
MonoObject *item = mono_array_get(mono_array, MonoObject *, i);
|
|
||||||
godot_icall_Array_SetAt(godot_array, i, item);
|
|
||||||
}
|
|
||||||
return godot_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) {
|
|
||||||
return memnew(Array(ptr->duplicate(deep)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Array *godot_icall_Array_Concatenate(Array *left, Array *right) {
|
|
||||||
int count = left->size() + right->size();
|
|
||||||
Array *new_array = memnew(Array(left->duplicate(false)));
|
|
||||||
new_array->resize(count);
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)right->size(); i++) {
|
|
||||||
new_array->operator[](i + left->size()) = right->operator[](i);
|
|
||||||
}
|
|
||||||
return new_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
|
|
||||||
return ptr->find(GDMonoMarshal::mono_object_to_variant(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_Insert(Array *ptr, int32_t index, MonoObject *item) {
|
|
||||||
if (index < 0 || index > ptr->size()) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
|
|
||||||
int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
|
|
||||||
if (idx >= 0) {
|
|
||||||
ptr->remove(idx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_RemoveAt(Array *ptr, int32_t index) {
|
|
||||||
if (index < 0 || index >= ptr->size()) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr->remove(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Array_Resize(Array *ptr, int32_t new_size) {
|
|
||||||
return (int32_t)ptr->resize(new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_Shuffle(Array *ptr) {
|
|
||||||
ptr->shuffle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
|
|
||||||
MonoType *elem_type = mono_reflection_type_get_type(refltype);
|
|
||||||
|
|
||||||
*type_encoding = mono_type_get_type(elem_type);
|
|
||||||
MonoClass *type_class_raw = mono_class_from_mono_type(elem_type);
|
|
||||||
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_Array_ToString(Array *ptr) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary *godot_icall_Dictionary_Ctor() {
|
|
||||||
return memnew(Dictionary);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_Dtor(Dictionary *ptr) {
|
|
||||||
memdelete(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
|
|
||||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
if (ret == nullptr) {
|
|
||||||
MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
CRASH_COND(!exc);
|
|
||||||
#endif
|
|
||||||
GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
|
|
||||||
GDMonoUtils::set_pending_exception((MonoException *)exc);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) {
|
|
||||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
if (ret == nullptr) {
|
|
||||||
MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
CRASH_COND(!exc);
|
|
||||||
#endif
|
|
||||||
GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
|
|
||||||
GDMonoUtils::set_pending_exception((MonoException *)exc);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
|
||||||
ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array *godot_icall_Dictionary_Keys(Dictionary *ptr) {
|
|
||||||
return memnew(Array(ptr->keys()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
|
|
||||||
return memnew(Array(ptr->values()));
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
|
|
||||||
return ptr->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) {
|
|
||||||
*keys = godot_icall_Dictionary_Keys(ptr);
|
|
||||||
*values = godot_icall_Dictionary_Values(ptr);
|
|
||||||
return godot_icall_Dictionary_Count(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) {
|
|
||||||
Array *keys = godot_icall_Dictionary_Keys(ptr);
|
|
||||||
Array *values = godot_icall_Dictionary_Values(ptr);
|
|
||||||
*key = GDMonoMarshal::variant_to_mono_object(keys->get(index));
|
|
||||||
*value = GDMonoMarshal::variant_to_mono_object(values->get(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
|
||||||
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
|
|
||||||
Variant *ret = ptr->getptr(varKey);
|
|
||||||
if (ret != nullptr) {
|
|
||||||
GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr->operator[](varKey) = GDMonoMarshal::mono_object_to_variant(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_Clear(Dictionary *ptr) {
|
|
||||||
ptr->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
|
||||||
// no dupes
|
|
||||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
return ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
|
|
||||||
return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep) {
|
|
||||||
return memnew(Dictionary(ptr->duplicate(deep)));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
|
|
||||||
return ptr->erase(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
|
||||||
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
|
|
||||||
|
|
||||||
// no dupes
|
|
||||||
Variant *ret = ptr->getptr(varKey);
|
|
||||||
if (ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value)) {
|
|
||||||
ptr->erase(varKey);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
|
|
||||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
if (ret == nullptr) {
|
|
||||||
*value = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*value = GDMonoMarshal::variant_to_mono_object(ret);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
|
|
||||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
|
||||||
if (ret == nullptr) {
|
|
||||||
*value = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
|
|
||||||
MonoType *value_type = mono_reflection_type_get_type(refltype);
|
|
||||||
|
|
||||||
*type_encoding = mono_type_get_type(value_type);
|
|
||||||
MonoClass *type_class_raw = mono_class_from_mono_type(value_type);
|
|
||||||
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_register_collections_icalls() {
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", godot_icall_Array_Ctor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", godot_icall_Array_Ctor_MonoArray);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", godot_icall_Array_Dtor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At", godot_icall_Array_At);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", godot_icall_Array_At_Generic);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", godot_icall_Array_SetAt);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", godot_icall_Array_Count);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", godot_icall_Array_Add);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", godot_icall_Array_Clear);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Concatenate", godot_icall_Array_Concatenate);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", godot_icall_Array_Contains);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", godot_icall_Array_CopyTo);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", godot_icall_Array_Duplicate);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", godot_icall_Array_IndexOf);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", godot_icall_Array_Insert);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", godot_icall_Array_Remove);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", godot_icall_Array_RemoveAt);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", godot_icall_Array_Resize);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Shuffle", godot_icall_Array_Shuffle);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", godot_icall_Array_Generic_GetElementTypeInfo);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", godot_icall_Array_ToString);
|
|
||||||
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", godot_icall_Dictionary_Ctor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", godot_icall_Dictionary_Dtor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", godot_icall_Dictionary_GetValue);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue_Generic", godot_icall_Dictionary_GetValue_Generic);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", godot_icall_Dictionary_SetValue);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", godot_icall_Dictionary_ContainsKey);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Duplicate", godot_icall_Dictionary_Duplicate);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", godot_icall_Dictionary_RemoveKey);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", godot_icall_Dictionary_Remove);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", godot_icall_Dictionary_TryGetValue);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue_Generic", godot_icall_Dictionary_TryGetValue_Generic);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Generic_GetValueTypeInfo", godot_icall_Dictionary_Generic_GetValueTypeInfo);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", godot_icall_Dictionary_ToString);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
|
@ -1,321 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* gd_glue.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include "core/io/marshalls.h"
|
|
||||||
#include "core/os/os.h"
|
|
||||||
#include "core/string/ustring.h"
|
|
||||||
#include "core/variant/array.h"
|
|
||||||
#include "core/variant/variant.h"
|
|
||||||
#include "core/variant/variant_parser.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_cache.h"
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
#include "../mono_gd/gd_mono_utils.h"
|
|
||||||
|
|
||||||
MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) {
|
|
||||||
Variant ret;
|
|
||||||
PackedByteArray varr = GDMonoMarshal::mono_array_to_PackedByteArray(p_bytes);
|
|
||||||
Error err = decode_variant(ret, varr.ptr(), varr.size(), nullptr, p_allow_objects);
|
|
||||||
if (err != OK) {
|
|
||||||
ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
|
|
||||||
}
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) {
|
|
||||||
Variant what = GDMonoMarshal::mono_object_to_variant(p_what);
|
|
||||||
const Variant *args[1] = { &what };
|
|
||||||
Callable::CallError ce;
|
|
||||||
Variant ret;
|
|
||||||
Variant::construct(Variant::Type(p_type), ret, args, 1, ce);
|
|
||||||
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
int godot_icall_GD_hash(MonoObject *p_var) {
|
|
||||||
return GDMonoMarshal::mono_object_to_variant(p_var).hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) {
|
|
||||||
return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(ObjectID(p_instance_id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_print(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
int length = mono_array_length(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
|
||||||
|
|
||||||
MonoException *exc = nullptr;
|
|
||||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
str += elem_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_line(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_printerr(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
int length = mono_array_length(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
|
||||||
|
|
||||||
MonoException *exc = nullptr;
|
|
||||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
str += elem_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_error(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_printraw(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
int length = mono_array_length(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
|
||||||
|
|
||||||
MonoException *exc = nullptr;
|
|
||||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
str += elem_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS::get_singleton()->print("%s", str.utf8().get_data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_prints(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
int length = mono_array_length(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
|
||||||
|
|
||||||
MonoException *exc = nullptr;
|
|
||||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i) {
|
|
||||||
str += " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
str += elem_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_line(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_printt(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
int length = mono_array_length(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
|
||||||
|
|
||||||
MonoException *exc = nullptr;
|
|
||||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
|
||||||
|
|
||||||
if (exc) {
|
|
||||||
GDMonoUtils::set_pending_exception(exc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i) {
|
|
||||||
str += "\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
str += elem_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_line(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
float godot_icall_GD_randf() {
|
|
||||||
return Math::randf();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t godot_icall_GD_randi() {
|
|
||||||
return Math::rand();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_randomize() {
|
|
||||||
Math::randomize();
|
|
||||||
}
|
|
||||||
|
|
||||||
double godot_icall_GD_randf_range(double from, double to) {
|
|
||||||
return Math::random(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_GD_randi_range(int32_t from, int32_t to) {
|
|
||||||
return Math::random(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed) {
|
|
||||||
uint32_t ret = Math::rand_from_seed(&seed);
|
|
||||||
*newSeed = seed;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_seed(uint64_t p_seed) {
|
|
||||||
Math::seed(p_seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GD_str(MonoArray *p_what) {
|
|
||||||
String str;
|
|
||||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
|
||||||
|
|
||||||
for (int i = 0; i < what.size(); i++) {
|
|
||||||
String os = what[i].operator String();
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
str = os;
|
|
||||||
} else {
|
|
||||||
str += os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_GD_str2var(MonoString *p_str) {
|
|
||||||
Variant ret;
|
|
||||||
|
|
||||||
VariantParser::StreamString ss;
|
|
||||||
ss.s = GDMonoMarshal::mono_string_to_godot(p_str);
|
|
||||||
|
|
||||||
String errs;
|
|
||||||
int line;
|
|
||||||
Error err = VariantParser::parse(&ss, ret, errs, line);
|
|
||||||
if (err != OK) {
|
|
||||||
String err_str = "Parse error at line " + itos(line) + ": " + errs + ".";
|
|
||||||
ERR_PRINT(err_str);
|
|
||||||
ret = err_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_GD_type_exists(StringName *p_type) {
|
|
||||||
StringName type = p_type ? *p_type : StringName();
|
|
||||||
return ClassDB::class_exists(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_pusherror(MonoString *p_str) {
|
|
||||||
ERR_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_GD_pushwarning(MonoString *p_str) {
|
|
||||||
WARN_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects) {
|
|
||||||
Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
|
|
||||||
|
|
||||||
PackedByteArray barr;
|
|
||||||
int len;
|
|
||||||
Error err = encode_variant(var, nullptr, len, p_full_objects);
|
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
|
|
||||||
|
|
||||||
barr.resize(len);
|
|
||||||
encode_variant(var, barr.ptrw(), len, p_full_objects);
|
|
||||||
|
|
||||||
return GDMonoMarshal::PackedByteArray_to_mono_array(barr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_GD_var2str(MonoObject *p_var) {
|
|
||||||
String vars;
|
|
||||||
VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars);
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t godot_icall_TypeToVariantType(MonoReflectionType *p_refl_type) {
|
|
||||||
return (uint32_t)GDMonoMarshal::managed_to_variant_type(ManagedType::from_reftype(p_refl_type));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoObject *godot_icall_DefaultGodotTaskScheduler() {
|
|
||||||
return GDMonoCache::cached_data.task_scheduler_handle->get_target();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_register_gd_icalls() {
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_bytes2var", godot_icall_GD_bytes2var);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_convert", godot_icall_GD_convert);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_hash", godot_icall_GD_hash);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_instance_from_id", godot_icall_GD_instance_from_id);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pusherror", godot_icall_GD_pusherror);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pushwarning", godot_icall_GD_pushwarning);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print", godot_icall_GD_print);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printerr", godot_icall_GD_printerr);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printt", godot_icall_GD_printt);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf", godot_icall_GD_randf);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi", godot_icall_GD_randi);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randomize", godot_icall_GD_randomize);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf_range", godot_icall_GD_randf_range);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi_range", godot_icall_GD_randi_range);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_rand_seed", godot_icall_GD_rand_seed);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_seed", godot_icall_GD_seed);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str", godot_icall_GD_str);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str2var", godot_icall_GD_str2var);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_type_exists", godot_icall_GD_type_exists);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2bytes", godot_icall_GD_var2bytes);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2str", godot_icall_GD_var2str);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_TypeToVariantType", godot_icall_TypeToVariantType);
|
|
||||||
|
|
||||||
// Dispatcher
|
|
||||||
GDMonoUtils::add_internal_call("Godot.Dispatcher::godot_icall_DefaultGodotTaskScheduler", godot_icall_DefaultGodotTaskScheduler);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* glue_header.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
|
|
||||||
void godot_register_collections_icalls();
|
|
||||||
void godot_register_gd_icalls();
|
|
||||||
void godot_register_string_name_icalls();
|
|
||||||
void godot_register_nodepath_icalls();
|
|
||||||
void godot_register_object_icalls();
|
|
||||||
void godot_register_rid_icalls();
|
|
||||||
void godot_register_string_icalls();
|
|
||||||
void godot_register_scene_tree_icalls();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers internal calls that were not generated. This function is called
|
|
||||||
* from the generated GodotSharpBindings::register_generated_icalls() function.
|
|
||||||
*/
|
|
||||||
void godot_register_glue_header_icalls() {
|
|
||||||
godot_register_collections_icalls();
|
|
||||||
godot_register_gd_icalls();
|
|
||||||
godot_register_string_name_icalls();
|
|
||||||
godot_register_nodepath_icalls();
|
|
||||||
godot_register_object_icalls();
|
|
||||||
godot_register_rid_icalls();
|
|
||||||
godot_register_string_icalls();
|
|
||||||
godot_register_scene_tree_icalls();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by the generated glue
|
|
||||||
|
|
||||||
#include "core/config/engine.h"
|
|
||||||
#include "core/object/class_db.h"
|
|
||||||
#include "core/object/method_bind.h"
|
|
||||||
#include "core/object/ref_counted.h"
|
|
||||||
#include "core/string/node_path.h"
|
|
||||||
#include "core/string/ustring.h"
|
|
||||||
#include "core/typedefs.h"
|
|
||||||
#include "core/variant/array.h"
|
|
||||||
#include "core/variant/dictionary.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_class.h"
|
|
||||||
#include "../mono_gd/gd_mono_internals.h"
|
|
||||||
#include "../mono_gd/gd_mono_utils.h"
|
|
||||||
|
|
||||||
#define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \
|
|
||||||
static ClassDB::ClassInfo *ci = nullptr; \
|
|
||||||
if (!ci) { \
|
|
||||||
ci = ClassDB::classes.getptr(m_type); \
|
|
||||||
} \
|
|
||||||
Object *m_instance = ci->creation_func();
|
|
||||||
|
|
||||||
#include "arguments_vector.h"
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* nodepath_glue.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include "core/string/node_path.h"
|
|
||||||
#include "core/string/ustring.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
|
|
||||||
NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) {
|
|
||||||
return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_NodePath_Dtor(NodePath *p_ptr) {
|
|
||||||
ERR_FAIL_NULL(p_ptr);
|
|
||||||
memdelete(p_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) {
|
|
||||||
return (MonoBoolean)p_ptr->is_absolute();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) {
|
|
||||||
return p_ptr->get_name_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) {
|
|
||||||
return p_ptr->get_subname_count();
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
|
|
||||||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
|
|
||||||
}
|
|
||||||
|
|
||||||
NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) {
|
|
||||||
return memnew(NodePath(p_ptr->get_as_property_path()));
|
|
||||||
}
|
|
||||||
|
|
||||||
MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) {
|
|
||||||
return (MonoBoolean)p_ptr->is_empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_register_nodepath_icalls() {
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Ctor", godot_icall_NodePath_Ctor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname", godot_icall_NodePath_get_subname);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname_count", godot_icall_NodePath_get_subname_count);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_absolute", godot_icall_NodePath_is_absolute);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_empty", godot_icall_NodePath_is_empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* rid_glue.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef MONO_GLUE_ENABLED
|
|
||||||
|
|
||||||
#include "core/io/resource.h"
|
|
||||||
#include "core/object/class_db.h"
|
|
||||||
#include "core/templates/rid.h"
|
|
||||||
|
|
||||||
#include "../mono_gd/gd_mono_marshal.h"
|
|
||||||
|
|
||||||
RID *godot_icall_RID_Ctor(Object *p_from) {
|
|
||||||
Resource *res_from = Object::cast_to<Resource>(p_from);
|
|
||||||
|
|
||||||
if (res_from) {
|
|
||||||
return memnew(RID(res_from->get_rid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return memnew(RID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_icall_RID_Dtor(RID *p_ptr) {
|
|
||||||
ERR_FAIL_NULL(p_ptr);
|
|
||||||
memdelete(p_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t godot_icall_RID_get_id(RID *p_ptr) {
|
|
||||||
return p_ptr->get_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
void godot_register_rid_icalls() {
|
|
||||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Ctor", godot_icall_RID_Ctor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Dtor", godot_icall_RID_Dtor);
|
|
||||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_get_id", godot_icall_RID_get_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MONO_GLUE_ENABLED
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue