Compare commits

19 Commits

Author SHA1 Message Date
305c0b1b65 doc: fix README 2024-11-08 15:17:45 +08:00
6f7202a86b feat: improve BMap bindings.
- Add IEquatable<T> interface for BMapSharp 2 abstract base classes to make they can be used in HashSet or Dictionary.
- Add corresponding testbench for this new added interface to make sure it works.
- Also add set and dict test for PyBMap although it has been proven works.
2024-11-08 14:58:50 +08:00
512729ed05 feat: improve PyBMap
- re-raise exception for run out of next() function to make end user know this is their fault, not PyBMap.
- write some primitive type getter setter for short code and less latent bugs.
- remove bmfile parameter in BMMeshTrans::Parse.
2024-11-07 20:56:16 +08:00
e2e7121c16 feat: update PyBMap and its testbench
- update PyBMap testbench according to BMapSharp testbench.
- use some wrapper function to fetch commonly used type in PyBMap to reduce line count.
- re-place some utils functions in PyBMap.
2024-11-07 17:28:11 +08:00
9dd46b88d9 dep: update stb.
- use a nasty way to update stb-image library (do not use new resize library, use moved depracted one. because idk how to program with new one. that lack doc).
2024-11-04 17:19:51 +08:00
7e7b21544d chore: update build script. 2024-11-04 14:58:53 +08:00
e72102496b fix: update YYCC dependency
- move EnumsHelper into YYCC because it is widely used.
- rename all calling to EnumsHelper due to this modification.
- add version checker in code to make sure that user use correct YYCC library to compile.
- modify some include syntax because the include directory layout changes of YYCC.
- update CMake script to resolve the bug that we can not export LibCmo (thanks doyaGu and BLumia).
2024-11-03 19:05:27 +08:00
73f1a1f829 fix: fix fatal layout issue about VxColor.
- fix wrong memory layout of VxColor.
2024-11-01 13:31:03 +08:00
33dc9a54be feat: finish BMapSharp
- basically finish BMapSharp bindings however done test does not cover all scenarios.
2024-11-01 11:13:05 +08:00
6eb95ddd1f feat: update BMapSharp
- finish BMMesh bindings.
- finish a half of BMMeshTrans bindings.
- use getGenericValue and setGenericValue for most bindings.
2024-11-01 10:48:45 +08:00
e8fedc8bff feat: update BMapSharp
- update virtools type defines in BMapSharp. expand its ctor for convenient usage.
- finish BMMaterial bindings.
- create a generic value getter setter for convenient calling.
- fix codegen error of BMapSharp (accident fallthrough for CKBYTE type and wrong marshal type for enum type).
2024-10-31 17:15:06 +08:00
74268d4ad4 feat: update BMapSharp
- finish BMTexture bindings and quater of BMMaterial.
- fix compile manual.
2024-10-30 15:41:17 +08:00
f7644319f0 doc: update build manual 2024-10-29 17:44:55 +08:00
73cda9f905 feat: update BMapSharp
- add struct assigner and iterator but still has bugs (struct padding issue)
- add function bindings for BM3dObject and BMGroup.
- add basic ctor and dtor for BMMeshTrans.
2024-10-29 15:12:00 +08:00
4d04b38d52 feat: continue improving BMapSharp.
- add BMFileWriter in BMapSharp.
2024-10-27 11:41:49 +08:00
623334f863 feat: update BMapSharp.
- update the function calling in BMapSharp.BMFileReader. (hope JIT can optimize my bad code served for beauty)
- remove outdated content in COMPILE.md
2024-10-24 16:39:11 +08:00
f781bcd63d doc: fix compile manual
- move compile infos into an individual file.
- remove outdated compile manual, use latest one instead.
2024-10-18 15:04:54 +08:00
b319e0fcb6 feat: finish basic function of BMapSharp.
- fix weird C sharp behavior about calling FreeNativeData without calling ManagedToNative, which cause segment fault.
- disable unhandled exception handler in debug mode for BMap.
- change all associated code involving these issues.
2024-10-05 11:58:25 +08:00
3566efa36a feat: update custom marshaler in BMapSharp 2024-10-04 21:45:04 +08:00
37 changed files with 1976 additions and 1031 deletions

View File

