feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ common_win = [
|
|||
"gl_manager_windows_angle.cpp",
|
||||
"wgl_detect_version.cpp",
|
||||
"rendering_context_driver_vulkan_windows.cpp",
|
||||
"drop_target_windows.cpp",
|
||||
]
|
||||
|
||||
if env.msvc:
|
||||
|
|
@ -58,6 +60,9 @@ sources += res_obj
|
|||
prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"])
|
||||
arrange_program_clean(prog)
|
||||
|
||||
if env.msvc:
|
||||
env.Depends(prog, "godot.natvis")
|
||||
|
||||
# Build console wrapper app.
|
||||
if env["windows_subsystem"] == "gui":
|
||||
env_wrap = env.Clone()
|
||||
|
|
@ -78,16 +83,6 @@ if env["windows_subsystem"] == "gui":
|
|||
env_wrap.Depends(prog_wrap, prog)
|
||||
sources += common_win_wrap + res_wrap_obj
|
||||
|
||||
# Microsoft Visual Studio Project Generation
|
||||
if env["vsproj"]:
|
||||
env.vs_srcs += ["platform/windows/" + res_file]
|
||||
env.vs_srcs += ["platform/windows/godot.natvis"]
|
||||
for x in common_win:
|
||||
env.vs_srcs += ["platform/windows/" + str(x)]
|
||||
if env["windows_subsystem"] == "gui":
|
||||
for x in common_win_wrap:
|
||||
env.vs_srcs += ["platform/windows/" + str(x)]
|
||||
|
||||
if env["d3d12"]:
|
||||
dxc_target_aliases = {
|
||||
"x86_32": "x86",
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Get executable name.
|
||||
WCHAR exe_name[MAX_PATH] = {};
|
||||
if (!GetModuleFileNameW(nullptr, exe_name, MAX_PATH)) {
|
||||
WCHAR exe_name[32767] = {};
|
||||
if (!GetModuleFileNameW(nullptr, exe_name, 32767)) {
|
||||
wprintf(L"GetModuleFileName failed, error %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -65,7 +65,9 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// Enable virtual terminal sequences processing.
|
||||
HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD out_mode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
DWORD out_mode = 0;
|
||||
GetConsoleMode(stdout_handle, &out_mode);
|
||||
out_mode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode(stdout_handle, out_mode);
|
||||
|
||||
// Find main executable name and check if it exist.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public:
|
|||
void initialize();
|
||||
|
||||
void disable();
|
||||
bool is_disabled() const { return disabled; };
|
||||
bool is_disabled() const { return disabled; }
|
||||
|
||||
CrashHandler();
|
||||
~CrashHandler();
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
|
|||
HANDLE process = GetCurrentProcess();
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
DWORD offset_from_symbol = 0;
|
||||
IMAGEHLP_LINE64 line = { 0 };
|
||||
IMAGEHLP_LINE64 line = {};
|
||||
std::vector<module_data> modules;
|
||||
DWORD cbNeeded;
|
||||
std::vector<HMODULE> module_handles(1);
|
||||
|
|
|
|||
|
|
@ -159,12 +159,18 @@ extern void CrashHandlerException(int signal) {
|
|||
|
||||
// Load process and image info to determine ASLR addresses offset.
|
||||
MODULEINFO mi;
|
||||
GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &mi, sizeof(mi));
|
||||
GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &mi, sizeof(mi));
|
||||
int64_t image_mem_base = reinterpret_cast<int64_t>(mi.lpBaseOfDll);
|
||||
int64_t image_file_base = get_image_base(_execpath);
|
||||
data.offset = image_mem_base - image_file_base;
|
||||
|
||||
data.state = backtrace_create_state(_execpath.utf8().get_data(), 0, &error_callback, reinterpret_cast<void *>(&data));
|
||||
if (FileAccess::exists(_execpath + ".debugsymbols")) {
|
||||
_execpath = _execpath + ".debugsymbols";
|
||||
}
|
||||
_execpath = _execpath.replace("/", "\\");
|
||||
|
||||
CharString cs = _execpath.utf8(); // Note: should remain in scope during backtrace_simple call.
|
||||
data.state = backtrace_create_state(cs.get_data(), 0, &error_callback, reinterpret_cast<void *>(&data));
|
||||
if (data.state != nullptr) {
|
||||
data.index = 1;
|
||||
backtrace_simple(data.state, 1, &trace_callback, &error_callback, reinterpret_cast<void *>(&data));
|
||||
|
|
|
|||
|
|
@ -6,47 +6,40 @@ from typing import TYPE_CHECKING
|
|||
|
||||
import methods
|
||||
from methods import print_error, print_warning
|
||||
from platform_methods import detect_arch
|
||||
from platform_methods import detect_arch, validate_arch
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from SCons.Script.SConscript import SConsEnvironment
|
||||
|
||||
# To match other platforms
|
||||
STACK_SIZE = 8388608
|
||||
STACK_SIZE_SANITIZERS = 30 * 1024 * 1024
|
||||
|
||||
|
||||
def get_name():
|
||||
return "Windows"
|
||||
|
||||
|
||||
def try_cmd(test, prefix, arch):
|
||||
def try_cmd(test, prefix, arch, check_clang=False):
|
||||
archs = ["x86_64", "x86_32", "arm64", "arm32"]
|
||||
if arch:
|
||||
archs = [arch]
|
||||
|
||||
for a in archs:
|
||||
try:
|
||||
out = subprocess.Popen(
|
||||
get_mingw_bin_prefix(prefix, arch) + test,
|
||||
get_mingw_bin_prefix(prefix, a) + test,
|
||||
shell=True,
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
out.communicate()
|
||||
outs, errs = out.communicate()
|
||||
if out.returncode == 0:
|
||||
if check_clang and not outs.startswith(b"clang"):
|
||||
return False
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
for a in ["x86_64", "x86_32", "arm64", "arm32"]:
|
||||
try:
|
||||
out = subprocess.Popen(
|
||||
get_mingw_bin_prefix(prefix, a) + test,
|
||||
shell=True,
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
out.communicate()
|
||||
if out.returncode == 0:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
|
@ -75,23 +68,23 @@ def can_build():
|
|||
|
||||
|
||||
def get_mingw_bin_prefix(prefix, arch):
|
||||
if not prefix:
|
||||
mingw_bin_prefix = ""
|
||||
elif prefix[-1] != "/":
|
||||
mingw_bin_prefix = prefix + "/bin/"
|
||||
else:
|
||||
mingw_bin_prefix = prefix + "bin/"
|
||||
bin_prefix = (os.path.normpath(os.path.join(prefix, "bin")) + os.sep) if prefix else ""
|
||||
ARCH_PREFIXES = {
|
||||
"x86_64": "x86_64-w64-mingw32-",
|
||||
"x86_32": "i686-w64-mingw32-",
|
||||
"arm32": "armv7-w64-mingw32-",
|
||||
"arm64": "aarch64-w64-mingw32-",
|
||||
}
|
||||
arch_prefix = ARCH_PREFIXES[arch] if arch else ""
|
||||
return bin_prefix + arch_prefix
|
||||
|
||||
if arch == "x86_64":
|
||||
mingw_bin_prefix += "x86_64-w64-mingw32-"
|
||||
elif arch == "x86_32":
|
||||
mingw_bin_prefix += "i686-w64-mingw32-"
|
||||
elif arch == "arm32":
|
||||
mingw_bin_prefix += "armv7-w64-mingw32-"
|
||||
elif arch == "arm64":
|
||||
mingw_bin_prefix += "aarch64-w64-mingw32-"
|
||||
|
||||
return mingw_bin_prefix
|
||||
def get_detected(env: "SConsEnvironment", tool: str) -> str:
|
||||
checks = [
|
||||
get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) + tool,
|
||||
get_mingw_bin_prefix(env["mingw_prefix"], "") + tool,
|
||||
]
|
||||
return str(env.Detect(checks))
|
||||
|
||||
|
||||
def detect_build_env_arch():
|
||||
|
|
@ -162,6 +155,13 @@ def detect_build_env_arch():
|
|||
return ""
|
||||
|
||||
|
||||
def get_tools(env: "SConsEnvironment"):
|
||||
if os.name != "nt" or env["use_mingw"]:
|
||||
return ["mingw"]
|
||||
else:
|
||||
return ["default"]
|
||||
|
||||
|
||||
def get_opts():
|
||||
from SCons.Variables import BoolVariable, EnumVariable
|
||||
|
||||
|
|
@ -203,6 +203,7 @@ def get_opts():
|
|||
BoolVariable("use_llvm", "Use the LLVM compiler", False),
|
||||
BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
|
||||
BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
|
||||
BoolVariable("use_ubsan", "Use LLVM compiler undefined behavior sanitizer (UBSAN)", False),
|
||||
BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False),
|
||||
BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False),
|
||||
BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting any errors to stderr.", True),
|
||||
|
|
@ -247,45 +248,10 @@ def get_flags():
|
|||
|
||||
return {
|
||||
"arch": arch,
|
||||
"supported": ["mono"],
|
||||
"supported": ["d3d12", "mono", "xaudio2"],
|
||||
}
|
||||
|
||||
|
||||
def build_res_file(target, source, env: "SConsEnvironment"):
|
||||
arch_aliases = {
|
||||
"x86_32": "pe-i386",
|
||||
"x86_64": "pe-x86-64",
|
||||
"arm32": "armv7-w64-mingw32",
|
||||
"arm64": "aarch64-w64-mingw32",
|
||||
}
|
||||
cmdbase = "windres --include-dir . --target=" + arch_aliases[env["arch"]]
|
||||
|
||||
mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
|
||||
|
||||
for x in range(len(source)):
|
||||
ok = True
|
||||
# Try prefixed executable (MinGW on Linux).
|
||||
cmd = mingw_bin_prefix + cmdbase + " -i " + str(source[x]) + " -o " + str(target[x])
|
||||
try:
|
||||
out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
|
||||
if len(out[1]):
|
||||
ok = False
|
||||
except Exception:
|
||||
ok = False
|
||||
|
||||
# Try generic executable (MSYS2).
|
||||
if not ok:
|
||||
cmd = cmdbase + " -i " + str(source[x]) + " -o " + str(target[x])
|
||||
try:
|
||||
out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
|
||||
if len(out[1]):
|
||||
return -1
|
||||
except Exception:
|
||||
return -1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def setup_msvc_manual(env: "SConsEnvironment"):
|
||||
"""Running from VCVARS environment"""
|
||||
|
||||
|
|
@ -387,7 +353,19 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
|
||||
## Compile/link flags
|
||||
|
||||
env["MAXLINELENGTH"] = 8192 # Windows Vista and beyond, so always applicable.
|
||||
if env["use_llvm"]:
|
||||
env["CC"] = "clang-cl"
|
||||
env["CXX"] = "clang-cl"
|
||||
env["LINK"] = "lld-link"
|
||||
env["AR"] = "llvm-lib"
|
||||
|
||||
env.AppendUnique(CPPDEFINES=["R128_STDC_ONLY"])
|
||||
env.extra_suffix = ".llvm" + env.extra_suffix
|
||||
|
||||
# Ensure intellisense tools like `compile_commands.json` play nice with MSVC syntax.
|
||||
env["CPPDEFPREFIX"] = "-D"
|
||||
env["INCPREFIX"] = "-I"
|
||||
env.AppendUnique(CPPDEFINES=[("alloca", "_alloca")])
|
||||
|
||||
if env["silence_msvc"] and not env.GetOption("clean"):
|
||||
from tempfile import mkstemp
|
||||
|
|
@ -471,7 +449,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
|
||||
env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
|
||||
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
|
||||
env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++
|
||||
# Once it was thought that only debug builds would be too large,
|
||||
# but this has recently stopped being true. See the mingw function
|
||||
# for notes on why this shouldn't be enabled for gcc
|
||||
|
|
@ -483,9 +460,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
else:
|
||||
print_warning("Missing environment variable: WindowsSdkDir")
|
||||
|
||||
if int(env["target_win_version"], 16) < 0x0601:
|
||||
print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
|
||||
sys.exit(255)
|
||||
validate_win_version(env)
|
||||
|
||||
env.AppendUnique(
|
||||
CPPDEFINES=[
|
||||
|
|
@ -507,6 +482,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
if env["use_asan"]:
|
||||
env.extra_suffix += ".san"
|
||||
prebuilt_lib_extra_suffix = ".san"
|
||||
env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"])
|
||||
env.Append(CCFLAGS=["/fsanitize=address"])
|
||||
env.Append(LINKFLAGS=["/INFERASANLIBS"])
|
||||
|
||||
|
|
@ -548,15 +524,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
LIBS += ["vulkan"]
|
||||
|
||||
if env["d3d12"]:
|
||||
# Check whether we have d3d12 dependencies installed.
|
||||
if not os.path.exists(env["mesa_libs"]):
|
||||
print_error(
|
||||
"The Direct3D 12 rendering driver requires dependencies to be installed.\n"
|
||||
"You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
|
||||
"See the documentation for more information:\n\t"
|
||||
"https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
|
||||
)
|
||||
sys.exit(255)
|
||||
check_d3d12_installed(env)
|
||||
|
||||
env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
|
||||
LIBS += ["dxgi", "dxguid"]
|
||||
|
|
@ -595,6 +563,9 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
if env["target"] in ["editor", "template_debug"]:
|
||||
LIBS += ["psapi", "dbghelp"]
|
||||
|
||||
if env["use_llvm"]:
|
||||
LIBS += [f"clang_rt.builtins-{env['arch']}"]
|
||||
|
||||
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
|
||||
|
||||
if vcvars_msvc_config:
|
||||
|
|
@ -610,14 +581,20 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
|
||||
if env["lto"] != "none":
|
||||
if env["lto"] == "thin":
|
||||
print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
|
||||
sys.exit(255)
|
||||
env.AppendUnique(CCFLAGS=["/GL"])
|
||||
env.AppendUnique(ARFLAGS=["/LTCG"])
|
||||
if not env["use_llvm"]:
|
||||
print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
|
||||
sys.exit(255)
|
||||
|
||||
env.AppendUnique(CCFLAGS=["-flto=thin"])
|
||||
elif env["use_llvm"]:
|
||||
env.AppendUnique(CCFLAGS=["-flto"])
|
||||
else:
|
||||
env.AppendUnique(CCFLAGS=["/GL"])
|
||||
if env["progress"]:
|
||||
env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
|
||||
else:
|
||||
env.AppendUnique(LINKFLAGS=["/LTCG"])
|
||||
env.AppendUnique(ARFLAGS=["/LTCG"])
|
||||
|
||||
if vcvars_msvc_config:
|
||||
env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])
|
||||
|
|
@ -628,7 +605,77 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
|
|||
env["BUILDERS"]["Program"] = methods.precious_program
|
||||
|
||||
env.Append(LINKFLAGS=["/NATVIS:platform\\windows\\godot.natvis"])
|
||||
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
|
||||
|
||||
if env["use_asan"]:
|
||||
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE_SANITIZERS)])
|
||||
else:
|
||||
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
|
||||
|
||||
|
||||
def get_ar_version(env):
|
||||
ret = {
|
||||
"major": -1,
|
||||
"minor": -1,
|
||||
"patch": -1,
|
||||
"is_llvm": False,
|
||||
}
|
||||
try:
|
||||
output = (
|
||||
subprocess.check_output([env.subst(env["AR"]), "--version"], shell=(os.name == "nt"))
|
||||
.strip()
|
||||
.decode("utf-8")
|
||||
)
|
||||
except (subprocess.CalledProcessError, OSError):
|
||||
print_warning("Couldn't check version of `ar`.")
|
||||
return ret
|
||||
|
||||
match = re.search(r"GNU ar(?: \(GNU Binutils\)| version) (\d+)\.(\d+)(?:\.(\d+))?", output)
|
||||
if match:
|
||||
ret["major"] = int(match[1])
|
||||
ret["minor"] = int(match[2])
|
||||
if match[3]:
|
||||
ret["patch"] = int(match[3])
|
||||
else:
|
||||
ret["patch"] = 0
|
||||
return ret
|
||||
|
||||
match = re.search(r"LLVM version (\d+)\.(\d+)\.(\d+)", output)
|
||||
if match:
|
||||
ret["major"] = int(match[1])
|
||||
ret["minor"] = int(match[2])
|
||||
ret["patch"] = int(match[3])
|
||||
ret["is_llvm"] = True
|
||||
return ret
|
||||
|
||||
print_warning("Couldn't parse version of `ar`.")
|
||||
return ret
|
||||
|
||||
|
||||
def get_is_ar_thin_supported(env):
|
||||
"""Check whether `ar --thin` is supported. It is only supported since Binutils 2.38 or LLVM 14."""
|
||||
ar_version = get_ar_version(env)
|
||||
if ar_version["major"] == -1:
|
||||
return False
|
||||
|
||||
if ar_version["is_llvm"]:
|
||||
return ar_version["major"] >= 14
|
||||
|
||||
if ar_version["major"] == 2:
|
||||
return ar_version["minor"] >= 38
|
||||
|
||||
print_warning("Unknown Binutils `ar` version.")
|
||||
return False
|
||||
|
||||
|
||||
WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)")
|
||||
|
||||
|
||||
def tempfile_arg_esc_func(arg):
|
||||
from SCons.Subst import quote_spaces
|
||||
|
||||
arg = quote_spaces(arg)
|
||||
# GCC requires double Windows slashes, let's use UNIX separator
|
||||
return WINPATHSEP_RE.sub(r"/\1", arg)
|
||||
|
||||
|
||||
def configure_mingw(env: "SConsEnvironment"):
|
||||
|
|
@ -636,6 +683,20 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
# https://www.scons.org/wiki/LongCmdLinesOnWin32
|
||||
env.use_windows_spawn_fix()
|
||||
|
||||
# HACK: For some reason, Windows-native shells have their MinGW tools
|
||||
# frequently fail as a result of parsing path separators incorrectly.
|
||||
# For some other reason, this issue is circumvented entirely if the
|
||||
# `mingw_prefix` bin is prepended to PATH.
|
||||
if os.sep == "\\":
|
||||
env.PrependENVPath("PATH", os.path.join(env["mingw_prefix"], "bin"))
|
||||
|
||||
# In case the command line to AR is too long, use a response file.
|
||||
env["ARCOM_ORIG"] = env["ARCOM"]
|
||||
env["ARCOM"] = "${TEMPFILE('$ARCOM_ORIG', '$ARCOMSTR')}"
|
||||
env["TEMPFILESUFFIX"] = ".rsp"
|
||||
if os.name == "nt":
|
||||
env["TEMPFILEARGESCFUNC"] = tempfile_arg_esc_func
|
||||
|
||||
## Build type
|
||||
|
||||
if not env["use_llvm"] and not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]):
|
||||
|
|
@ -644,11 +705,11 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
if env["use_llvm"] and not try_cmd("clang --version", env["mingw_prefix"], env["arch"]):
|
||||
env["use_llvm"] = False
|
||||
|
||||
# TODO: Re-evaluate the need for this / streamline with common config.
|
||||
if env["target"] == "template_release":
|
||||
if env["arch"] != "arm64":
|
||||
env.Append(CCFLAGS=["-msse2"])
|
||||
elif env.dev_build:
|
||||
if not env["use_llvm"] and try_cmd("gcc --version", env["mingw_prefix"], env["arch"], True):
|
||||
print("Detected GCC to be a wrapper for Clang.")
|
||||
env["use_llvm"] = True
|
||||
|
||||
if env.dev_build:
|
||||
# Allow big objects. It's supposed not to have drawbacks but seems to break
|
||||
# GCC LTO, so enabling for debug builds only (which are not built with LTO
|
||||
# and are the only ones with too big objects).
|
||||
|
|
@ -662,9 +723,6 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
|
||||
## Compiler configuration
|
||||
|
||||
if os.name != "nt":
|
||||
env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation
|
||||
|
||||
if env["arch"] == "x86_32":
|
||||
if env["use_static_cpp"]:
|
||||
env.Append(LINKFLAGS=["-static"])
|
||||
|
|
@ -679,33 +737,36 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
|
||||
env.Append(CCFLAGS=["-ffp-contract=off"])
|
||||
|
||||
mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
|
||||
|
||||
if env["use_llvm"]:
|
||||
env["CC"] = mingw_bin_prefix + "clang"
|
||||
env["CXX"] = mingw_bin_prefix + "clang++"
|
||||
if try_cmd("as --version", env["mingw_prefix"], env["arch"]):
|
||||
env["AS"] = mingw_bin_prefix + "as"
|
||||
env.Append(ASFLAGS=["-c"])
|
||||
if try_cmd("ar --version", env["mingw_prefix"], env["arch"]):
|
||||
env["AR"] = mingw_bin_prefix + "ar"
|
||||
if try_cmd("ranlib --version", env["mingw_prefix"], env["arch"]):
|
||||
env["RANLIB"] = mingw_bin_prefix + "ranlib"
|
||||
env["CC"] = get_detected(env, "clang")
|
||||
env["CXX"] = get_detected(env, "clang++")
|
||||
env["AR"] = get_detected(env, "ar")
|
||||
env["RANLIB"] = get_detected(env, "ranlib")
|
||||
env.Append(ASFLAGS=["-c"])
|
||||
env.extra_suffix = ".llvm" + env.extra_suffix
|
||||
else:
|
||||
env["CC"] = mingw_bin_prefix + "gcc"
|
||||
env["CXX"] = mingw_bin_prefix + "g++"
|
||||
if try_cmd("as --version", env["mingw_prefix"], env["arch"]):
|
||||
env["AS"] = mingw_bin_prefix + "as"
|
||||
if try_cmd("gcc-ar --version", env["mingw_prefix"], env["arch"]):
|
||||
env["AR"] = mingw_bin_prefix + "gcc-ar"
|
||||
if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]):
|
||||
env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib"
|
||||
env["CC"] = get_detected(env, "gcc")
|
||||
env["CXX"] = get_detected(env, "g++")
|
||||
env["AR"] = get_detected(env, "gcc-ar" if os.name != "nt" else "ar")
|
||||
env["RANLIB"] = get_detected(env, "gcc-ranlib")
|
||||
|
||||
env["RC"] = get_detected(env, "windres")
|
||||
ARCH_TARGETS = {
|
||||
"x86_32": "pe-i386",
|
||||
"x86_64": "pe-x86-64",
|
||||
"arm32": "armv7-w64-mingw32",
|
||||
"arm64": "aarch64-w64-mingw32",
|
||||
}
|
||||
env.AppendUnique(RCFLAGS=f"--target={ARCH_TARGETS[env['arch']]}")
|
||||
|
||||
env["AS"] = get_detected(env, "as")
|
||||
env["OBJCOPY"] = get_detected(env, "objcopy")
|
||||
env["STRIP"] = get_detected(env, "strip")
|
||||
|
||||
## LTO
|
||||
|
||||
if env["lto"] == "auto": # Full LTO for production with MinGW.
|
||||
env["lto"] = "full"
|
||||
if env["lto"] == "auto": # Enable LTO for production with MinGW.
|
||||
env["lto"] = "thin" if env["use_llvm"] else "full"
|
||||
|
||||
if env["lto"] != "none":
|
||||
if env["lto"] == "thin":
|
||||
|
|
@ -720,18 +781,47 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
else:
|
||||
env.Append(CCFLAGS=["-flto"])
|
||||
env.Append(LINKFLAGS=["-flto"])
|
||||
if not env["use_llvm"]:
|
||||
# For mingw-gcc LTO, disable linker plugin and enable whole program to work around GH-102867.
|
||||
env.Append(CCFLAGS=["-fno-use-linker-plugin", "-fwhole-program"])
|
||||
env.Append(LINKFLAGS=["-fno-use-linker-plugin", "-fwhole-program"])
|
||||
|
||||
env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE)])
|
||||
if env["use_asan"]:
|
||||
env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE_SANITIZERS)])
|
||||
else:
|
||||
env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE)])
|
||||
|
||||
## Compile flags
|
||||
|
||||
if int(env["target_win_version"], 16) < 0x0601:
|
||||
print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
|
||||
sys.exit(255)
|
||||
validate_win_version(env)
|
||||
|
||||
if not env["use_llvm"]:
|
||||
env.Append(CCFLAGS=["-mwindows"])
|
||||
|
||||
if env["use_asan"] or env["use_ubsan"]:
|
||||
if not env["use_llvm"]:
|
||||
print("GCC does not support sanitizers on Windows.")
|
||||
sys.exit(255)
|
||||
if env["arch"] not in ["x86_32", "x86_64"]:
|
||||
print("Sanitizers are only supported for x86_32 and x86_64.")
|
||||
sys.exit(255)
|
||||
|
||||
env.extra_suffix += ".san"
|
||||
env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"])
|
||||
san_flags = []
|
||||
if env["use_asan"]:
|
||||
san_flags.append("-fsanitize=address")
|
||||
if env["use_ubsan"]:
|
||||
san_flags.append("-fsanitize=undefined")
|
||||
# Disable the vptr check since it gets triggered on any COM interface calls.
|
||||
san_flags.append("-fno-sanitize=vptr")
|
||||
env.Append(CFLAGS=san_flags)
|
||||
env.Append(CCFLAGS=san_flags)
|
||||
env.Append(LINKFLAGS=san_flags)
|
||||
|
||||
if get_is_ar_thin_supported(env):
|
||||
env.Append(ARFLAGS=["--thin"])
|
||||
|
||||
env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"])
|
||||
env.Append(
|
||||
CPPDEFINES=[
|
||||
|
|
@ -778,15 +868,7 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
env.Append(LIBS=["vulkan"])
|
||||
|
||||
if env["d3d12"]:
|
||||
# Check whether we have d3d12 dependencies installed.
|
||||
if not os.path.exists(env["mesa_libs"]):
|
||||
print_error(
|
||||
"The Direct3D 12 rendering driver requires dependencies to be installed.\n"
|
||||
"You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
|
||||
"See the documentation for more information:\n\t"
|
||||
"https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
|
||||
)
|
||||
sys.exit(255)
|
||||
check_d3d12_installed(env)
|
||||
|
||||
env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
|
||||
env.Append(LIBS=["dxgi", "dxguid"])
|
||||
|
|
@ -822,19 +904,11 @@ def configure_mingw(env: "SConsEnvironment"):
|
|||
|
||||
env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)])
|
||||
|
||||
# resrc
|
||||
env.Append(BUILDERS={"RES": env.Builder(action=build_res_file, suffix=".o", src_suffix=".rc")})
|
||||
|
||||
|
||||
def configure(env: "SConsEnvironment"):
|
||||
# Validate arch.
|
||||
supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
|
||||
if env["arch"] not in supported_arches:
|
||||
print_error(
|
||||
'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.'
|
||||
% (env["arch"], ", ".join(supported_arches))
|
||||
)
|
||||
sys.exit(255)
|
||||
validate_arch(env["arch"], get_name(), supported_arches)
|
||||
|
||||
# At this point the env has been set up with basic tools/compilers.
|
||||
env.Prepend(CPPPATH=["#platform/windows"])
|
||||
|
|
@ -862,3 +936,20 @@ def configure(env: "SConsEnvironment"):
|
|||
|
||||
else: # MinGW
|
||||
configure_mingw(env)
|
||||
|
||||
|
||||
def check_d3d12_installed(env):
|
||||
if not os.path.exists(env["mesa_libs"]):
|
||||
print_error(
|
||||
"The Direct3D 12 rendering driver requires dependencies to be installed.\n"
|
||||
"You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
|
||||
"See the documentation for more information:\n\t"
|
||||
"https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
|
||||
)
|
||||
sys.exit(255)
|
||||
|
||||
|
||||
def validate_win_version(env):
|
||||
if int(env["target_win_version"], 16) < 0x0601:
|
||||
print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
|
||||
sys.exit(255)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -38,8 +38,8 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "drivers/unix/ip_unix.h"
|
||||
#include "drivers/wasapi/audio_driver_wasapi.h"
|
||||
#include "drivers/winmidi/midi_driver_winmidi.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
|
@ -167,7 +167,7 @@ typedef bool(WINAPI *ShouldAppsUseDarkModePtr)();
|
|||
typedef DWORD(WINAPI *GetImmersiveColorFromColorSetExPtr)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode);
|
||||
typedef int(WINAPI *GetImmersiveColorTypeFromNamePtr)(const WCHAR *name);
|
||||
typedef int(WINAPI *GetImmersiveUserColorSetPreferencePtr)(bool bForceCheckRegistry, bool bSkipCheckOnFail);
|
||||
typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOW *lpVersionInformation);
|
||||
typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOEXW *lpVersionInformation);
|
||||
typedef bool(WINAPI *AllowDarkModeForAppPtr)(bool darkMode);
|
||||
typedef PreferredAppMode(WINAPI *SetPreferredAppModePtr)(PreferredAppMode appMode);
|
||||
typedef void(WINAPI *RefreshImmersiveColorPolicyStatePtr)();
|
||||
|
|
@ -350,9 +350,27 @@ typedef struct {
|
|||
ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
|
||||
} ICONDIR, *LPICONDIR;
|
||||
|
||||
typedef enum _SHC_PROCESS_DPI_AWARENESS {
|
||||
SHC_PROCESS_DPI_UNAWARE = 0,
|
||||
SHC_PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||
SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2,
|
||||
} SHC_PROCESS_DPI_AWARENESS;
|
||||
|
||||
#ifndef WS_EX_NOREDIRECTIONBITMAP
|
||||
#define WS_EX_NOREDIRECTIONBITMAP 0x00200000L
|
||||
#endif
|
||||
|
||||
class DropTargetWindows;
|
||||
|
||||
#ifndef WDA_EXCLUDEFROMCAPTURE
|
||||
#define WDA_EXCLUDEFROMCAPTURE 0x00000011
|
||||
#endif
|
||||
|
||||
class DisplayServerWindows : public DisplayServer {
|
||||
// No need to register with GDCLASS, it's platform-specific and nothing is added.
|
||||
|
||||
friend class DropTargetWindows;
|
||||
|
||||
_THREAD_SAFE_CLASS_
|
||||
|
||||
// UXTheme API
|
||||
|
|
@ -387,12 +405,23 @@ class DisplayServerWindows : public DisplayServer {
|
|||
void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver);
|
||||
String tablet_driver;
|
||||
Vector<String> tablet_drivers;
|
||||
bool winink_disabled = false;
|
||||
|
||||
enum DriverID {
|
||||
DRIVER_ID_COMPAT_OPENGL3 = 1 << 0,
|
||||
DRIVER_ID_COMPAT_ANGLE_D3D11 = 1 << 1,
|
||||
DRIVER_ID_RD_VULKAN = 1 << 2,
|
||||
DRIVER_ID_RD_D3D12 = 1 << 3,
|
||||
};
|
||||
static BitField<DriverID> tested_drivers;
|
||||
|
||||
enum TimerID {
|
||||
TIMER_ID_MOVE_REDRAW = 1,
|
||||
TIMER_ID_WINDOW_ACTIVATION = 2,
|
||||
};
|
||||
|
||||
OSVERSIONINFOEXW os_ver;
|
||||
|
||||
enum {
|
||||
KEY_EVENT_BUFFER_SIZE = 512
|
||||
};
|
||||
|
|
@ -453,12 +482,17 @@ class DisplayServerWindows : public DisplayServer {
|
|||
bool resizable = true;
|
||||
bool window_focused = false;
|
||||
int activate_state = 0;
|
||||
bool was_maximized_pre_fs = false;
|
||||
bool was_fullscreen_pre_min = false;
|
||||
bool first_activation_done = false;
|
||||
bool was_maximized = false;
|
||||
bool always_on_top = false;
|
||||
bool no_focus = false;
|
||||
bool exclusive = false;
|
||||
bool context_created = false;
|
||||
bool mpass = false;
|
||||
bool sharp_corners = false;
|
||||
bool hide_from_capture = false;
|
||||
|
||||
// Used to transfer data between events using timer.
|
||||
WPARAM saved_wparam;
|
||||
|
|
@ -505,11 +539,18 @@ class DisplayServerWindows : public DisplayServer {
|
|||
Callable input_text_callback;
|
||||
Callable drop_files_callback;
|
||||
|
||||
// OLE API
|
||||
DropTargetWindows *drop_target = nullptr;
|
||||
|
||||
WindowID transient_parent = INVALID_WINDOW_ID;
|
||||
HashSet<WindowID> transient_children;
|
||||
|
||||
bool is_popup = false;
|
||||
Rect2i parent_safe_rect;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
HWND parent_hwnd = 0;
|
||||
};
|
||||
|
||||
JoypadWindows *joypad = nullptr;
|
||||
|
|
@ -518,12 +559,12 @@ class DisplayServerWindows : public DisplayServer {
|
|||
uint64_t time_since_popup = 0;
|
||||
Ref<Image> icon;
|
||||
|
||||
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent);
|
||||
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent, HWND p_parent_hwnd);
|
||||
WindowID window_id_counter = MAIN_WINDOW_ID;
|
||||
RBMap<WindowID, WindowData> windows;
|
||||
|
||||
WindowID last_focused_window = INVALID_WINDOW_ID;
|
||||
|
||||
WindowID last_mouse_button_down_window = INVALID_WINDOW_ID;
|
||||
HCURSOR hCursor;
|
||||
|
||||
WNDPROC user_proc = nullptr;
|
||||
|
|
@ -536,15 +577,54 @@ class DisplayServerWindows : public DisplayServer {
|
|||
IndicatorID indicator_id_counter = 0;
|
||||
HashMap<IndicatorID, IndicatorData> indicators;
|
||||
|
||||
struct FileDialogData {
|
||||
HWND hwnd_owner = 0;
|
||||
Rect2i wrect;
|
||||
String appid;
|
||||
String title;
|
||||
String current_directory;
|
||||
String root;
|
||||
String filename;
|
||||
bool show_hidden = false;
|
||||
DisplayServer::FileDialogMode mode = FileDialogMode::FILE_DIALOG_MODE_OPEN_ANY;
|
||||
Vector<String> filters;
|
||||
TypedArray<Dictionary> options;
|
||||
WindowID window_id = DisplayServer::INVALID_WINDOW_ID;
|
||||
Callable callback;
|
||||
bool options_in_cb = false;
|
||||
Thread listener_thread;
|
||||
SafeFlag close_requested;
|
||||
SafeFlag finished;
|
||||
};
|
||||
Mutex file_dialog_mutex;
|
||||
List<FileDialogData *> file_dialogs;
|
||||
HashMap<HWND, FileDialogData *> file_dialog_wnd;
|
||||
struct FileDialogCallback {
|
||||
Callable callback;
|
||||
Variant status;
|
||||
Variant files;
|
||||
Variant index;
|
||||
Variant options;
|
||||
bool opt_in_cb = false;
|
||||
};
|
||||
List<FileDialogCallback> pending_cbs;
|
||||
void process_file_dialog_callbacks();
|
||||
|
||||
static void _thread_fd_monitor(void *p_ud);
|
||||
|
||||
HashMap<int64_t, MouseButton> pointer_prev_button;
|
||||
HashMap<int64_t, MouseButton> pointer_button;
|
||||
HashMap<int64_t, LONG> pointer_down_time;
|
||||
HashMap<int64_t, Vector2> pointer_last_pos;
|
||||
|
||||
void _send_window_event(const WindowData &wd, WindowEvent p_event);
|
||||
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
|
||||
void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex);
|
||||
|
||||
MouseMode mouse_mode;
|
||||
MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE;
|
||||
MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE;
|
||||
bool mouse_mode_override_enabled = false;
|
||||
void _mouse_update_mode();
|
||||
int restore_mouse_trails = 0;
|
||||
|
||||
bool use_raw_input = false;
|
||||
|
|
@ -564,6 +644,8 @@ class DisplayServerWindows : public DisplayServer {
|
|||
void _drag_event(WindowID p_window, float p_x, float p_y, int idx);
|
||||
void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx);
|
||||
|
||||
bool _is_always_on_top_recursive(WindowID p_window) const;
|
||||
|
||||
void _update_window_style(WindowID p_window, bool p_repaint = true);
|
||||
void _update_window_mouse_passthrough(WindowID p_window);
|
||||
|
||||
|
|
@ -596,7 +678,17 @@ class DisplayServerWindows : public DisplayServer {
|
|||
String _get_keyboard_layout_display_name(const String &p_klid) const;
|
||||
String _get_klid(HKL p_hkl) const;
|
||||
|
||||
struct EmbeddedProcessData {
|
||||
HWND window_handle = 0;
|
||||
HWND parent_window_handle = 0;
|
||||
bool is_visible = false;
|
||||
};
|
||||
HashMap<OS::ProcessID, EmbeddedProcessData *> embedded_processes;
|
||||
|
||||
HWND _find_window_from_process_id(OS::ProcessID p_pid, HWND p_current_hwnd);
|
||||
|
||||
public:
|
||||
LRESULT WndProcFileDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT MouseProc(int code, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
|
@ -624,8 +716,14 @@ public:
|
|||
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override;
|
||||
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override;
|
||||
|
||||
virtual void beep() const override;
|
||||
|
||||
virtual void mouse_set_mode(MouseMode p_mode) override;
|
||||
virtual MouseMode mouse_get_mode() const override;
|
||||
virtual void mouse_set_mode_override(MouseMode p_mode) override;
|
||||
virtual MouseMode mouse_get_mode_override() const override;
|
||||
virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override;
|
||||
virtual bool mouse_is_mode_override_enabled() const override;
|
||||
|
||||
virtual void warp_mouse(const Point2i &p_position) override;
|
||||
virtual Point2i mouse_get_position() const override;
|
||||
|
|
@ -647,6 +745,7 @@ public:
|
|||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Color screen_get_pixel(const Point2i &p_position) const override;
|
||||
virtual Ref<Image> screen_get_image(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Ref<Image> screen_get_image_rect(const Rect2i &p_rect) const override;
|
||||
|
||||
virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver
|
||||
virtual bool screen_is_kept_on() const override;
|
||||
|
|
@ -728,6 +827,9 @@ public:
|
|||
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
|
||||
|
||||
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
|
||||
virtual void cursor_set_shape(CursorShape p_shape) override;
|
||||
virtual CursorShape cursor_get_shape() const override;
|
||||
virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
|
||||
|
|
@ -735,6 +837,10 @@ public:
|
|||
virtual bool get_swap_cancel_ok() override;
|
||||
|
||||
virtual void enable_for_stealing_focus(OS::ProcessID pid) override;
|
||||
virtual Error embed_process(WindowID p_window, OS::ProcessID p_pid, const Rect2i &p_rect, bool p_visible, bool p_grab_focus) override;
|
||||
virtual Error request_close_embedded_process(OS::ProcessID p_pid) override;
|
||||
virtual Error remove_embedded_process(OS::ProcessID p_pid) override;
|
||||
virtual OS::ProcessID get_focused_process_id() override;
|
||||
|
||||
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
|
||||
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
|
||||
|
|
@ -746,6 +852,7 @@ public:
|
|||
virtual String keyboard_get_layout_name(int p_index) const override;
|
||||
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
|
||||
virtual Key keyboard_get_label_from_physical(Key p_keycode) const override;
|
||||
virtual void show_emoji_and_symbol_picker() const override;
|
||||
|
||||
virtual int tablet_get_driver_count() const override;
|
||||
virtual String tablet_get_driver_name(int p_driver) const override;
|
||||
|
|
@ -774,11 +881,11 @@ public:
|
|||
|
||||
virtual bool is_window_transparency_available() const override;
|
||||
|
||||
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
|
||||
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error);
|
||||
static Vector<String> get_rendering_drivers_func();
|
||||
static void register_windows_driver();
|
||||
|
||||
DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
|
||||
DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error);
|
||||
~DisplayServerWindows();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@
|
|||
<member name="binary_format/architecture" type="String" setter="" getter="">
|
||||
Application executable architecture.
|
||||
Supported architectures: [code]x86_32[/code], [code]x86_64[/code], and [code]arm64[/code].
|
||||
Official export templates include [code]x86_32[/code] and [code]x86_64[/code] binaries only.
|
||||
</member>
|
||||
<member name="binary_format/embed_pck" type="bool" setter="" getter="">
|
||||
If [code]true[/code], project resources are embedded into the executable.
|
||||
|
|
|
|||
375
engine/platform/windows/drop_target_windows.cpp
Normal file
375
engine/platform/windows/drop_target_windows.cpp
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/**************************************************************************/
|
||||
/* drop_target_windows.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "drop_target_windows.h"
|
||||
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/math/random_pcg.h"
|
||||
#include "core/os/time.h"
|
||||
|
||||
#include <fileapi.h>
|
||||
|
||||
// Helpers
|
||||
|
||||
static String create_temp_dir() {
|
||||
Char16String buf;
|
||||
int bufsize = GetTempPathW(0, nullptr) + 1;
|
||||
buf.resize(bufsize);
|
||||
if (GetTempPathW(bufsize, (LPWSTR)buf.ptrw()) == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String tmp_dir = String::utf16((const char16_t *)buf.ptr());
|
||||
RandomPCG gen(Time::get_singleton()->get_ticks_usec());
|
||||
|
||||
const int attempts = 4;
|
||||
|
||||
for (int i = 0; i < attempts; ++i) {
|
||||
uint32_t rnd = gen.rand();
|
||||
String dirname = "godot_tmp_" + String::num_uint64(rnd);
|
||||
String res_dir = tmp_dir.path_join(dirname);
|
||||
Char16String res_dir16 = res_dir.utf16();
|
||||
|
||||
if (CreateDirectoryW((LPCWSTR)res_dir16.ptr(), nullptr)) {
|
||||
return res_dir;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool remove_dir_recursive(const String &p_dir) {
|
||||
Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (dir_access->change_dir(p_dir) != OK) {
|
||||
return false;
|
||||
}
|
||||
return dir_access->erase_contents_recursive() == OK;
|
||||
}
|
||||
|
||||
static bool stream2file(IStream *p_stream, FILEDESCRIPTORW *p_desc, const String &p_path) {
|
||||
if (DirAccess::make_dir_recursive_absolute(p_path.get_base_dir()) != OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Char16String path16 = p_path.utf16();
|
||||
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
|
||||
if (p_desc->dwFlags & FD_ATTRIBUTES) {
|
||||
dwFlagsAndAttributes = p_desc->dwFileAttributes;
|
||||
}
|
||||
|
||||
HANDLE file = CreateFileW(
|
||||
(LPCWSTR)path16.ptr(),
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
nullptr,
|
||||
CREATE_NEW,
|
||||
dwFlagsAndAttributes,
|
||||
nullptr);
|
||||
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int bufsize = 4096;
|
||||
char buf[bufsize];
|
||||
ULONG nread = 0;
|
||||
DWORD nwritten = 0;
|
||||
HRESULT read_result = S_OK;
|
||||
bool result = true;
|
||||
|
||||
while (true) {
|
||||
read_result = p_stream->Read(buf, bufsize, &nread);
|
||||
if (read_result != S_OK && read_result != S_FALSE) {
|
||||
result = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!nread) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (nread > 0) {
|
||||
if (!WriteFile(file, buf, nread, &nwritten, nullptr) || !nwritten) {
|
||||
result = false;
|
||||
goto cleanup;
|
||||
}
|
||||
nread -= nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CloseHandle(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
// DropTargetWindows
|
||||
|
||||
bool DropTargetWindows::is_valid_filedescriptor() {
|
||||
return cf_filedescriptor != 0 && cf_filecontents != 0;
|
||||
}
|
||||
|
||||
HRESULT DropTargetWindows::handle_hdrop_format(Vector<String> *p_files, IDataObject *pDataObj) {
|
||||
FORMATETC fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stg;
|
||||
HRESULT res = S_OK;
|
||||
|
||||
if (pDataObj->GetData(&fmt, &stg) != S_OK) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
HDROP hDropInfo = (HDROP)GlobalLock(stg.hGlobal);
|
||||
|
||||
Char16String buf;
|
||||
|
||||
if (hDropInfo == nullptr) {
|
||||
ReleaseStgMedium(&stg);
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0);
|
||||
|
||||
for (int i = 0; i < fcount; i++) {
|
||||
int buffsize = DragQueryFileW(hDropInfo, i, nullptr, 0);
|
||||
buf.resize(buffsize + 1);
|
||||
if (DragQueryFileW(hDropInfo, i, (LPWSTR)buf.ptrw(), buffsize + 1) == 0) {
|
||||
res = E_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
String file = String::utf16((const char16_t *)buf.ptr());
|
||||
p_files->push_back(file);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
GlobalUnlock(stg.hGlobal);
|
||||
ReleaseStgMedium(&stg);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT DropTargetWindows::handle_filedescriptor_format(Vector<String> *p_files, IDataObject *pDataObj) {
|
||||
FORMATETC fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stg;
|
||||
HRESULT res = S_OK;
|
||||
|
||||
if (pDataObj->GetData(&fmt, &stg) != S_OK) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
FILEGROUPDESCRIPTORW *filegroup_desc = (FILEGROUPDESCRIPTORW *)GlobalLock(stg.hGlobal);
|
||||
|
||||
if (!filegroup_desc) {
|
||||
ReleaseStgMedium(&stg);
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
tmp_path = create_temp_dir();
|
||||
Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
PackedStringArray copied;
|
||||
|
||||
if (dir_access->change_dir(tmp_path) != OK) {
|
||||
res = E_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)filegroup_desc->cItems; ++i) {
|
||||
res = save_as_file(tmp_path, filegroup_desc->fgd + i, pDataObj, i);
|
||||
if (res != S_OK) {
|
||||
res = E_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
copied = dir_access->get_files();
|
||||
for (const String &file : copied) {
|
||||
p_files->push_back(tmp_path.path_join(file));
|
||||
}
|
||||
|
||||
copied = dir_access->get_directories();
|
||||
for (const String &dir : copied) {
|
||||
p_files->push_back(tmp_path.path_join(dir));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
GlobalUnlock(filegroup_desc);
|
||||
ReleaseStgMedium(&stg);
|
||||
if (res != S_OK) {
|
||||
remove_dir_recursive(tmp_path);
|
||||
tmp_path.clear();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT DropTargetWindows::save_as_file(const String &p_out_dir, FILEDESCRIPTORW *p_file_desc, IDataObject *pDataObj, int p_file_idx) {
|
||||
String relpath = String::utf16((const char16_t *)p_file_desc->cFileName);
|
||||
String fullpath = p_out_dir.path_join(relpath);
|
||||
|
||||
if (p_file_desc->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (DirAccess::make_dir_recursive_absolute(fullpath) != OK) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FORMATETC fmt = { cf_filecontents, nullptr, DVASPECT_CONTENT, p_file_idx, TYMED_ISTREAM };
|
||||
STGMEDIUM stg;
|
||||
HRESULT res = S_OK;
|
||||
|
||||
if (pDataObj->GetData(&fmt, &stg) != S_OK) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
IStream *stream = stg.pstm;
|
||||
if (stream == nullptr) {
|
||||
res = E_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!stream2file(stream, p_file_desc, fullpath)) {
|
||||
res = E_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
ReleaseStgMedium(&stg);
|
||||
return res;
|
||||
}
|
||||
|
||||
DropTargetWindows::DropTargetWindows(DisplayServerWindows::WindowData *p_window_data) :
|
||||
ref_count(1), window_data(p_window_data) {
|
||||
cf_filedescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
|
||||
cf_filecontents = RegisterClipboardFormat(CFSTR_FILECONTENTS);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DropTargetWindows::QueryInterface(REFIID riid, void **ppvObject) {
|
||||
if (riid == IID_IUnknown || riid == IID_IDropTarget) {
|
||||
*ppvObject = static_cast<IDropTarget *>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE DropTargetWindows::AddRef() {
|
||||
return InterlockedIncrement(&ref_count);
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE DropTargetWindows::Release() {
|
||||
ULONG count = InterlockedDecrement(&ref_count);
|
||||
if (count == 0) {
|
||||
memfree(this);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DropTargetWindows::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
|
||||
(void)grfKeyState;
|
||||
(void)pt;
|
||||
|
||||
FORMATETC hdrop_fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
FORMATETC filedesc_fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
|
||||
if (!window_data->drop_files_callback.is_valid()) {
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
} else if (pDataObj->QueryGetData(&hdrop_fmt) == S_OK) {
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
} else if (is_valid_filedescriptor() && pDataObj->QueryGetData(&filedesc_fmt) == S_OK) {
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
} else {
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DropTargetWindows::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
|
||||
(void)grfKeyState;
|
||||
(void)pt;
|
||||
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DropTargetWindows::DragLeave() {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DropTargetWindows::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
|
||||
(void)grfKeyState;
|
||||
(void)pt;
|
||||
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
if (!window_data->drop_files_callback.is_valid()) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FORMATETC hdrop_fmt = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
FORMATETC filedesc_fmt = { cf_filedescriptor, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
Vector<String> files;
|
||||
|
||||
if (pDataObj->QueryGetData(&hdrop_fmt) == S_OK) {
|
||||
HRESULT res = handle_hdrop_format(&files, pDataObj);
|
||||
if (res != S_OK) {
|
||||
return res;
|
||||
}
|
||||
} else if (pDataObj->QueryGetData(&filedesc_fmt) == S_OK && is_valid_filedescriptor()) {
|
||||
HRESULT res = handle_filedescriptor_format(&files, pDataObj);
|
||||
if (res != S_OK) {
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!files.size()) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Variant v_files = files;
|
||||
const Variant *v_args[1] = { &v_files };
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
window_data->drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
|
||||
|
||||
if (!tmp_path.is_empty()) {
|
||||
remove_dir_recursive(tmp_path);
|
||||
tmp_path.clear();
|
||||
}
|
||||
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(window_data->drop_files_callback, v_args, 1, ce)));
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
return S_OK;
|
||||
}
|
||||
77
engine/platform/windows/drop_target_windows.h
Normal file
77
engine/platform/windows/drop_target_windows.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/**************************************************************************/
|
||||
/* drop_target_windows.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 DROP_TARGET_WINDOWS_H
|
||||
#define DROP_TARGET_WINDOWS_H
|
||||
|
||||
#include "display_server_windows.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
// Silence warning due to a COM API weirdness.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-dodragdrop#remarks
|
||||
class DropTargetWindows : public IDropTarget {
|
||||
LONG ref_count;
|
||||
DisplayServerWindows::WindowData *window_data = nullptr;
|
||||
CLIPFORMAT cf_filedescriptor = 0;
|
||||
CLIPFORMAT cf_filecontents = 0;
|
||||
String tmp_path;
|
||||
|
||||
bool is_valid_filedescriptor();
|
||||
HRESULT handle_hdrop_format(Vector<String> *p_files, IDataObject *pDataObj);
|
||||
HRESULT handle_filedescriptor_format(Vector<String> *p_files, IDataObject *pDataObj);
|
||||
HRESULT save_as_file(const String &p_out_dir, FILEDESCRIPTORW *p_file_desc, IDataObject *pDataObj, int p_file_idx);
|
||||
|
||||
public:
|
||||
DropTargetWindows(DisplayServerWindows::WindowData *p_window_data);
|
||||
virtual ~DropTargetWindows() {}
|
||||
|
||||
// IUnknown
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
|
||||
// IDropTarget
|
||||
HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
|
||||
HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
|
||||
HRESULT STDMETHODCALLTYPE DragLeave() override;
|
||||
HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
|
||||
};
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // DROP_TARGET_WINDOWS_H
|
||||
|
|
@ -39,17 +39,18 @@ void register_windows_exporter_types() {
|
|||
}
|
||||
|
||||
void register_windows_exporter() {
|
||||
// TODO: Move to editor_settings.cpp
|
||||
#ifndef ANDROID_ENABLED
|
||||
EDITOR_DEF("export/windows/rcedit", "");
|
||||
EDITOR_DEF_BASIC("export/windows/rcedit", "");
|
||||
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
||||
#ifdef WINDOWS_ENABLED
|
||||
EDITOR_DEF("export/windows/signtool", "");
|
||||
EDITOR_DEF_BASIC("export/windows/signtool", "");
|
||||
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
||||
#else
|
||||
EDITOR_DEF("export/windows/osslsigncode", "");
|
||||
EDITOR_DEF_BASIC("export/windows/osslsigncode", "");
|
||||
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/osslsigncode", PROPERTY_HINT_GLOBAL_FILE));
|
||||
// On non-Windows we need WINE to run rcedit
|
||||
EDITOR_DEF("export/windows/wine", "");
|
||||
EDITOR_DEF_BASIC("export/windows/wine", "");
|
||||
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE));
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@
|
|||
#include "editor/export/editor_export.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // For svg.
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
#include "modules/svg/image_loader_svg.h"
|
||||
#endif
|
||||
|
||||
Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &p_preset, const String &p_src_path, const String &p_dst_path) {
|
||||
static const uint8_t icon_size[] = { 16, 32, 48, 64, 128, 0 /*256*/ };
|
||||
|
|
@ -96,10 +93,9 @@ Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &
|
|||
f->seek(prev_offset);
|
||||
}
|
||||
} else {
|
||||
Ref<Image> src_image;
|
||||
src_image.instantiate();
|
||||
err = ImageLoader::load_image(p_src_path, src_image);
|
||||
ERR_FAIL_COND_V(err != OK || src_image->is_empty(), ERR_CANT_OPEN);
|
||||
Ref<Image> src_image = _load_icon_or_splash_image(p_src_path, &err);
|
||||
ERR_FAIL_COND_V(err != OK || src_image.is_null() || src_image->is_empty(), ERR_CANT_OPEN);
|
||||
|
||||
for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
|
||||
int size = (icon_size[i] == 0) ? 256 : icon_size[i];
|
||||
|
||||
|
|
@ -167,7 +163,7 @@ Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPres
|
|||
}
|
||||
}
|
||||
|
||||
Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
||||
Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
|
||||
if (p_preset->get("application/modify_resources")) {
|
||||
_rcedit_add_data(p_preset, p_path, false);
|
||||
String wrapper_path = p_path.get_basename() + ".console.exe";
|
||||
|
|
@ -178,7 +174,7 @@ Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset>
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
||||
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
|
||||
String custom_debug = p_preset->get("custom_template/debug");
|
||||
String custom_release = p_preset->get("custom_template/release");
|
||||
String arch = p_preset->get("binary_format/architecture");
|
||||
|
|
@ -187,53 +183,11 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
|
|||
template_path = template_path.strip_edges();
|
||||
if (template_path.is_empty()) {
|
||||
template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", arch));
|
||||
}
|
||||
|
||||
int export_angle = p_preset->get("application/export_angle");
|
||||
bool include_angle_libs = false;
|
||||
if (export_angle == 0) {
|
||||
include_angle_libs = (String(GLOBAL_GET("rendering/gl_compatibility/driver.windows")) == "opengl3_angle") && (String(GLOBAL_GET("rendering/renderer/rendering_method")) == "gl_compatibility");
|
||||
} else if (export_angle == 1) {
|
||||
include_angle_libs = true;
|
||||
}
|
||||
if (include_angle_libs) {
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"), p_path.get_base_dir().path_join("libEGL.dll"), get_chmod_flags());
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"), p_path.get_base_dir().path_join("libGLESv2.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
|
||||
int export_d3d12 = p_preset->get("application/export_d3d12");
|
||||
bool agility_sdk_multiarch = p_preset->get("application/d3d12_agility_sdk_multiarch");
|
||||
bool include_d3d12_extra_libs = false;
|
||||
if (export_d3d12 == 0) {
|
||||
include_d3d12_extra_libs = (String(GLOBAL_GET("rendering/rendering_device/driver.windows")) == "d3d12") && (String(GLOBAL_GET("rendering/renderer/rendering_method")) != "gl_compatibility");
|
||||
} else if (export_d3d12 == 1) {
|
||||
include_d3d12_extra_libs = true;
|
||||
}
|
||||
if (include_d3d12_extra_libs) {
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"))) {
|
||||
if (agility_sdk_multiarch) {
|
||||
da->make_dir_recursive(p_path.get_base_dir().path_join(arch));
|
||||
da->copy(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"), p_path.get_base_dir().path_join(arch).path_join("D3D12Core.dll"), get_chmod_flags());
|
||||
} else {
|
||||
da->copy(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"), p_path.get_base_dir().path_join("D3D12Core.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"))) {
|
||||
if (agility_sdk_multiarch) {
|
||||
da->make_dir_recursive(p_path.get_base_dir().path_join(arch));
|
||||
da->copy(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"), p_path.get_base_dir().path_join(arch).path_join("d3d12SDKLayers.dll"), get_chmod_flags());
|
||||
} else {
|
||||
da->copy(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"), p_path.get_base_dir().path_join("d3d12SDKLayers.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("WinPixEventRuntime." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("WinPixEventRuntime." + arch + ".dll"), p_path.get_base_dir().path_join("WinPixEventRuntime.dll"), get_chmod_flags());
|
||||
} else {
|
||||
String exe_arch = _get_exe_arch(template_path);
|
||||
if (arch != exe_arch) {
|
||||
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch));
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +205,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
|
|||
|
||||
// Setup temp folder.
|
||||
String path = p_path;
|
||||
String tmp_dir_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name);
|
||||
String tmp_dir_path = EditorPaths::get_singleton()->get_temp_dir().path_join(pkg_name);
|
||||
Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_dir_path);
|
||||
if (export_as_zip) {
|
||||
if (tmp_app_dir.is_null()) {
|
||||
|
|
@ -267,6 +221,54 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
|
|||
path = tmp_dir_path.path_join(p_path.get_file().get_basename() + ".exe");
|
||||
}
|
||||
|
||||
int export_angle = p_preset->get("application/export_angle");
|
||||
bool include_angle_libs = false;
|
||||
if (export_angle == 0) {
|
||||
include_angle_libs = (String(GLOBAL_GET("rendering/gl_compatibility/driver.windows")) == "opengl3_angle") && (String(GLOBAL_GET("rendering/renderer/rendering_method")) == "gl_compatibility");
|
||||
} else if (export_angle == 1) {
|
||||
include_angle_libs = true;
|
||||
}
|
||||
if (include_angle_libs) {
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"), path.get_base_dir().path_join("libEGL.dll"), get_chmod_flags());
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"), path.get_base_dir().path_join("libGLESv2.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
|
||||
int export_d3d12 = p_preset->get("application/export_d3d12");
|
||||
bool agility_sdk_multiarch = p_preset->get("application/d3d12_agility_sdk_multiarch");
|
||||
bool include_d3d12_extra_libs = false;
|
||||
if (export_d3d12 == 0) {
|
||||
include_d3d12_extra_libs = (String(GLOBAL_GET("rendering/rendering_device/driver.windows")) == "d3d12") && (String(GLOBAL_GET("rendering/renderer/rendering_method")) != "gl_compatibility");
|
||||
} else if (export_d3d12 == 1) {
|
||||
include_d3d12_extra_libs = true;
|
||||
}
|
||||
if (include_d3d12_extra_libs) {
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"))) {
|
||||
if (agility_sdk_multiarch) {
|
||||
da->make_dir_recursive(path.get_base_dir().path_join(arch));
|
||||
da->copy(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"), path.get_base_dir().path_join(arch).path_join("D3D12Core.dll"), get_chmod_flags());
|
||||
} else {
|
||||
da->copy(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"), path.get_base_dir().path_join("D3D12Core.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"))) {
|
||||
if (agility_sdk_multiarch) {
|
||||
da->make_dir_recursive(path.get_base_dir().path_join(arch));
|
||||
da->copy(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"), path.get_base_dir().path_join(arch).path_join("d3d12SDKLayers.dll"), get_chmod_flags());
|
||||
} else {
|
||||
da->copy(template_path.get_base_dir().path_join("d3d12SDKLayers." + arch + ".dll"), path.get_base_dir().path_join("d3d12SDKLayers.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
if (da->file_exists(template_path.get_base_dir().path_join("WinPixEventRuntime." + arch + ".dll"))) {
|
||||
da->copy(template_path.get_base_dir().path_join("WinPixEventRuntime." + arch + ".dll"), path.get_base_dir().path_join("WinPixEventRuntime.dll"), get_chmod_flags());
|
||||
}
|
||||
}
|
||||
|
||||
// Export project.
|
||||
String pck_path = path;
|
||||
if (embedded) {
|
||||
|
|
@ -343,7 +345,7 @@ String EditorExportPlatformWindows::get_export_option_warning(const EditorExport
|
|||
PackedStringArray version_array = file_version.split(".", false);
|
||||
if (version_array.size() != 4 || !version_array[0].is_valid_int() ||
|
||||
!version_array[1].is_valid_int() || !version_array[2].is_valid_int() ||
|
||||
!version_array[3].is_valid_int() || file_version.contains("-")) {
|
||||
!version_array[3].is_valid_int() || file_version.contains_char('-')) {
|
||||
return TTR("Invalid file version.");
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +355,7 @@ String EditorExportPlatformWindows::get_export_option_warning(const EditorExport
|
|||
PackedStringArray version_array = product_version.split(".", false);
|
||||
if (version_array.size() != 4 || !version_array[0].is_valid_int() ||
|
||||
!version_array[1].is_valid_int() || !version_array[2].is_valid_int() ||
|
||||
!version_array[3].is_valid_int() || product_version.contains("-")) {
|
||||
!version_array[3].is_valid_int() || product_version.contains_char('-')) {
|
||||
return TTR("Invalid product version.");
|
||||
}
|
||||
}
|
||||
|
|
@ -392,7 +394,13 @@ bool EditorExportPlatformWindows::get_export_option_visibility(const EditorExpor
|
|||
return false;
|
||||
}
|
||||
|
||||
if (p_option == "dotnet/embed_build_outputs") {
|
||||
if (p_option == "dotnet/embed_build_outputs" ||
|
||||
p_option == "custom_template/debug" ||
|
||||
p_option == "custom_template/release" ||
|
||||
p_option == "application/d3d12_agility_sdk_multiarch" ||
|
||||
p_option == "application/export_angle" ||
|
||||
p_option == "application/export_d3d12" ||
|
||||
p_option == "application/icon_interpolation") {
|
||||
return advanced_options_enabled;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -431,7 +439,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
|
|||
String run_script = "Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'\n"
|
||||
"$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'\n"
|
||||
"$trigger = New-ScheduledTaskTrigger -Once -At 00:00\n"
|
||||
"$settings = New-ScheduledTaskSettingsSet\n"
|
||||
"$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries\n"
|
||||
"$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings\n"
|
||||
"Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true\n"
|
||||
"Start-ScheduledTask -TaskName godot_remote_debug\n"
|
||||
|
|
@ -495,7 +503,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|||
}
|
||||
}
|
||||
|
||||
String tmp_icon_path = EditorPaths::get_singleton()->get_cache_dir().path_join("_rcedit.ico");
|
||||
String tmp_icon_path = EditorPaths::get_singleton()->get_temp_dir().path_join("_rcedit.ico");
|
||||
if (!icon_path.is_empty()) {
|
||||
if (_process_icon(p_preset, icon_path, tmp_icon_path) != OK) {
|
||||
add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Invalid icon file \"%s\"."), icon_path));
|
||||
|
|
@ -503,7 +511,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|||
}
|
||||
}
|
||||
|
||||
String file_verion = p_preset->get_version("application/file_version", true);
|
||||
String file_version = p_preset->get_version("application/file_version", true);
|
||||
String product_version = p_preset->get_version("application/product_version", true);
|
||||
String company_name = p_preset->get("application/company_name");
|
||||
String product_name = p_preset->get("application/product_name");
|
||||
|
|
@ -518,9 +526,9 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|||
args.push_back("--set-icon");
|
||||
args.push_back(tmp_icon_path);
|
||||
}
|
||||
if (!file_verion.is_empty()) {
|
||||
if (!file_version.is_empty()) {
|
||||
args.push_back("--set-file-version");
|
||||
args.push_back(file_verion);
|
||||
args.push_back(file_version);
|
||||
}
|
||||
if (!product_version.is_empty()) {
|
||||
args.push_back("--set-product-version");
|
||||
|
|
@ -753,9 +761,26 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|||
}
|
||||
|
||||
bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
|
||||
String err = "";
|
||||
String err;
|
||||
bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug);
|
||||
|
||||
String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges();
|
||||
String custom_release = p_preset->get("custom_template/release").operator String().strip_edges();
|
||||
String arch = p_preset->get("binary_format/architecture");
|
||||
|
||||
if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) {
|
||||
String exe_arch = _get_exe_arch(custom_debug);
|
||||
if (arch != exe_arch) {
|
||||
err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
|
||||
}
|
||||
}
|
||||
if (!custom_release.is_empty() && FileAccess::exists(custom_release)) {
|
||||
String exe_arch = _get_exe_arch(custom_release);
|
||||
if (arch != exe_arch) {
|
||||
err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
String rcedit_path = EDITOR_GET("export/windows/rcedit");
|
||||
if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) {
|
||||
err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > rcedit) to change the icon or app information data.") + "\n";
|
||||
|
|
@ -769,7 +794,7 @@ bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<Edito
|
|||
}
|
||||
|
||||
bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
|
||||
String err = "";
|
||||
String err;
|
||||
bool valid = true;
|
||||
|
||||
List<ExportOption> options;
|
||||
|
|
@ -793,6 +818,43 @@ bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<Edit
|
|||
return valid;
|
||||
}
|
||||
|
||||
String EditorExportPlatformWindows::_get_exe_arch(const String &p_path) const {
|
||||
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
|
||||
if (f.is_null()) {
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
// Jump to the PE header and check the magic number.
|
||||
{
|
||||
f->seek(0x3c);
|
||||
uint32_t pe_pos = f->get_32();
|
||||
|
||||
f->seek(pe_pos);
|
||||
uint32_t magic = f->get_32();
|
||||
if (magic != 0x00004550) {
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
// Process header.
|
||||
uint16_t machine = f->get_16();
|
||||
f->close();
|
||||
|
||||
switch (machine) {
|
||||
case 0x014c:
|
||||
return "x86_32";
|
||||
case 0x8664:
|
||||
return "x86_64";
|
||||
case 0x01c0:
|
||||
case 0x01c4:
|
||||
return "arm32";
|
||||
case 0xaa64:
|
||||
return "arm64";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
|
||||
// Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
|
||||
|
||||
|
|
@ -936,7 +998,7 @@ void EditorExportPlatformWindows::cleanup() {
|
|||
cleanup_commands.clear();
|
||||
}
|
||||
|
||||
Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
|
||||
Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
|
||||
cleanup();
|
||||
if (p_device) { // Stop command, cleanup only.
|
||||
return OK;
|
||||
|
|
@ -944,7 +1006,7 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
|
|||
|
||||
EditorProgress ep("run", TTR("Running..."), 5);
|
||||
|
||||
const String dest = EditorPaths::get_singleton()->get_cache_dir().path_join("windows");
|
||||
const String dest = EditorPaths::get_singleton()->get_temp_dir().path_join("windows");
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
if (!da->dir_exists(dest)) {
|
||||
Error err = da->make_dir_recursive(dest);
|
||||
|
|
@ -990,8 +1052,7 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
|
|||
|
||||
String cmd_args;
|
||||
{
|
||||
Vector<String> cmd_args_list;
|
||||
gen_debug_flags(cmd_args_list, p_debug_flags);
|
||||
Vector<String> cmd_args_list = gen_export_flags(p_debug_flags);
|
||||
for (int i = 0; i < cmd_args_list.size(); i++) {
|
||||
if (i != 0) {
|
||||
cmd_args += " ";
|
||||
|
|
@ -1000,7 +1061,7 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
|
|||
}
|
||||
}
|
||||
|
||||
const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
|
||||
const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
|
||||
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
|
||||
|
||||
print_line("Creating temporary directory...");
|
||||
|
|
@ -1085,7 +1146,6 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset,
|
|||
|
||||
EditorExportPlatformWindows::EditorExportPlatformWindows() {
|
||||
if (EditorNode::get_singleton()) {
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
Ref<Image> img = memnew(Image);
|
||||
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
|
||||
|
||||
|
|
@ -1094,7 +1154,6 @@ EditorExportPlatformWindows::EditorExportPlatformWindows() {
|
|||
|
||||
ImageLoaderSVG::create_image_from_string(img, _windows_run_icon_svg, EDSCALE, upsample, false);
|
||||
run_icon = ImageTexture::create_from_image(img);
|
||||
#endif
|
||||
|
||||
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
|
||||
if (theme.is_valid()) {
|
||||
|
|
|
|||
|
|
@ -52,14 +52,14 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC {
|
|||
String cmd_args;
|
||||
bool wait = false;
|
||||
|
||||
SSHCleanupCommand(){};
|
||||
SSHCleanupCommand() {}
|
||||
SSHCleanupCommand(const String &p_host, const String &p_port, const Vector<String> &p_ssh_arg, const String &p_cmd_args, bool p_wait = false) {
|
||||
host = p_host;
|
||||
port = p_port;
|
||||
ssh_args = p_ssh_arg;
|
||||
cmd_args = p_cmd_args;
|
||||
wait = p_wait;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Ref<ImageTexture> run_icon;
|
||||
|
|
@ -73,9 +73,11 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC {
|
|||
Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon);
|
||||
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
||||
|
||||
String _get_exe_arch(const String &p_path) const;
|
||||
|
||||
public:
|
||||
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
|
||||
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) override;
|
||||
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
|
||||
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) override;
|
||||
virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override;
|
||||
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
|
||||
virtual void get_export_options(List<ExportOption> *r_options) const override;
|
||||
|
|
@ -93,7 +95,7 @@ public:
|
|||
virtual int get_options_count() const override;
|
||||
virtual String get_option_label(int p_index) const override;
|
||||
virtual String get_option_tooltip(int p_index) const override;
|
||||
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
|
||||
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
|
||||
virtual void cleanup() override;
|
||||
|
||||
EditorExportPlatformWindows();
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ private:
|
|||
public:
|
||||
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
|
||||
|
||||
GLManagerANGLE_Windows(){};
|
||||
~GLManagerANGLE_Windows(){};
|
||||
GLManagerANGLE_Windows() {}
|
||||
~GLManagerANGLE_Windows() {}
|
||||
};
|
||||
|
||||
#endif // WINDOWS_ENABLED && GLES3_ENABLED
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/version.h"
|
||||
|
||||
#include "thirdparty/nvapi/nvapi_minimal.h"
|
||||
#include "thirdparty/misc/nvapi_minimal.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -452,8 +452,8 @@ Error GLManagerNative_Windows::window_create(DisplayServer::WindowID p_window_id
|
|||
return FAILED;
|
||||
}
|
||||
|
||||
// WARNING: p_window_id is an eternally growing integer since popup windows keep coming and going
|
||||
// and each of them has a higher id than the previous, so it must be used in a map not a vector
|
||||
// WARNING: `p_window_id` is an eternally growing integer since popup windows keep coming and going
|
||||
// and each of them has a higher id than the previous, so it must be used in a map not a vector.
|
||||
_windows[p_window_id] = win;
|
||||
|
||||
// make current
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<Type Name="Ref<*>">
|
||||
<SmartPointer Usage="Minimal">reference</SmartPointer>
|
||||
<DisplayString Condition="!reference">[empty]</DisplayString>
|
||||
<DisplayString Condition="!!reference">{*reference}</DisplayString>
|
||||
<Expand>
|
||||
<Item Condition="!!reference" Name="[ptr]">reference</Item>
|
||||
<Item Condition="!!reference" Name="[refcount]">reference->refcount.count.value</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Vector<*>">
|
||||
<Expand>
|
||||
<Item Name="[size]">_cowdata._ptr ? (((const unsigned long long *)(_cowdata._ptr))[-1]) : 0</Item>
|
||||
|
|
@ -20,16 +30,6 @@
|
|||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="TypedArray<*>">
|
||||
<Expand>
|
||||
<Item Name="[size]"> _p->array._cowdata._ptr ? (((const unsigned long long *)(_p->array._cowdata._ptr))[-1]) : 0</Item>
|
||||
<ArrayItems>
|
||||
<Size>_p->array._cowdata._ptr ? (((const unsigned long long *)(_p->array._cowdata._ptr))[-1]) : 0</Size>
|
||||
<ValuePointer >(Variant *) _p->array._cowdata._ptr</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Dictionary">
|
||||
<Expand>
|
||||
<Item Name="[size]">_p && _p->variant_map.head_element ? _p->variant_map.num_elements : 0</Item>
|
||||
|
|
@ -91,6 +91,16 @@
|
|||
<StringView Condition="_data && !_data->cname">_data->name,s32b</StringView>
|
||||
</Type>
|
||||
|
||||
<Type Name="HashSet<*,*,*>">
|
||||
<Expand>
|
||||
<Item Name="[size]">num_elements</Item>
|
||||
<ArrayItems>
|
||||
<Size>num_elements</Size>
|
||||
<ValuePointer>($T1 *) keys._cowdata._ptr</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="HashMapElement<*,*>">
|
||||
<DisplayString>{{Key = {($T1 *) &data.key} Value = {($T2 *) &data.value}}}</DisplayString>
|
||||
<Expand>
|
||||
|
|
@ -133,7 +143,7 @@
|
|||
<Type Name="HashMapElement<*,*>" IncludeView="MapHelper">
|
||||
<DisplayString>{data.value}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[key]" >($T1 *) &data.key</Item>
|
||||
<Item Name="[key]">($T1 *) &data.key</Item>
|
||||
<Item Name="[value]">($T2 *) &data.value</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
|
@ -265,39 +275,164 @@
|
|||
</Type>
|
||||
|
||||
<Type Name="Vector2">
|
||||
<DisplayString>{{{x},{y}}}</DisplayString>
|
||||
<DisplayString>({x,g}, {y,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="x">x</Item>
|
||||
<Item Name="y">y</Item>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="Vector2i">
|
||||
<DisplayString>({x}, {y})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Vector3">
|
||||
<DisplayString>{{{x},{y},{z}}}</DisplayString>
|
||||
<DisplayString>({x,g}, {y,g}, {z,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="x">x</Item>
|
||||
<Item Name="y">y</Item>
|
||||
<Item Name="z">z</Item>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
<Item Name="[z]">z</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="Vector3i">
|
||||
<DisplayString>({x}, {y}, {z})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
<Item Name="[z]">z</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Vector4">
|
||||
<DisplayString>({x,g}, {y,g}, {z,g}, {w,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
<Item Name="[z]">z</Item>
|
||||
<Item Name="[w]">w</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="Vector4i">
|
||||
<DisplayString>({x}, {y}, {z}, {w})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
<Item Name="[z]">z</Item>
|
||||
<Item Name="[w]">w</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Quaternion">
|
||||
<DisplayString>Quaternion {{{x},{y},{z},{w}}}</DisplayString>
|
||||
<DisplayString>({x,g}, {y,g}, {z,g}, {w,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="x">x</Item>
|
||||
<Item Name="y">y</Item>
|
||||
<Item Name="z">z</Item>
|
||||
<Item Name="w">w</Item>
|
||||
<Item Name="[x]">x</Item>
|
||||
<Item Name="[y]">y</Item>
|
||||
<Item Name="[z]">z</Item>
|
||||
<Item Name="[w]">w</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Color">
|
||||
<DisplayString>Color {{{r},{g},{b},{a}}}</DisplayString>
|
||||
<DisplayString>({r,g}, {g,g}, {b,g}, {a,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="red">r</Item>
|
||||
<Item Name="green">g</Item>
|
||||
<Item Name="blue">b</Item>
|
||||
<Item Name="alpha">a</Item>
|
||||
<Item Name="[red]">r</Item>
|
||||
<Item Name="[green]">g</Item>
|
||||
<Item Name="[blue]">b</Item>
|
||||
<Item Name="[alpha]">a</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Rect2">
|
||||
<DisplayString>[P: {position}, S: {size}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[position]">position,nr</Item>
|
||||
<Item Name="[size]">size,nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="Rect2i">
|
||||
<DisplayString>[P: {position}, S: {size}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[position]">position,nr</Item>
|
||||
<Item Name="[size]">size,nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="AABB">
|
||||
<DisplayString>[P: {position}, S: {size}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[position]">position,nr</Item>
|
||||
<Item Name="[size]">size,nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Plane">
|
||||
<DisplayString>[N: {normal}, D: {d,g}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[normal]">normal,nr</Item>
|
||||
<Item Name="[d]">d</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Basis">
|
||||
<DisplayString>[X: {rows[0]}, Y: {rows[1]}, Z: {rows[2]}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">rows[0],nr</Item>
|
||||
<Item Name="[y]">rows[1],nr</Item>
|
||||
<Item Name="[z]">rows[2],nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Transform2D">
|
||||
<DisplayString>[X: {columns[0]}, Y: {columns[1]}, O: {columns[2]}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">columns[0],nr</Item>
|
||||
<Item Name="[y]">columns[1],nr</Item>
|
||||
<Item Name="[origin]">columns[2],nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Transform3D">
|
||||
<!-- Can't call column functions, so just pretend we can via obscene code duplication. -->
|
||||
<DisplayString>[X: ({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g}), Y: ({basis.rows[0].y,g}, {basis.rows[1].y,g}, {basis.rows[2].y,g}), Z: ({basis.rows[0].z,g}, {basis.rows[1].z,g}, {basis.rows[2].z,g}), O: {origin}]</DisplayString>
|
||||
<Expand>
|
||||
<Synthetic Name="[x]">
|
||||
<DisplayString>({basis.rows[0].x,g}, {basis.rows[1].x,g}, {basis.rows[2].x,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">basis.rows[0].x</Item>
|
||||
<Item Name="[y]">basis.rows[1].x</Item>
|
||||
<Item Name="[z]">basis.rows[2].x</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[y]">
|
||||
<DisplayString>({basis.rows[0].y,g}, {basis.rows[1].y,g}, {basis.rows[2].y,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">basis.rows[0].y</Item>
|
||||
<Item Name="[y]">basis.rows[1].y</Item>
|
||||
<Item Name="[z]">basis.rows[2].y</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[z]">
|
||||
<DisplayString>({basis.rows[0].z,g}, {basis.rows[1].z,g}, {basis.rows[2].z,g})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">basis.rows[0].z</Item>
|
||||
<Item Name="[y]">basis.rows[1].z</Item>
|
||||
<Item Name="[z]">basis.rows[2].z</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Item Name="[origin]">origin,nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="Projection">
|
||||
<DisplayString>[X: {columns[0]}, Y: {columns[1]}, Z: {columns[2]}, W: {columns[3]}]</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[x]">columns[0],nr</Item>
|
||||
<Item Name="[y]">columns[1],nr</Item>
|
||||
<Item Name="[z]">columns[2],nr</Item>
|
||||
<Item Name="[w]">columns[3],nr</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
#include "core/version.h"
|
||||
|
||||
#ifndef RT_MANIFEST
|
||||
#define RT_MANIFEST 24
|
||||
#endif
|
||||
|
||||
GODOT_ICON ICON platform/windows/godot_console.ico
|
||||
1 RT_MANIFEST "godot.manifest"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
|
||||
|
|
|
|||
|
|
@ -57,90 +57,6 @@ static const char dummy[8] __attribute__((section("pck"), used)) = { 0 };
|
|||
#endif
|
||||
#endif
|
||||
|
||||
PCHAR *
|
||||
CommandLineToArgvA(
|
||||
PCHAR CmdLine,
|
||||
int *_argc) {
|
||||
PCHAR *argv;
|
||||
PCHAR _argv;
|
||||
ULONG len;
|
||||
ULONG argc;
|
||||
CHAR a;
|
||||
ULONG i, j;
|
||||
|
||||
BOOLEAN in_QM;
|
||||
BOOLEAN in_TEXT;
|
||||
BOOLEAN in_SPACE;
|
||||
|
||||
len = strlen(CmdLine);
|
||||
i = ((len + 2) / 2) * sizeof(PVOID) + sizeof(PVOID);
|
||||
|
||||
argv = (PCHAR *)GlobalAlloc(GMEM_FIXED,
|
||||
i + (len + 2) * sizeof(CHAR));
|
||||
|
||||
_argv = (PCHAR)(((PUCHAR)argv) + i);
|
||||
|
||||
argc = 0;
|
||||
argv[argc] = _argv;
|
||||
in_QM = FALSE;
|
||||
in_TEXT = FALSE;
|
||||
in_SPACE = TRUE;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
a = CmdLine[i];
|
||||
while (a) {
|
||||
if (in_QM) {
|
||||
if (a == '\"') {
|
||||
in_QM = FALSE;
|
||||
} else {
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
switch (a) {
|
||||
case '\"':
|
||||
in_QM = TRUE;
|
||||
in_TEXT = TRUE;
|
||||
if (in_SPACE) {
|
||||
argv[argc] = _argv + j;
|
||||
argc++;
|
||||
}
|
||||
in_SPACE = FALSE;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if (in_TEXT) {
|
||||
_argv[j] = '\0';
|
||||
j++;
|
||||
}
|
||||
in_TEXT = FALSE;
|
||||
in_SPACE = TRUE;
|
||||
break;
|
||||
default:
|
||||
in_TEXT = TRUE;
|
||||
if (in_SPACE) {
|
||||
argv[argc] = _argv + j;
|
||||
argc++;
|
||||
}
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
in_SPACE = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
a = CmdLine[i];
|
||||
}
|
||||
_argv[j] = '\0';
|
||||
argv[argc] = nullptr;
|
||||
|
||||
(*_argc) = argc;
|
||||
return argv;
|
||||
}
|
||||
|
||||
char *wc_to_utf8(const wchar_t *wc) {
|
||||
int ulen = WideCharToMultiByte(CP_UTF8, 0, wc, -1, nullptr, 0, nullptr, nullptr);
|
||||
char *ubuf = new char[ulen + 1];
|
||||
|
|
|
|||
|
|
@ -46,17 +46,23 @@ DWORD WINAPI _xinput_set_state(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration)
|
|||
return ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
MMRESULT WINAPI _winmm_get_joycaps(UINT uJoyID, LPJOYCAPSW pjc, UINT cbjc) {
|
||||
return MMSYSERR_NODRIVER;
|
||||
}
|
||||
|
||||
JoypadWindows::JoypadWindows() {
|
||||
}
|
||||
|
||||
JoypadWindows::JoypadWindows(HWND *hwnd) {
|
||||
input = Input::get_singleton();
|
||||
hWnd = hwnd;
|
||||
joypad_count = 0;
|
||||
x_joypad_probe_count = 0;
|
||||
d_joypad_count = 0;
|
||||
dinput = nullptr;
|
||||
xinput_dll = nullptr;
|
||||
xinput_get_state = nullptr;
|
||||
xinput_set_state = nullptr;
|
||||
winmm_get_joycaps = nullptr;
|
||||
|
||||
load_xinput();
|
||||
|
||||
|
|
@ -79,14 +85,15 @@ JoypadWindows::JoypadWindows(HWND *hwnd) {
|
|||
}
|
||||
|
||||
JoypadWindows::~JoypadWindows() {
|
||||
close_joypad();
|
||||
close_d_joypad();
|
||||
if (dinput) {
|
||||
dinput->Release();
|
||||
}
|
||||
unload_winmm();
|
||||
unload_xinput();
|
||||
}
|
||||
|
||||
bool JoypadWindows::have_device(const GUID &p_guid) {
|
||||
bool JoypadWindows::is_d_joypad_known(const GUID &p_guid) {
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
if (d_joypads[i].guid == p_guid) {
|
||||
d_joypads[i].confirmed = true;
|
||||
|
|
@ -97,7 +104,7 @@ bool JoypadWindows::have_device(const GUID &p_guid) {
|
|||
}
|
||||
|
||||
// adapted from SDL2, works a lot better than the MSDN version
|
||||
bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
|
||||
bool JoypadWindows::is_xinput_joypad(const GUID *p_guid) {
|
||||
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x28DE, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
|
|
@ -122,8 +129,9 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
|
|||
memcmp(p_guid, &IID_XOneSWirelessGamepad, sizeof(*p_guid)) == 0 ||
|
||||
memcmp(p_guid, &IID_XOneSBluetoothGamepad, sizeof(*p_guid)) == 0 ||
|
||||
memcmp(p_guid, &IID_XOneEliteWirelessGamepad, sizeof(*p_guid)) == 0 ||
|
||||
memcmp(p_guid, &IID_XOneElite2WirelessGamepad, sizeof(*p_guid)) == 0)
|
||||
memcmp(p_guid, &IID_XOneElite2WirelessGamepad, sizeof(*p_guid)) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PRAWINPUTDEVICELIST dev_list = nullptr;
|
||||
unsigned int dev_list_count = 0;
|
||||
|
|
@ -158,12 +166,56 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void JoypadWindows::probe_xinput_joypad(const String &name) {
|
||||
if (x_joypad_probe_count >= XUSER_MAX_COUNT) {
|
||||
return;
|
||||
}
|
||||
int i = x_joypad_probe_count;
|
||||
x_joypad_probe_count++;
|
||||
|
||||
ZeroMemory(&x_joypads[i].state, sizeof(XINPUT_STATE));
|
||||
|
||||
DWORD dwResult = xinput_get_state(i, &x_joypads[i].state);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
int id = input->get_unused_joy_id();
|
||||
if (id != -1 && !x_joypads[i].attached) {
|
||||
x_joypads[i].attached = true;
|
||||
x_joypads[i].id = id;
|
||||
x_joypads[i].ff_timestamp = 0;
|
||||
x_joypads[i].ff_end_timestamp = 0;
|
||||
x_joypads[i].vibrating = false;
|
||||
attached_joypads[id] = true;
|
||||
Dictionary joypad_info;
|
||||
String joypad_name;
|
||||
|
||||
joypad_info["xinput_index"] = (int)i;
|
||||
|
||||
JOYCAPSW jc;
|
||||
memset(&jc, 0, sizeof(JOYCAPSW));
|
||||
MMRESULT jcResult = winmm_get_joycaps((UINT)id, &jc, sizeof(JOYCAPSW));
|
||||
if (jcResult == JOYERR_NOERROR) {
|
||||
joypad_info["vendor_id"] = itos(jc.wMid);
|
||||
joypad_info["product_id"] = itos(jc.wPid);
|
||||
if (!name.is_empty()) {
|
||||
joypad_name = name.trim_prefix("Controller (").trim_suffix(")");
|
||||
}
|
||||
}
|
||||
|
||||
input->joy_connection_changed(id, true, joypad_name, "__XINPUT_DEVICE__", joypad_info);
|
||||
}
|
||||
} else if (x_joypads[i].attached) {
|
||||
x_joypads[i].attached = false;
|
||||
attached_joypads[x_joypads[i].id] = false;
|
||||
input->joy_connection_changed(x_joypads[i].id, false, "");
|
||||
}
|
||||
}
|
||||
|
||||
bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE *instance) {
|
||||
ERR_FAIL_NULL_V_MSG(dinput, false, "DirectInput not initialized. Rebooting your PC may solve this issue.");
|
||||
HRESULT hr;
|
||||
int num = input->get_unused_joy_id();
|
||||
|
||||
if (have_device(instance->guidInstance) || num == -1) {
|
||||
if (is_d_joypad_known(instance->guidInstance) || num == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -192,6 +244,10 @@ bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE *instance) {
|
|||
WORD version = 0;
|
||||
sprintf_s(uid, "%04x%04x%04x%04x%04x%04x%04x%04x", type, 0, vendor, 0, product, 0, version, 0);
|
||||
|
||||
Dictionary joypad_info;
|
||||
joypad_info["vendor_id"] = itos(vendor);
|
||||
joypad_info["product_id"] = itos(product);
|
||||
|
||||
id_to_change = num;
|
||||
slider_count = 0;
|
||||
|
||||
|
|
@ -201,16 +257,17 @@ bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE *instance) {
|
|||
joy->joy_axis.sort();
|
||||
|
||||
joy->guid = instance->guidInstance;
|
||||
input->joy_connection_changed(num, true, instance->tszProductName, uid);
|
||||
const String &name = String(instance->tszProductName).trim_prefix("Controller (").trim_suffix(")");
|
||||
input->joy_connection_changed(num, true, name, uid, joypad_info);
|
||||
joy->attached = true;
|
||||
joy->id = num;
|
||||
attached_joypads[num] = true;
|
||||
joy->confirmed = true;
|
||||
joypad_count++;
|
||||
d_joypad_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoypadWindows::setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id) {
|
||||
void JoypadWindows::setup_d_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id) {
|
||||
if (ob->dwType & DIDFT_AXIS) {
|
||||
HRESULT res;
|
||||
DIPROPRANGE prop_range;
|
||||
|
|
@ -269,7 +326,8 @@ void JoypadWindows::setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_
|
|||
|
||||
BOOL CALLBACK JoypadWindows::enumCallback(const DIDEVICEINSTANCE *p_instance, void *p_context) {
|
||||
JoypadWindows *self = static_cast<JoypadWindows *>(p_context);
|
||||
if (self->is_xinput_device(&p_instance->guidProduct)) {
|
||||
if (self->is_xinput_joypad(&p_instance->guidProduct)) {
|
||||
self->probe_xinput_joypad(p_instance->tszProductName);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
self->setup_dinput_joypad(p_instance);
|
||||
|
|
@ -278,15 +336,15 @@ BOOL CALLBACK JoypadWindows::enumCallback(const DIDEVICEINSTANCE *p_instance, vo
|
|||
|
||||
BOOL CALLBACK JoypadWindows::objectsCallback(const DIDEVICEOBJECTINSTANCE *p_instance, void *p_context) {
|
||||
JoypadWindows *self = static_cast<JoypadWindows *>(p_context);
|
||||
self->setup_joypad_object(p_instance, self->id_to_change);
|
||||
self->setup_d_joypad_object(p_instance, self->id_to_change);
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
void JoypadWindows::close_joypad(int id) {
|
||||
void JoypadWindows::close_d_joypad(int id) {
|
||||
if (id == -1) {
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
close_joypad(i);
|
||||
close_d_joypad(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -301,45 +359,29 @@ void JoypadWindows::close_joypad(int id) {
|
|||
attached_joypads[d_joypads[id].id] = false;
|
||||
d_joypads[id].guid.Data1 = d_joypads[id].guid.Data2 = d_joypads[id].guid.Data3 = 0;
|
||||
input->joy_connection_changed(d_joypads[id].id, false, "");
|
||||
joypad_count--;
|
||||
d_joypad_count--;
|
||||
}
|
||||
|
||||
void JoypadWindows::probe_joypads() {
|
||||
ERR_FAIL_NULL_MSG(dinput, "DirectInput not initialized. Rebooting your PC may solve this issue.");
|
||||
DWORD dwResult;
|
||||
for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
ZeroMemory(&x_joypads[i].state, sizeof(XINPUT_STATE));
|
||||
|
||||
dwResult = xinput_get_state(i, &x_joypads[i].state);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
int id = input->get_unused_joy_id();
|
||||
if (id != -1 && !x_joypads[i].attached) {
|
||||
x_joypads[i].attached = true;
|
||||
x_joypads[i].id = id;
|
||||
x_joypads[i].ff_timestamp = 0;
|
||||
x_joypads[i].ff_end_timestamp = 0;
|
||||
x_joypads[i].vibrating = false;
|
||||
attached_joypads[id] = true;
|
||||
Dictionary joypad_info;
|
||||
joypad_info["xinput_index"] = (int)i;
|
||||
input->joy_connection_changed(id, true, "XInput Gamepad", "__XINPUT_DEVICE__", joypad_info);
|
||||
}
|
||||
} else if (x_joypads[i].attached) {
|
||||
x_joypads[i].attached = false;
|
||||
attached_joypads[x_joypads[i].id] = false;
|
||||
input->joy_connection_changed(x_joypads[i].id, false, "");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < joypad_count; i++) {
|
||||
d_joypads[i].confirmed = false;
|
||||
for (int i = 0; i < d_joypad_count; i++) {
|
||||
d_joypads[i].confirmed = false; // Flag DirectInput devices for re-checking their availability.
|
||||
}
|
||||
|
||||
x_joypad_probe_count = 0;
|
||||
// Probe _all attached_ joypad devices.
|
||||
dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback, this, DIEDFL_ATTACHEDONLY);
|
||||
|
||||
for (int i = 0; i < joypad_count; i++) {
|
||||
for (int i = x_joypad_probe_count; i < XUSER_MAX_COUNT; i++) {
|
||||
// Handle disconnect of XInput devices.
|
||||
// And act as a fallback, just in case DirectInput could not find the device.
|
||||
probe_xinput_joypad();
|
||||
}
|
||||
|
||||
for (int i = 0; i < d_joypad_count; i++) {
|
||||
if (!d_joypads[i].confirmed) {
|
||||
close_joypad(i);
|
||||
close_d_joypad(i); // Any DirectInput device not found during probing is considered as disconnected.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -347,6 +389,7 @@ void JoypadWindows::probe_joypads() {
|
|||
void JoypadWindows::process_joypads() {
|
||||
HRESULT hr;
|
||||
|
||||
// Handle XInput joypads.
|
||||
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
xinput_gamepad &joy = x_joypads[i];
|
||||
if (!joy.attached) {
|
||||
|
|
@ -387,6 +430,7 @@ void JoypadWindows::process_joypads() {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle DirectIndput joypads.
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
dinput_gamepad *joy = &d_joypads[i];
|
||||
|
||||
|
|
@ -534,7 +578,9 @@ void JoypadWindows::joypad_vibration_stop_xinput(int p_device, uint64_t p_timest
|
|||
void JoypadWindows::load_xinput() {
|
||||
xinput_get_state = &_xinput_get_state;
|
||||
xinput_set_state = &_xinput_set_state;
|
||||
winmm_get_joycaps = &_winmm_get_joycaps;
|
||||
bool legacy_xinput = false;
|
||||
|
||||
xinput_dll = LoadLibrary("XInput1_4.dll");
|
||||
if (!xinput_dll) {
|
||||
xinput_dll = LoadLibrary("XInput1_3.dll");
|
||||
|
|
@ -559,6 +605,16 @@ void JoypadWindows::load_xinput() {
|
|||
}
|
||||
xinput_get_state = func;
|
||||
xinput_set_state = set_func;
|
||||
|
||||
winmm_dll = LoadLibrary("Winmm.dll");
|
||||
if (winmm_dll) {
|
||||
joyGetDevCaps_t caps_func = (joyGetDevCaps_t)GetProcAddress((HMODULE)winmm_dll, "joyGetDevCapsW");
|
||||
if (caps_func) {
|
||||
winmm_get_joycaps = caps_func;
|
||||
} else {
|
||||
unload_winmm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadWindows::unload_xinput() {
|
||||
|
|
@ -566,3 +622,9 @@ void JoypadWindows::unload_xinput() {
|
|||
FreeLibrary((HMODULE)xinput_dll);
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadWindows::unload_winmm() {
|
||||
if (winmm_dll) {
|
||||
FreeLibrary((HMODULE)winmm_dll);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#include <dinput.h>
|
||||
#include <xinput.h>
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
#ifndef SAFE_RELEASE // when Windows Media Device M? is not present
|
||||
#define SAFE_RELEASE(x) \
|
||||
if (x != nullptr) { \
|
||||
|
|
@ -107,14 +109,18 @@ private:
|
|||
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE *pState);
|
||||
typedef DWORD(WINAPI *XInputSetState_t)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
|
||||
|
||||
typedef MMRESULT(WINAPI *joyGetDevCaps_t)(UINT uJoyID, LPJOYCAPSW pjc, UINT cbjc);
|
||||
|
||||
HWND *hWnd = nullptr;
|
||||
HANDLE xinput_dll;
|
||||
HANDLE winmm_dll;
|
||||
LPDIRECTINPUT8 dinput;
|
||||
Input *input = nullptr;
|
||||
|
||||
int id_to_change;
|
||||
int slider_count;
|
||||
int joypad_count;
|
||||
int x_joypad_probe_count; // XInput equivalent to dinput_gamepad.confirmed.
|
||||
int d_joypad_count;
|
||||
bool attached_joypads[JOYPADS_MAX];
|
||||
dinput_gamepad d_joypads[JOYPADS_MAX];
|
||||
xinput_gamepad x_joypads[XUSER_MAX_COUNT];
|
||||
|
|
@ -122,22 +128,25 @@ private:
|
|||
static BOOL CALLBACK enumCallback(const DIDEVICEINSTANCE *p_instance, void *p_context);
|
||||
static BOOL CALLBACK objectsCallback(const DIDEVICEOBJECTINSTANCE *instance, void *context);
|
||||
|
||||
void setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id);
|
||||
void close_joypad(int id = -1);
|
||||
void setup_d_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id);
|
||||
void close_d_joypad(int id = -1);
|
||||
void load_xinput();
|
||||
void unload_xinput();
|
||||
void unload_winmm();
|
||||
|
||||
void post_hat(int p_device, DWORD p_dpad);
|
||||
|
||||
bool have_device(const GUID &p_guid);
|
||||
bool is_xinput_device(const GUID *p_guid);
|
||||
bool is_d_joypad_known(const GUID &p_guid);
|
||||
bool is_xinput_joypad(const GUID *p_guid);
|
||||
bool setup_dinput_joypad(const DIDEVICEINSTANCE *instance);
|
||||
void probe_xinput_joypad(const String &name = ""); // Handles connect, disconnect & re-connect for XInput joypads.
|
||||
void joypad_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
|
||||
void joypad_vibration_stop_xinput(int p_device, uint64_t p_timestamp);
|
||||
|
||||
float axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
|
||||
XInputGetState_t xinput_get_state;
|
||||
XInputSetState_t xinput_set_state;
|
||||
joyGetDevCaps_t winmm_get_joycaps; // Only for reading info on XInput joypads.
|
||||
};
|
||||
|
||||
#endif // JOYPAD_WINDOWS_H
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ Size2 NativeMenuWindows::get_size(const RID &p_rid) const {
|
|||
int count = GetMenuItemCount(md->menu);
|
||||
for (int i = 0; i < count; i++) {
|
||||
RECT rect;
|
||||
if (GetMenuItemRect(NULL, md->menu, i, &rect)) {
|
||||
if (GetMenuItemRect(nullptr, md->menu, i, &rect)) {
|
||||
size.x = MAX(size.x, rect.right - rect.left);
|
||||
size.y += rect.bottom - rect.top;
|
||||
}
|
||||
|
|
@ -177,6 +177,16 @@ void NativeMenuWindows::popup(const RID &p_rid, const Vector2i &p_position) {
|
|||
}
|
||||
SetForegroundWindow(hwnd);
|
||||
TrackPopupMenuEx(md->menu, flags, p_position.x, p_position.y, hwnd, nullptr);
|
||||
|
||||
if (md->close_cb.is_valid()) {
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
md->close_cb.callp(nullptr, 0, ret, ce);
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
ERR_PRINT(vformat("Failed to execute popup close callback: %s.", Variant::get_callable_error_text(md->close_cb, nullptr, 0, ce)));
|
||||
}
|
||||
}
|
||||
|
||||
PostMessage(hwnd, WM_NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -200,12 +210,17 @@ Callable NativeMenuWindows::get_popup_open_callback(const RID &p_rid) const {
|
|||
}
|
||||
|
||||
void NativeMenuWindows::set_popup_close_callback(const RID &p_rid, const Callable &p_callback) {
|
||||
// Not supported.
|
||||
MenuData *md = menus.get_or_null(p_rid);
|
||||
ERR_FAIL_NULL(md);
|
||||
|
||||
md->close_cb = p_callback;
|
||||
}
|
||||
|
||||
Callable NativeMenuWindows::get_popup_close_callback(const RID &p_rid) const {
|
||||
// Not supported.
|
||||
return Callable();
|
||||
const MenuData *md = menus.get_or_null(p_rid);
|
||||
ERR_FAIL_NULL_V(md, Callable());
|
||||
|
||||
return md->close_cb;
|
||||
}
|
||||
|
||||
void NativeMenuWindows::set_minimum_width(const RID &p_rid, float p_width) {
|
||||
|
|
@ -992,7 +1007,7 @@ void NativeMenuWindows::set_item_submenu(const RID &p_rid, int p_idx, const RID
|
|||
if (p_submenu_rid.is_valid()) {
|
||||
item.hSubMenu = md_sub->menu;
|
||||
} else {
|
||||
item.hSubMenu = 0;
|
||||
item.hSubMenu = nullptr;
|
||||
}
|
||||
SetMenuItemInfoW(md->menu, p_idx, true, &item);
|
||||
}
|
||||
|
|
@ -1095,7 +1110,7 @@ void NativeMenuWindows::set_item_icon(const RID &p_rid, int p_idx, const Ref<Tex
|
|||
item_data->bmp = _make_bitmap(item_data->img);
|
||||
} else {
|
||||
item_data->img = Ref<Image>();
|
||||
item_data->bmp = 0;
|
||||
item_data->bmp = nullptr;
|
||||
}
|
||||
item.hbmpItem = item_data->bmp;
|
||||
SetMenuItemInfoW(md->menu, p_idx, true, &item);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#ifndef NATIVE_MENU_WINDOWS_H
|
||||
#define NATIVE_MENU_WINDOWS_H
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/display/native_menu.h"
|
||||
|
|
@ -60,6 +61,8 @@ class NativeMenuWindows : public NativeMenu {
|
|||
|
||||
struct MenuData {
|
||||
HMENU menu = 0;
|
||||
|
||||
Callable close_cb;
|
||||
bool is_rtl = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,7 +37,6 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/os/os.h"
|
||||
#include "drivers/unix/ip_unix.h"
|
||||
#include "drivers/wasapi/audio_driver_wasapi.h"
|
||||
#include "drivers/winmidi/midi_driver_winmidi.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
|
@ -95,8 +94,10 @@ public:
|
|||
class JoypadWindows;
|
||||
|
||||
class OS_Windows : public OS {
|
||||
uint64_t target_ticks = 0;
|
||||
uint64_t ticks_start = 0;
|
||||
uint64_t ticks_per_second = 0;
|
||||
uint64_t delay_resolution = 1000;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
MainLoop *main_loop = nullptr;
|
||||
|
|
@ -134,6 +135,8 @@ class OS_Windows : public OS {
|
|||
DWRITE_FONT_WEIGHT _weight_to_dw(int p_weight) const;
|
||||
DWRITE_FONT_STRETCH _stretch_to_dw(int p_stretch) const;
|
||||
|
||||
bool is_using_con_wrapper() const;
|
||||
|
||||
// functions used by main to initialize/deinitialize the OS
|
||||
protected:
|
||||
virtual void initialize() override;
|
||||
|
|
@ -143,12 +146,17 @@ protected:
|
|||
|
||||
virtual void finalize() override;
|
||||
virtual void finalize_core() override;
|
||||
virtual String get_stdin_string() override;
|
||||
|
||||
virtual String get_stdin_string(int64_t p_buffer_size = 1024) override;
|
||||
virtual PackedByteArray get_stdin_buffer(int64_t p_buffer_size = 1024) override;
|
||||
virtual StdHandleType get_stdin_type() const override;
|
||||
virtual StdHandleType get_stdout_type() const override;
|
||||
virtual StdHandleType get_stderr_type() const override;
|
||||
|
||||
String _quote_command_line_argument(const String &p_text) const;
|
||||
|
||||
struct ProcessInfo {
|
||||
STARTUPINFO si;
|
||||
STARTUPINFOEX si;
|
||||
PROCESS_INFORMATION pi;
|
||||
mutable bool is_running = true;
|
||||
mutable int exit_code = -1;
|
||||
|
|
@ -170,8 +178,10 @@ public:
|
|||
virtual String get_name() const override;
|
||||
virtual String get_distribution_name() const override;
|
||||
virtual String get_version() const override;
|
||||
virtual String get_version_alias() const override;
|
||||
|
||||
virtual Vector<String> get_video_adapter_driver_info() const override;
|
||||
virtual bool get_user_prefers_integrated_gpu() const override;
|
||||
|
||||
virtual void initialize_joypads() override {}
|
||||
|
||||
|
|
@ -181,13 +191,14 @@ public:
|
|||
|
||||
virtual Error set_cwd(const String &p_cwd) override;
|
||||
|
||||
virtual void add_frame_delay(bool p_can_draw) override;
|
||||
virtual void delay_usec(uint32_t p_usec) const override;
|
||||
virtual uint64_t get_ticks_usec() const override;
|
||||
|
||||
virtual Dictionary get_memory_info() const override;
|
||||
|
||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
|
||||
virtual Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments) override;
|
||||
virtual Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments, bool p_blocking = true) override;
|
||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||
virtual Error kill(const ProcessID &p_pid) override;
|
||||
virtual int get_process_id() const override;
|
||||
|
|
@ -209,15 +220,18 @@ public:
|
|||
|
||||
virtual String get_processor_name() const override;
|
||||
|
||||
virtual String get_model_name() const override;
|
||||
|
||||
virtual uint64_t get_embedded_pck_offset() const override;
|
||||
|
||||
virtual String get_config_path() const override;
|
||||
virtual String get_data_path() const override;
|
||||
virtual String get_cache_path() const override;
|
||||
virtual String get_temp_path() const override;
|
||||
virtual String get_godot_dir_name() const override;
|
||||
|
||||
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
|
||||
virtual String get_user_data_dir() const override;
|
||||
virtual String get_user_data_dir(const String &p_user_dir) const override;
|
||||
|
||||
virtual String get_unique_id() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,23 +2,11 @@
|
|||
|
||||
import os
|
||||
|
||||
from detect import get_mingw_bin_prefix, try_cmd
|
||||
|
||||
|
||||
def make_debug_mingw(target, source, env):
|
||||
dst = str(target[0])
|
||||
# Force separate debug symbols if executable size is larger than 1.9 GB.
|
||||
if env["separate_debug_symbols"] or os.stat(dst).st_size >= 2040109465:
|
||||
mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
|
||||
if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
|
||||
os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst))
|
||||
else:
|
||||
os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst))
|
||||
if try_cmd("strip --version", env["mingw_prefix"], env["arch"]):
|
||||
os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(dst))
|
||||
else:
|
||||
os.system("strip --strip-debug --strip-unneeded {0}".format(dst))
|
||||
if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
|
||||
os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst))
|
||||
else:
|
||||
os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst))
|
||||
os.system("{0} --only-keep-debug {1} {1}.debugsymbols".format(env["OBJCOPY"], dst))
|
||||
os.system("{0} --strip-debug --strip-unneeded {1}".format(env["STRIP"], dst))
|
||||
os.system("{0} --add-gnu-debuglink={1}.debugsymbols {1}".format(env["OBJCOPY"], dst))
|
||||
|
|
|
|||
|
|
@ -34,11 +34,7 @@
|
|||
|
||||
#include "rendering_context_driver_vulkan_windows.h"
|
||||
|
||||
#ifdef USE_VOLK
|
||||
#include <volk.h>
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#include "drivers/vulkan/godot_vulkan.h"
|
||||
|
||||
const char *RenderingContextDriverVulkanWindows::_get_platform_surface_extension() const {
|
||||
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
|
||||
|
|
@ -64,7 +60,7 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWindows::surface_c
|
|||
create_info.hwnd = wpd->window;
|
||||
|
||||
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
|
||||
VkResult err = vkCreateWin32SurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
|
||||
VkResult err = vkCreateWin32SurfaceKHR(instance_get(), &create_info, get_allocation_callbacks(VK_OBJECT_TYPE_SURFACE_KHR), &vk_surface);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
|
||||
|
||||
Surface *surface = memnew(Surface);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam)
|
|||
} else if (event.eEventId == SPEI_END_INPUT_STREAM) {
|
||||
DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, tts->ids[stream_num].id);
|
||||
tts->ids.erase(stream_num);
|
||||
tts->_update_tts();
|
||||
tts->update_requested = true;
|
||||
} else if (event.eEventId == SPEI_WORD_BOUNDARY) {
|
||||
const Char16String &string = tts->ids[stream_num].string;
|
||||
int pos = 0;
|
||||
|
|
@ -60,8 +60,8 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
|
||||
void TTS_Windows::_update_tts() {
|
||||
if (!is_speaking() && !paused && queue.size() > 0) {
|
||||
void TTS_Windows::process_events() {
|
||||
if (update_requested && !paused && queue.size() > 0 && !is_speaking()) {
|
||||
DisplayServer::TTSUtterance &message = queue.front()->get();
|
||||
|
||||
String text;
|
||||
|
|
@ -110,6 +110,8 @@ void TTS_Windows::_update_tts() {
|
|||
ids[(uint32_t)stream_number] = ut;
|
||||
|
||||
queue.pop_front();
|
||||
|
||||
update_requested = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +209,7 @@ void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volum
|
|||
if (is_paused()) {
|
||||
resume();
|
||||
} else {
|
||||
_update_tts();
|
||||
update_requested = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ class TTS_Windows {
|
|||
int id;
|
||||
};
|
||||
HashMap<uint32_t, UTData> ids;
|
||||
bool update_requested = false;
|
||||
|
||||
static void __stdcall speech_event_callback(WPARAM wParam, LPARAM lParam);
|
||||
void _update_tts();
|
||||
|
||||
static TTS_Windows *singleton;
|
||||
|
||||
|
|
@ -73,6 +73,8 @@ public:
|
|||
void resume();
|
||||
void stop();
|
||||
|
||||
void process_events();
|
||||
|
||||
TTS_Windows();
|
||||
~TTS_Windows();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "windows_terminal_logger.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -78,8 +80,8 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
|
|||
}
|
||||
|
||||
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
|
||||
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
if (OS::get_singleton()->get_stdout_type() != OS::STD_HANDLE_CONSOLE || !hCon || hCon == INVALID_HANDLE_VALUE) {
|
||||
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
|
||||
} else {
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
|
||||
GetConsoleScreenBufferInfo(hCon, &sbi);
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
|
|||
{
|
||||
// The custom LoadLibraryExW is used instead of open_dynamic_library
|
||||
// to avoid loading the original PDB into the debugger.
|
||||
HMODULE library_ptr = LoadLibraryExW((LPCWSTR)(p_dll_path.utf16().get_data()), NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
|
||||
HMODULE library_ptr = LoadLibraryExW((LPCWSTR)(p_dll_path.utf16().get_data()), nullptr, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
|
||||
|
||||
ERR_FAIL_NULL_V_MSG(library_ptr, ERR_FILE_CANT_OPEN, vformat("Failed to load library '%s'.", p_dll_path));
|
||||
|
||||
IMAGE_DEBUG_DIRECTORY *dbg_dir = (IMAGE_DEBUG_DIRECTORY *)ImageDirectoryEntryToDataEx(library_ptr, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dbg_info_size, NULL);
|
||||
IMAGE_DEBUG_DIRECTORY *dbg_dir = (IMAGE_DEBUG_DIRECTORY *)ImageDirectoryEntryToDataEx(library_ptr, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dbg_info_size, nullptr);
|
||||
|
||||
bool has_debug = dbg_dir && dbg_dir->Type == IMAGE_DEBUG_TYPE_CODEVIEW;
|
||||
if (has_debug) {
|
||||
|
|
@ -155,7 +155,11 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
|
|||
} else if (!FileAccess::exists(copy_pdb_path)) {
|
||||
copy_pdb_path = dll_base_dir.path_join(copy_pdb_path.get_file());
|
||||
}
|
||||
ERR_FAIL_COND_V_MSG(!FileAccess::exists(copy_pdb_path), FAILED, vformat("File '%s' does not exist.", copy_pdb_path));
|
||||
if (!FileAccess::exists(copy_pdb_path)) {
|
||||
// The PDB file may be distributed separately on purpose, so we don't consider this an error.
|
||||
WARN_VERBOSE(vformat("PDB file '%s' for library '%s' was not found, skipping copy/rename.", copy_pdb_path, p_dll_path));
|
||||
return ERR_SKIP;
|
||||
}
|
||||
|
||||
String new_pdb_base_name = p_dll_path.get_file().get_basename() + "_";
|
||||
|
||||
|
|
@ -175,9 +179,7 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
|
|||
if (new_expected_buffer_size > original_path_size) {
|
||||
ERR_FAIL_COND_V_MSG(original_path_size < min_base_size + suffix_size, FAILED, vformat("The original PDB path size in bytes is too small: '%s'. Expected size: %d or more bytes, but available %d.", pdb_info.path, min_base_size + suffix_size, original_path_size));
|
||||
|
||||
utf8_name.resize(original_path_size - suffix_size + 1); // +1 for the \0
|
||||
utf8_name[utf8_name.size() - 1] = '\0';
|
||||
new_pdb_base_name.parse_utf8(utf8_name);
|
||||
new_pdb_base_name.parse_utf8(utf8_name, original_path_size - suffix_size);
|
||||
new_pdb_base_name[new_pdb_base_name.length() - 1] = '_'; // Restore the last '_'
|
||||
WARN_PRINT(vformat("The original path size of '%s' in bytes was too small to fit the new name, so it was shortened to '%s%d.pdb'.", pdb_info.path, new_pdb_base_name, max_pdb_names - 1));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue