feat: Introduce terrain SVG export functionality via FFI to a Windows DLL, providing an Arma 3 exportSVG command.
This commit is contained in:
parent
082f0c6f8f
commit
4d7e3520eb
@ -4,29 +4,31 @@
|
|||||||
//! rendering options (location names, grid, contour lines, etc.).
|
//! rendering options (location names, grid, contour lines, etc.).
|
||||||
|
|
||||||
use arma_rs::Group;
|
use arma_rs::Group;
|
||||||
use std::ffi::CString;
|
|
||||||
use std::os::raw::{c_char, c_void};
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
#[link(name = "kernel32")]
|
mod windows_ffi {
|
||||||
unsafe extern "stdcall" {
|
use std::os::raw::{c_char, c_void};
|
||||||
fn GetModuleHandleA(lpModuleName: *const u8) -> *mut c_void;
|
|
||||||
fn LoadLibraryA(lpLibFileName: *const u8) -> *mut c_void;
|
#[link(name = "kernel32")]
|
||||||
fn GetProcAddress(hModule: *mut c_void, lpProcName: *const u8) -> *mut c_void;
|
unsafe extern "system" {
|
||||||
|
pub(super) fn GetModuleHandleA(lpModuleName: *const u8) -> *mut c_void;
|
||||||
|
pub(super) fn LoadLibraryA(lpLibFileName: *const u8) -> *mut c_void;
|
||||||
|
pub(super) fn GetProcAddress(hModule: *mut c_void, lpProcName: *const u8) -> *mut c_void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mangled C++ name for the ExportSVG function.
|
||||||
|
/// Format: `?ExportSVG@@YAXPEBD_N11111@Z` matches signature:
|
||||||
|
/// `void ExportSVG(const char*, bool, bool, bool, bool, bool, bool)`
|
||||||
|
pub(super) const EXPORT_SVG_PROC_NAME: &[u8] = b"?ExportSVG@@YAXPEBD_N11111@Z\0";
|
||||||
|
|
||||||
|
/// Name of the DLL containing the ExportSVG function.
|
||||||
|
/// Update this to match your actual DLL name.
|
||||||
|
pub(super) const TERRAIN_DLL_NAME: &[u8] = b"TerrainExport.dll\0";
|
||||||
|
|
||||||
|
pub(super) type FnExportSVG =
|
||||||
|
extern "system" fn(*const c_char, bool, bool, bool, bool, bool, bool) -> *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mangled C++ name for the ExportSVG function.
|
|
||||||
/// Format: `?ExportSVG@@YAXPEBD_N11111@Z` matches signature:
|
|
||||||
/// `void ExportSVG(const char*, bool, bool, bool, bool, bool, bool)`
|
|
||||||
const EXPORT_SVG_PROC_NAME: &[u8] = b"?ExportSVG@@YAXPEBD_N11111@Z\0";
|
|
||||||
|
|
||||||
/// Name of the DLL containing the ExportSVG function.
|
|
||||||
/// Update this to match your actual DLL name.
|
|
||||||
const TERRAIN_DLL_NAME: &[u8] = b"TerrainExport.dll\0";
|
|
||||||
|
|
||||||
type FnExportSVG =
|
|
||||||
extern "stdcall" fn(*const c_char, bool, bool, bool, bool, bool, bool) -> *const c_void;
|
|
||||||
|
|
||||||
/// Creates the Arma 3 command group for the terrain module.
|
/// Creates the Arma 3 command group for the terrain module.
|
||||||
///
|
///
|
||||||
/// Registers the `exportSVG` command with the Arma 3 extension.
|
/// Registers the `exportSVG` command with the Arma 3 extension.
|
||||||
@ -59,6 +61,8 @@ pub fn export_terrain_svg(
|
|||||||
simple_roads: bool,
|
simple_roads: bool,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
use windows_ffi::*;
|
||||||
|
|
||||||
// Try to get already loaded module, or load the DLL
|
// Try to get already loaded module, or load the DLL
|
||||||
let module = GetModuleHandleA(TERRAIN_DLL_NAME.as_ptr());
|
let module = GetModuleHandleA(TERRAIN_DLL_NAME.as_ptr());
|
||||||
let module = if module.is_null() {
|
let module = if module.is_null() {
|
||||||
@ -85,7 +89,7 @@ pub fn export_terrain_svg(
|
|||||||
|
|
||||||
// Convert file path to C string
|
// Convert file path to C string
|
||||||
let file_path_cstr =
|
let file_path_cstr =
|
||||||
CString::new(file_path).map_err(|e| format!("Invalid file path: {}", e))?;
|
std::ffi::CString::new(file_path).map_err(|e| format!("Invalid file path: {}", e))?;
|
||||||
|
|
||||||
// Call the export function
|
// Call the export function
|
||||||
export_svg(
|
export_svg(
|
||||||
@ -137,15 +141,27 @@ struct ExportSvgOptions {
|
|||||||
///
|
///
|
||||||
/// # SQF Usage
|
/// # SQF Usage
|
||||||
/// ```sqf
|
/// ```sqf
|
||||||
/// ["forge", ["terrain", "exportSVG", "{
|
/// // Register callback handler (optional, for async result)
|
||||||
/// ""filePath"": ""C:\\path\\to\\output.svg"",
|
/// ["terrain:exportSVG", {
|
||||||
/// ""drawLocationNames"": true,
|
/// params ["_response"];
|
||||||
/// ""drawGrid"": true,
|
/// systemChat format ["Export %1: %2",
|
||||||
/// ""drawContourlines"": true,
|
/// _response get "status",
|
||||||
/// ""drawTreeObjects"": false,
|
/// _response get "message"
|
||||||
/// ""drawMountainHeightpoints"": true,
|
/// ];
|
||||||
/// ""simpleRoads"": false
|
/// }] call forge_x_extension_fnc_setHandler;
|
||||||
/// }"]] call forge_fnc_callExtension;
|
///
|
||||||
|
/// // Create options and call extension
|
||||||
|
/// private _options = createHashMapFromArray [
|
||||||
|
/// ["filePath", "C:\terrain.svg"],
|
||||||
|
/// ["drawLocationNames", true],
|
||||||
|
/// ["drawGrid", true],
|
||||||
|
/// ["drawContourlines", true],
|
||||||
|
/// ["drawTreeObjects", false],
|
||||||
|
/// ["drawMountainHeightpoints", true],
|
||||||
|
/// ["simpleRoads", false]
|
||||||
|
/// ];
|
||||||
|
///
|
||||||
|
/// ["terrain:exportSVG", [toJSON _options]] call forge_x_extension_fnc_extCall;
|
||||||
/// ```
|
/// ```
|
||||||
fn export_svg(options_json: String) -> String {
|
fn export_svg(options_json: String) -> String {
|
||||||
// Parse options from JSON
|
// Parse options from JSON
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user