@ -55,7 +55,7 @@ bool BMInit() {
if (CheckInited()) return false;
// register exception handler if we are in Windows.
#if YYCC_OS == YYCC_OS_WINDOWS
#if defined(LIBCMO_BUILD_RELEASE) && (YYCC_OS == YYCC_OS_WINDOWS)
YYCC::ExceptionHelper::Register();
#endif
@ -89,7 +89,7 @@ bool BMDispose() {
LibCmo::CK2::CKShutdown();
// unregister exception handler if we are in Windows
#if YYCC_OS == YYCC_OS_WINDOWS
#if defined(LIBCMO_BUILD_RELEASE) && (YYCC_OS == YYCC_OS_WINDOWS)
YYCC::ExceptionHelper::Unregister();
#endif

View File

@ -18,8 +18,6 @@ FILES
target_include_directories(BMap
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
YYCC::YYCCommonplace
LibCmo
)
# Setup linked library infomation
target_link_libraries(BMap
@ -52,6 +50,6 @@ PRIVATE
# Install BMap only on Release mode
install(TARGETS BMap
CONFIGURATIONS Release
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
RUNTIME DESTINATION ${YYCC_INSTALL_BIN_PATH}
)

View File

@ -0,0 +1,364 @@
root = true
# All files
[*]
indent_style = space
# Xml files
[*.xml]
indent_size = 2
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = false
#### .NET Coding Conventions ####
[*.{cs,vb}]
# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset
# this. and Me. preferences
dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_property = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
# Expression-level preferences
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_object_initializer = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
# Field preferences
dotnet_style_readonly_field = true:warning
# Parameter preferences
dotnet_code_quality_unused_parameters = all:suggestion
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
#### C# Coding Conventions ####
[*.cs]
# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:suggestion
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_prefer_switch_expression = true:suggestion
# Null-checking preferences
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
# Code-block preferences
csharp_prefer_braces = true:silent
csharp_prefer_simple_using_statement = true:suggestion
# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:silent
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = false
csharp_new_line_before_else = false
csharp_new_line_before_finally = false
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = none
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### Naming styles ####
[*.{cs,vb}]
# Naming rules
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion
dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces
dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase
dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion
dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters
dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase
dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods
dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties
dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.events_should_be_pascalcase.symbols = events
dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion
dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields
dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
# Symbol specifications
dotnet_naming_symbols.interfaces.applicable_kinds = interface
dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interfaces.required_modifiers =
dotnet_naming_symbols.enums.applicable_kinds = enum
dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enums.required_modifiers =
dotnet_naming_symbols.events.applicable_kinds = event
dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.events.required_modifiers =
dotnet_naming_symbols.methods.applicable_kinds = method
dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.methods.required_modifiers =
dotnet_naming_symbols.properties.applicable_kinds = property
dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.properties.required_modifiers =
dotnet_naming_symbols.public_fields.applicable_kinds = field
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_fields.required_modifiers =
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_fields.required_modifiers =
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types_and_namespaces.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
dotnet_naming_symbols.type_parameters.required_modifiers =
dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_constant_fields.required_modifiers = const
dotnet_naming_symbols.local_variables.applicable_kinds = local
dotnet_naming_symbols.local_variables.applicable_accessibilities = local
dotnet_naming_symbols.local_variables.required_modifiers =
dotnet_naming_symbols.local_constants.applicable_kinds = local
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
dotnet_naming_symbols.local_constants.required_modifiers = const
dotnet_naming_symbols.parameters.applicable_kinds = parameter
dotnet_naming_symbols.parameters.applicable_accessibilities = *
dotnet_naming_symbols.parameters.required_modifiers =
dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_constant_fields.required_modifiers = const
dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
dotnet_naming_symbols.local_functions.required_modifiers =
# Naming styles
dotnet_naming_style.pascalcase.required_prefix =
dotnet_naming_style.pascalcase.required_suffix =
dotnet_naming_style.pascalcase.word_separator =
dotnet_naming_style.pascalcase.capitalization = pascal_case
dotnet_naming_style.ipascalcase.required_prefix = I
dotnet_naming_style.ipascalcase.required_suffix =
dotnet_naming_style.ipascalcase.word_separator =
dotnet_naming_style.ipascalcase.capitalization = pascal_case
dotnet_naming_style.tpascalcase.required_prefix = T
dotnet_naming_style.tpascalcase.required_suffix =
dotnet_naming_style.tpascalcase.word_separator =
dotnet_naming_style.tpascalcase.capitalization = pascal_case
dotnet_naming_style._camelcase.required_prefix = _
dotnet_naming_style._camelcase.required_suffix =
dotnet_naming_style._camelcase.word_separator =
dotnet_naming_style._camelcase.capitalization = camel_case
dotnet_naming_style.camelcase.required_prefix =
dotnet_naming_style.camelcase.required_suffix =
dotnet_naming_style.camelcase.word_separator =
dotnet_naming_style.camelcase.capitalization = camel_case
dotnet_naming_style.s_camelcase.required_prefix = s_
dotnet_naming_style.s_camelcase.required_suffix =
dotnet_naming_style.s_camelcase.word_separator =
dotnet_naming_style.s_camelcase.capitalization = camel_case

View File

@ -19,40 +19,48 @@ namespace BMapSharp {
public static class BMap {
/// <summary>The callback function of BMap.</summary>
/// <param name="msg">The message content need to be printed.</param>
public delegate void OutputCallback([In, MarshalAs(UnmanagedType.LPUTF8Str)] string msg);
#region Custom Marshalers
// References:
// https://stackoverflow.com/questions/18498452/how-do-i-write-a-custom-marshaler-which-allows-data-to-flow-from-native-to-manag
// https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-runtime-interopservices-icustommarshaler
//
// NOTE: I do not create a member to store the object we are marshaling.
// Because my binding do not have In, Out parameter. All parameters are In OR Out.
// So there is no reason to keep that member.
// IDK why Microsoft try to call ICustomMarshaler.CleanUpNativeData without calling ICustomMarshaler.MarshalManagedToNative.
// It is trying to free the pointer managed by LibCmo self (for example, it will try to free we got string when getting object name)!
// So as the compromise, we use "cookie" feature to explicit specify the marshaler In/Out behavior when getting it.
[Flags]
internal enum MarshalerType {
None = 0b0,
In = 0b1,
Out = 0b10
}
/// <summary>The custom marshaler for BMap string array.</summary>
public class BMStringArrayMarshaler : ICustomMarshaler {
// References:
// https://stackoverflow.com/questions/18498452/how-do-i-write-a-custom-marshaler-which-allows-data-to-flow-from-native-to-manag
// https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-runtime-interopservices-icustommarshaler
//
// NOTE: I do not create a member to store the object we are marshaling.
// Because my binding do not have In, Out parameter. All parameters are In OR Out.
// So there is no reason to keep that member.
private static readonly BMStringArrayMarshaler g_InInstance = new BMStringArrayMarshaler(MarshalerType.In);
private static readonly BMStringArrayMarshaler g_OutInstance = new BMStringArrayMarshaler(MarshalerType.Out);
public static ICustomMarshaler GetInstance(string pstrCookie) {
if (pstrCookie == "In") return g_InInstance;
else if (pstrCookie == "Out") return g_OutInstance;
else throw new MarshalDirectiveException("Not supported cookie string for BMStringArrayMarshaler.");
}
private static readonly BMStringArrayMarshaler g_Instance = new BMStringArrayMarshaler();
public static ICustomMarshaler GetInstance(string pstrCookie) => g_Instance;
private readonly MarshalerType m_MarshalerType;
private BMStringArrayMarshaler(MarshalerType marshaler_type) {
m_MarshalerType = marshaler_type;
}
// For respecting the standard of BMap,
// the native memory we created is a simple array and each item is a pointer to a NULL-terminated UTF8 string.
// Please note the array self is not NULL-terminated because its length is provided by another argument in function calling.
// However, this memory layout is not good for our marshaling.
// We can not know the size of array we created. Because we need iterate it when freeing or fetching data.
// We also can not know the size of string we created because we need read them when parsing them to C# string.
//
// So the solution we made is adding an uint32_t header before the array to indicate the size of array.
// And also add an uint32_t header for each string to indicate the length of string (in bytes, NULL exclusive).
// So the pointer put in array is not the address we allocated, it has an offset.
// Also we return native pointer is not the address we allocated, it also has an offset.
private static readonly int szLengthHeaderSize = Marshal.SizeOf<int>();
private static readonly int szArrayItemSize = Marshal.SizeOf<IntPtr>();
private static readonly int szStringItemSize = Marshal.SizeOf<byte>();
// Please note the array self is also NULL-terminated otherwise we don't know its length.
public IntPtr MarshalManagedToNative(object ManagedObj) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.In)) return IntPtr.Zero;
// Check nullptr object.
if (ManagedObj is null) return IntPtr.Zero;
// Check argument type.
@ -62,66 +70,50 @@ namespace BMapSharp {
// Allocate string items first
int szArrayItemCount = castManagedObj.Length;
IntPtr[] apStrings = new IntPtr[szArrayItemCount];
int szArrayItemSize = Marshal.SizeOf<IntPtr>();
IntPtr[] apString = new IntPtr[szArrayItemCount];
for (int i = 0; i < szArrayItemCount; ++i) {
// Encode string first.
byte[] encString = Encoding.UTF8.GetBytes(castManagedObj[i]);
// Allocate string memory with extra NULL terminal.
int szStringItemCount = encString.Length;
IntPtr pString = Marshal.AllocHGlobal(szStringItemSize * (szStringItemCount + 1) + szLengthHeaderSize);
// Setup length field
Marshal.WriteInt32(pString, 0, szStringItemCount);
// Copy string data with offset.
IntPtr pFakeString = pString + szLengthHeaderSize;
Marshal.Copy(encString, 0, pFakeString, szStringItemCount);
// Set NULL terminal.
Marshal.WriteByte(pFakeString, szStringItemSize * szStringItemCount, 0);
// Set item in string pointer
apStrings[i] = pFakeString;
// Check null string
string stringObj = castManagedObj[i];
if (stringObj is null) apString[i] = IntPtr.Zero;
else apString[i] = BMStringMarshaler.ToNative(stringObj);
}
// Allocate array pointer now.
IntPtr pArray = Marshal.AllocHGlobal(szArrayItemSize * szArrayItemCount + szLengthHeaderSize);
// Setup length field
Marshal.WriteInt32(pArray, 0, szArrayItemCount);
// Copy string pointer data with offset.
IntPtr pFakeArray = pArray + szLengthHeaderSize;
Marshal.Copy(apStrings, 0, pFakeArray, szArrayItemCount);
IntPtr pArray = Marshal.AllocHGlobal(szArrayItemSize * (szArrayItemCount + 1));
// Copy string pointer data
Marshal.Copy(apString, 0, pArray, szArrayItemCount);
// Setup NULL ternimal
Marshal.WriteIntPtr(pArray + (szArrayItemSize * szArrayItemCount), IntPtr.Zero);
// Return value
return pFakeArray;
return pArray;
}
public object MarshalNativeToManaged(IntPtr pNativeData) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.Out)) return null;
// Check nullptr
if (pNativeData == IntPtr.Zero) return null;
// Get real array pointer
IntPtr pFakeArray = pNativeData;
IntPtr pArray = pFakeArray - szLengthHeaderSize;
// Get the count of array and read string pointers
int szArrayItemCount = Marshal.ReadInt32(pArray, 0);
IntPtr[] apStrings = new IntPtr[szArrayItemCount];
Marshal.Copy(pFakeArray, apStrings, 0, szArrayItemCount);
// Get the length of array
int szArrayItemCount = BMStringArrayMarshaler.GetArrayLength(pNativeData);
int szArrayItemSize = Marshal.SizeOf<IntPtr>();
// Prepare array cache and read it.
IntPtr[] apString = new IntPtr[szArrayItemCount];
Marshal.Copy(pNativeData, apString, 0, szArrayItemCount);
// Iterate the array and process each string one by one.
string[] ret = new string[szArrayItemCount];
for (int i = 0; i < szArrayItemCount; ++i) {
// Get string pointer
IntPtr pFakeString = apStrings[i];
if (pFakeString == IntPtr.Zero) {
IntPtr pString = apString[i];
if (pString == IntPtr.Zero) {
ret[i] = null;
continue;
}
IntPtr pString = pFakeString - szLengthHeaderSize;
// Read string length
int szStringItemCount = Marshal.ReadInt32(pString, 0);
// Read string body
byte[] encString = new byte[szStringItemCount];
Marshal.Copy(pFakeString, encString, 0, szStringItemCount);
// Decode string with UTF8
ret[i] = Encoding.UTF8.GetString(encString);
// Extract string
ret[i] = BMStringMarshaler.ToManaged(pString);
}
// Return result
@ -129,30 +121,26 @@ namespace BMapSharp {
}
public void CleanUpNativeData(IntPtr pNativeData) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.In)) return;
// Check nullptr
if (pNativeData == IntPtr.Zero) return;
// Get real array pointer
IntPtr pFakeArray = pNativeData;
IntPtr pArray = pFakeArray - szLengthHeaderSize;
// Get the length of array
int szArrayItemCount = BMStringArrayMarshaler.GetArrayLength(pNativeData);
int szArrayItemSize = Marshal.SizeOf<IntPtr>();
// Prepare array cache and read it.
IntPtr[] apString = new IntPtr[szArrayItemCount];
Marshal.Copy(pNativeData, apString, 0, szArrayItemCount);
// Free array self
Marshal.FreeHGlobal(pNativeData);
// Get the count of array and read string pointers
int szArrayItemCount = Marshal.ReadInt32(pArray, 0);
IntPtr[] apStrings = new IntPtr[szArrayItemCount];
Marshal.Copy(pFakeArray, apStrings, 0, szArrayItemCount);
// Iterate the array and free them one by one.
for (int i = 0; i < szArrayItemCount; ++i) {
// Get string pointer
IntPtr pFakeString = apStrings[i];
if (pFakeString == IntPtr.Zero) continue;
IntPtr pString = pFakeString - szLengthHeaderSize;
// Iterate the string pointer array and free them one by one.
foreach (IntPtr pString in apString) {
// Free string pointer
if (pString == IntPtr.Zero) continue;
Marshal.FreeHGlobal(pString);
}
// Free array self
Marshal.FreeHGlobal(pArray);
}
public void CleanUpManagedData(object ManagedObj) {
@ -164,8 +152,132 @@ namespace BMapSharp {
return -1;
}
/// <summary>
/// Return the length of array created by this marshaler.
/// </summary>
/// <param name="ptr">The pointer to array for checking.</param>
/// <returns>The length of array (NULL terminal exclusive).</returns>
internal static int GetArrayLength(IntPtr ptr) {
int count = 0, unit = Marshal.SizeOf<IntPtr>();
while (Marshal.ReadIntPtr(ptr) != IntPtr.Zero) {
ptr += unit;
++count;
}
return count;
}
}
public class BMStringMarshaler : ICustomMarshaler {
private static readonly BMStringMarshaler g_InInstance = new BMStringMarshaler(MarshalerType.In);
private static readonly BMStringMarshaler g_OutInstance = new BMStringMarshaler(MarshalerType.Out);
public static ICustomMarshaler GetInstance(string pstrCookie) {
if (pstrCookie == "In") return g_InInstance;
else if (pstrCookie == "Out") return g_OutInstance;
else throw new MarshalDirectiveException("Not supported cookie string for BMStringMarshaler.");
}
private readonly MarshalerType m_MarshalerType;
private BMStringMarshaler(MarshalerType marshaler_type) {
m_MarshalerType = marshaler_type;
}
public IntPtr MarshalManagedToNative(object ManagedObj) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.In)) return IntPtr.Zero;
// Check requirements.
if (ManagedObj is null) return IntPtr.Zero;
string castManagedObj = ManagedObj as string;
if (castManagedObj is null)
throw new MarshalDirectiveException("BMStringMarshaler must be used on a string.");
// Call self
return BMStringMarshaler.ToNative(castManagedObj);
}
public object MarshalNativeToManaged(IntPtr pNativeData) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.Out)) return null;
// Check nullptr
if (pNativeData == IntPtr.Zero) return null;
// Call self
return BMStringMarshaler.ToManaged(pNativeData);
}
public void CleanUpNativeData(IntPtr pNativeData) {
// Check marshaler type
if (!m_MarshalerType.HasFlag(MarshalerType.In)) return;
// Check nullptr
if (pNativeData == IntPtr.Zero) return;
// Free native pointer
Marshal.FreeHGlobal(pNativeData);
}
public void CleanUpManagedData(object ManagedObj) {
// Do nothing, because managed data do not need any clean up.
}
public int GetNativeDataSize() {
// Return -1 to indicate the managed type this marshaler handles is not a value type.
return -1;
}
/// <summary>
/// Return the length in byte of given pointer represented C style string.
/// </summary>
/// <param name="ptr">The pointer for checking.</param>
/// <returns>The length of C style string (NUL exclusive).</returns>
internal static int GetCStringLength(IntPtr ptr) {
int count = 0, unit = Marshal.SizeOf<byte>();
while (Marshal.ReadByte(ptr) != (byte)0) {
ptr += unit;
++count;
}
return count;
}
/// <summary>
/// Convert given string object to native data.
/// This function is shared by 2 marshalers.
/// </summary>
/// <param name="obj">String object. Caller must make sure this object is not null.</param>
/// <returns>The created native data pointer.</returns>
internal static IntPtr ToNative(string obj) {
// Encode string first
byte[] encString = Encoding.UTF8.GetBytes(obj);
// Allocate string memory with extra NUL.
int szStringItemCount = encString.Length;
int szStringItemSize = Marshal.SizeOf<byte>();
IntPtr pString = Marshal.AllocHGlobal(szStringItemSize * (szStringItemCount + 1));
// Copy encoded string data
Marshal.Copy(encString, 0, pString, szStringItemCount);
// Setup NUL
Marshal.WriteByte(pString + (szStringItemSize * szStringItemCount), (byte)0);
// Return value
return pString;
}
/// <summary>
/// Extract managed string from given native pointer holding C style string data.
/// This function is shared by 2 marshalers.
/// </summary>
/// <param name="ptr">Native pointer holding string data. Caller must make sure this pointer is not nullptr.</param>
/// <returns>The extracted managed string data.</returns>
internal static string ToManaged(IntPtr ptr) {
// Get the length of given string.
int szStringItemCount = BMStringMarshaler.GetCStringLength(ptr);
int szStringItemSize = Marshal.SizeOf<byte>();
// Prepare cache and copy string data
byte[] encString = new byte[szStringItemCount];
Marshal.Copy(ptr, encString, 0, szStringItemCount);
// Decode string and return
return Encoding.UTF8.GetString(encString);
}
}
#endregion
/// <summary>The callback function of BMap.</summary>
/// <param name="msg">The message content need to be printed.</param>
internal delegate void OutputCallback([In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler))] string msg);
// Decide the file name of loaded DLL.
#if BMAP_OS_WINDOWS
@ -203,7 +315,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMFile_Load", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMFile_Load([In, MarshalAs(UnmanagedType.LPUTF8Str)] string file_name, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string temp_folder, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string texture_folder, [In, MarshalAs(UnmanagedType.FunctionPtr)] OutputCallback raw_callback, [In, MarshalAs(UnmanagedType.U4)] uint encoding_count, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler))] string[] encodings, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr out_file);
internal static extern bool BMFile_Load([In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string file_name, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string temp_folder, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string texture_folder, [In, MarshalAs(UnmanagedType.FunctionPtr)] OutputCallback raw_callback, [In, MarshalAs(UnmanagedType.U4)] uint encoding_count, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler), MarshalCookie = "In")] string[] encodings, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr out_file);
/// <summary>BMFile_Create</summary>
/// <param name="temp_folder">Type: LibCmo::CKSTRING. </param>
/// <param name="texture_folder">Type: LibCmo::CKSTRING. </param>
@ -214,7 +326,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMFile_Create", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMFile_Create([In, MarshalAs(UnmanagedType.LPUTF8Str)] string temp_folder, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string texture_folder, [In, MarshalAs(UnmanagedType.FunctionPtr)] OutputCallback raw_callback, [In, MarshalAs(UnmanagedType.U4)] uint encoding_count, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler))] string[] encodings, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr out_file);
internal static extern bool BMFile_Create([In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string temp_folder, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string texture_folder, [In, MarshalAs(UnmanagedType.FunctionPtr)] OutputCallback raw_callback, [In, MarshalAs(UnmanagedType.U4)] uint encoding_count, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler), MarshalCookie = "In")] string[] encodings, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr out_file);
/// <summary>BMFile_Save</summary>
/// <param name="map_file">Type: BMap::BMFile*. </param>
/// <param name="file_name">Type: LibCmo::CKSTRING. </param>
@ -224,7 +336,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMFile_Save", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMFile_Save([In, MarshalAs(UnmanagedType.SysInt)] IntPtr map_file, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string file_name, [In, MarshalAs(UnmanagedType.U4)] uint texture_save_opt, [In, MarshalAs(UnmanagedType.U1)] bool use_compress, [In, MarshalAs(UnmanagedType.I4)] int compreess_level);
internal static extern bool BMFile_Save([In, MarshalAs(UnmanagedType.SysInt)] IntPtr map_file, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string file_name, [In, MarshalAs(UnmanagedType.U4)] CK_TEXTURE_SAVEOPTIONS texture_save_opt, [In, MarshalAs(UnmanagedType.U1)] bool use_compress, [In, MarshalAs(UnmanagedType.I4)] int compreess_level);
/// <summary>BMFile_Free</summary>
/// <param name="map_file">Type: BMap::BMFile*. </param>
/// <returns>True if no error, otherwise False.</returns>
@ -459,7 +571,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMObject_GetName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMObject_GetName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.LPUTF8Str)] out string out_name);
internal static extern bool BMObject_GetName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "Out")] out string out_name);
/// <summary>BMObject_SetName</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -467,7 +579,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMObject_SetName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMObject_SetName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string name);
internal static extern bool BMObject_SetName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string name);
/// <summary>BMGroup_AddObject</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -500,7 +612,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_GetFileName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_GetFileName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.LPUTF8Str)] out string out_filename);
internal static extern bool BMTexture_GetFileName([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "Out")] out string out_filename);
/// <summary>BMTexture_LoadImage</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -508,7 +620,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_LoadImage", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_LoadImage([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string filename);
internal static extern bool BMTexture_LoadImage([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string filename);
/// <summary>BMTexture_SaveImage</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -516,7 +628,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_SaveImage", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_SaveImage([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.LPUTF8Str)] string filename);
internal static extern bool BMTexture_SaveImage([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = "In")] string filename);
/// <summary>BMTexture_GetSaveOptions</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -524,7 +636,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_GetSaveOptions", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_GetSaveOptions([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_saveopt);
internal static extern bool BMTexture_GetSaveOptions([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out CK_TEXTURE_SAVEOPTIONS out_saveopt);
/// <summary>BMTexture_SetSaveOptions</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -532,7 +644,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_SetSaveOptions", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_SetSaveOptions([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint saveopt);
internal static extern bool BMTexture_SetSaveOptions([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] CK_TEXTURE_SAVEOPTIONS saveopt);
/// <summary>BMTexture_GetVideoFormat</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -540,7 +652,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_GetVideoFormat", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_GetVideoFormat([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_vfmt);
internal static extern bool BMTexture_GetVideoFormat([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VX_PIXELFORMAT out_vfmt);
/// <summary>BMTexture_SetVideoFormat</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -548,7 +660,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMTexture_SetVideoFormat", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMTexture_SetVideoFormat([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint vfmt);
internal static extern bool BMTexture_SetVideoFormat([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VX_PIXELFORMAT vfmt);
/// <summary>BMMaterial_GetDiffuse</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -668,7 +780,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetTextureBlendMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetTextureBlendMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetTextureBlendMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXTEXTURE_BLENDMODE out_val);
/// <summary>BMMaterial_SetTextureBlendMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -676,7 +788,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetTextureBlendMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetTextureBlendMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetTextureBlendMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXTEXTURE_BLENDMODE val);
/// <summary>BMMaterial_GetTextureMinMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -684,7 +796,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetTextureMinMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetTextureMinMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetTextureMinMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXTEXTURE_FILTERMODE out_val);
/// <summary>BMMaterial_SetTextureMinMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -692,7 +804,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetTextureMinMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetTextureMinMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetTextureMinMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXTEXTURE_FILTERMODE val);
/// <summary>BMMaterial_GetTextureMagMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -700,7 +812,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetTextureMagMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetTextureMagMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetTextureMagMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXTEXTURE_FILTERMODE out_val);
/// <summary>BMMaterial_SetTextureMagMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -708,7 +820,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetTextureMagMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetTextureMagMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetTextureMagMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXTEXTURE_FILTERMODE val);
/// <summary>BMMaterial_GetTextureAddressMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -716,7 +828,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetTextureAddressMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetTextureAddressMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetTextureAddressMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXTEXTURE_ADDRESSMODE out_val);
/// <summary>BMMaterial_SetTextureAddressMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -724,7 +836,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetTextureAddressMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetTextureAddressMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetTextureAddressMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXTEXTURE_ADDRESSMODE val);
/// <summary>BMMaterial_GetSourceBlend</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -732,7 +844,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetSourceBlend", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetSourceBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetSourceBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXBLEND_MODE out_val);
/// <summary>BMMaterial_SetSourceBlend</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -740,7 +852,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetSourceBlend", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetSourceBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetSourceBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXBLEND_MODE val);
/// <summary>BMMaterial_GetDestBlend</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -748,7 +860,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetDestBlend", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetDestBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetDestBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXBLEND_MODE out_val);
/// <summary>BMMaterial_SetDestBlend</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -756,7 +868,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetDestBlend", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetDestBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetDestBlend([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXBLEND_MODE val);
/// <summary>BMMaterial_GetFillMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -764,7 +876,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetFillMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetFillMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetFillMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXFILL_MODE out_val);
/// <summary>BMMaterial_SetFillMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -772,7 +884,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetFillMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetFillMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetFillMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXFILL_MODE val);
/// <summary>BMMaterial_GetShadeMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -780,7 +892,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetShadeMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetShadeMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetShadeMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXSHADE_MODE out_val);
/// <summary>BMMaterial_SetShadeMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -788,7 +900,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetShadeMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetShadeMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetShadeMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXSHADE_MODE val);
/// <summary>BMMaterial_GetAlphaTestEnabled</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -876,7 +988,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetAlphaRef", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetAlphaRef([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetAlphaRef([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U1)] out byte out_val);
/// <summary>BMMaterial_SetAlphaRef</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -884,7 +996,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetAlphaRef", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetAlphaRef([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetAlphaRef([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U1)] byte val);
/// <summary>BMMaterial_GetAlphaFunc</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -892,7 +1004,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetAlphaFunc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetAlphaFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetAlphaFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXCMPFUNC out_val);
/// <summary>BMMaterial_SetAlphaFunc</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -900,7 +1012,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetAlphaFunc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetAlphaFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetAlphaFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXCMPFUNC val);
/// <summary>BMMaterial_GetZFunc</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -908,7 +1020,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_GetZFunc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_GetZFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_val);
internal static extern bool BMMaterial_GetZFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXCMPFUNC out_val);
/// <summary>BMMaterial_SetZFunc</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -916,7 +1028,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMaterial_SetZFunc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMaterial_SetZFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint val);
internal static extern bool BMMaterial_SetZFunc([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXCMPFUNC val);
/// <summary>BMMesh_GetLitMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -924,7 +1036,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMesh_GetLitMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMesh_GetLitMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out uint out_mode);
internal static extern bool BMMesh_GetLitMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [Out, MarshalAs(UnmanagedType.U4)] out VXMESH_LITMODE out_mode);
/// <summary>BMMesh_SetLitMode</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>
@ -932,7 +1044,7 @@ namespace BMapSharp {
/// <returns>True if no error, otherwise False.</returns>
[DllImport(g_DllName, EntryPoint = "BMMesh_SetLitMode", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool BMMesh_SetLitMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] uint mode);
internal static extern bool BMMesh_SetLitMode([In, MarshalAs(UnmanagedType.SysInt)] IntPtr bmfile, [In, MarshalAs(UnmanagedType.U4)] uint objid, [In, MarshalAs(UnmanagedType.U4)] VXMESH_LITMODE mode);
/// <summary>BMMesh_GetVertexCount</summary>
/// <param name="bmfile">Type: BMap::BMFile*. The pointer to corresponding BMFile.</param>
/// <param name="objid">Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.</param>

View File

@ -1,5 +1,5 @@
using System;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BMapSharp.VirtoolsTypes;
@ -23,6 +23,9 @@ namespace BMapSharp.BMapWrapper {
}
public static class Utils {
#region Constant Values
/// <summary>The representation of invalid raw pointer.</summary>
internal static readonly IntPtr INVALID_PTR = IntPtr.Zero;
/// <summary>The representation of invalid CK_ID.</summary>
@ -32,16 +35,75 @@ namespace BMapSharp.BMapWrapper {
/// It just writes the data in console.
/// </summary>
internal static void BMapSharpCallback(string msg) {
Console.WriteLine(msg);
Console.WriteLine($"[BMapSharp] {msg}");
}
#endregion
#region Help Functions
private static void StructAssigner<T>(IntPtr pstruct, uint count, IEnumerable<T> iem) {
var stride = Marshal.SizeOf<T>();
var itor = iem.GetEnumerator();
for (uint i = 0; i < count; ++i) {
if (!itor.MoveNext()) throw new BMapException("The length of given data is too short when assigning struct array.");
Marshal.StructureToPtr<T>(itor.Current, pstruct, false);
pstruct += stride;
}
}
internal static void VxVector3Assigner(IntPtr pstruct, uint count, IEnumerable<VxVector3> iem)
=> StructAssigner<VxVector3>(pstruct, count, iem);
internal static void VxVector2Assigner(IntPtr pstruct, uint count, IEnumerable<VxVector2> iem)
=> StructAssigner<VxVector2>(pstruct, count, iem);
internal static void CKFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable<CKFaceIndices> iem)
=> StructAssigner<CKFaceIndices>(pstruct, count, iem);
internal static void CKShortFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable<CKShortFaceIndices> iem)
=> StructAssigner<CKShortFaceIndices>(pstruct, count, iem);
internal static void ShortAssigner(IntPtr pstruct, uint count, IEnumerable<short> iem)
=> StructAssigner<short>(pstruct, count, iem);
internal static void CKIDAssigner(IntPtr pstruct, uint count, IEnumerable<uint> iem)
=> StructAssigner<uint>(pstruct, count, iem);
internal static void CKDWORDAssigner(IntPtr pstruct, uint count, IEnumerable<uint> iem)
=> StructAssigner<uint>(pstruct, count, iem);
private static IEnumerable<T> StructIterator<T>(IntPtr pstruct, uint count) {
var stride = Marshal.SizeOf<T>();
for (uint i = 0; i < count; ++i) {
yield return Marshal.PtrToStructure<T>(pstruct);
pstruct += stride;
}
}
internal static IEnumerable<VxVector3> VxVector3Iterator(IntPtr pstruct, uint count)
=> StructIterator<VxVector3>(pstruct, count);
internal static IEnumerable<VxVector2> VxVector2Iterator(IntPtr pstruct, uint count)
=> StructIterator<VxVector2>(pstruct, count);
internal static IEnumerable<CKFaceIndices> CKFaceIndicesIterator(IntPtr pstruct, uint count)
=> StructIterator<CKFaceIndices>(pstruct, count);
internal static IEnumerable<CKShortFaceIndices> CKShortFaceIndicesIterator(IntPtr pstruct, uint count)
=> StructIterator<CKShortFaceIndices>(pstruct, count);
internal static IEnumerable<short> ShortIterator(IntPtr pstruct, uint count)
=> StructIterator<short>(pstruct, count);
internal static IEnumerable<uint> CKIDIterator(IntPtr pstruct, uint count)
=> StructIterator<uint>(pstruct, count);
internal static IEnumerable<uint> CKDWORDIterator(IntPtr pstruct, uint count)
=> StructIterator<uint>(pstruct, count);
#endregion
#region End User Exposed
private static readonly BMapGuard Singleton = new BMapGuard();
public static bool IsBMapAvailable() {
return !Singleton.IsInvalid;
}
#endregion
}
public abstract class AbstractPointer : SafeHandle {
// TODO: Maybe I need to implement IEquatable, IComparable<T>, and IComparable for AbstractPointer and AbstractCKObject.
// But I give it up. I am lazy. What I have written barely works for me now.
public abstract class AbstractPointer : SafeHandle, IEquatable<AbstractPointer> {
internal AbstractPointer(IntPtr raw_pointer) : base(Utils.INVALID_PTR, true) {
this.handle = raw_pointer;
}
@ -49,144 +111,309 @@ namespace BMapSharp.BMapWrapper {
public override bool IsInvalid => this.handle == Utils.INVALID_PTR;
protected override bool ReleaseHandle() => throw new NotImplementedException();
protected bool isValid() => this.handle != Utils.INVALID_PTR;
protected IntPtr getPointer() => this.handle;
internal bool isValid() => this.handle != Utils.INVALID_PTR;
internal IntPtr getPointer() => this.handle;
// protected AbstractPointer(IntPtr raw_pointer) : base(raw_pointer, true) {}
#region IEquatable
// protected IntPtr GetPointer() => this.handle;
// public override bool IsInvalid { get { return this.handle == Utils.INVALID_PTR; } }
public override bool Equals(object obj) => this.Equals(obj as AbstractPointer);
public bool Equals(AbstractPointer obj) {
if (obj is null) return false;
// Optimization for a common success case
if (Object.ReferenceEquals(this, obj)) return true;
// If run-time types are not exactly the same, return false.
if (this.GetType() != obj.GetType()) return false;
// Return true if the fields match.
return this.handle == obj.handle;
}
// #region IComparable
public override int GetHashCode() => this.handle.GetHashCode();
// public int CompareTo(AbstractPointer other) {
// return m_RawPointer.CompareTo(other.m_RawPointer);
// }
public static bool operator ==(AbstractPointer lhs, AbstractPointer rhs) {
if (lhs is null) {
if (rhs is null) return true;
// Only left side is null.
return false;
}
// Equals handles case of null on right side
return lhs.Equals(rhs);
}
public static bool operator !=(AbstractPointer lhs, AbstractPointer rhs) => !(lhs == rhs);
// #endregion
// #region IEquatable
// public override bool Equals(object obj) => this.Equals(obj as AbstractPointer);
// public bool Equals(AbstractPointer other) {
// if (other is null) return false;
// if (Object.ReferenceEquals(this, other)) return true;
// // if (this.GetType() != other.GetType()) return false;
// return this.m_RawPointer == other.m_RawPointer;
// }
// public static bool operator ==(AbstractPointer lhs, AbstractPointer rhs) {
// if (lhs is null) {
// if (rhs is null) return true;
// return false;
// }
// return lhs.Equals(rhs);
// }
// public static bool operator !=(AbstractPointer lhs, AbstractPointer rhs) => !(lhs == rhs);
// #endregion
#endregion
#region Misc
public override int GetHashCode() => this.handle.GetHashCode();
public override string ToString() => this.handle.ToString();
#endregion
}
public abstract class AbstractCKObject {
internal AbstractCKObject(IntPtr raw_pointer, uint ckid) {
m_RawPointer = raw_pointer;
public abstract class AbstractCKObject : SafeHandle, IEquatable<AbstractCKObject> {
// Same as AbstractPointer, but not own this handle.
internal AbstractCKObject(IntPtr raw_pointer, uint ckid) : base(Utils.INVALID_PTR, false) {
this.handle = raw_pointer;
m_CKID = ckid;
}
private readonly IntPtr m_RawPointer;
public override bool IsInvalid => this.handle == Utils.INVALID_PTR;
protected override bool ReleaseHandle() => throw new NotImplementedException();
private readonly uint m_CKID;
protected bool isValid() => m_RawPointer != Utils.INVALID_PTR && m_RawPointer != Utils.INVALID_CKID;
protected IntPtr getPointer() => m_RawPointer;
protected uint getCKID() => m_CKID;
internal bool isValid() => this.handle != Utils.INVALID_PTR && m_CKID != Utils.INVALID_CKID;
internal IntPtr getPointer() => this.handle;
internal uint getCKID() => m_CKID;
// private uint m_CKID;
#region IEquatable
// protected AbstractCKObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer) {
// m_CKID = ckid;
// }
public override bool Equals(object obj) => this.Equals(obj as AbstractCKObject);
public bool Equals(AbstractCKObject obj) {
if (obj is null) return false;
// Optimization for a common success case
if (Object.ReferenceEquals(this, obj)) return true;
// If run-time types are not exactly the same, return false.
if (this.GetType() != obj.GetType()) return false;
// Return true if the fields match.
return (this.m_CKID == obj.m_CKID) && (this.handle == obj.handle);
}
// protected override bool IsValid() => base.IsValid() && m_CKID != Utils.INVALID_CKID;
// protected uint GetCKID() => m_CKID;
public override int GetHashCode() => HashCode.Combine(this.handle, m_CKID);
// #region IComparable
public static bool operator ==(AbstractCKObject lhs, AbstractCKObject rhs) {
if (lhs is null) {
if (rhs is null) return true;
// Only left side is null.
return false;
}
// Equals handles case of null on right side
return lhs.Equals(rhs);
}
public static bool operator !=(AbstractCKObject lhs, AbstractCKObject rhs) => !(lhs == rhs);
// public int CompareTo(AbstractCKObject other) {
// var ret = base.CompareTo((AbstractPointer)other);
// if (ret != 0) return ret;
// return m_CKID.CompareTo(other.m_CKID);
// }
// #endregion
// #region IEquatable
// public override bool Equals(object obj) => this.Equals(obj as AbstractCKObject);
// public bool Equals(AbstractCKObject other) {
// if (other is null) return false;
// if (Object.ReferenceEquals(this, other)) return true;
// }
// public static bool operator ==(AbstractCKObject left, AbstractCKObject right) =>
// ((AbstractPointer)left == (AbstractPointer)right) && left.m_CKID == right.m_CKID;
// public static bool operator !=(AbstractCKObject left, AbstractCKObject right) =>
// ((AbstractPointer)left != (AbstractPointer)right) || left.m_CKID != right.m_CKID;
// #endregion
#endregion
#region Misc
public override int GetHashCode() => HashCode.Combine(m_RawPointer, m_CKID);
public override string ToString() => $"{m_RawPointer}, {m_CKID}";
public override string ToString() => $"{this.handle}, {m_CKID}";
#endregion
#region Subclass Utilities
protected delegate bool FctGenericValueGetter<T>(IntPtr bmf, uint id, out T val);
protected delegate bool FctGenericValueSetter<T>(IntPtr bmf, uint id, T val);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected T getGenericValue<T>(FctGenericValueGetter<T> fct) {
BMapException.ThrowIfFailed(fct(getPointer(), getCKID(), out T out_val));
return out_val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void setGenericValue<T>(FctGenericValueSetter<T> fct, T val) {
BMapException.ThrowIfFailed(fct(getPointer(), getCKID(), val));
}
#endregion
}
public class BMObject : AbstractCKObject {
internal BMObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BMObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public string GetName() {
BMapException.ThrowIfFailed(BMap.BMObject_GetName(
this.getPointer(), this.getCKID(), out string out_name
));
return out_name;
}
public void SetName(string name) {
BMapException.ThrowIfFailed(BMap.BMObject_SetName(
this.getPointer(), this.getCKID(), name
));
}
public string GetName() => getGenericValue<string>(BMap.BMObject_GetName);
public void SetName(string name) => setGenericValue<string>(BMap.BMObject_SetName, name);
}
public class BMTexture : BMObject {
internal BMTexture(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BMTexture(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public string GetFileName() => getGenericValue<string>(BMap.BMTexture_GetFileName);
public void LoadImage(string filepath) {
BMapException.ThrowIfFailed(BMap.BMTexture_LoadImage(getPointer(), getCKID(), filepath));
}
public void SaveImage(string filepath) {
BMapException.ThrowIfFailed(BMap.BMTexture_SaveImage(getPointer(), getCKID(), filepath));
}
public CK_TEXTURE_SAVEOPTIONS GetSaveOptions() => getGenericValue<CK_TEXTURE_SAVEOPTIONS>(BMap.BMTexture_GetSaveOptions);
public void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opt) => setGenericValue<CK_TEXTURE_SAVEOPTIONS>(BMap.BMTexture_SetSaveOptions, opt);
public VX_PIXELFORMAT GetVideoFormat() => getGenericValue<VX_PIXELFORMAT>(BMap.BMTexture_GetVideoFormat);
public void SetVideoFormat(VX_PIXELFORMAT vfmt) => setGenericValue<VX_PIXELFORMAT>(BMap.BMTexture_SetVideoFormat, vfmt);
}
public class BMMaterial : BMObject {
internal BMMaterial(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BMMaterial(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public VxColor GetDiffuse() => getGenericValue<VxColor>(BMap.BMMaterial_GetDiffuse);
public void SetDiffuse(VxColor col) => setGenericValue<VxColor>(BMap.BMMaterial_SetDiffuse, col);
public VxColor GetAmbient() => getGenericValue<VxColor>(BMap.BMMaterial_GetAmbient);
public void SetAmbient(VxColor col) => setGenericValue<VxColor>(BMap.BMMaterial_SetAmbient, col);
public VxColor GetSpecular() => getGenericValue<VxColor>(BMap.BMMaterial_GetSpecular);
public void SetSpecular(VxColor col) => setGenericValue<VxColor>(BMap.BMMaterial_SetSpecular, col);
public VxColor GetEmissive() => getGenericValue<VxColor>(BMap.BMMaterial_GetEmissive);
public void SetEmissive(VxColor col) => setGenericValue<VxColor>(BMap.BMMaterial_SetEmissive, col);
public float GetSpecularPower() => getGenericValue<float>(BMap.BMMaterial_GetSpecularPower);
public void SetSpecularPower(float val) => setGenericValue<float>(BMap.BMMaterial_SetSpecularPower, val);
public VxColor GetTextureBorderColor() {
BMapException.ThrowIfFailed(BMap.BMMaterial_GetTextureBorderColor(getPointer(), getCKID(), out uint out_val));
return new VxColor(out_val);
}
public void SetTextureBorderColor(VxColor col) {
BMapException.ThrowIfFailed(BMap.BMMaterial_SetTextureBorderColor(getPointer(), getCKID(), col.ToDword()));
}
public VXTEXTURE_BLENDMODE GetTextureBlendMode() => getGenericValue<VXTEXTURE_BLENDMODE>(BMap.BMMaterial_GetTextureBlendMode);
public void SetTextureBlendMode(VXTEXTURE_BLENDMODE val) => setGenericValue<VXTEXTURE_BLENDMODE>(BMap.BMMaterial_SetTextureBlendMode, val);
public VXTEXTURE_FILTERMODE GetTextureMinMode() => getGenericValue<VXTEXTURE_FILTERMODE>(BMap.BMMaterial_GetTextureMinMode);
public void SetTextureMinMode(VXTEXTURE_FILTERMODE val) => setGenericValue<VXTEXTURE_FILTERMODE>(BMap.BMMaterial_SetTextureMinMode, val);
public VXTEXTURE_FILTERMODE GetTextureMagMode() => getGenericValue<VXTEXTURE_FILTERMODE>(BMap.BMMaterial_GetTextureMagMode);
public void SetTextureMagMode(VXTEXTURE_FILTERMODE val) => setGenericValue<VXTEXTURE_FILTERMODE>(BMap.BMMaterial_SetTextureMagMode, val);
public VXTEXTURE_ADDRESSMODE GetTextureAddressMode() => getGenericValue<VXTEXTURE_ADDRESSMODE>(BMap.BMMaterial_GetTextureAddressMode);
public void SetTextureAddressMode(VXTEXTURE_ADDRESSMODE val) => setGenericValue<VXTEXTURE_ADDRESSMODE>(BMap.BMMaterial_SetTextureAddressMode, val);
public VXBLEND_MODE GetSourceBlend() => getGenericValue<VXBLEND_MODE>(BMap.BMMaterial_GetSourceBlend);
public void SetSourceBlend(VXBLEND_MODE val) => setGenericValue<VXBLEND_MODE>(BMap.BMMaterial_SetSourceBlend, val);
public VXBLEND_MODE GetDestBlend() => getGenericValue<VXBLEND_MODE>(BMap.BMMaterial_GetDestBlend);
public void SetDestBlend(VXBLEND_MODE val) => setGenericValue<VXBLEND_MODE>(BMap.BMMaterial_SetDestBlend, val);
public VXFILL_MODE GetFillMode() => getGenericValue<VXFILL_MODE>(BMap.BMMaterial_GetFillMode);
public void SetFillMode(VXFILL_MODE val) => setGenericValue<VXFILL_MODE>(BMap.BMMaterial_SetFillMode, val);
public VXSHADE_MODE GetShadeMode() => getGenericValue<VXSHADE_MODE>(BMap.BMMaterial_GetShadeMode);
public void SetShadeMode(VXSHADE_MODE val) => setGenericValue<VXSHADE_MODE>(BMap.BMMaterial_SetShadeMode, val);
public bool GetAlphaTestEnabled() => getGenericValue<bool>(BMap.BMMaterial_GetAlphaTestEnabled);
public void SetAlphaTestEnabled(bool val) => setGenericValue<bool>(BMap.BMMaterial_SetAlphaTestEnabled, val);
public bool GetAlphaBlendEnabled() => getGenericValue<bool>(BMap.BMMaterial_GetAlphaBlendEnabled);
public void SetAlphaBlendEnabled(bool val) => setGenericValue<bool>(BMap.BMMaterial_SetAlphaBlendEnabled, val);
public bool GetPerspectiveCorrectionEnabled() => getGenericValue<bool>(BMap.BMMaterial_GetPerspectiveCorrectionEnabled);
public void SetPerspectiveCorrectionEnabled(bool val) => setGenericValue<bool>(BMap.BMMaterial_SetPerspectiveCorrectionEnabled, val);
public bool GetZWriteEnabled() => getGenericValue<bool>(BMap.BMMaterial_GetZWriteEnabled);
public void SetZWriteEnabled(bool val) => setGenericValue<bool>(BMap.BMMaterial_SetZWriteEnabled, val);
public bool GetTwoSidedEnabled() => getGenericValue<bool>(BMap.BMMaterial_GetTwoSidedEnabled);
public void SetTwoSidedEnabled(bool val) => setGenericValue<bool>(BMap.BMMaterial_SetTwoSidedEnabled, val);
public byte GetAlphaRef() => getGenericValue<byte>(BMap.BMMaterial_GetAlphaRef);
public void SetAlphaRef(byte val) => setGenericValue<byte>(BMap.BMMaterial_SetAlphaRef, val);
public VXCMPFUNC GetAlphaFunc() => getGenericValue<VXCMPFUNC>(BMap.BMMaterial_GetAlphaFunc);
public void SetAlphaFunc(VXCMPFUNC val) => setGenericValue<VXCMPFUNC>(BMap.BMMaterial_SetAlphaFunc, val);
public VXCMPFUNC GetZFunc() => getGenericValue<VXCMPFUNC>(BMap.BMMaterial_GetZFunc);
public void SetZFunc(VXCMPFUNC val) => setGenericValue<VXCMPFUNC>(BMap.BMMaterial_SetZFunc, val);
}
public class BMMesh : BMObject {
internal BMMesh(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BMMesh(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public VXMESH_LITMODE GetLitMode() => getGenericValue<VXMESH_LITMODE>(BMap.BMMesh_GetLitMode);
public void SetLitMode(VXMESH_LITMODE mode) => setGenericValue<VXMESH_LITMODE>(BMap.BMMesh_SetLitMode, mode);
public uint GetVertexCount() => getGenericValue<uint>(BMap.BMMesh_GetVertexCount);
public void SetVertexCount(uint count) => setGenericValue<uint>(BMap.BMMesh_SetVertexCount, count);
public IEnumerable<VxVector3> GetVertexPositions() {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexPositions(getPointer(), getCKID(), out IntPtr out_mem));
return Utils.VxVector3Iterator(out_mem, GetVertexCount());
}
public void SetVertexPositions(IEnumerable<VxVector3> iem) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexPositions(getPointer(), getCKID(), out IntPtr out_mem));
Utils.VxVector3Assigner(out_mem, GetVertexCount(), iem);
}
public IEnumerable<VxVector3> GetVertexNormals() {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexNormals(getPointer(), getCKID(), out IntPtr out_mem));
return Utils.VxVector3Iterator(out_mem, GetVertexCount());
}
public void SetVertexNormals(IEnumerable<VxVector3> iem) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexNormals(getPointer(), getCKID(), out IntPtr out_mem));
Utils.VxVector3Assigner(out_mem, GetVertexCount(), iem);
}
public IEnumerable<VxVector2> GetVertexUVs() {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexUVs(getPointer(), getCKID(), out IntPtr out_mem));
return Utils.VxVector2Iterator(out_mem, GetVertexCount());
}
public void SetVertexUVs(IEnumerable<VxVector2> iem) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetVertexUVs(getPointer(), getCKID(), out IntPtr out_mem));
Utils.VxVector2Assigner(out_mem, GetVertexCount(), iem);
}
public uint GetFaceCount() => getGenericValue<uint>(BMap.BMMesh_GetFaceCount);
public void SetFaceCount(uint count) => setGenericValue<uint>(BMap.BMMesh_SetFaceCount, count);
public IEnumerable<CKShortFaceIndices> GetFaceIndices() {
BMapException.ThrowIfFailed(BMap.BMMesh_GetFaceIndices(getPointer(), getCKID(), out IntPtr out_mem));
return Utils.CKShortFaceIndicesIterator(out_mem, GetFaceCount());
}
public void SetFaceIndices(IEnumerable<CKShortFaceIndices> iem) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetFaceIndices(getPointer(), getCKID(), out IntPtr out_mem));
Utils.CKShortFaceIndicesAssigner(out_mem, GetFaceCount(), iem);
}
public IEnumerable<short> GetFaceMaterialSlotIndexs() {
BMapException.ThrowIfFailed(BMap.BMMesh_GetFaceMaterialSlotIndexs(getPointer(), getCKID(), out IntPtr out_mem));
return Utils.ShortIterator(out_mem, GetFaceCount());
}
public void SetFaceMaterialSlotIndexs(IEnumerable<short> iem) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetFaceMaterialSlotIndexs(getPointer(), getCKID(), out IntPtr out_mem));
Utils.ShortAssigner(out_mem, GetFaceCount(), iem);
}
public uint GetMaterialSlotCount() => getGenericValue<uint>(BMap.BMMesh_GetMaterialSlotCount);
public void SetMaterialSlotCount(uint count) => setGenericValue<uint>(BMap.BMMesh_SetMaterialSlotCount, count);
public IEnumerable<BMMaterial> GetMaterialSlots() {
uint count = GetMaterialSlotCount();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMMesh_GetMaterialSlot(getPointer(), getCKID(), i, out uint out_mtlid));
if (out_mtlid == Utils.INVALID_CKID) yield return null;
else yield return new BMMaterial(getPointer(), out_mtlid);
}
}
public void SetMaterialSlots(IEnumerable<BMMaterial> iem) {
uint count = GetMaterialSlotCount();
var itor = iem.GetEnumerator();
for (uint i = 0; i < count; ++i) {
if (!itor.MoveNext()) throw new BMapException("The length of given material array is too short when assigning material slots.");
uint mtlid = itor.Current is null ? Utils.INVALID_CKID : itor.Current.getCKID();
BMapException.ThrowIfFailed(BMap.BMMesh_SetMaterialSlot(getPointer(), getCKID(), i, mtlid));
}
}
}
public class BM3dObject : BMObject {
internal BM3dObject(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BM3dObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public VxMatrix GetWorldMatrix() => getGenericValue<VxMatrix>(BMap.BM3dObject_GetWorldMatrix);
public void SetWorldMatrix(VxMatrix mat) => setGenericValue<VxMatrix>(BMap.BM3dObject_SetWorldMatrix, mat);
public BMMesh GetCurrentMesh() {
BMapException.ThrowIfFailed(BMap.BM3dObject_GetCurrentMesh(getPointer(), getCKID(), out uint out_meshid));
if (out_meshid == Utils.INVALID_CKID) return null;
else return new BMMesh(getPointer(), out_meshid);
}
public void SetCurrentMesh(BMMesh mesh) {
uint meshid = (mesh is null) ? Utils.INVALID_CKID : mesh.getCKID();
BMapException.ThrowIfFailed(BMap.BM3dObject_SetCurrentMesh(getPointer(), getCKID(), meshid));
}
public bool GetVisibility() => getGenericValue<bool>(BMap.BM3dObject_GetVisibility);
public void SetVisibility(bool visb) => setGenericValue<bool>(BMap.BM3dObject_SetVisibility, visb);
}
public class BMGroup : BMObject {
internal BMGroup(nint raw_pointer, uint ckid) : base(raw_pointer, ckid) {}
internal BMGroup(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public void AddObject(BM3dObject member) {
BMapException.ThrowIfFailed(BMap.BMGroup_AddObject(getPointer(), getCKID(), member.getCKID()));
}
public uint GetObjectCount() => getGenericValue<uint>(BMap.BMGroup_GetObjectCount);
public IEnumerable<BM3dObject> GetObjects() {
var size = GetObjectCount();
for (uint i = 0; i < size; ++i) {
BMapException.ThrowIfFailed(BMap.BMGroup_GetObject(getPointer(), getCKID(), i, out uint out_objid));
yield return new BM3dObject(getPointer(), out_objid);
}
}
}
public sealed class BMFileReader : AbstractPointer {
private static IntPtr AllocateHandle(string file_name, string temp_folder, string texture_folder, string[] encodings) {
private static IntPtr allocateHandle(string file_name, string temp_folder, string texture_folder, string[] encodings) {
BMapException.ThrowIfFailed(BMap.BMFile_Load(
file_name, temp_folder, texture_folder,
Utils.BMapSharpCallback,
@ -196,69 +423,151 @@ namespace BMapSharp.BMapWrapper {
return out_file;
}
protected override bool ReleaseHandle() {
return BMap.BMFile_Free(this.handle);
return BMap.BMFile_Free(this.getPointer());
}
public BMFileReader(string file_name, string temp_folder, string texture_folder, string[] encodings)
: base(AllocateHandle(file_name, temp_folder, texture_folder, encodings)) {}
: base(allocateHandle(file_name, temp_folder, texture_folder, encodings)) { }
public uint GetTextureCount() {
BMapException.ThrowIfFailed(BMap.BMFile_GetTextureCount(this.getPointer(), out uint out_count));
private delegate bool FctProtoGetCount(IntPtr bmf, out uint cnt);
private delegate bool FctProtoGetObject(IntPtr bmf, uint idx, out uint id);
private delegate T FctProtoCreateInstance<T>(IntPtr bmf, uint id);
private uint getCKObjectCount(FctProtoGetCount fct_cnt) {
BMapException.ThrowIfFailed(fct_cnt(this.getPointer(), out uint out_count));
return out_count;
}
public IEnumerable<BMTexture> GetTextures() {
uint count = GetTextureCount();
private IEnumerable<T> getCKObjects<T>(FctProtoGetCount fct_cnt, FctProtoGetObject fct_obj, FctProtoCreateInstance<T> fct_crt) {
uint count = getCKObjectCount(fct_cnt);
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMFile_GetTexture(this.getPointer(), i, out uint out_id));
yield return new BMTexture(this.getPointer(), out_id);
BMapException.ThrowIfFailed(fct_obj(this.getPointer(), i, out uint out_id));
yield return fct_crt(this.getPointer(), out_id);
}
}
public uint GetMaterialCount() {
BMapException.ThrowIfFailed(BMap.BMFile_GetMaterialCount(this.getPointer(), out uint out_count));
return out_count;
public uint GetTextureCount() =>
getCKObjectCount(BMap.BMFile_GetTextureCount);
public IEnumerable<BMTexture> GetTextures() =>
getCKObjects<BMTexture>(BMap.BMFile_GetTextureCount, BMap.BMFile_GetTexture, (bmf, id) => new BMTexture(bmf, id));
public uint GetMaterialCount() =>
getCKObjectCount(BMap.BMFile_GetMaterialCount);
public IEnumerable<BMMaterial> GetMaterials() =>
getCKObjects<BMMaterial>(BMap.BMFile_GetMaterialCount, BMap.BMFile_GetMaterial, (bmf, id) => new BMMaterial(bmf, id));
public uint GetMeshCount() =>
getCKObjectCount(BMap.BMFile_GetMeshCount);
public IEnumerable<BMMesh> GetMeshes() =>
getCKObjects<BMMesh>(BMap.BMFile_GetMeshCount, BMap.BMFile_GetMesh, (bmf, id) => new BMMesh(bmf, id));
public uint Get3dObjectCount() =>
getCKObjectCount(BMap.BMFile_Get3dObjectCount);
public IEnumerable<BM3dObject> Get3dObjects() =>
getCKObjects<BM3dObject>(BMap.BMFile_Get3dObjectCount, BMap.BMFile_Get3dObject, (bmf, id) => new BM3dObject(bmf, id));
public uint GetGroupCount() =>
getCKObjectCount(BMap.BMFile_GetGroupCount);
public IEnumerable<BMGroup> GetGroups() =>
getCKObjects<BMGroup>(BMap.BMFile_GetGroupCount, BMap.BMFile_GetGroup, (bmf, id) => new BMGroup(bmf, id));
}
public sealed class BMFileWriter : AbstractPointer {
private static IntPtr allocateHandle(string temp_folder, string texture_folder, string[] encodings) {
BMapException.ThrowIfFailed(BMap.BMFile_Create(
temp_folder, texture_folder,
Utils.BMapSharpCallback,
(uint)encodings.Length, encodings,
out IntPtr out_file
));
return out_file;
}
public IEnumerable<BMMaterial> GetMaterials() {
uint count = GetMaterialCount();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMFile_GetMaterial(this.getPointer(), i, out uint out_id));
yield return new BMMaterial(this.getPointer(), out_id);
}
protected override bool ReleaseHandle() {
return BMap.BMFile_Free(this.getPointer());
}
public BMFileWriter(string temp_folder, string texture_folder, string[] encodings)
: base(allocateHandle(temp_folder, texture_folder, encodings)) { }
public void Save(string filename, CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, int compress_level) {
BMapException.ThrowIfFailed(BMap.BMFile_Save(
getPointer(),
filename,
texture_save_opt,
use_compress,
compress_level
));
}
public uint GetMeshCount() {
BMapException.ThrowIfFailed(BMap.BMFile_GetMeshCount(this.getPointer(), out uint out_count));
return out_count;
}
public IEnumerable<BMMesh> GetMeshs() {
uint count = GetMeshCount();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMFile_GetMesh(this.getPointer(), i, out uint out_id));
yield return new BMMesh(this.getPointer(), out_id);
}
private delegate bool FctProtoCreateObject(IntPtr bmf, out uint id);
private delegate T FctProtoCreateInstance<T>(IntPtr bmf, uint id);
private T createCKObject<T>(FctProtoCreateObject fct_crt, FctProtoCreateInstance<T> fct_inst) {
BMapException.ThrowIfFailed(fct_crt(this.getPointer(), out uint out_id));
return fct_inst(this.getPointer(), out_id);
}
public uint Get3dObjectCount() {
BMapException.ThrowIfFailed(BMap.BMFile_Get3dObjectCount(this.getPointer(), out uint out_count));
return out_count;
public BMTexture CreateTexture() => createCKObject<BMTexture>(BMap.BMFile_CreateTexture, (bmf, id) => new BMTexture(bmf, id));
public BMMaterial CreateMaterial() => createCKObject<BMMaterial>(BMap.BMFile_CreateMaterial, (bmf, id) => new BMMaterial(bmf, id));
public BMMesh CreateMesh() => createCKObject<BMMesh>(BMap.BMFile_CreateMesh, (bmf, id) => new BMMesh(bmf, id));
public BM3dObject Create3dObject() => createCKObject<BM3dObject>(BMap.BMFile_Create3dObject, (bmf, id) => new BM3dObject(bmf, id));
public BMGroup CreateGroup() => createCKObject<BMGroup>(BMap.BMFile_CreateGroup, (bmf, id) => new BMGroup(bmf, id));
}
public sealed class BMMeshTrans : AbstractPointer {
private static IntPtr allocateHandle() {
BMapException.ThrowIfFailed(BMap.BMMeshTrans_New(out IntPtr out_trans));
return out_trans;
}
public IEnumerable<BM3dObject> Get3dObjects() {
uint count = Get3dObjectCount();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMFile_Get3dObject(this.getPointer(), i, out uint out_id));
yield return new BM3dObject(this.getPointer(), out_id);
}
protected override bool ReleaseHandle() {
return BMap.BMMeshTrans_Delete(this.getPointer());
}
public BMMeshTrans() : base(allocateHandle()) { }
public void Parse(BMMesh objmesh) {
BMapException.ThrowIfFailed(BMap.BMMeshTrans_Parse(
getPointer(),
objmesh.getPointer(),
objmesh.getCKID()
));
}
public uint GetGroupCount() {
BMapException.ThrowIfFailed(BMap.BMFile_GetGroupCount(this.getPointer(), out uint out_count));
return out_count;
public void PrepareVertex(uint count, IEnumerable<VxVector3> iem) {
// Prepare count first
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareVertexCount(getPointer(), count));
// Then put data
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareVertex(getPointer(), out IntPtr out_mem));
Utils.VxVector3Assigner(out_mem, count, iem);
}
public IEnumerable<BMGroup> GetGroups() {
uint count = GetGroupCount();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(BMap.BMFile_GetGroup(this.getPointer(), i, out uint out_id));
yield return new BMGroup(this.getPointer(), out_id);
}
public void PrepareNormal(uint count, IEnumerable<VxVector3> iem) {
// Prepare count first
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareNormalCount(getPointer(), count));
// Then put data
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareNormal(getPointer(), out IntPtr out_mem));
Utils.VxVector3Assigner(out_mem, count, iem);
}
public void PrepareUV(uint count, IEnumerable<VxVector2> iem) {
// Prepare count first
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareUVCount(getPointer(), count));
// Then put data
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareUV(getPointer(), out IntPtr out_mem));
Utils.VxVector2Assigner(out_mem, count, iem);
}
public void PrepareMtlSlot(uint count, IEnumerable<BMMaterial> iem) {
// Prepare count first
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareMtlSlotCount(getPointer(), count));
// Then put data
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareMtlSlot(getPointer(), out IntPtr out_mem));
var cast_iem = iem.Select((mtl) => mtl is null ? Utils.INVALID_CKID : mtl.getCKID());
Utils.CKIDAssigner(out_mem, count, cast_iem);
}
public void PrepareFace(uint count, IEnumerable<CKFaceIndices> vec_idx, IEnumerable<CKFaceIndices> nml_idx, IEnumerable<CKFaceIndices> uv_idx, IEnumerable<uint> mtl_idx) {
// Prepare count first
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareFaceCount(getPointer(), count));
// Get data address
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareFaceVertexIndices(getPointer(), out IntPtr raw_vec_idx));
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareFaceNormalIndices(getPointer(), out IntPtr raw_nml_idx));
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareFaceUVIndices(getPointer(), out IntPtr raw_uv_idx));
BMapException.ThrowIfFailed(BMap.BMMeshTrans_PrepareFaceMtlSlot(getPointer(), out IntPtr raw_mtl_idx));
// Assign data
Utils.CKFaceIndicesAssigner(raw_vec_idx, count, vec_idx);
Utils.CKFaceIndicesAssigner(raw_nml_idx, count, nml_idx);
Utils.CKFaceIndicesAssigner(raw_uv_idx, count, uv_idx);
Utils.CKDWORDAssigner(raw_mtl_idx, count, mtl_idx);
}
}

View File

@ -15,12 +15,14 @@ namespace BMapSharp.VirtoolsTypes {
public float X, Y;
public VxVector2(float _x = 0.0f, float _y = 0.0f) {
X = _x;
Y = _y;
X = _x; Y = _y;
}
public VxVector2(Vector2 vec) {
FromManaged(vec);
}
public void FromManaged(Vector2 vec) {
X = vec.X;
Y = vec.Y;
X = vec.X; Y = vec.Y;
}
public Vector2 ToManaged() {
return new Vector2(X, Y);
@ -33,14 +35,14 @@ namespace BMapSharp.VirtoolsTypes {
public float X, Y, Z;
public VxVector3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f) {
X = _x;
Y = _y;
Z = _z;
X = _x; Y = _y; Z = _z;
}
public VxVector3(Vector3 vec) {
FromManaged(vec);
}
public void FromManaged(Vector3 vec) {
X = vec.X;
Y = vec.Y;
Z = vec.Z;
X = vec.X; Y = vec.Y; Z = vec.Z;
}
public Vector3 ToManaged() {
return new Vector3(X, Y, Z);
@ -50,29 +52,31 @@ namespace BMapSharp.VirtoolsTypes {
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct VxColor {
[MarshalAs(UnmanagedType.R4)]
public float A, R, G, B;
public float R, G, B, A;
public VxColor(float _r, float _g, float _b, float _a) {
A = _a;
R = _r;
G = _g;
B = _b;
A = _a; R = _r; G = _g; B = _b;
Regulate();
}
public VxColor(Vector4 col) {
FromManagedRGBA(col);
}
public VxColor(Vector3 col) {
FromManagedRGB(col);
}
public VxColor(uint val) {
FromDword(val);
}
public void FromManagedRGBA(Vector4 col) {
R = col.X;
G = col.Y;
B = col.Z;
A = col.W;
R = col.X; G = col.Y; B = col.Z; A = col.W;
Regulate();
}
public Vector4 ToManagedRGBA() {
return new Vector4(R, G, B, A);
}
public void FromManagedRGB(Vector3 col) {
R = col.X;
G = col.Y;
B = col.Z;
R = col.X; G = col.Y; B = col.Z; A = 1.0f;
Regulate();
}
public Vector3 ToManagedRGB() {
@ -101,6 +105,7 @@ namespace BMapSharp.VirtoolsTypes {
val |= (uint)(B * 255.0f);
return val;
}
public static float ClampFactor(float factor) {
return System.Math.Clamp(factor, 0.0f, 1.0f);
}
@ -166,6 +171,18 @@ namespace BMapSharp.VirtoolsTypes {
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct CKShortFaceIndices {
[MarshalAs(UnmanagedType.U2)]
public ushort I1, I2, I3;
public CKShortFaceIndices(ushort i1 = 0, ushort i2 = 0, ushort i3 = 0) {
I1 = i1;
I2 = i2;
I3 = i3;
}
}
public enum CK_TEXTURE_SAVEOPTIONS : uint {
CKTEXTURE_RAWDATA = 0, /**< Save raw data inside file. The bitmap is saved in a raw 32 bit per pixel format. */
CKTEXTURE_EXTERNAL = 1, /**< Store only the file name for the texture. The bitmap file must be present in the bitmap paths when loading the composition. */

View File

@ -1,10 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\BMapSharp\BMapSharp.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,12 +1,146 @@
using BMapSharp.BMapWrapper;
using System;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
namespace BMapSharpTestbench {
internal class Program {
static void Main(string[] args) {
// Check environment
Console.OutputEncoding = Encoding.UTF8;
if (!BMapSharp.BMapWrapper.Utils.IsBMapAvailable()) {
Console.WriteLine("Fail to initialize native BMap.");
Environment.Exit(0);
}
// Waiting debugger
int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
Console.WriteLine($"C# PID is {pid}. Waiting debugger, press any key to continue...");
Console.ReadKey(true);
// Start testbench
string file_name = "Level_02.NMO";
string temp_folder = "Temp";
string texture_folder = "F:\\Ballance\\Ballance\\Textures";
string[] encodings = ["cp1252", "gb2312"];
using (var reader = new BMapSharp.BMapWrapper.BMFileReader(file_name, temp_folder, texture_folder, encodings)) {
TestCommon(reader);
TestIEquatable(reader);
}
Console.WriteLine("Press any key to quit...");
Console.ReadKey(true);
namespace BMapSharpTestbench // Note: actual namespace depends on the project name.
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
static void TestCommon(BMapSharp.BMapWrapper.BMFileReader reader) {
// Console.WriteLine("===== Groups =====");
// foreach (var gp in reader.GetGroups()) {
// Console.WriteLine(gp.GetName());
// foreach (var gp_item in gp.GetObjects()) {
// Console.WriteLine($"\t{gp_item.GetName()}");
// }
// }
// Console.WriteLine("===== 3dObjects =====");
// foreach (var obj in reader.Get3dObjects()) {
// Console.WriteLine(obj.GetName());
// var current_mesh = obj.GetCurrentMesh();
// var mesh_name = current_mesh is null ? "<null>" : current_mesh.GetName();
// Console.WriteLine($"\tMesh: {mesh_name}");
// Console.WriteLine($"\tVisibility: {obj.GetVisibility()}");
// Console.WriteLine($"\tMatrix: {obj.GetWorldMatrix().ToManaged()}");
// }
// Console.WriteLine("===== Meshes =====");
// foreach (var mesh in reader.GetMeshes()) {
// Console.WriteLine(mesh.GetName());
// Console.WriteLine($"\tLit Mode: {mesh.GetLitMode()}");
// Console.WriteLine($"\tVertex Count: {mesh.GetVertexCount()}");
// Console.WriteLine($"\tFace Count: {mesh.GetFaceCount()}");
// Console.WriteLine($"\tMaterial Slot Count: {mesh.GetMaterialSlotCount()}");
// }
Console.WriteLine("===== Materials =====");
foreach (var mtl in reader.GetMaterials()) {
Console.WriteLine(mtl.GetName());
Console.WriteLine($"\tDiffuse: {mtl.GetDiffuse().ToManagedRGBA()}");
Console.WriteLine($"\tAmbient: {mtl.GetAmbient().ToManagedRGBA()}");
Console.WriteLine($"\tSpecular: {mtl.GetSpecular().ToManagedRGBA()}");
Console.WriteLine($"\tEmissive: {mtl.GetEmissive().ToManagedRGBA()}");
Console.WriteLine($"\tSpecular Power: {mtl.GetSpecularPower()}");
Console.WriteLine($"\tTexture Border Color: {mtl.GetTextureBorderColor().ToManagedRGBA()}");
Console.WriteLine($"\tTexture Blend Mode: {mtl.GetTextureBlendMode()}");
Console.WriteLine($"\tTexture Min Mode: {mtl.GetTextureMinMode()}");
Console.WriteLine($"\tTexture Mag Mode: {mtl.GetTextureMagMode()}");
Console.WriteLine($"\tSource Blend: {mtl.GetSourceBlend()}");
Console.WriteLine($"\tDest Blend: {mtl.GetDestBlend()}");
Console.WriteLine($"\tFill Mode: {mtl.GetFillMode()}");
Console.WriteLine($"\tShade Mode: {mtl.GetShadeMode()}");
Console.WriteLine($"\tAlpha Test Enabled: {mtl.GetAlphaTestEnabled()}");
Console.WriteLine($"\tAlpha Blend Enabled: {mtl.GetAlphaBlendEnabled()}");
Console.WriteLine($"\tPerspective Correction Enabled: {mtl.GetPerspectiveCorrectionEnabled()}");
Console.WriteLine($"\tZ Write Enabled: {mtl.GetZWriteEnabled()}");
Console.WriteLine($"\tTwo Sided Enabled: {mtl.GetTwoSidedEnabled()}");
Console.WriteLine($"\tAlpha Ref: {mtl.GetAlphaRef()}");
Console.WriteLine($"\tAlpha Func: {mtl.GetAlphaFunc()}");
Console.WriteLine($"\tZ Func: {mtl.GetZFunc()}");
}
// Console.WriteLine("===== Textures =====");
// foreach (var tex in reader.GetTextures()) {
// Console.WriteLine(tex.GetName());
// Console.WriteLine($"\tFile Name: {tex.GetFileName()}");
// Console.WriteLine($"\tSave Options: {tex.GetSaveOptions()}");
// Console.WriteLine($"\tVideo Format: {tex.GetVideoFormat()}");
// }
Console.WriteLine("===== END =====");
}
static void TestIEquatable(BMapSharp.BMapWrapper.BMFileReader reader) {
if (reader.Get3dObjectCount() < 2u) {
Debug.Fail(
"Invalid file for test IEquatable.",
"We can not perform IEquatable test because the length of 3dObject is too short (must greater than 2). Please choose another file to perform."
);
return;
}
// Prepare test variables
var all_3dobjects = new List<BM3dObject>(reader.Get3dObjects());
var first_3dobj = all_3dobjects[0];
var second_3dobj = all_3dobjects[1];
all_3dobjects = new List<BM3dObject>(reader.Get3dObjects());
var first_3dobj_again = all_3dobjects[0];
Debug.Assert(!Object.ReferenceEquals(first_3dobj, first_3dobj_again));
// Hashtable test
var test_hashset = new HashSet<BM3dObject>();
Debug.Assert(test_hashset.Add(first_3dobj));
Debug.Assert(!test_hashset.Add(first_3dobj_again));
Debug.Assert(test_hashset.Add(second_3dobj));
// Dictionary test
var test_dictionary = new Dictionary<BM3dObject, string>();
Debug.Assert(test_dictionary.TryAdd(first_3dobj, first_3dobj.GetName()));
Debug.Assert(!test_dictionary.TryAdd(first_3dobj_again, first_3dobj_again.GetName()));
Debug.Assert(test_dictionary.TryAdd(second_3dobj, second_3dobj.GetName()));
}
}
}

View File

@ -1,4 +1,4 @@
import ctypes, typing, atexit
import ctypes, typing, atexit, enum
from . import bmap, virtools_types
#region Basic Class & Constant Defines
@ -13,12 +13,85 @@ def _python_callback(strl: bytes):
Simply add a prefix when output.
Need a convertion before passing to BMFile.
"""
# the passing value is bytes, not bmap.bm_CKSTRING.
# i think Python do a auto convertion here.
# YYC Remarks:
# The passing value to this function is bytes, not bmap.bm_CKSTRING.
# I think Python do an auto convertion in there.
if strl is not None:
print(f'[PyBMap] {strl.decode(g_BMapEncoding)}')
_g_RawCallback: bmap.bm_callback = bmap.bm_callback(_python_callback)
#endregion
#region Help Functions
class _Utils:
@staticmethod
def raise_out_of_length_exception() -> None:
raise bmap.BMapException("The length of given data is too short when assigning struct array.")
@staticmethod
def _vector_assigner(pdata: typing.Any, item_count: int, factor_count: int, itor: typing.Iterator[tuple[typing.Any, ...]]) -> None:
idx: int = 0
try:
for _i in range(item_count):
user_vector: tuple[typing.Any, ...] = next(itor)
for _j in range(factor_count):
pdata[idx] = user_vector[_j]
idx += 1
except StopIteration:
_Utils.raise_out_of_length_exception()
@staticmethod
def _vector_iterator(pdata: typing.Any, item_count: int, factor_count: int) -> typing.Iterator[tuple[typing.Any, ...]]:
idx: int = 0
for _i in range(item_count):
yield tuple(map(
lambda _j: pdata[idx + _j],
range(factor_count)
))
idx += factor_count
@staticmethod
def vxvector3_assigner(pvector: bmap.bm_VxVector3_p, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
_Utils._vector_assigner(ctypes.cast(pvector, bmap.bm_CKFLOAT_p), count, 3, map(lambda v: (v.x, v.y, v.z), itor))
@staticmethod
def vxvector3_iterator(pvector: bmap.bm_VxVector3_p, count: int) -> typing.Iterator[virtools_types.VxVector3]:
return map(
lambda v: virtools_types.VxVector3(*v),
_Utils._vector_iterator(ctypes.cast(pvector, bmap.bm_CKFLOAT_p), count, 3)
)
@staticmethod
def vxvector2_assigner(pvector: bmap.bm_VxVector2_p, count: int, itor: typing.Iterator[virtools_types.VxVector2]) -> None:
_Utils._vector_assigner(ctypes.cast(pvector, bmap.bm_CKFLOAT_p), count, 2, map(lambda v: (v.x, v.y), itor))
@staticmethod
def vxvector2_iterator(pvector: bmap.bm_VxVector2_p, count: int) -> typing.Iterator[virtools_types.VxVector2]:
return map(
lambda v: virtools_types.VxVector2(*v),
_Utils._vector_iterator(ctypes.cast(pvector, bmap.bm_CKFLOAT_p), count, 2)
)
"""!
@remarks
bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p is just a type hint.
We actually do not need distinguish them in code.
Because the stride when increasing them is decided by their runtime type.
"""
@staticmethod
def ckfaceindices_assigner(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int, itor: typing.Iterator[virtools_types.CKFaceIndices]) -> None:
_Utils._vector_assigner(pindices, count, 3, map(lambda v: (v.i1, v.i2, v.i3), itor))
@staticmethod
def ckfaceindices_iterator(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int) -> typing.Iterator[virtools_types.CKFaceIndices]:
return map(
lambda v: virtools_types.CKFaceIndices(*v),
_Utils._vector_iterator(pindices, count, 3)
)
#endregion
#region Basic Classes
class _AbstractPointer():
__mRawPointer: int
@ -46,6 +119,11 @@ class _AbstractPointer():
def __hash__(self) -> int:
return hash(self.__mRawPointer)
TEnumType = typing.TypeVar('TEnumType', bound = enum.IntEnum)
TIntegralType = bmap.bm_CKDWORD | bmap.bm_CKWORD | bmap.bm_CKINT | bmap.bm_CKBYTE | bmap.bm_CKID
TFloatPointType = bmap.bm_CKFLOAT
TPointerType = typing.TypeVar('TPointerType')
class _AbstractCKObject(_AbstractPointer):
__mCKID: int
@ -70,78 +148,76 @@ class _AbstractCKObject(_AbstractPointer):
def __hash__(self) -> int:
return hash((_AbstractPointer.__hash__(self), self.__mCKID))
#endregion
# Convenient Value Getter Setter
# Focusing on those which widely called types.
#region Help Function & Type Define
def _get_primitive_value(self, primitive_type_: typing.Any, getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool]) -> typing.Any:
data = primitive_type_()
getter_(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
def _set_primitive_value(self, primitive_type_: typing.Any, setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool], data_: typing.Any) -> None:
data = primitive_type_(data_)
setter_(self._get_pointer(), self._get_ckid(), data)
TCKObj = typing.TypeVar('TCKObj', bound = _AbstractCKObject)
def _get_integral_value(self, integral_type_: type[TIntegralType], getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool]) -> int:
return self._get_primitive_value(integral_type_, getter_)
def _set_integral_value(self, integral_type_: type[TIntegralType], setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool], data_: int) -> None:
self._set_primitive_value(integral_type_, setter_, data_)
def _vxvector3_assigner(pvector: bmap.bm_VxVector3_p, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
pfloat: bmap.bm_CKFLOAT_p = ctypes.cast(pvector, bmap.bm_CKFLOAT_p)
idx: int = 0
for _ in range(count):
uservector: virtools_types.VxVector3 = next(itor)
pfloat[idx] = uservector.x
pfloat[idx + 1] = uservector.y
pfloat[idx + 2] = uservector.z
idx += 3
def _get_float_point_value(self, float_point_type_: type[TFloatPointType], getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool]) -> float:
return self._get_primitive_value(float_point_type_, getter_)
def _set_float_point_value(self, float_point_type_: type[TFloatPointType], setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool], data_: float) -> None:
self._set_primitive_value(float_point_type_, setter_, data_)
def _vxvector3_iterator(pvector: bmap.bm_VxVector3_p, count: int) -> typing.Iterator[virtools_types.VxVector3]:
ret: virtools_types.VxVector3 = virtools_types.VxVector3()
pfloat: bmap.bm_CKFLOAT_p = ctypes.cast(pvector, bmap.bm_CKFLOAT_p)
idx: int = 0
for _ in range(count):
ret.x = pfloat[idx]
ret.y = pfloat[idx + 1]
ret.z = pfloat[idx + 2]
idx += 3
yield ret
def _get_bool_value(self, getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_bool_p], bmap.bm_bool]) -> bool:
return self._get_primitive_value(bmap.bm_bool, getter_)
def _set_bool_value(self, setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_bool], bmap.bm_bool], data_: bool) -> None:
self._set_primitive_value(bmap.bm_bool, setter_, data_)
def _vxvector2_assigner(pvector: bmap.bm_VxVector2_p, count: int, itor: typing.Iterator[virtools_types.VxVector2]) -> None:
pfloat: bmap.bm_CKFLOAT_p = ctypes.cast(pvector, bmap.bm_CKFLOAT_p)
idx: int = 0
for _ in range(count):
uservector: virtools_types.VxVector2 = next(itor)
pfloat[idx] = uservector.x
pfloat[idx + 1] = uservector.y
idx += 2
def _get_enum_value(self, enum_type_: type[TEnumType], getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_enum_p], bmap.bm_bool]) -> TEnumType:
return enum_type_(self._get_primitive_value(bmap.bm_enum, getter_))
def _set_enum_value(self, setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_enum], bmap.bm_bool], data_: TEnumType) -> None:
self._set_primitive_value(bmap.bm_enum, setter_, data_.value)
def _vxvector2_iterator(pvector: bmap.bm_VxVector2_p, count: int) -> typing.Iterator[virtools_types.VxVector2]:
ret: virtools_types.VxVector2 = virtools_types.VxVector2()
pfloat: bmap.bm_CKFLOAT_p = ctypes.cast(pvector, bmap.bm_CKFLOAT_p)
idx: int = 0
for _ in range(count):
ret.x = pfloat[idx]
ret.y = pfloat[idx + 1]
idx += 2
yield ret
def _get_str_value(self, getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_CKSTRING_p], bmap.bm_bool]) -> str | None:
data: bmap.bm_CKSTRING = bmap.bm_CKSTRING()
getter_(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
if data.value is None: return None
else: return data.value.decode(g_BMapEncoding)
def _set_str_value(self, setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_CKSTRING], bmap.bm_bool], data_: str | None) -> None:
data: bmap.bm_CKSTRING
if data_ is None: data = bmap.bm_CKSTRING(0)
else: data = bmap.bm_CKSTRING(data_.encode(g_BMapEncoding))
setter_(self._get_pointer(), self._get_ckid(), data)
# bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p is just a type hint
# wo do not need distinguish them in code.
# because the type of pindices is decided by runtime.
def _set_vxcolor_value(self,
setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_VxColor], bmap.bm_bool],
col_: virtools_types.VxColor) -> None:
# set to raw color
col: bmap.bm_VxColor = bmap.bm_VxColor()
(col.r, col.g, col.b, col.a) = (col_.r, col_.g, col_.b, col_.a)
# assign
setter_(self._get_pointer(), self._get_ckid(), col)
def _get_vxcolor_value(self,
getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_VxColor_p], bmap.bm_bool]) -> virtools_types.VxColor:
# get raw color
col: bmap.bm_VxColor = bmap.bm_VxColor()
getter_(self._get_pointer(), self._get_ckid(), ctypes.byref(col))
# get from raw color
ret: virtools_types.VxColor = virtools_types.VxColor()
(ret.r, ret.g, ret.b, ret.a) = (col.r, col.g, col.b, col.a)
return ret
def _ckfaceindices_assigner(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int, itor: typing.Iterator[virtools_types.CKFaceIndices]) -> None:
idx: int = 0
for _ in range(count):
userindices: virtools_types.CKFaceIndices = next(itor)
pindices[idx] = userindices.i1
pindices[idx + 1] = userindices.i2
pindices[idx + 2] = userindices.i3
idx += 3
def _get_pointer_value(self, ptr_type_: type[TPointerType], getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, typing.Any], bmap.bm_bool]) -> TPointerType:
data = ptr_type_()
getter_(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data
def _ckfaceindices_iterator(pindices: bmap.bm_CKWORD_p | bmap.bm_CKDWORD_p, count: int) -> typing.Iterator[virtools_types.CKFaceIndices]:
ret: virtools_types.CKFaceIndices = virtools_types.CKFaceIndices()
idx: int = 0
for _ in range(count):
ret.i1 = pindices[idx]
ret.i2 = pindices[idx + 1]
ret.i3 = pindices[idx + 2]
idx += 3
yield ret
TCKObject = typing.TypeVar('TCKObject', bound = _AbstractCKObject)
#endregion
#region Valid Check, Init and Dispose
#region Validation Check, Init and Dispose
def is_bmap_available() -> bool:
return bmap.is_bmap_available()
@ -159,7 +235,7 @@ if is_bmap_available():
#region Real Type Defines
"""!
@remark
@remarks
BMFileReader, BMFileWriter, and BMMeshTrans can be create by given constructor.
But they must be destroyed by calling dispose(). Otherwise it may cause memory leak.
You also can use python `with` statement to achieve this automatically.
@ -173,337 +249,204 @@ We just provide them as a visitor.
class BMObject(_AbstractCKObject):
def get_name(self) -> str | None:
name: bmap.bm_CKSTRING = bmap.bm_CKSTRING()
bmap.BMObject_GetName(self._get_pointer(), self._get_ckid(), ctypes.byref(name))
if name.value is None:
return None
else:
return name.value.decode(g_BMapEncoding)
return self._get_str_value(bmap.BMObject_GetName)
def set_name(self, name_: str | None) -> None:
name: bmap.bm_CKSTRING
if name_ is None:
name = bmap.bm_CKSTRING(0)
else:
name = bmap.bm_CKSTRING(name_.encode(g_BMapEncoding))
bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name)
self._set_str_value(bmap.BMObject_SetName, name_)
class BMTexture(BMObject):
def get_file_name(self) -> str | None:
filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING()
bmap.BMTexture_GetFileName(self._get_pointer(), self._get_ckid(), ctypes.byref(filename))
if filename.value is None:
return None
else:
return filename.value.decode(g_BMapEncoding)
return self._get_str_value(bmap.BMTexture_GetFileName)
def load_image(self, filepath: str) -> None:
filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING(filepath.encode(g_BMapEncoding))
bmap.BMTexture_LoadImage(self._get_pointer(), self._get_ckid(), filename)
def save_image(self, filepath: str) -> None:
filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING(filepath.encode(g_BMapEncoding))
bmap.BMTexture_SaveImage(self._get_pointer(), self._get_ckid(), filename)
def get_save_options(self) -> virtools_types.CK_TEXTURE_SAVEOPTIONS:
opt: bmap.bm_enum = bmap.bm_enum()
bmap.BMTexture_GetSaveOptions(self._get_pointer(), self._get_ckid(), ctypes.byref(opt))
return virtools_types.CK_TEXTURE_SAVEOPTIONS(opt.value)
return self._get_enum_value(virtools_types.CK_TEXTURE_SAVEOPTIONS, bmap.BMTexture_GetSaveOptions)
def set_save_options(self, opt_: virtools_types.CK_TEXTURE_SAVEOPTIONS) -> None:
opt: bmap.bm_enum = bmap.bm_enum(opt_.value)
bmap.BMTexture_SetSaveOptions(self._get_pointer(), self._get_ckid(), opt)
self._set_enum_value(bmap.BMTexture_SetSaveOptions, opt_)
def get_video_format(self) -> virtools_types.VX_PIXELFORMAT:
fmt: bmap.bm_enum = bmap.bm_enum()
bmap.BMTexture_GetVideoFormat(self._get_pointer(), self._get_ckid(), ctypes.byref(fmt))
return virtools_types.VX_PIXELFORMAT(fmt.value)
return self._get_enum_value(virtools_types.VX_PIXELFORMAT, bmap.BMTexture_GetVideoFormat)
def set_video_format(self, fmt_: virtools_types.VX_PIXELFORMAT) -> None:
fmt: bmap.bm_enum = bmap.bm_enum(fmt_.value)
bmap.BMTexture_SetVideoFormat(self._get_pointer(), self._get_ckid(), fmt)
self._set_enum_value(bmap.BMTexture_SetVideoFormat, fmt_)
class BMMaterial(BMObject):
def _set_vxcolor(self,
setter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_VxColor], bool],
col_: virtools_types.VxColor) -> None:
# set to raw color
col: bmap.bm_VxColor = bmap.bm_VxColor()
col.r = col_.r
col.g = col_.g
col.b = col_.b
col.a = col_.a
# assign
setter_(self._get_pointer(), self._get_ckid(), col)
def _get_vxcolor(self,
getter_: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID, bmap.bm_VxColor_p], bool]) -> virtools_types.VxColor:
# get raw color
col: bmap.bm_VxColor = bmap.bm_VxColor()
getter_(self._get_pointer(), self._get_ckid(), ctypes.byref(col))
# get from raw color
ret: virtools_types.VxColor = virtools_types.VxColor()
ret.r = col.r
ret.g = col.g
ret.b = col.b
ret.a = col.a
return ret
def get_diffuse(self) -> virtools_types.VxColor:
return self._get_vxcolor(bmap.BMMaterial_GetDiffuse)
return self._get_vxcolor_value(bmap.BMMaterial_GetDiffuse)
def set_diffuse(self, col: virtools_types.VxColor) -> None:
self._set_vxcolor(bmap.BMMaterial_SetDiffuse, col)
self._set_vxcolor_value(bmap.BMMaterial_SetDiffuse, col)
def get_ambient(self) -> virtools_types.VxColor:
return self._get_vxcolor(bmap.BMMaterial_GetAmbient)
return self._get_vxcolor_value(bmap.BMMaterial_GetAmbient)
def set_ambient(self, col: virtools_types.VxColor) -> None:
self._set_vxcolor(bmap.BMMaterial_SetAmbient, col)
self._set_vxcolor_value(bmap.BMMaterial_SetAmbient, col)
def get_specular(self) -> virtools_types.VxColor:
return self._get_vxcolor(bmap.BMMaterial_GetSpecular)
return self._get_vxcolor_value(bmap.BMMaterial_GetSpecular)
def set_specular(self, col: virtools_types.VxColor) -> None:
self._set_vxcolor(bmap.BMMaterial_SetSpecular, col)
self._set_vxcolor_value(bmap.BMMaterial_SetSpecular, col)
def get_emissive(self) -> virtools_types.VxColor:
return self._get_vxcolor(bmap.BMMaterial_GetEmissive)
return self._get_vxcolor_value(bmap.BMMaterial_GetEmissive)
def set_emissive(self, col: virtools_types.VxColor) -> None:
self._set_vxcolor(bmap.BMMaterial_SetEmissive, col)
self._set_vxcolor_value(bmap.BMMaterial_SetEmissive, col)
def get_specular_power(self) -> float:
power: bmap.bm_CKFLOAT = bmap.bm_CKFLOAT()
bmap.BMMaterial_GetSpecularPower(self._get_pointer(), self._get_ckid(), ctypes.byref(power))
return power.value
return self._get_float_point_value(bmap.bm_CKFLOAT, bmap.BMMaterial_GetSpecularPower)
def set_specular_power(self, power_: float) -> None:
power: bmap.bm_CKFLOAT = bmap.bm_CKFLOAT(power_)
bmap.BMMaterial_SetSpecularPower(self._get_pointer(), self._get_ckid(), power)
self._set_float_point_value(bmap.bm_CKFLOAT, bmap.BMMaterial_SetSpecularPower, power_)
def get_texture(self) -> BMTexture | None:
objid: bmap.bm_CKID = bmap.bm_CKID()
bmap.BMMaterial_GetTexture(self._get_pointer(), self._get_ckid(), ctypes.byref(objid))
if objid.value == g_InvalidCKID:
return None
else:
return BMTexture(self._get_pointer(), objid)
if objid.value == g_InvalidCKID: return None
else: return BMTexture(self._get_pointer(), objid)
def set_texture(self, tex_: BMTexture | None) -> None:
objid: bmap.bm_CKID = bmap.bm_CKID(g_InvalidCKID)
if tex_ is not None:
objid = tex_._get_ckid()
if tex_ is not None: objid = tex_._get_ckid()
bmap.BMMaterial_SetTexture(self._get_pointer(), self._get_ckid(), objid)
def get_texture_border_color(self) -> virtools_types.VxColor:
col: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
bmap.BMMaterial_GetTextureBorderColor(self._get_pointer(), self._get_ckid(), ctypes.byref(col))
dword_color: int = self._get_integral_value(bmap.bm_CKDWORD, bmap.BMMaterial_GetTextureBorderColor)
ret: virtools_types.VxColor = virtools_types.VxColor()
ret.from_dword(col.value)
ret.from_dword(dword_color)
return ret
def set_texture_border_color(self, col_: virtools_types.VxColor) -> None:
col: bmap.bm_CKDWORD = bmap.bm_CKDWORD(col_.to_dword())
bmap.BMMaterial_SetTextureBorderColor(self._get_pointer(), self._get_ckid(), col)
self._set_integral_value(bmap.bm_CKDWORD, bmap.BMMaterial_SetTextureBorderColor, col_.to_dword())
def get_texture_blend_mode(self) -> virtools_types.VXTEXTURE_BLENDMODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetTextureBlendMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXTEXTURE_BLENDMODE(data.value)
return self._get_enum_value(virtools_types.VXTEXTURE_BLENDMODE, bmap.BMMaterial_GetTextureBlendMode)
def set_texture_blend_mode(self, data_: virtools_types.VXTEXTURE_BLENDMODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetTextureBlendMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetTextureBlendMode, data_)
def get_texture_min_mode(self) -> virtools_types.VXTEXTURE_FILTERMODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetTextureMinMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXTEXTURE_FILTERMODE(data.value)
return self._get_enum_value(virtools_types.VXTEXTURE_FILTERMODE, bmap.BMMaterial_GetTextureMinMode)
def set_texture_min_mode(self, data_: virtools_types.VXTEXTURE_FILTERMODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetTextureMinMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetTextureMinMode, data_)
def get_texture_mag_mode(self) -> virtools_types.VXTEXTURE_FILTERMODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetTextureMagMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXTEXTURE_FILTERMODE(data.value)
return self._get_enum_value(virtools_types.VXTEXTURE_FILTERMODE, bmap.BMMaterial_GetTextureMagMode)
def set_texture_mag_mode(self, data_: virtools_types.VXTEXTURE_FILTERMODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetTextureMagMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetTextureMagMode, data_)
def get_texture_address_mode(self) -> virtools_types.VXTEXTURE_ADDRESSMODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetTextureAddressMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXTEXTURE_ADDRESSMODE(data.value)
return self._get_enum_value(virtools_types.VXTEXTURE_ADDRESSMODE, bmap.BMMaterial_GetTextureAddressMode)
def set_texture_address_mode(self, data_: virtools_types.VXTEXTURE_ADDRESSMODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetTextureAddressMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetTextureAddressMode, data_)
def get_source_blend(self) -> virtools_types.VXBLEND_MODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetSourceBlend(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXBLEND_MODE(data.value)
return self._get_enum_value(virtools_types.VXBLEND_MODE, bmap.BMMaterial_GetSourceBlend)
def set_source_blend(self, data_: virtools_types.VXBLEND_MODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetSourceBlend(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetSourceBlend, data_)
def get_dest_blend(self) -> virtools_types.VXBLEND_MODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetDestBlend(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXBLEND_MODE(data.value)
return self._get_enum_value(virtools_types.VXBLEND_MODE, bmap.BMMaterial_GetDestBlend)
def set_dest_blend(self, data_: virtools_types.VXBLEND_MODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetDestBlend(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetDestBlend, data_)
def get_fill_mode(self) -> virtools_types.VXFILL_MODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetFillMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXFILL_MODE(data.value)
return self._get_enum_value(virtools_types.VXFILL_MODE, bmap.BMMaterial_GetFillMode)
def set_fill_mode(self, data_: virtools_types.VXFILL_MODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetFillMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetFillMode, data_)
def get_shade_mode(self) -> virtools_types.VXSHADE_MODE:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetShadeMode(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXSHADE_MODE(data.value)
return self._get_enum_value(virtools_types.VXSHADE_MODE, bmap.BMMaterial_GetShadeMode)
def set_shade_mode(self, data_: virtools_types.VXSHADE_MODE) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetShadeMode(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetShadeMode, data_)
def get_alpha_test_enabled(self) -> bool:
data: bmap.bm_bool = bmap.bm_bool()
bmap.BMMaterial_GetAlphaTestEnabled(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_bool_value(bmap.BMMaterial_GetAlphaTestEnabled)
def set_alpha_test_enabled(self, data_: bool) -> None:
data: bmap.bm_bool = bmap.bm_bool(data_)
bmap.BMMaterial_SetAlphaTestEnabled(self._get_pointer(), self._get_ckid(), data)
self._set_bool_value(bmap.BMMaterial_SetAlphaTestEnabled, data_)
def get_alpha_blend_enabled(self) -> bool:
data: bmap.bm_bool = bmap.bm_bool()
bmap.BMMaterial_GetAlphaBlendEnabled(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_bool_value(bmap.BMMaterial_GetAlphaBlendEnabled)
def set_alpha_blend_enabled(self, data_: bool) -> None:
data: bmap.bm_bool = bmap.bm_bool(data_)
bmap.BMMaterial_SetAlphaBlendEnabled(self._get_pointer(), self._get_ckid(), data)
self._set_bool_value(bmap.BMMaterial_SetAlphaBlendEnabled, data_)
def get_perspective_correction_enabled(self) -> bool:
data: bmap.bm_bool = bmap.bm_bool()
bmap.BMMaterial_GetPerspectiveCorrectionEnabled(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_bool_value(bmap.BMMaterial_GetPerspectiveCorrectionEnabled)
def set_perspective_correction_enabled(self, data_: bool) -> None:
data: bmap.bm_bool = bmap.bm_bool(data_)
bmap.BMMaterial_SetPerspectiveCorrectionEnabled(self._get_pointer(), self._get_ckid(), data)
self._set_bool_value(bmap.BMMaterial_SetPerspectiveCorrectionEnabled, data_)
def get_z_write_enabled(self) -> bool:
data: bmap.bm_bool = bmap.bm_bool()
bmap.BMMaterial_GetZWriteEnabled(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_bool_value(bmap.BMMaterial_GetZWriteEnabled)
def set_z_write_enabled(self, data_: bool) -> None:
data: bmap.bm_bool = bmap.bm_bool(data_)
bmap.BMMaterial_SetZWriteEnabled(self._get_pointer(), self._get_ckid(), data)
self._set_bool_value(bmap.BMMaterial_SetZWriteEnabled, data_)
def get_two_sided_enabled(self) -> bool:
data: bmap.bm_bool = bmap.bm_bool()
bmap.BMMaterial_GetTwoSidedEnabled(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_bool_value(bmap.BMMaterial_GetTwoSidedEnabled)
def set_two_sided_enabled(self, data_: bool) -> None:
data: bmap.bm_bool = bmap.bm_bool(data_)
bmap.BMMaterial_SetTwoSidedEnabled(self._get_pointer(), self._get_ckid(), data)
self._set_bool_value(bmap.BMMaterial_SetTwoSidedEnabled, data_)
def get_alpha_ref(self) -> int:
data: bmap.bm_CKBYTE = bmap.bm_CKBYTE()
bmap.BMMaterial_GetAlphaRef(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return data.value
return self._get_integral_value(bmap.bm_CKBYTE, bmap.BMMaterial_GetAlphaRef)
def set_alpha_ref(self, data_: int):
data: bmap.bm_CKBYTE = bmap.bm_CKBYTE(data_)
bmap.BMMaterial_SetAlphaRef(self._get_pointer(), self._get_ckid(), data)
self._set_integral_value(bmap.bm_CKBYTE, bmap.BMMaterial_SetAlphaRef, data_)
def get_alpha_func(self) -> virtools_types.VXCMPFUNC:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetAlphaFunc(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXCMPFUNC(data.value)
return self._get_enum_value(virtools_types.VXCMPFUNC, bmap.BMMaterial_GetAlphaFunc)
def set_alpha_func(self, data_: virtools_types.VXCMPFUNC) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetAlphaFunc(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetAlphaFunc, data_)
def get_z_func(self) -> virtools_types.VXCMPFUNC:
data: bmap.bm_enum = bmap.bm_enum()
bmap.BMMaterial_GetZFunc(self._get_pointer(), self._get_ckid(), ctypes.byref(data))
return virtools_types.VXCMPFUNC(data.value)
return self._get_enum_value(virtools_types.VXCMPFUNC, bmap.BMMaterial_GetZFunc)
def set_z_func(self, data_: virtools_types.VXCMPFUNC) -> None:
data: bmap.bm_enum = bmap.bm_enum(data_.value)
bmap.BMMaterial_SetZFunc(self._get_pointer(), self._get_ckid(), data)
self._set_enum_value(bmap.BMMaterial_SetZFunc, data_)
class BMMesh(BMObject):
def get_lit_mode(self) -> virtools_types.VXMESH_LITMODE:
mode: bmap.bm_enum = bmap.bm_enum()
bmap.BMMesh_GetLitMode(self._get_pointer(), self._get_ckid(), ctypes.byref(mode))
return virtools_types.VXMESH_LITMODE(mode.value)
return self._get_enum_value(virtools_types.VXMESH_LITMODE, bmap.BMMesh_GetLitMode)
def set_lit_mode(self, mode_: virtools_types.VXMESH_LITMODE) -> None:
mode: bmap.bm_enum = bmap.bm_enum(mode_.value)
bmap.BMMesh_SetLitMode(self._get_pointer(), self._get_ckid(), mode)
self._set_enum_value(bmap.BMMesh_SetLitMode, mode_)
def get_vertex_count(self) -> int:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
bmap.BMMesh_GetVertexCount(self._get_pointer(), self._get_ckid(), ctypes.byref(count))
return count.value
return self._get_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_GetVertexCount)
def set_vertex_count(self, count_: int) -> None:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count_)
bmap.BMMesh_SetVertexCount(self._get_pointer(), self._get_ckid(), count)
self._set_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_SetVertexCount, count_)
def get_vertex_positions(self) -> typing.Iterator[virtools_types.VxVector3]:
# get raw pointer and return
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMesh_GetVertexPositions(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
return _vxvector3_iterator(raw_vector, self.get_vertex_count())
raw_vector = self._get_pointer_value(bmap.bm_VxVector3_p, bmap.BMMesh_GetVertexPositions)
return _Utils.vxvector3_iterator(raw_vector, self.get_vertex_count())
def set_vertex_positions(self, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
# get raw float pointer and assign
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMesh_GetVertexPositions(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
_vxvector3_assigner(raw_vector, self.get_vertex_count(), itor)
raw_vector = self._get_pointer_value(bmap.bm_VxVector3_p, bmap.BMMesh_GetVertexPositions)
_Utils.vxvector3_assigner(raw_vector, self.get_vertex_count(), itor)
def get_vertex_normals(self) -> typing.Iterator[virtools_types.VxVector3]:
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMesh_GetVertexNormals(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
return _vxvector3_iterator(raw_vector, self.get_vertex_count())
raw_vector = self._get_pointer_value(bmap.bm_VxVector3_p, bmap.BMMesh_GetVertexNormals)
return _Utils.vxvector3_iterator(raw_vector, self.get_vertex_count())
def set_vertex_normals(self, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMesh_GetVertexNormals(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
_vxvector3_assigner(raw_vector, self.get_vertex_count(), itor)
raw_vector = self._get_pointer_value(bmap.bm_VxVector3_p, bmap.BMMesh_GetVertexNormals)
_Utils.vxvector3_assigner(raw_vector, self.get_vertex_count(), itor)
def get_vertex_uvs(self) -> typing.Iterator[virtools_types.VxVector2]:
raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p()
bmap.BMMesh_GetVertexUVs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
return _vxvector2_iterator(raw_vector, self.get_vertex_count())
raw_vector = self._get_pointer_value(bmap.bm_VxVector2_p, bmap.BMMesh_GetVertexUVs)
return _Utils.vxvector2_iterator(raw_vector, self.get_vertex_count())
def set_vertex_uvs(self, itor: typing.Iterator[virtools_types.VxVector2]) -> None:
raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p()
bmap.BMMesh_GetVertexUVs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector))
_vxvector2_assigner(raw_vector, self.get_vertex_count(), itor)
raw_vector = self._get_pointer_value(bmap.bm_VxVector2_p, bmap.BMMesh_GetVertexUVs)
_Utils.vxvector2_assigner(raw_vector, self.get_vertex_count(), itor)
def get_face_count(self) -> int:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
bmap.BMMesh_GetFaceCount(self._get_pointer(), self._get_ckid(), ctypes.byref(count))
return count.value
return self._get_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_GetFaceCount)
def set_face_count(self, count_: int) -> None:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count_)
bmap.BMMesh_SetFaceCount(self._get_pointer(), self._get_ckid(), count)
self._set_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_SetFaceCount, count_)
def get_face_indices(self) -> typing.Iterator[virtools_types.CKFaceIndices]:
raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p()
bmap.BMMesh_GetFaceIndices(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx))
return _ckfaceindices_iterator(raw_idx, self.get_face_count())
raw_idx = self._get_pointer_value(bmap.bm_CKWORD_p, bmap.BMMesh_GetFaceIndices)
return _Utils.ckfaceindices_iterator(raw_idx, self.get_face_count())
def set_face_indices(self, itor: typing.Iterator[virtools_types.CKFaceIndices]) -> None:
raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p()
bmap.BMMesh_GetFaceIndices(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx))
_ckfaceindices_assigner(raw_idx, self.get_face_count(), itor)
raw_idx = self._get_pointer_value(bmap.bm_CKWORD_p, bmap.BMMesh_GetFaceIndices)
_Utils.ckfaceindices_assigner(raw_idx, self.get_face_count(), itor)
def get_face_material_slot_indexs(self) -> typing.Iterator[int]:
raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p()
bmap.BMMesh_GetFaceMaterialSlotIndexs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx))
raw_idx = self._get_pointer_value(bmap.bm_CKWORD_p, bmap.BMMesh_GetFaceMaterialSlotIndexs)
for i in range(self.get_face_count()):
yield raw_idx[i]
def set_face_material_slot_indexs(self, itor: typing.Iterator[int]) -> None:
raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p()
bmap.BMMesh_GetFaceMaterialSlotIndexs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx))
for i in range(self.get_face_count()):
raw_idx[i] = next(itor)
raw_idx = self._get_pointer_value(bmap.bm_CKWORD_p, bmap.BMMesh_GetFaceMaterialSlotIndexs)
try:
for i in range(self.get_face_count()):
raw_idx[i] = next(itor)
except StopIteration:
_Utils.raise_out_of_length_exception()
def get_material_slot_count(self) -> int:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
bmap.BMMesh_GetMaterialSlotCount(self._get_pointer(), self._get_ckid(), ctypes.byref(count))
return count.value
return self._get_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_GetMaterialSlotCount)
def set_material_slot_count(self, count_: int) -> None:
count: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count_)
bmap.BMMesh_SetMaterialSlotCount(self._get_pointer(), self._get_ckid(), count)
self._set_integral_value(bmap.bm_CKDWORD, bmap.BMMesh_SetMaterialSlotCount, count_)
def get_material_slots(self) -> typing.Iterator[BMMaterial | None]:
idx: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
@ -519,16 +462,19 @@ class BMMesh(BMObject):
def set_material_slots(self, itor: typing.Iterator[BMMaterial | None]) -> None:
idx: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
mtlid: bmap.bm_CKID = bmap.bm_CKID()
for i in range(self.get_material_slot_count()):
idx.value = i
# analyze mtl item
mtlobj: BMMaterial | None = next(itor)
if mtlobj is None:
mtlid.value = g_InvalidCKID
else:
mtlid = mtlobj._get_ckid()
# set
bmap.BMMesh_SetMaterialSlot(self._get_pointer(), self._get_ckid(), idx, mtlid)
try:
for i in range(self.get_material_slot_count()):
idx.value = i
# analyze mtl item
mtlobj: BMMaterial | None = next(itor)
if mtlobj is None:
mtlid.value = g_InvalidCKID
else:
mtlid = mtlobj._get_ckid()
# set
bmap.BMMesh_SetMaterialSlot(self._get_pointer(), self._get_ckid(), idx, mtlid)
except StopIteration:
_Utils.raise_out_of_length_exception()
class BM3dObject(BMObject):
def get_world_matrix(self) -> virtools_types.VxMatrix:
@ -560,26 +506,20 @@ class BM3dObject(BMObject):
bmap.BM3dObject_SetCurrentMesh(self._get_pointer(), self._get_ckid(), ckid)
def get_visibility(self) -> bool:
visb: bmap.bm_bool = bmap.bm_bool()
bmap.BM3dObject_GetVisibility(self._get_pointer(), self._get_ckid(), ctypes.byref(visb))
return visb.value
return self._get_bool_value(bmap.BM3dObject_GetVisibility)
def set_visibility(self, visb_: bool) -> None:
visb: bmap.bm_bool = bmap.bm_bool(visb_)
bmap.BM3dObject_SetVisibility(self._get_pointer(), self._get_ckid(), visb)
self._set_bool_value(bmap.BM3dObject_SetVisibility, visb_)
class BMGroup(BMObject):
def add_object(self, member: BM3dObject) -> None:
bmap.BMGroup_AddObject(self._get_pointer(), self._get_ckid(), member._get_ckid())
def get_object_count(self) -> int:
csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
bmap.BMGroup_GetObjectCount(self._get_pointer(), self._get_ckid(), ctypes.byref(csize))
return csize.value
return self._get_integral_value(bmap.bm_CKDWORD, bmap.BMGroup_GetObjectCount)
def get_objects(self) -> typing.Iterator[BM3dObject]:
# get list size
csize: int = self.get_object_count()
# iterate list
cidx: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
retid: bmap.bm_CKID = bmap.bm_CKID()
@ -621,16 +561,16 @@ class BMFileReader(_AbstractPointer):
self._set_pointer(g_InvalidPtr)
def __get_ckobject_count(self,
count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bool]) -> int:
count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bmap.bm_bool]) -> int:
# get size
csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD()
count_getter(self._get_pointer(), ctypes.byref(csize))
return csize.value
def __get_ckobjects(self,
class_type: type[TCKObj],
count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bool],
obj_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD, bmap.bm_CKID_p], bool]) -> typing.Iterator[TCKObj]:
class_type: type[TCKObject],
count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bmap.bm_bool],
obj_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD, bmap.bm_CKID_p], bmap.bm_bool]) -> typing.Iterator[TCKObject]:
# get size first
csize: int = self.__get_ckobject_count(count_getter)
@ -646,47 +586,23 @@ class BMFileReader(_AbstractPointer):
def get_texture_count(self) -> int:
return self.__get_ckobject_count(bmap.BMFile_GetTextureCount)
def get_textures(self) -> typing.Iterator[BMTexture]:
return self.__get_ckobjects(
BMTexture,
bmap.BMFile_GetTextureCount,
bmap.BMFile_GetTexture
)
return self.__get_ckobjects(BMTexture, bmap.BMFile_GetTextureCount, bmap.BMFile_GetTexture)
def get_material_count(self) -> int:
return self.__get_ckobject_count(bmap.BMFile_GetMaterialCount)
def get_materials(self) -> typing.Iterator[BMMaterial]:
return self.__get_ckobjects(
BMMaterial,
bmap.BMFile_GetMaterialCount,
bmap.BMFile_GetMaterial
)
return self.__get_ckobjects(BMMaterial, bmap.BMFile_GetMaterialCount, bmap.BMFile_GetMaterial)
def get_mesh_count(self) -> int:
return self.__get_ckobject_count(bmap.BMFile_GetMeshCount)
def get_meshs(self) -> typing.Iterator[BMMesh]:
return self.__get_ckobjects(
BMMesh,
bmap.BMFile_GetMeshCount,
bmap.BMFile_GetMesh
)
return self.__get_ckobjects(BMMesh, bmap.BMFile_GetMeshCount, bmap.BMFile_GetMesh)
def get_3dobject_count(self) -> int:
return self.__get_ckobject_count(bmap.BMFile_Get3dObjectCount)
def get_3dobjects(self) -> typing.Iterator[BM3dObject]:
return self.__get_ckobjects(
BM3dObject,
bmap.BMFile_Get3dObjectCount,
bmap.BMFile_Get3dObject
)
return self.__get_ckobjects(BM3dObject, bmap.BMFile_Get3dObjectCount, bmap.BMFile_Get3dObject)
def get_group_count(self) -> int:
return self.__get_ckobject_count(bmap.BMFile_GetGroupCount)
def get_groups(self) -> typing.Iterator[BMGroup]:
return self.__get_ckobjects(
BMGroup,
bmap.BMFile_GetGroupCount,
bmap.BMFile_GetGroup
)
return self.__get_ckobjects(BMGroup, bmap.BMFile_GetGroupCount, bmap.BMFile_GetGroup)
class BMFileWriter(_AbstractPointer):
def __init__(self, temp_folder_: str, texture_folder_: str, encodings_: tuple[str]):
@ -728,8 +644,8 @@ class BMFileWriter(_AbstractPointer):
self._set_pointer(g_InvalidPtr)
def __create_ckobject(self,
class_type: type[TCKObj],
creator: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID_p], bool]) -> TCKObj:
class_type: type[TCKObject],
creator: typing.Callable[[bmap.bm_void_p, bmap.bm_CKID_p], bmap.bm_bool]) -> TCKObject:
# prepare id container
retid: bmap.bm_CKID = bmap.bm_CKID()
# create new one
@ -738,34 +654,15 @@ class BMFileWriter(_AbstractPointer):
return class_type(self._get_pointer(), retid)
def create_texture(self) -> BMTexture:
return self.__create_ckobject(
BMTexture,
bmap.BMFile_CreateTexture
)
return self.__create_ckobject(BMTexture, bmap.BMFile_CreateTexture)
def create_material(self) -> BMMaterial:
return self.__create_ckobject(
BMMaterial,
bmap.BMFile_CreateMaterial
)
return self.__create_ckobject(BMMaterial, bmap.BMFile_CreateMaterial)
def create_mesh(self) -> BMMesh:
return self.__create_ckobject(
BMMesh,
bmap.BMFile_CreateMesh
)
return self.__create_ckobject(BMMesh, bmap.BMFile_CreateMesh)
def create_3dobject(self) -> BM3dObject:
return self.__create_ckobject(
BM3dObject,
bmap.BMFile_Create3dObject
)
return self.__create_ckobject(BM3dObject, bmap.BMFile_Create3dObject)
def create_group(self) -> BMGroup:
return self.__create_ckobject(
BMGroup,
bmap.BMFile_CreateGroup
)
return self.__create_ckobject(BMGroup, bmap.BMFile_CreateGroup)
class BMMeshTrans(_AbstractPointer):
def __init__(self):
@ -784,8 +681,8 @@ class BMMeshTrans(_AbstractPointer):
bmap.BMMeshTrans_Delete(self._get_pointer())
self._set_pointer(g_InvalidPtr)
def parse(self, bmfile: BMFileWriter, objmesh: BMMesh) -> None:
bmap.BMMeshTrans_Parse(self._get_pointer(), bmfile._get_pointer(), objmesh._get_ckid())
def parse(self, objmesh: BMMesh) -> None:
bmap.BMMeshTrans_Parse(self._get_pointer(), objmesh._get_pointer(), objmesh._get_ckid())
def prepare_vertex(self, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
# prepare count first
@ -795,7 +692,7 @@ class BMMeshTrans(_AbstractPointer):
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMeshTrans_PrepareVertex(self._get_pointer(), ctypes.byref(raw_vector))
# set by pointer
_vxvector3_assigner(raw_vector, count, itor)
_Utils.vxvector3_assigner(raw_vector, count, itor)
def prepare_normal(self, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None:
csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count)
@ -804,7 +701,7 @@ class BMMeshTrans(_AbstractPointer):
raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p()
bmap.BMMeshTrans_PrepareNormal(self._get_pointer(), ctypes.byref(raw_vector))
_vxvector3_assigner(raw_vector, count, itor)
_Utils.vxvector3_assigner(raw_vector, count, itor)
def prepare_uv(self, count: int, itor: typing.Iterator[virtools_types.VxVector2]) -> None:
csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count)
@ -813,7 +710,7 @@ class BMMeshTrans(_AbstractPointer):
raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p()
bmap.BMMeshTrans_PrepareUV(self._get_pointer(), ctypes.byref(raw_vector))
_vxvector2_assigner(raw_vector, count, itor)
_Utils.vxvector2_assigner(raw_vector, count, itor)
def prepare_mtl_slot(self, count: int, itor: typing.Iterator[BMMaterial | None]) -> None:
csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count)
@ -821,15 +718,17 @@ class BMMeshTrans(_AbstractPointer):
raw_ckid: bmap.bm_CKID_p = bmap.bm_CKID_p()
bmap.BMMeshTrans_PrepareMtlSlot(self._get_pointer(), ctypes.byref(raw_ckid))
idx: int = 0
for _ in range(count):
usermtl: BMMaterial | None = next(itor)
if usermtl is None:
raw_ckid[idx] = g_InvalidCKID
else:
raw_ckid[idx] = usermtl._get_ckid().value
idx += 1
try:
idx: int = 0
for _ in range(count):
usermtl: BMMaterial | None = next(itor)
if usermtl is None:
raw_ckid[idx] = g_InvalidCKID
else:
raw_ckid[idx] = usermtl._get_ckid().value
idx += 1
except StopIteration:
_Utils.raise_out_of_length_exception()
def prepare_face(self,
count: int,
@ -853,13 +752,16 @@ class BMMeshTrans(_AbstractPointer):
# iterate and assign
# assigne triple indices
_ckfaceindices_assigner(raw_vec_idx, count, vec_idx)
_ckfaceindices_assigner(raw_nml_idx, count, nml_idx)
_ckfaceindices_assigner(raw_uv_idx, count, uv_idx)
_Utils.ckfaceindices_assigner(raw_vec_idx, count, vec_idx)
_Utils.ckfaceindices_assigner(raw_nml_idx, count, nml_idx)
_Utils.ckfaceindices_assigner(raw_uv_idx, count, uv_idx)
# assign mtl index
idx: int = 0
for _ in range(count):
raw_mtl_idx[idx] = next(mtl_idx)
idx += 1
try:
idx: int = 0
for _ in range(count):
raw_mtl_idx[idx] = next(mtl_idx)
idx += 1
except StopIteration:
_Utils.raise_out_of_length_exception()
#endregion

View File

@ -9,27 +9,124 @@ def main() -> None:
texture_folder: str = 'F:\\Ballance\\Ballance\\Textures'
encodings: tuple[str, ...] = ('cp1252', )
with bmap.BMFileReader(file_name, temp_folder, texture_folder, encodings) as reader:
print('===== Groups =====')
for gp in reader.get_groups():
print(gp.get_name())
test_common(reader)
test_equatable(reader)
print('===== Objects =====')
for obj in reader.get_3dobjects():
print(obj.get_name())
def test_common(reader: bmap.BMFileReader):
# print('===== Groups =====')
# for gp in reader.get_groups():
# print(gp.get_name())
# for gp_item in gp.get_objects():
# print(f'\t{gp_item.get_name()}')
print('===== Meshes =====')
for mesh in reader.get_meshs():
print(mesh.get_name())
# print('===== 3dObjects =====')
# for obj in reader.get_3dobjects():
# print(obj.get_name())
print('===== Materials =====')
for mtl in reader.get_materials():
print(mtl.get_name())
# current_mesh = obj.get_current_mesh()
# mesh_name = '<null>' if current_mesh is None else current_mesh.get_name()
# print(f'\tMesh: {mesh_name}')
# print(f'\tVisibility: {obj.get_visibility()}')
# print(f'\tMatrix: {obj.get_world_matrix().to_const()}')
print('===== Textures =====')
for tex in reader.get_textures():
print(tex.get_name())
# print('===== Meshes =====')
# for mesh in reader.get_meshs():
# print(mesh.get_name())
# print(f'\tLit Mode: {mesh.get_lit_mode()}')
# print(f'\tVertex Count: {mesh.get_vertex_count()}')
# print(f'\tFace Count: {mesh.get_face_count()}')
# print(f'\tMaterial Slot Count: {mesh.get_material_slot_count()}')
print('===== Materials =====')
for mtl in reader.get_materials():
print(mtl.get_name())
print(f'\tDiffuse: {mtl.get_diffuse().to_const_rgba()}')
print(f'\tAmbient: {mtl.get_ambient().to_const_rgba()}')
print(f'\tSpecular: {mtl.get_specular().to_const_rgba()}')
print(f'\tEmissive: {mtl.get_emissive().to_const_rgba()}')
print(f'\tSpecular Power: {mtl.get_specular_power()}')
print(f'\tTexture Border Color: {mtl.get_texture_border_color().to_const_rgba()}')
print(f'\tTexture Blend Mode: {mtl.get_texture_blend_mode()}')
print(f'\tTexture Min Mode: {mtl.get_texture_min_mode()}')
print(f'\tTexture Mag Mode: {mtl.get_texture_mag_mode()}')
print(f'\tSource Blend: {mtl.get_source_blend()}')
print(f'\tDest Blend: {mtl.get_dest_blend()}')
print(f'\tFill Mode: {mtl.get_fill_mode()}')
print(f'\tShade Mode: {mtl.get_shade_mode()}')
print(f'\tAlpha Test Enabled: {mtl.get_alpha_test_enabled()}')
print(f'\tAlpha Blend Enabled: {mtl.get_alpha_blend_enabled()}')
print(f'\tPerspective Correction Enabled: {mtl.get_perspective_correction_enabled()}')
print(f'\tZ Write Enabled: {mtl.get_z_write_enabled()}')
print(f'\tTwo Sided Enabled: {mtl.get_two_sided_enabled()}')
print(f'\tAlpha Ref: {mtl.get_alpha_ref()}')
print(f'\tAlpha Func: {mtl.get_alpha_func()}')
print(f'\tZ Func: {mtl.get_z_func()}')
# print('===== Textures =====')
# for tex in reader.get_textures():
# print(tex.get_name())
# print(f'\tFile Name: {tex.get_file_name()}')
# print(f'\tSave Options: {tex.get_save_options()}')
# print(f'\tVideo Format: {tex.get_video_format()}')
print('===== END =====')
def test_equatable(reader: bmap.BMFileReader):
# Check requirements
assert (reader.get_3dobject_count() >= 2), '''
Invalid file for test IEquatable.
We can not perform IEquatable test because the length of 3dObject is too short (must greater than 2). Please choose another file to perform.
'''
# Prepare variables
all_3dobjects: tuple[bmap.BM3dObject, ...] = tuple(reader.get_3dobjects())
first_3dobj: bmap.BM3dObject = all_3dobjects[0]
second_3dobj: bmap.BM3dObject = all_3dobjects[1]
all_3dobjects = tuple(reader.get_3dobjects())
first_3dobj_again: bmap.BM3dObject = all_3dobjects[0]
# Test set
test_set: set[bmap.BM3dObject] = set()
test_set.add(first_3dobj)
assert len(test_set) == 1
assert first_3dobj in test_set
assert first_3dobj_again in test_set
assert second_3dobj not in test_set
test_set.add(first_3dobj_again)
assert len(test_set) == 1
test_set.add(second_3dobj)
assert len(test_set) == 2
assert second_3dobj in test_set
# Test dict
test_dict: dict[bmap.BM3dObject, str | None] = {}
test_dict[first_3dobj] = first_3dobj.get_name()
assert len(test_dict) == 1
assert first_3dobj in test_dict
assert first_3dobj_again in test_dict
assert second_3dobj not in test_dict
test_dict[first_3dobj_again] = first_3dobj_again.get_name()
assert len(test_dict) == 1
test_dict[second_3dobj] = second_3dobj.get_name()
assert len(test_dict) == 2
assert second_3dobj in test_dict
if __name__ == '__main__':
main()

View File

@ -6,6 +6,10 @@ endif()
# Find YYCC library
# It will produce YYCC::YYCCommonplace target for including and linking.
find_package(YYCCommonplace REQUIRED
HINTS ${YYCC_PATH} NO_DEFAULT_PATH
)
#
# Please note we MUST set CMake variable YYCCommonplace_ROOT to make sure CMake can found YYCC in out given path.
# The cache status of YYCCommonplace_ROOT is doesn't matter.
# CMake will throw error if we use HINTS feature in find_package to find YYCC.
set(YYCCommonplace_ROOT ${YYCC_PATH} CACHE PATH
"The path to YYCC CMake distribution installation path.")
find_package(YYCCommonplace REQUIRED)

83
COMPILE.md Normal file
View File

@ -0,0 +1,83 @@
# Compile Manual
## Requirements
This project require:
* CMake 3.23 at least.
* The common compiler supporting C++ 20 (GCC / Clang / MSVC).
* Littile-endian architecture system.
* zlib.
* iconv (non-Windows system required).
* [stb](https://github.com/nothings/stb): For image read and write.
* [YYCCommonplace](https://github.com/yyc12345/YYCCommonplace): My personal invented library concentrating some common functions for mine.
Since libcmo21 0.2.0, we only provide it in CMake build system. So Windows user should install CMake first or use Visual Studio directly (Visual Studio provides CMake build system supports).
## Preparations
### YYCCommonplace
You should clone YYCCommonplace and switch to the latest release tag (or specified commit hash provided with libcmo21 release infos if you are building for specific libcmo21 version). When configuring YYCCommonplace, you should notice following infos:
* Please make sure that you have specified C++ 20 explicitly by passing `-DCMAKE_CXX_STANDARD=20` in command line. This is crucial because libcmo21 use C++ 20, and YYCCommonplace's ABI is incompatible between C++ 17 version and C++ 20 version.
* If you need `BMap` in final libcmo21 built artifacts, and you are in non-Windows system now, please specify position independent code flag by passing `-DCMAKE_POSITION_INDEPENDENT_CODE=True` in command line. GCC and Clang will reject linking if you don't flag it.
After configuring, you can normally build YYCCommonplace like a common CMake project.
Please note if your final program or dynamic library is provided for end user, please choose `RelWithDebInfo` build type (`Release` is not suggested because it will strip all debug infos and it is not good for bug reporter, which is embedded in program, to report crash). If final program is served for programmer debugging, please choose `Debug` build type.
### stb
You should clone stb repository first, then switch to a specific commit hash `2e2bef463a5b53ddf8bb788e25da6b8506314c08`. In ideally scenario, people like to choose the latest commit. However, I not frequently update this dependency.
### zlib
If you are in Windows, you should download zlib source code and build it with given Visual Studio solution files. The final file we needed is `zlibwapi.dll` with `ZlibDllRelease` build type.
If you are running on non-Windows system. You usually do not need to do anything. Because zlib development environment may be configured by your package manager correctly.
## Compile
### Directory Hierarchy
First, create subdirectory `Bin/build` and `Bin/install` at the root directory of libcmo21.
### Configuration
Then enter subdirectory `Bin/build` and use following command to configure CMake:
- Windows (MSVC): `cmake -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_DOC=OFF -DSTB_IMAGE_PATH=<path-to-stb> -DYYCC_PATH=<path-to-yycc-install> -DZLIB_HEADER_PATH=<path-to-zlib-hdr> -DZLIB_BINARY_PATH=<path-to-zlib-bin> ../..`
- non-Windows: `cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_DOC=OFF -DSTB_IMAGE_PATH=<path-to-stb> -DYYCC_PATH=<path-to-yycc-install> ../..`
The arguments in command should be replaced by:
* `<path-to-stb>`: The root directory of your cloned stb repository.
* `<path-to-yycc-install>`: The directory to installed CMake package you chosen when building YYCCommonplace.
* `<path-to-zlib-hdr>` (Windows only): The root directory of downloaded zlib source code.
* `<path-to-zlib-bin>` (Windows only): The directory where you can find built `zlibwapi.dll`.
The switches in command can be switched as you wish:
* `NEMO_BUILD_UNVIRT`: Build `Unvirt`, a command line application debugging Virtools files.
* `NEMO_BUILD_BMAP`: Build `BMap`, a dynamic library specific used for loading Ballance map file. If you are coming from my another project [BallanceBlenderPlugin](https://github.com/yyc12345/BallanceBlenderHelper), this is what you need.
* `NEMO_BUILD_DOC`: Build the document of libcmo21.
### Build
Execute following command to build libcmo21.
* Windows: `cmake --build . --config RelWithDebInfo`
* non-Windows: `cmake --build .`
### Build Type
Like YYCCommonplace, we suggest `RelWithDebInfo` for end user. If you want to build for programmer debugging, please replace all `RelWithDebInfo` to `Debug`. The build type between YYCCommonplace and libcmo21 should keep same to reduce any possibility about ABI incompatible issue.
## Install
Currently the CMake install script still has some bugs and can not work as expected. So as the alternative, just go into build directory and find your final program please. It's pretty simple.
## Note
You may face issue when compiling this program on Linux or macOS because I develop this project on Windows frequently. The compatibility with Linux will only be checked just before releasing. And I don't have any Apple device to check the compatibility with macOS. So, for Linux issue, please report it directly and I will try to fix. For macOS bug, PR is welcomed.

View File

@ -45,14 +45,22 @@ public class CSharpWriter {
// use "switch" to check variable type
switch (vt_base_type) {
case "CKSTRING":
// decide direction cookies
String direction_cookie = "";
if (paramdecl.mIsInput) {
direction_cookie = "In";
} else {
direction_cookie = "Out";
}
// only allow 0 and 1 pointer level for string.
switch (vt_pointer_level) {
case 0:
ret.mMarshalAs = "UnmanagedType.LPUTF8Str";
ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = \"" + direction_cookie + "\"";
// ret.mMarshalAs = "UnmanagedType.LPUTF8Str";
ret.mCsType = "string";
break;
case 1:
ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler)";
ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler), MarshalCookie = \"" + direction_cookie + "\"";
ret.mCsType = "string[]";
break;
}
@ -110,6 +118,7 @@ public class CSharpWriter {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CK_ID":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U4";
@ -187,11 +196,14 @@ public class CSharpWriter {
case "VXSHADE_MODE":
case "VXCMPFUNC":
case "VXMESH_LITMODE":
// all enum share the same underlying type.
// all enum type use the same strategy
if (vt_pointer_level == 0) {
// all enum type should be marshaled as its underlying type
// but we can use its name in C# directly.
ret.mMarshalAs = "UnmanagedType.U4";
ret.mCsType = "uint";
ret.mCsType = vt_base_type;
} else {
// for pointer type, use IntPtr instead.
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}

View File

@ -14,5 +14,6 @@ add_custom_target (NeMoDocuments
# Install built documentation
install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
DESTINATION ${NEMO_INSTALL_DOC_PATH}
)

View File

@ -521,7 +521,7 @@ namespace LibCmo::CK2 {
m_Slots.resize(count);
if (count == 0) {
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_INVALID);
YYCC::EnumHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_INVALID);
}
}
@ -535,8 +535,8 @@ namespace LibCmo::CK2 {
m_CurrentSlot = slot;
// NOTE: idk what the fuck this is. just interpter the IDA decompiled code.
if (EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP)) {
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_FORCERESTORE);
if (YYCC::EnumHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP)) {
YYCC::EnumHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_FORCERESTORE);
}
}
@ -660,14 +660,14 @@ namespace LibCmo::CK2 {
// but we decide split the flag settings and slot.
// User should set slot count manually.
if (is_cube) {
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
YYCC::EnumHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
} else {
EnumsHelper::Rm(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
YYCC::EnumHelper::Remove(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
}
}
bool CKBitmapData::IsCubeMap() const {
return EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
return YYCC::EnumHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_CUBEMAP);
}
const CKBitmapProperties& CKBitmapData::GetSaveFormat() const {
@ -688,14 +688,14 @@ namespace LibCmo::CK2 {
void CKBitmapData::SetTransparent(bool Transparency) {
if (Transparency) {
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
YYCC::EnumHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
} else {
EnumsHelper::Rm(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
YYCC::EnumHelper::Remove(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
}
}
bool CKBitmapData::IsTransparent() const {
return EnumsHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
return YYCC::EnumHelper::Has(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
}
void CKBitmapData::SetTransparentColor(CKDWORD col) {

View File

@ -205,8 +205,8 @@ namespace LibCmo::CK2 {
std::string name_conv;
// ========== compress feature process ==========
if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
if (YYCC::EnumHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
YYCC::EnumHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
if (decomp_buffer != nullptr) {

View File

@ -216,8 +216,8 @@ namespace LibCmo::CK2 {
}
// compress header if needed
if (EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
if (YYCC::EnumHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
YYCC::EnumHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
CKDWORD comp_buf_size = 0;
void* comp_buffer = CKPackData(hdrparser->GetBase(), hdrparser->GetSize(), comp_buf_size, m_Ctx->GetCompressionLevel());
@ -263,8 +263,8 @@ namespace LibCmo::CK2 {
}
// compress header if needed
if (EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
EnumsHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
if (YYCC::EnumHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
YYCC::EnumHelper::Has(fileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
CKDWORD comp_buf_size = 0;
void* comp_buffer = CKPackData(datparser->GetBase(), datparser->GetSize(), comp_buf_size, m_Ctx->GetCompressionLevel());

View File

@ -419,23 +419,23 @@ namespace LibCmo::CK2 {
std::memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
bufpos += this->m_DataDwSize;
}
if (!EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
if (!YYCC::EnumHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
// forced no bind file
this->m_BindFile = nullptr;
}
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
if (YYCC::EnumHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
this->m_ObjectList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
bufpos += this->m_ObjectList.size();
}
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
if (YYCC::EnumHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
this->m_ChunkList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
bufpos += this->m_ChunkList.size();
}
if (EnumsHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
if (YYCC::EnumHelper::Has(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
this->m_ManagerList.resize(dwbuf[bufpos]);
bufpos += 1u;
std::memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
@ -459,19 +459,19 @@ namespace LibCmo::CK2 {
if (!m_ObjectList.empty()) {
size += CKSizeof(CKDWORD) * static_cast<CKDWORD>(m_ObjectList.size()) + sizeof(CKDWORD);
EnumsHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS);
YYCC::EnumHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS);
}
if (!m_ChunkList.empty()) {
size += CKSizeof(CKDWORD) * static_cast<CKDWORD>(m_ChunkList.size()) + sizeof(CKDWORD);
EnumsHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN);
YYCC::EnumHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN);
}
if (!m_ManagerList.empty()) {
size += CKSizeof(CKDWORD) * static_cast<CKDWORD>(m_ManagerList.size()) + sizeof(CKDWORD);
EnumsHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN);
YYCC::EnumHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN);
}
if (this->m_BindFile != nullptr) {
EnumsHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE);
YYCC::EnumHelper::Add(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE);
}
// if buffer provided, write it

View File

@ -86,7 +86,7 @@ namespace LibCmo::CK2::MgrImpls {
// set to be deleted
CK_OBJECT_FLAGS objflag = obj->GetObjectFlags();
EnumsHelper::Add(objflag, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED);
YYCC::EnumHelper::Add(objflag, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED);
obj->SetObjectFlags(objflag);
// collect class id

View File

@ -9,12 +9,12 @@ namespace LibCmo::CK2::ObjImpls {
CKRenderObject(ctx, ckid, name),
m_PotentialMeshes(), m_CurrentMesh(nullptr),
m_WorldMatrix(), m_ZOrder(0),
m_MoveableFlags(EnumsHelper::Merge({
m_MoveableFlags(YYCC::EnumHelper::Merge(
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_PICKABLE,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_RENDERCHANNELS,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_INVERSEWORLDMATVALID
})),
)),
m_3dEntityFlags(static_cast<CK_3DENTITY_FLAGS>(0)) {}
CK3dEntity::~CK3dEntity() {}
@ -53,15 +53,15 @@ namespace LibCmo::CK2::ObjImpls {
// regulate self flag again
// MARK: originally we should check parent here.
// but we do not support parent and hierarchy feature, so we simply remove flag
EnumsHelper::Rm(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID);
YYCC::EnumHelper::Remove(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID);
// MARK: originally we should check grouped into CKPlace here.
// but we do not support CKPlace, so we simply remove this flag
EnumsHelper::Rm(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID);
YYCC::EnumHelper::Remove(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID);
// check z-order, if not zero, save it
if (m_ZOrder != 0) {
EnumsHelper::Add(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID);
YYCC::EnumHelper::Add(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID);
} else {
EnumsHelper::Rm(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID);
YYCC::EnumHelper::Remove(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID);
}
// write 2 flags
@ -94,7 +94,7 @@ namespace LibCmo::CK2::ObjImpls {
if (!suc) return false;
// backup moveable flags
bool hasWorldAligned = EnumsHelper::Has(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_WORLDALIGNED);
bool hasWorldAligned = YYCC::EnumHelper::Has(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_WORLDALIGNED);
// MARK: object animation is skipped
@ -132,11 +132,11 @@ namespace LibCmo::CK2::ObjImpls {
chunk->ReadStruct(m_3dEntityFlags);
chunk->ReadStruct(m_MoveableFlags);
// remove some properties
EnumsHelper::Rm(m_3dEntityFlags, EnumsHelper::Merge({
YYCC::EnumHelper::Remove(m_3dEntityFlags,
CK_3DENTITY_FLAGS::CK_3DENTITY_UPDATELASTFRAME,
CK_3DENTITY_FLAGS::CK_3DENTITY_RESERVED0
}));
EnumsHelper::Rm(m_MoveableFlags, EnumsHelper::Merge({
);
YYCC::EnumHelper::Remove(m_MoveableFlags,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_RESERVED2,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_STENCILONLY,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_DONTUPDATEFROMPARENT,
@ -145,13 +145,13 @@ namespace LibCmo::CK2::ObjImpls {
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_BOXVALID,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_USERBOX,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_UPTODATE
}));
);
if (hasWorldAligned) {
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_WORLDALIGNED);
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_WORLDALIGNED);
}
// if order render first
if (EnumsHelper::Has(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_RENDERFIRST)) {
if (YYCC::EnumHelper::Has(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_RENDERFIRST)) {
m_ZOrder = 10000;
}
@ -171,47 +171,47 @@ namespace LibCmo::CK2::ObjImpls {
VxMath::VxVector3 crossProduct = VxMath::NSVxVector::CrossProduct(col0, col1);
CKFLOAT dotProduct = VxMath::NSVxVector::DotProduct(crossProduct, col2);
if (dotProduct >= 0.0f) {
EnumsHelper::Rm(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_INDIRECTMATRIX);
YYCC::EnumHelper::Remove(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_INDIRECTMATRIX);
} else {
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_INDIRECTMATRIX);
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_INDIRECTMATRIX);
}
// copy visible data
// process direct visible
if (EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE)) {
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
if (YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE)) {
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
} else {
EnumsHelper::Rm(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
YYCC::EnumHelper::Remove(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
}
// process indirect visible
if (EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE)) {
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
if (YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE)) {
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
} else {
EnumsHelper::Rm(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
YYCC::EnumHelper::Remove(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
}
// read associated CKPlace
if (EnumsHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID)) {
if (YYCC::EnumHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID)) {
// MARK: we drop the support of CKPlace.
// so we just read it and skip it.
CK_ID placeid;
chunk->ReadObjectID(placeid);
// and remove this flag
EnumsHelper::Rm(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID);
YYCC::EnumHelper::Remove(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PLACEVALID);
}
// read parent
if (EnumsHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID)) {
if (YYCC::EnumHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID)) {
// MAKR: we drop the support of parent and the whole 3dentity hierarchy system
// we ignore this field.
CK_ID parentid;
chunk->ReadObjectID(parentid);
// and remove this flag
EnumsHelper::Rm(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID);
YYCC::EnumHelper::Remove(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_PARENTVALID);
}
// read priority (non-zero zorder)
if (EnumsHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID)) {
if (YYCC::EnumHelper::Has(m_3dEntityFlags, CK_3DENTITY_FLAGS::CK_3DENTITY_ZORDERVALID)) {
chunk->ReadStruct(m_ZOrder);
}
@ -227,16 +227,16 @@ namespace LibCmo::CK2::ObjImpls {
void CK3dEntity::Show(CK_OBJECT_SHOWOPTION show) {
CKObject::Show(show);
EnumsHelper::Rm(m_MoveableFlags, EnumsHelper::Merge({
YYCC::EnumHelper::Remove(m_MoveableFlags,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE,
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE,
}));
VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE
);
switch (show) {
case CK_OBJECT_SHOWOPTION::CKSHOW:
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_VISIBLE);
break;
case CK_OBJECT_SHOWOPTION::CKHIERARCHICALHIDE:
EnumsHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
YYCC::EnumHelper::Add(m_MoveableFlags, VxMath::VX_MOVEABLE_FLAGS::VX_MOVEABLE_HIERARCHICALHIDE);
break;
case CK_OBJECT_SHOWOPTION::CKHIDE:
break;

View File

@ -21,12 +21,12 @@ namespace LibCmo::CK2::ObjImpls {
m_LineCount(0),
m_LineIndices(),
// init flags
m_Flags(EnumsHelper::Merge({
m_Flags(YYCC::EnumHelper::Merge(
VxMath::VXMESH_FLAGS::VXMESH_VISIBLE,
VxMath::VXMESH_FLAGS::VXMESH_RENDERCHANNELS
})) {
)) {
// set visible in default
EnumsHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
YYCC::EnumHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
}
CKMesh::~CKMesh() {}
@ -145,7 +145,7 @@ namespace LibCmo::CK2::ObjImpls {
rawbuf += CKSizeof(CKDWORD);
// write vertex position
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::NoPos)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::NoPos)) {
CKDWORD consumed = CKSizeof(VxMath::VxVector3) * vtxCount;
std::memcpy(rawbuf, m_VertexPosition.data(), consumed);
rawbuf += consumed;
@ -154,7 +154,7 @@ namespace LibCmo::CK2::ObjImpls {
// write color and specular color
{
CKDWORD consumed = 0;
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleColor)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleColor)) {
consumed = CKSizeof(CKDWORD) * vtxCount;
} else {
consumed = CKSizeof(CKDWORD);
@ -165,7 +165,7 @@ namespace LibCmo::CK2::ObjImpls {
}
{
CKDWORD consumed = 0;
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleSpecularColor)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleSpecularColor)) {
consumed = CKSizeof(CKDWORD) * vtxCount;
} else {
consumed = CKSizeof(CKDWORD);
@ -176,7 +176,7 @@ namespace LibCmo::CK2::ObjImpls {
}
// write normal
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
CKDWORD consumed = CKSizeof(VxMath::VxVector3) * vtxCount;
std::memcpy(rawbuf, m_VertexNormal.data(), consumed);
rawbuf += consumed;
@ -185,7 +185,7 @@ namespace LibCmo::CK2::ObjImpls {
// write uv
{
CKDWORD consumed = 0;
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleUV)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleUV)) {
consumed = CKSizeof(VxMath::VxVector2) * vtxCount;
} else {
consumed = CKSizeof(VxMath::VxVector2);
@ -229,13 +229,13 @@ namespace LibCmo::CK2::ObjImpls {
// read flag
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_MESH::CK_STATESAVE_MESHFLAGS)) {
chunk->ReadStruct(m_Flags);
EnumsHelper::Mask(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_ALLFLAGS);
YYCC::EnumHelper::Mask(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_ALLFLAGS);
// I don't know why, just interpter the IDA code.
EnumsHelper::Rm(m_Flags, EnumsHelper::Merge({
YYCC::EnumHelper::Remove(m_Flags,
VxMath::VXMESH_FLAGS::VXMESH_BOUNDINGUPTODATE,
VxMath::VXMESH_FLAGS::VXMESH_OPTIMIZED
}));
);
}
// read material slots
@ -285,14 +285,14 @@ namespace LibCmo::CK2::ObjImpls {
const CKBYTE* rawbuf = static_cast<const CKBYTE*>(buf.get());
// copy position if it have
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::NoPos)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::NoPos)) {
CKDWORD consumed = CKSizeof(VxMath::VxVector3) * vertexCount;
std::memcpy(m_VertexPosition.data(), rawbuf, consumed);
rawbuf += consumed;
}
// copy color or apply single color
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleColor)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleColor)) {
CKDWORD consumed = CKSizeof(CKDWORD) * vertexCount;
std::memcpy(m_VertexColor.data(), rawbuf, consumed);
rawbuf += consumed;
@ -309,7 +309,7 @@ namespace LibCmo::CK2::ObjImpls {
}
// copy specular color or apply a single color
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleSpecularColor)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleSpecularColor)) {
CKDWORD consumed = CKSizeof(CKDWORD) * vertexCount;
std::memcpy(m_VertexSpecularColor.data(), rawbuf, consumed);
rawbuf += consumed;
@ -326,14 +326,14 @@ namespace LibCmo::CK2::ObjImpls {
}
// copy normals if it has
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
CKDWORD consumed = CKSizeof(VxMath::VxVector3) * vertexCount;
std::memcpy(m_VertexNormal.data(), rawbuf, consumed);
rawbuf += consumed;
}
// copy uv or apply single uv
if (!EnumsHelper::Has(saveflags, VertexSaveFlags::SingleUV)) {
if (!YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::SingleUV)) {
CKDWORD consumed = CKSizeof(VxMath::VxVector2) * vertexCount;
std::memcpy(m_VertexUV.data(), rawbuf, consumed);
rawbuf += consumed;
@ -407,7 +407,7 @@ namespace LibCmo::CK2::ObjImpls {
}
// build normals
if (EnumsHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
if (YYCC::EnumHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
BuildNormals();
} else {
BuildFaceNormals();
@ -425,9 +425,9 @@ namespace LibCmo::CK2::ObjImpls {
CKObject::Show(show);
if (show == CK_OBJECT_SHOWOPTION::CKSHOW) {
EnumsHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE);
YYCC::EnumHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE);
} else {
EnumsHelper::Rm(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE);
YYCC::EnumHelper::Remove(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE);
}
}
@ -449,15 +449,15 @@ namespace LibCmo::CK2::ObjImpls {
m_Flags = flags;
// sync visibility to CKObject layer.
if (EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE)) {
EnumsHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
if (YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_VISIBLE)) {
YYCC::EnumHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
} else {
EnumsHelper::Rm(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
YYCC::EnumHelper::Remove(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
}
}
VxMath::VXMESH_LITMODE CKMesh::GetLitMode() const {
if (EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE)) {
if (YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE)) {
return VxMath::VXMESH_LITMODE::VX_PRELITMESH;
} else {
return VxMath::VXMESH_LITMODE::VX_LITMESH;
@ -467,10 +467,10 @@ namespace LibCmo::CK2::ObjImpls {
void CKMesh::SetLitMode(VxMath::VXMESH_LITMODE mode) {
switch (mode) {
case VxMath::VXMESH_LITMODE::VX_PRELITMESH:
EnumsHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE);
YYCC::EnumHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE);
break;
case VxMath::VXMESH_LITMODE::VX_LITMESH:
EnumsHelper::Rm(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE);
YYCC::EnumHelper::Remove(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PRELITMODE);
break;
}
}
@ -478,51 +478,51 @@ namespace LibCmo::CK2::ObjImpls {
VxMath::VXTEXTURE_WRAPMODE CKMesh::GetWrapMode() const {
VxMath::VXTEXTURE_WRAPMODE ret = VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_NONE;
if (EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU)) {
EnumsHelper::Add(ret, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_U);
if (YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU)) {
YYCC::EnumHelper::Add(ret, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_U);
}
if (EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV)) {
EnumsHelper::Add(ret, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_V);
if (YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV)) {
YYCC::EnumHelper::Add(ret, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_V);
}
return ret;
}
void CKMesh::SetWrapMode(VxMath::VXTEXTURE_WRAPMODE mode) {
if (EnumsHelper::Has(mode, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_U)) {
EnumsHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU);
if (YYCC::EnumHelper::Has(mode, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_U)) {
YYCC::EnumHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU);
} else {
EnumsHelper::Rm(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU);
YYCC::EnumHelper::Remove(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPU);
}
if (EnumsHelper::Has(mode, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_V)) {
EnumsHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV);
if (YYCC::EnumHelper::Has(mode, VxMath::VXTEXTURE_WRAPMODE::VXTEXTUREWRAP_V)) {
YYCC::EnumHelper::Add(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV);
} else {
EnumsHelper::Rm(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV);
YYCC::EnumHelper::Remove(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_WRAPV);
}
}
CKMesh::VertexSaveFlags CKMesh::GenerateSaveFlags() {
// set to initial status
VertexSaveFlags saveflags = EnumsHelper::Merge({
VertexSaveFlags saveflags = YYCC::EnumHelper::Merge(
VertexSaveFlags::SingleColor,
VertexSaveFlags::SingleSpecularColor,
VertexSaveFlags::NoNormal,
VertexSaveFlags::SingleUV
});
);
// check no pos
// if position is generated, skip saving position
if (EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALPOS)) {
EnumsHelper::Add(saveflags, VertexSaveFlags::NoPos);
if (YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALPOS)) {
YYCC::EnumHelper::Add(saveflags, VertexSaveFlags::NoPos);
}
// check uv
// if uv is not generated and all uv are not the same value, remove single uv
if (!EnumsHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALUV)) {
if (!YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALUV)) {
for (const auto& uv : m_VertexUV) {
if (uv != m_VertexUV.front()) {
EnumsHelper::Rm(saveflags, VertexSaveFlags::SingleUV);
YYCC::EnumHelper::Remove(saveflags, VertexSaveFlags::SingleUV);
break;
}
}
@ -532,19 +532,19 @@ namespace LibCmo::CK2::ObjImpls {
// if all color are not the same value, remove single color
for (const auto& col : m_VertexColor) {
if (col != m_VertexColor.front()) {
EnumsHelper::Rm(saveflags, VertexSaveFlags::SingleColor);
YYCC::EnumHelper::Remove(saveflags, VertexSaveFlags::SingleColor);
break;
}
}
for (const auto& col : m_VertexSpecularColor) {
if (col != m_VertexSpecularColor.front()) {
EnumsHelper::Rm(saveflags, VertexSaveFlags::SingleSpecularColor);
YYCC::EnumHelper::Remove(saveflags, VertexSaveFlags::SingleSpecularColor);
break;
}
}
// if normal not changed, and position is not generated, we should consider whether we need save normal (step into if)
if (!EnumsHelper::Has(m_Flags, EnumsHelper::Merge({ VxMath::VXMESH_FLAGS::VXMESH_NORMAL_CHANGED, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALPOS }))) {
if (!YYCC::EnumHelper::Has(m_Flags, VxMath::VXMESH_FLAGS::VXMESH_NORMAL_CHANGED, VxMath::VXMESH_FLAGS::VXMESH_PROCEDURALPOS)) {
// MARK: we should build face normal first
// then we build vertex normal like BuildNormals.
// then, we compare the difference between the generated normals and user specified normals, by simply using operator- (userNml - generatedNml) and abs the result.
@ -581,7 +581,7 @@ namespace LibCmo::CK2::ObjImpls {
accnml /= static_cast<CKFLOAT>(m_VertexCount);
if (accnml.Length() > 0.001f) {
// too large difference, we need save normal
EnumsHelper::Rm(saveflags, VertexSaveFlags::NoNormal);
YYCC::EnumHelper::Remove(saveflags, VertexSaveFlags::NoNormal);
}
}

View File

@ -32,7 +32,7 @@ namespace LibCmo::CK2::ObjImpls {
m_ObjectFlags = flags;
}
bool CKObject::IsToBeDeleted() const {
return EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED);
return YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_TOBEDELETED);
}
CKContext* CKObject::GetCKContext() const {
return m_Context;
@ -51,10 +51,10 @@ namespace LibCmo::CK2::ObjImpls {
void CKObject::PreSave(CKFileVisitor* file, CKDWORD flags) {}
bool CKObject::Save(CKStateChunk* chunk, CKFileVisitor* file, CKDWORD flags) {
if (EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE)) {
if (YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE)) {
// if hierarchy hidden
chunk->WriteIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIERAHIDDEN);
} else if (!EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE)) {
} else if (!YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE)) {
// if really hidden
chunk->WriteIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN);
}
@ -65,18 +65,20 @@ namespace LibCmo::CK2::ObjImpls {
bool CKObject::Load(CKStateChunk* chunk, CKFileVisitor* file) {
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIDDEN)) {
EnumsHelper::Rm(this->m_ObjectFlags,
EnumsHelper::Merge({ CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE }));
YYCC::EnumHelper::Remove(this->m_ObjectFlags,
CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE,
CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE
);
} else {
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_OBJECT::CK_STATESAVE_OBJECTHIERAHIDDEN)) {
// != 0
EnumsHelper::Rm(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
EnumsHelper::Add(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
YYCC::EnumHelper::Remove(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
YYCC::EnumHelper::Add(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
} else {
// == 0
EnumsHelper::Add(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
EnumsHelper::Rm(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
YYCC::EnumHelper::Add(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
YYCC::EnumHelper::Remove(this->m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
}
}
@ -89,17 +91,17 @@ namespace LibCmo::CK2::ObjImpls {
void CKObject::Show(CK_OBJECT_SHOWOPTION show) {
// clear all visible data of object flags
EnumsHelper::Rm(m_ObjectFlags, EnumsHelper::Merge({
YYCC::EnumHelper::Remove(m_ObjectFlags,
CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE,
CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE
}));
);
switch (show) {
case CK_OBJECT_SHOWOPTION::CKSHOW:
EnumsHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
YYCC::EnumHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
break;
case CK_OBJECT_SHOWOPTION::CKHIERARCHICALHIDE:
EnumsHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
YYCC::EnumHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_HIERACHICALHIDE);
break;
case CK_OBJECT_SHOWOPTION::CKHIDE:
return;
@ -107,7 +109,7 @@ namespace LibCmo::CK2::ObjImpls {
}
bool CKObject::IsVisible() const {
return EnumsHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
return YYCC::EnumHelper::Has(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
}

View File

@ -86,19 +86,15 @@ target_include_directories(LibCmo
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE
YYCC::YYCCommonplace
ZLIB::ZLIB
stb::stb-image
)
target_link_libraries(LibCmo
PRIVATE
PUBLIC
YYCC::YYCCommonplace
PRIVATE
ZLIB::ZLIB
stb::stb-image
)
if (NOT WIN32)
target_include_directories(LibCmo PRIVATE Iconv::Iconv)
target_link_libraries(LibCmo PRIVATE Iconv::Iconv)
endif ()
# Setup C++ standard

View File

@ -2,10 +2,10 @@
#include <map>
#if YYCC_OS == YYCC_OS_WINDOWS
#include <WinImportPrefix.hpp>
#include <YYCC/WinImportPrefix.hpp>
#include <Windows.h>
#include <fileapi.h>
#include <WinImportSuffix.hpp>
#include <YYCC/WinImportSuffix.hpp>
#else
#include <iconv.h>
#endif

View File

@ -10,4 +10,4 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb_image_resize.h>
#include <deprecated/stb_image_resize.h>

View File

@ -5,13 +5,14 @@
#error "You must define ONE of LIBCMO_BUILD_DEBUG and LIBCMO_BUILD_RELEASE to indicate build type!"
#endif
// Include YYCC helper library
// Include YYCC helper library and check its version
#include <YYCCommonplace.hpp>
#if YYCC_VERCMP_NE(YYCC_VER_MAJOR, YYCC_VER_MINOR, YYCC_VER_PATCH, 1, 3, 0)
#error "YYCC library version is not matched with our expected version. Please check your library configuration."
#endif
// Header for this namespace implementation
#include <string>
#include <type_traits>
#include <initializer_list>
/**
* @brief The core namespace of LibCmo project.
@ -69,91 +70,4 @@ namespace LibCmo {
#pragma endregion
/**
* @brief The namespace for convenient C++ enum class logic operations.
* @details
* C++ enum class statement is a modern way to declare enum in C++.
* But it lack essential logic operations which is commonly used by programmer.
* So we create this helper to resolve this issue.
*/
namespace EnumsHelper {
/**
* @brief Merge given enum flags like performing <TT>e1 | e2 | ... | en</TT>
* @tparam TEnum Enum type for processing.
* @param[in] il The list of enum flags to be merged.
* @return The merged enum flag.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr TEnum Merge(std::initializer_list<TEnum> il) {
using ut = std::underlying_type_t<TEnum>;
ut result = 0;
for (auto it = il.begin(); it != il.end(); ++it) {
result |= static_cast<ut>(*it);
}
return static_cast<TEnum>(result);
}
/**
* @brief Reverse given enum flags like performing <TT>~(e)</TT>
* @tparam TEnum Enum type for processing.
* @param[in] e The list of enum flags to be inversed.
* @return The inversed enum flag.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr TEnum Inv(TEnum e) {
using ut = std::underlying_type_t<TEnum>;
return static_cast<TEnum>(~(static_cast<ut>(e)));
}
/**
* @brief Remove specified enum flags from given enum flags like performing <TT>e1 &= (~e2)</TT>
* @tparam TEnum Enum type for processing.
* @param[in,out] e1 The enum flags to be processed.
* @param[in] e2 The enum flag to be removed.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr void Rm(TEnum& e1, TEnum e2) {
using ut = std::underlying_type_t<TEnum>;
e1 = static_cast<TEnum>(static_cast<ut>(e1) & static_cast<ut>(Inv(e2)));
}
/**
* @brief Use specified enum flags to mask given enum flags like performing <TT>e1 &= e2</TT>
* @tparam TEnum Enum type for processing.
* @param[in,out] e1 The enum flags to be masked.
* @param[in] e2 The mask enum flag.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr void Mask(TEnum& e1, TEnum e2) {
using ut = std::underlying_type_t<TEnum>;
e1 = static_cast<TEnum>(static_cast<ut>(e1) & static_cast<ut>(e2));
}
/**
* @brief Add specified enum flags to given enum flags like performing <TT>e1 |= e2</TT>
* @tparam TEnum Enum type for processing.
* @param[in,out] e1 The enum flags to be processed.
* @param[in] e2 The enum flag to be added.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr void Add(TEnum& e1, TEnum e2) {
using ut = std::underlying_type_t<TEnum>;
e1 = static_cast<TEnum>(static_cast<ut>(e1) | static_cast<ut>(e2));
}
/**
* @brief Check whether given enum flags has specified enum flag like performing <TT>bool(e & probe)</TT>
* @tparam TEnum Enum type for processing.
* @param[in] e1 The enum flags to be checked.
* @param[in] e2 The enum flag for checking.
* @return True if it has, otherwise false.
*/
template<typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, int> = 0>
constexpr bool Has(TEnum e1, TEnum e2) {
using ut = std::underlying_type_t<TEnum>;
return static_cast<bool>(static_cast<ut>(e1) & static_cast<ut>(e2));
}
}
}

View File

@ -1,6 +1,6 @@
#include "VxMath.hpp"
#include <cmath>
#include <stb_image_resize.h>
#include <deprecated/stb_image_resize.h>
namespace LibCmo::VxMath {

View File

@ -2,9 +2,9 @@
#include "../VTInternal.hpp"
#if YYCC_OS == YYCC_OS_WINDOWS
#include <WinImportPrefix.hpp>
#include <YYCC/WinImportPrefix.hpp>
#include <Windows.h>
#include <WinImportSuffix.hpp>
#include <YYCC/WinImportSuffix.hpp>
#else
#include <sys/mman.h>
#include <sys/stat.h>

View File

@ -1,7 +1,7 @@
# libcmo21
The Library for CMO (also accept NMO, VMO and NMS) File Read/Write. Also the Minimalist Virtools Environment.
Write with one Library and Load Virtools File Everywhere.
The Library for CMO (also accept NMO, VMO and NMS) File RW (Read and Write). Also the Minimalist Virtools Environment.
Write with one Library and Load/Save Virtools File Everywhere.
## Status
@ -10,12 +10,15 @@ This project welcome everyone's contribution, except the employee of Dassault, w
## Introduction
The aim of this project is creating a universal library which can read / write CMO files or any other Virtools files without any Virtools dependencies.
This project will not link any original Virtools dynamic library. So this project can be ported to any platform if the compiler supports.
This project only involving specific Virtools version, 2.1. Other Virtools versions are not considered by this project.
This project is based on reverse work of `CK2.dll`, `VxMath.dll` and `CK2_3D.dll`. The program [unvirt](https://aluigi.altervista.org/papers.htm#unvirt) created by Luigi Auriemma, which is licensed by GPL-v2, also help my work.
The aim of this project is creating a universal library which can RW CMO files or any other Virtools files without any Virtools dependencies.
**The difference between this project and other Virtools libraries (e.g. [doyaGu/CK2](https://github.com/doyaGu/CK2)), is that we are not focusing on re-creating the whole Virtools engine. We only focus on the Virtools files RW, and we only just implement a minimalist Virtools environment for achieving this.**
This project will not link any original Virtools dynamic library. So this project can be ported to any platform if the compiler and runtime libraries support.
This project only involving specific Virtools version, 2.1. Other too higher Virtools versions are not considered by this project.
This project is barely based on the reverse work of doyaGu who decompile `CK2.dll`, `VxMath.dll` and `CK2_3D.dll`. The program [unvirt](https://aluigi.altervista.org/papers.htm#unvirt) created by Luigi Auriemma, which is licensed by GPL-v2, also help my work.
**The difference between this project and other Virtools libraries (e.g. [doyaGu/CK2](https://github.com/doyaGu/CK2)), is that this project is not focusing on re-creating the whole Virtools engine. This project only focus on the Virtools files RW, and it only just implement a minimalist Virtools environment for achieving this.**
## Goals
@ -23,22 +26,20 @@ The ultimate goals of this project are:
* Create a library which can read Virtools file and do not limited on x86 platform by original Virtools implement.
* Create a universal dynamic library for Ballance Map file loading.
* Create a Python binding for the loader. And allow user can export Ballance Map from Blender on Linux platform natively.
* Create a C# binding for the loader to enable that I can load Ballance Map in Godot on Linux / Android platform natively.
- Create a Python binding for the loader. And allow user can export Ballance Map from Blender on Linux platform natively.
- Create a C# binding for the loader to enable that I can load Ballance Map in Godot on Linux / Android platform natively.
There is still a long way to go. But I will try my best.
## Project Layout
* LibCmo: Core library. It is a static library. Link to your program freely because I don't want to process export table things.
* IronPad: A tiny Crashpad like static library. Used by Unvirt and BMap. Report crash log and coredump only on Windows (Because I assume all Linux users have capacity to enable coredump and deliver it to developer.).
* Unvirt: Interactive Virtools file viewer. Can provide more detail than Luigi Auriemma's unvirt but only can accept version limited Virtools file (< 4.0 I guess).
* BMap: A dynamic library which is specific for Ballance Map loading by using LibCmo.
## Contributions
However, not all contribution will be accepted. Just like I said, we create **Minimalist** Virtools Environment. The basic RW functions is enough. We do not accept complex function implementations.
There are 3 lists which indicate our accept guideline.
However, not all contribution will be accepted. Just like I said, we create **Minimalist** Virtools Environment. The basic RW functions is enough. We do not accept complex function implementations. There are 3 lists which indicate our accept guideline.
### Wanted Features
@ -64,14 +65,4 @@ These features explicitly will not be merged.
## Compile
This project require:
* The compiler supporting C++ 20
* Littile-endian architecture system.
* zlib
* [stb](https://github.com/nothings/stb) (For image read / write)
* iconv (non-Windows system required)
It can be compiled on Windows via sln file. You should set up `LibRef.props` when using sln file to build this project on Windows.
You also can use CMake file to compile this project on Linux or anything else platform. However CMake may not be updated in time because I develop this project on Windows frequently.
You may need use this command to configure CMake: `cmake .. -DSTB_IMAGE_PATH="/path/to/stb-image" -DCMAKE_BUILD_TYPE=Release`
See [Compile Manual](./COMPILE.md)

3
Scripts/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Disable output
win_build.bat
linux_build.sh

View File

@ -0,0 +1,67 @@
import os
import argparse
import jinja2
def get_root_directory() -> str:
return os.path.dirname(os.path.dirname(__file__))
class ScriptSettings:
m_BuildDoc: bool
def __init__(self, build_doc: bool):
self.m_BuildDoc = build_doc
class TemplateRender:
m_Loader: jinja2.BaseLoader
m_Environment: jinja2.Environment
m_WinTemplate: jinja2.Template
m_LinuxTemplate: jinja2.Template
m_Settings: ScriptSettings
def __init__(self, settings: ScriptSettings) -> None:
self.m_Loader = jinja2.FileSystemLoader(self.__get_dir())
self.m_Environment = jinja2.Environment(loader=self.m_Loader)
self.m_WinTemplate = self.m_Environment.get_template('win_build.template.bat')
self.m_LinuxTemplate = self.m_Environment.get_template('linux_build.template.sh')
self.m_Settings = settings
def __get_dir(self) -> str:
return os.path.dirname(__file__)
def __render(self, template: jinja2.Template, dest_file: str, is_win: bool) -> None:
with open(os.path.join(self.__get_dir(), dest_file), 'w', encoding='utf-8') as f:
f.write(template.render(
repo_root_dir = os.path.dirname(self.__get_dir()),
build_doc = self.m_Settings.m_BuildDoc
))
def render_win_script(self) -> None:
self.__render(self.m_WinTemplate, 'win_build.bat', True)
def render_linux_script(self) -> None:
self.__render(self.m_LinuxTemplate, 'linux_build.sh', False)
if __name__ == '__main__':
# parse argument
parser = argparse.ArgumentParser(
prog='LibCmo Windows Build Script',
description='LibCmo Windows Build Script'
)
parser.add_argument(
'-d', '--build-doc',
action='store_true', dest='build_doc',
help='Build LibCmo without documentation.'
)
args = parser.parse_args()
# build settings
settings = ScriptSettings(args.build_doc)
# build template render and render result
render = TemplateRender(settings)
render.render_win_script()
render.render_linux_script()

View File

View File

@ -1,38 +0,0 @@
@ECHO OFF
:: Check environment
SET README_PATH=%CD%\README.md
IF EXIST %README_PATH% (
REM DO NOTHING
) ELSE (
ECHO Error: You must run this script at the root folder of this project!
EXIT /b
)
:: Create main binary directory
MKDIR bin
CD bin
:: Create build and install folder
MKDIR build
MKDIR install
:: Check build doc switch
IF NOT "%1"=="NODOC" (
SET BUILD_DOC_SWITCH=ON
) ELSE (
SET BUILD_DOC_SWITCH=OFF
)
:: Build project
CD build
cmake -G "Visual Studio 16 2019" -A x64 -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_DOC=%BUILD_DOC_SWITCH% -DSTB_IMAGE_PATH="D:\CppLib\stb" -DYYCC_PATH="J:\YYCCommonplace\bin\cpp20\install\x64_Debug" -DZLIB_HEADER_PATH="D:\zlib" -DZLIB_BINARY_PATH="D:\zlib\contrib\vstudio\vc14\x64\ZlibDllRelease" ../..
pause
cmake --build . --config Release
IF NOT "%1"=="NODOC" (
cmake --build . --target NeMoDocuments
)
cmake --install . --prefix=../install --config Release
CD ..
:: Exit to original path
CD ..
ECHO Windows CMake Build Done

View File

@ -1,48 +0,0 @@
import subprocess
import os
import shutil
import argparse
def get_root_directory() -> str:
return os.path.dirname(os.path.dirname(__file__))
def execute_cmd(prog: str, args: tuple[str, ...], cwd: str) -> None:
# find program first
found_prog = shutil.which(prog)
if found_prog is None:
raise RuntimeError(f'Fail to find program {prog}')
# run command
subprocess.run(
list((found_prog, ) + args), # program + arguments
stdin=subprocess.PIPE, # redirect
stdout=subprocess.PIPE, # redirect
stderr=subprocess.STDOUT, # stderr use the same output with stdout
cwd=cwd, # work directory
shell=True, # enable shell feature
check=True, # if program failed, raise exception and exit
)
def build(no_doc: bool) -> None:
# create directory
root_dir: str = get_root_directory()
os.makedirs(os.path.join(root_dir, 'Bin', 'build'))
os.makedirs(os.path.join(root_dir, 'Bin', 'install'))
# build project
args = [
''
]
if __name__ == '__main__':
# parse argument
parser = argparse.ArgumentParser(
prog='LibCmo Windows Build Script',
description='LibCmo Windows Build Script'
)
parser.add_argument(
'-d', '--no-doc',
action='store_true', dest='no_doc',
help='Build LibCmo without documentation.'
)
args = parser.parse_args()
build(args.no_doc)

View File

@ -0,0 +1,24 @@
@ECHO OFF
:: Navigate to root directory
CD /d {{ repo_root_dir }}
:: Create main binary directory
MKDIR bin
CD bin
:: Create build and install folder
MKDIR build
MKDIR install
:: Build project
CD build
cmake -A x64 -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON {{ '-DNEMO_BUILD_DOC=ON' if build_doc }} -DSTB_IMAGE_PATH="D:\CppLib\stb" -DYYCC_PATH="J:\YYCCommonplace\bin\cpp20\install\x64_Release" -DZLIB_HEADER_PATH="D:\zlib" -DZLIB_BINARY_PATH="D:\zlib\contrib\vstudio\vc14\x64\ZlibDllRelease" ../..
cmake --build . --config RelWithDebInfo
{% if build_doc %}
cmake --build . --target NeMoDocuments
{% endif %}
cmake --install . --prefix=../install --config RelWithDebInfo
CD ..
:: Exit to original path
CD ..
ECHO Windows CMake Build Done

View File

@ -61,7 +61,7 @@ namespace Unvirt {
}
// check flag match
if (LibCmo::EnumsHelper::Has(val, item.first)) {
if (YYCC::EnumHelper::Has(val, item.first)) {
// add splittor if it not the first entry
if (strl.size() != 0u && splitor != nullptr) {
strl += splitor;

View File

@ -23,8 +23,6 @@ FILES
target_include_directories(Unvirt
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
YYCC::YYCCommonplace
LibCmo
)
# Setup linked library infomation
target_link_libraries(Unvirt
@ -53,6 +51,6 @@ PRIVATE
# Install Unvirt only on Release mode
install(TARGETS Unvirt
CONFIGURATIONS Release
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
RUNTIME DESTINATION ${YYCC_INSTALL_BIN_PATH}
)