Compare commits

61 Commits

Author SHA1 Message Date
af6a50c2f9 feat: use cmdline args as the args of BMap bindings.
- update testbench of PyBMap and BMapSharp. use command line arguments as the arguments of testbench, instead of hardcoded variables in code.
2025-01-02 10:59:16 +08:00
0bf0519c4c fix: fix linux build issue
- use std::cos and std::sin instead of std::cosf and std::sinf. it seems that some linux environment do not have these 2 functions in std namespace.
2024-12-31 18:25:44 +08:00
c18ff8f2e3 fix: fix various issues.
- fix convertion loss in CKCamera.
- bump up version to 0.3.0
- use CMake to generate version info header.
- fix annotation about Dassault ComputeCRC error.
- change member field initialization value in CKLight.
2024-12-31 17:48:24 +08:00
fe4a58e864 feat: add CKLight support and apply BMap changes to Python and CSharp bindings.
- add CKLight and CKTargetLight in BMap bindings
- apply BMap changes, for example, the rename of BM3dObject_ prefix to BM3dEntity_, to BMap bindings.
2024-12-30 11:28:59 +08:00
eaeaf956b5 fix: fix type error in BMap type check macro. 2024-12-29 10:13:56 +08:00
6bb2421e1f feat: add CKLight into BMap.
- add CKLight support in BMap.
- move the implementation of BMFile into CPP file from HPP file.
- swap the order of the implementation of BMFile and BMMeshTransition to correspond with the order of their declaration.
- add document for some member functions of BMFile.
2024-12-29 10:05:13 +08:00
ead22d13ff fix: remove useless void in function parameter list
- according to c++ standard, single void in function parameter is equal to empty parameter list. for removing this syntax which may cause misunderstanding (becuase in C, they are different I guess), I replace all `(void)` to `()`.
2024-12-28 22:09:26 +08:00
aeb2e86b14 fix: fix the issue when loading new version created files.
- Fix the CRC check issue when loading new Virtools created files (> 4.0)
	* This is caused by a bug written by stupid Virtools programmer. For more detail, see code annotation.
	* After this patch, LibCmo have ability that load new Virtools created files including max2nmo exported NMO, Virtools 5.0 created CMO and etc.
2024-12-28 16:29:35 +08:00
86b27557c9 feat: add 4 new added classes in Unvirt.
- fix a fatal issue that make the output message from CKContext is empty.
- fix argument type error for CKCamera::GetAspect and CKCamera::SetAspect.
- add enums annotation and struct diaplay function in Unvirt for showing 4 new added classes.
2024-12-25 13:58:39 +08:00
eef3a352d9 feat: finish CKTargetCamera and CKTargetLight.
- finish all new added 4 classes, CKCamera, CKTargetCamera, CKLight, CKTargetLight. but no test.
2024-12-25 11:12:23 +08:00
b74f1b965c feat: finish CKCamera 2024-12-25 09:07:02 +08:00
c235524403 fix: fix 2 issues
- rename float to CKFLOAT in VxMatrix.
- move CKLightData struct to CKDefine.hpp because it not a private struct used by CKLight, but a CKRasterizer struct.
2024-12-25 08:28:42 +08:00
4bfc4782b5 refactor: refactor VxVector and its generator.
- refactor VxVector-like struct. split their declaration and implementatio because their implementation is too long. and occupy too much space in header.
- refactor VxVector struct generator. use jinja2 template engine, rather ran hand-written format string to make it is easy to read (although it still tough when first reading).
- add unary operator overloading for VxVector-like struct.
- add some VxMatrix functions which are essential to CKCamera.
- rename VxMatrix::ResetToIdentity to VxMatrix::SetIdentity to make it same as original Virtools SDK.
- the spaceship overloading with auto return value still may have bugs. please watch it carefully.
2024-12-24 23:37:04 +08:00
3eeb1f6cb6 feat: finish CKLight class.
- basically finish CKLight but no test now.
2024-12-24 10:59:19 +08:00
ff5a590cf4 feat: add basic layout for CKLight and CKCamera.
- add basic class layout and member function for CKLight and CKCamera.
- register CKLight and CKCamera in CKGlobals to let CK engine can recognize them.
- modify EnumsMigration to add new 2 enums for CKLight and CKCamera.
2024-12-23 22:21:50 +08:00
d29d40448b fix: fix CMake install path issue.
- fix the wrong reference in CMake script which install lib target into wrong directory.
- add file, change CMake script and modify header file for preparing develop of CKLight and CKCamera.
- fix doc typo.
2024-12-23 09:23:46 +08:00
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
334580acdc feat: update BMapSharp code 2024-10-03 21:39:36 +08:00
2ce5203ac7 feat: update BMap bindings
- add testbench file in BMap bindings.
- reorganise BMap bindings code.
- write some BMapSharp binding code.
2024-10-02 13:33:32 +08:00
5e5eed03f5 feat: finish c sharp custom marshaler.
- Finish BMapStringArrayMarshaler but not test.
2024-09-21 22:01:25 +08:00
7c88b3614a fix: update BMap bindings
- send message in console if PyBMap fail to load native dynamic library. this is good for user experience.
- remove snippet from BMap bindings generator. We now insert generated code manually.
- fix C sharp code generation issue in BMap bidnings generator.
- add some content for BMapSharp.
2024-09-21 16:50:53 +08:00
8ef1c6e30a fix: fix linux build issue 2024-08-27 20:48:27 +08:00
85ff80cbf7 fix: fix Bmap build issue. add banner for Unvirt 2024-08-27 17:13:52 +08:00
65861143bf fix: fix issues
- restore some CKGlobals behavior because it will cause runtime exception.
- move some classes from CmdHelper to UnvirtContext to make CmdHelper more common to use.
- output warning string when fail to get utf8 or ordinary string.
2024-08-27 11:25:53 +08:00
3735a202f3 fix: fix Unvirt build issue, but it doesn't work 2024-08-26 21:28:13 +08:00
34015d2d1c refactor: finish refactor of CmdHelper of Unvirt 2024-08-26 12:24:09 +08:00
bd96f26cfd fix: fix CmdHelper but still not finished 2024-08-25 22:27:17 +08:00
0db8007fcb fix: update CmdHelper in Unvirt but not finished 2024-08-24 23:05:41 +08:00
88ce33c358 fix: fix build issue in Unvirt 2024-08-24 21:27:23 +08:00
d74b4645f0 fix: fix build issue in Unvirt and LibCmo
- fix build issue in Unvirt and LibCmo
- due to we use UTF8 string. the accessible value generator in EnumsMigration need to be changed at the same time.
- remove string helper in Unvirt because we no longer need it.
2024-08-23 17:38:45 +08:00
0447381896 fix: fix libcmo build issue 2024-08-23 11:28:49 +08:00
1028aad155 doc: add documentation
- add documentation for CKDefines, CKGlobals and VxMemoryMappedFile.
- fix build issue in VxMemoryMappedFile.
- add file size limitation in VxMemoryMappedFile. File whose size exceed the maximum value can not be opened.
2024-08-22 10:57:53 +08:00
a7c1028926 doc: add documentation
- add documentation for CKGlobals, VxMath (partly)
- Fix build issue in CKDefines, CKGlobals, VxMath.
- Bring libcmo exception in CKGlobals and VxMath for some illegal input.
2024-08-21 17:57:35 +08:00
f7708c28e0 doc: add documentation for VxTypes 2024-08-20 10:52:05 +08:00
35d508b1b9 doc: finish XTypes documentation 2024-08-19 10:43:30 +08:00
1483466211 doc: fix issue. add documentation.
- fix build issue in CKTypes
- add documentation for CKTypes, VTAll and VTImage.
2024-08-18 11:33:51 +08:00
9903b61cac fix: fix issues
- fix BMapBindings generator due to the rename of LIBCMO_EXPORT -> BMAP_EXPORT.
- fix relative path issue in Python scripts within CodeGen.
- remove all references to LIBCMO_PANIC. use exception instead to tell user they are fool.
- basically finish universal encoding tables. add lost encoding name.
2024-08-17 23:29:08 +08:00
e682a87d25 refactor: refactor project
- rename LIBCMO_DISABLE_COPY_MOVE -> YYCC_DEL_CLS_COPY_MOVE and LIBCMO_DEFAULT_COPY_MOVE -> YYCC_DEF_CLS_COPY_MOVE.
- fix Vector declaration generator. throw exception when operator[] face invalid index, instead of do fallback.
- rename VTAll.hpp -> VTInternal.hpp and VYUserAll -> VTAll.hpp for easy to understand.
- fix project name error in Doxygen template.
- replace all LIBCMO_OS_WIN32 to YYCC_OS == YYCC_OS_WINDOWS.
- fix some compile error (involving utf8 encoding) but not the final result.
- use correct way to include std-image library (use <> instead of "")
- finish documentation for VTUtils.hpp and VTEncoding.hpp.
2024-08-17 20:43:27 +08:00
f870d4dde3 refactor: update project
- add documentation CMake build script. re-organise document layout for future changes.
- move LIBCMO_EXPORT to BMap and rename it to BMAP_EXPORT because only BMap need to use this macro.
- fully refactor VTEncoding to make it more like Python
	- Now language name is platform independent.
	- Hide implementation detail as possible as I can.
	- Language mapping are still work in progress.
- add code gen for new added universal encoding feature to generate language name mapping in Windows and Iconv respectively.
- remove old code of CMake build script.
- update VTUtils for new requirement.
	- remove useless functions.
	- create LibCmo specific custom exception classes.
2024-08-16 22:07:23 +08:00
afa06339b2 chore: switch to CMake build system instead of native Visual Studio project 2024-08-15 22:20:51 +08:00
da575e42f5 fix: update csharp interop code generator.
- update csharp interop code generator to have short output result.
2024-08-15 19:11:27 +08:00
a2fb376231 feat: add csharp interop code generation but no test.
- add csharp interop code generation without testing.
- add annotation for bmap binding project.
- fix README.
2024-04-23 16:01:26 +08:00
8a1fc03965 do some preparation work
- establish BMapSharp project for future development.
- refactor EnumsMigration. add csharp code output for it.
- add README for VectorGen and modify other READMEs.
2024-04-22 14:15:27 +08:00
166 changed files with 16361 additions and 6734 deletions

6
.gitattributes vendored
View File

@ -1,2 +1,4 @@
*.fods eol=lf
Doxyfile.in eol=lf
*.bat eol=crlf
*.sh eol=lf
*.fods eol=lf

10
.gitignore vendored
View File

@ -5,9 +5,13 @@
*.nms
*.vmo
# Ignore temporary folders
/out/
/temp/
# Ignore CMake generated version header
LibCmo/VTVersion.hpp
# Ignore temporary Visual Studio files and folders
temp/
out/
CMakeSettings.json
# -------------------- VSCode --------------------
.vscode/

View File

@ -1,5 +1,5 @@
#include "BMExports.hpp"
#include <IronPad.hpp>
#include <YYCCommonplace.hpp>
#include <set>
#include <type_traits>
#include <memory>
@ -42,10 +42,13 @@ _Ty CheckGeneralObject(BMap::BMFile* possible_bmfile, LibCmo::CK2::CK_ID possibl
#define CheckCKObject(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKObject*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_OBJECT)
#define CheckCKGroup(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKGroup*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_GROUP)
#define CheckCK3dEntity(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CK3dEntity*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_3DENTITY)
#define CheckCK3dObject(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CK3dObject*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT)
#define CheckCKMesh(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKMesh*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_MESH)
#define CheckCKMaterial(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKMaterial*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL)
#define CheckCKTexture(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKTexture*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE)
#define CheckCKLight(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKLight*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_LIGHT)
#define CheckCKTargetLight(bmfile, objid) CheckGeneralObject<LibCmo::CK2::ObjImpls::CKTargetLight*>(bmfile, objid, LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT)
#pragma endregion
@ -54,8 +57,11 @@ _Ty CheckGeneralObject(BMap::BMFile* possible_bmfile, LibCmo::CK2::CK_ID possibl
bool BMInit() {
if (CheckInited()) return false;
// register IronPad
IronPad::IronPadRegister();
// register exception handler if we are in Windows.
#if defined(LIBCMO_BUILD_RELEASE) && (YYCC_OS == YYCC_OS_WINDOWS)
YYCC::ExceptionHelper::Register();
#endif
// and startup CK environment
LibCmo::CK2::CKStartUp();
@ -84,8 +90,11 @@ bool BMDispose() {
// shutdown CK environment
LibCmo::CK2::CKShutdown();
// unregister iron pad
IronPad::IronPadUnregister();
// unregister exception handler if we are in Windows
#if defined(LIBCMO_BUILD_RELEASE) && (YYCC_OS == YYCC_OS_WINDOWS)
YYCC::ExceptionHelper::Unregister();
#endif
return true;
}
@ -137,7 +146,7 @@ bool BMFile_Create(
bool BMFile_Save(
BMPARAM_IN(BMap::BMFile*, map_file),
BMPARAM_IN(LibCmo::CKSTRING, file_name),
BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, texture_save_opt),
BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, texture_save_opt),
BMPARAM_IN(bool, use_compress),
BMPARAM_IN(LibCmo::CKINT, compreess_level)) {
if (!CheckBMFile(map_file)) return false;
@ -228,6 +237,21 @@ bool BMFile_CreateTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK
BMPARAM_OUT_ASSIGN(out_id, bmfile->CreateTexture());
return true;
}
bool BMFile_GetTargetLightCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count)) {
if (!CheckBMFile(bmfile)) return false;
BMPARAM_OUT_ASSIGN(out_count, bmfile->GetTargetLightCount());
return true;
}
bool BMFile_GetTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id)) {
if (!CheckBMFile(bmfile)) return false;
BMPARAM_OUT_ASSIGN(out_id, bmfile->GetTargetLight(idx));
return true;
}
bool BMFile_CreateTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id)) {
if (!CheckBMFile(bmfile)) return false;
BMPARAM_OUT_ASSIGN(out_id, bmfile->CreateTargetLight());
return true;
}
#pragma endregion
@ -721,14 +745,14 @@ bool BMMaterial_SetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::
#pragma region CKMesh
LIBCMO_EXPORT bool BMMesh_GetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXMESH_LITMODE, out_mode)) {
bool BMMesh_GetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXMESH_LITMODE, out_mode)) {
auto obj = CheckCKMesh(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_mode, obj->GetLitMode());
return true;
}
LIBCMO_EXPORT bool BMMesh_SetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXMESH_LITMODE, mode)) {
bool BMMesh_SetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXMESH_LITMODE, mode)) {
auto obj = CheckCKMesh(bmfile, objid);
if (obj == nullptr) return false;
@ -835,34 +859,34 @@ bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCm
#pragma endregion
#pragma region CK3dObject
#pragma region CK3dEntity
bool BM3dObject_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat)) {
auto obj = CheckCK3dEntity(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_mat, obj->GetWorldMatrix());
return true;
}
bool BM3dObject_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat)) {
auto obj = CheckCK3dEntity(bmfile, objid);
if (obj == nullptr) return false;
obj->SetWorldMatrix(mat);
return true;
}
bool BM3dObject_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid)) {
auto obj = CheckCK3dEntity(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_meshid, SafeGetID(obj->GetCurrentMesh()));
return true;
}
bool BM3dObject_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid)) {
auto obj = CheckCK3dEntity(bmfile, objid);
auto meshobj = CheckCKMesh(bmfile, meshid);
if (obj == nullptr /*|| meshobj == nullptr*/) return false; //allow nullptr assign
@ -870,16 +894,16 @@ bool BM3dObject_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(Li
return true;
}
bool BM3dObject_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible)) {
auto obj = CheckCK3dEntity(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_isVisible, obj->IsVisible());
return true;
}
bool BM3dObject_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible)) {
auto obj = CheckCK3dObject(bmfile, objid);
bool BM3dEntity_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible)) {
auto obj = CheckCK3dEntity(bmfile, objid);
if (obj == nullptr) return false;
obj->Show(is_visible ? LibCmo::CK2::CK_OBJECT_SHOWOPTION::CKSHOW : LibCmo::CK2::CK_OBJECT_SHOWOPTION::CKHIDE);
@ -888,3 +912,131 @@ bool BM3dObject_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(boo
#pragma endregion
#pragma region CK3dObject
//nothing
#pragma endregion
#pragma region CKLight
bool BMLight_GetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXLIGHT_TYPE, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetType());
return true;
}
bool BMLight_SetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXLIGHT_TYPE, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetType(val);
return true;
}
bool BMLight_GetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetColor());
return true;
}
bool BMLight_SetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetColor(col);
return true;
}
bool BMLight_GetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetConstantAttenuation());
return true;
}
bool BMLight_SetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetConstantAttenuation(val);
return true;
}
bool BMLight_GetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetLinearAttenuation());
return true;
}
bool BMLight_SetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetLinearAttenuation(val);
return true;
}
bool BMLight_GetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetQuadraticAttenuation());
return true;
}
bool BMLight_SetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetQuadraticAttenuation(val);
return true;
}
bool BMLight_GetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetRange());
return true;
}
bool BMLight_SetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetRange(val);
return true;
}
bool BMLight_GetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetHotSpot());
return true;
}
bool BMLight_SetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetHotSpot(val);
return true;
}
bool BMLight_GetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetFalloff());
return true;
}
bool BMLight_SetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetFalloff(val);
return true;
}
bool BMLight_GetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
BMPARAM_OUT_ASSIGN(out_val, obj->GetFalloffShape());
return true;
}
bool BMLight_SetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val)) {
auto obj = CheckCKLight(bmfile, objid);
if (obj == nullptr) return false;
obj->SetFalloffShape(val);
return true;
}
#pragma endregion
#pragma region CKTargetLight
// nothing
#pragma endregion

View File

@ -11,7 +11,7 @@
All exported interface functions will always return a bool to indicate whether current operations is successful.
The layout of interface functions' parameters is Essential Param -> Input Param -> Out Param.
A example is in there: `LIBCMO_EXPORT bool BMSomeFunc(BMPARAM_OBJECT_DECL, BMPARAM_IN(LibCmo::CK2::CK_ID, someobj), BMPARAM_OUT(LibCmo::CKSTRING, out_name));`
A example is in there: `BMAP_EXPORT bool BMSomeFunc(BMPARAM_OBJECT_DECL, BMPARAM_IN(LibCmo::CK2::CK_ID, someobj), BMPARAM_OUT(LibCmo::CKSTRING, out_name));`
First param is `BMPARAM_OBJECT_DECL`. It is essential param for this function. In this exmaple, it is the combination of BMFile* and CK_ID. If your provide invalid value for them, the function will failed immediately.
Second param is `BMPARAM_IN(LibCmo::CK2::CK_ID, someobj)`. It declare this function accept a Object ID for underlying function calling.
Last param is `BMPARAM_OUT(LibCmo::CKSTRING, out_name)`. It is the return value of this function. Only will be filled when this function success.
@ -31,7 +31,46 @@ Each CK_ID also should be used with its corresponding BMFile*, because each BMfi
*/
// ===== Interface Used Macro =====
#pragma region Macros for Exporting Functions
// Reference: https://stackoverflow.com/questions/2164827/explicitly-exporting-shared-library-functions-in-linux
// Generate macro for import and export respectively.
#if defined(_MSC_VER)
// Microsoft
#define BMAP_RAW_EXPORT __declspec(dllexport)
#define BMAP_RAW_IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
// GCC
#define BMAP_RAW_EXPORT __attribute__((visibility("default")))
#define BMAP_RAW_IMPORT
#elif defined(__clang__)
// Clang
#define BMAP_RAW_EXPORT __attribute__((visibility("default")))
#define BMAP_RAW_IMPORT
#else
// Do nothing and hope for the best?
#define BMAP_RAW_EXPORT
#define BMAP_RAW_IMPORT
#error "Unknown dynamic link import/export semantics."
#endif
// Choosee import or export command according to special macro.
#if defined(BMAP_EXPORTING)
#define BMAP_NAKED_EXPORT BMAP_RAW_EXPORT
#else
#define BMAP_NAKED_EXPORT BMAP_RAW_IMPORT
#endif
// Create real export macro according to whether in C++ environment.
#if defined(__cplusplus)
#define BMAP_EXPORT extern "C" BMAP_NAKED_EXPORT
#else
#define BMAP_EXPORT BMAP_NAKED_EXPORT
#endif
#pragma endregion
#pragma region Interface Used Macros
/** The first param used by BMFile function family */
#define BMPARAM_FILE_DECL(_bmfile) BMap::BMFile* _bmfile
@ -42,7 +81,9 @@ Each CK_ID also should be used with its corresponding BMFile*, because each BMfi
/** Declare an input parameter */
#define BMPARAM_IN(_t, _name) _t _name
/**
@brief
Declare an output parameter.
@details
A pointer will be added automatically for caller receive it.
See BMPARAM_OUT_ASSIGN and BMPARAM_OUT_VAL to know how to use output param in function body.
@remark
@ -52,8 +93,8 @@ bool some_interface_func(BMPARAM_OUT(Type_t, param_name)) {
BMPARAM_OUT_ASSIGN(param_name, some_value); // assign to out param.
return BMPARAM_OUT_VAL(param_name) != other_value; // use out param value.
}
@see BMPARAM_OUT_ASSIGN, BMPARAM_OUT_VAL
```
@see BMPARAM_OUT_ASSIGN, BMPARAM_OUT_VAL
*/
#define BMPARAM_OUT(_t, _name) _t* _name
/** Assign value for out param in function body. */
@ -61,16 +102,18 @@ bool some_interface_func(BMPARAM_OUT(Type_t, param_name)) {
/** Visit value for out param in function body. */
#define BMPARAM_OUT_VAL(_name) (*(_name))
#pragma endregion
#pragma region Init / Dispose
LIBCMO_EXPORT bool BMInit();
LIBCMO_EXPORT bool BMDispose();
BMAP_EXPORT bool BMInit();
BMAP_EXPORT bool BMDispose();
#pragma endregion
#pragma region BMFile
LIBCMO_EXPORT bool BMFile_Load(
BMAP_EXPORT bool BMFile_Load(
BMPARAM_IN(LibCmo::CKSTRING, file_name),
BMPARAM_IN(LibCmo::CKSTRING, temp_folder),
BMPARAM_IN(LibCmo::CKSTRING, texture_folder),
@ -79,7 +122,7 @@ LIBCMO_EXPORT bool BMFile_Load(
BMPARAM_IN(LibCmo::CKSTRING*, encodings),
BMPARAM_OUT(BMap::BMFile*, out_file)
);
LIBCMO_EXPORT bool BMFile_Create(
BMAP_EXPORT bool BMFile_Create(
BMPARAM_IN(LibCmo::CKSTRING, temp_folder),
BMPARAM_IN(LibCmo::CKSTRING, texture_folder),
BMPARAM_IN(BMap::NakedOutputCallback, raw_callback),
@ -87,170 +130,212 @@ LIBCMO_EXPORT bool BMFile_Create(
BMPARAM_IN(LibCmo::CKSTRING*, encodings),
BMPARAM_OUT(BMap::BMFile*, out_file)
);
LIBCMO_EXPORT bool BMFile_Save(
BMAP_EXPORT bool BMFile_Save(
BMPARAM_IN(BMap::BMFile*, map_file),
BMPARAM_IN(LibCmo::CKSTRING, file_name),
BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, texture_save_opt),
BMPARAM_IN(bool, use_compress),
BMPARAM_IN(LibCmo::CKINT, compreess_level)
);
LIBCMO_EXPORT bool BMFile_Free(
BMAP_EXPORT bool BMFile_Free(
BMPARAM_IN(BMap::BMFile*, map_file)
);
LIBCMO_EXPORT bool BMFile_GetGroupCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMFile_GetGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_CreateGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_Get3dObjectCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMFile_Get3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_Create3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_GetMeshCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMFile_GetMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_CreateMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_GetMaterialCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMFile_GetMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_CreateMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_GetTextureCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMFile_GetTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
LIBCMO_EXPORT bool BMFile_CreateTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetGroupCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_Get3dObjectCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_Get3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_Create3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetMeshCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetMaterialCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetTextureCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetTargetLightCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
#pragma endregion
#pragma region BMMeshTransition
LIBCMO_EXPORT bool BMMeshTrans_New(BMPARAM_OUT(BMap::BMMeshTransition*, out_trans));
LIBCMO_EXPORT bool BMMeshTrans_Delete(BMPARAM_IN(BMap::BMMeshTransition*, trans));
BMAP_EXPORT bool BMMeshTrans_New(BMPARAM_OUT(BMap::BMMeshTransition*, out_trans));
BMAP_EXPORT bool BMMeshTrans_Delete(BMPARAM_IN(BMap::BMMeshTransition*, trans));
LIBCMO_EXPORT bool BMMeshTrans_PrepareVertexCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMeshTrans_PrepareVertex(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareNormalCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMeshTrans_PrepareNormal(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareUVCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMeshTrans_PrepareUV(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareMtlSlotCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMeshTrans_PrepareMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CK2::CK_ID*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareFaceCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMeshTrans_PrepareFaceVertexIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareFaceNormalIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareFaceUVIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_PrepareFaceMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
LIBCMO_EXPORT bool BMMeshTrans_Parse(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(BMap::BMFile*, bmfile), BMPARAM_IN(LibCmo::CK2::CK_ID, objid));
BMAP_EXPORT bool BMMeshTrans_PrepareVertexCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareVertex(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareNormalCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareNormal(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareUVCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareUV(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareMtlSlotCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CK2::CK_ID*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceVertexIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceNormalIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceUVIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_Parse(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(BMap::BMFile*, bmfile), BMPARAM_IN(LibCmo::CK2::CK_ID, objid));
#pragma endregion
#pragma region CKObject
LIBCMO_EXPORT bool BMObject_GetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_name));
LIBCMO_EXPORT bool BMObject_SetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, name));
BMAP_EXPORT bool BMObject_GetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_name));
BMAP_EXPORT bool BMObject_SetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, name));
#pragma endregion
#pragma region CKGroup
LIBCMO_EXPORT bool BMGroup_AddObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, memberid));
LIBCMO_EXPORT bool BMGroup_GetObjectCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMGroup_GetObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, pos), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_objid));
BMAP_EXPORT bool BMGroup_AddObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, memberid));
BMAP_EXPORT bool BMGroup_GetObjectCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMGroup_GetObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, pos), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_objid));
#pragma endregion
#pragma region CKTexture
LIBCMO_EXPORT bool BMTexture_GetFileName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_filename));
LIBCMO_EXPORT bool BMTexture_LoadImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
LIBCMO_EXPORT bool BMTexture_SaveImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
LIBCMO_EXPORT bool BMTexture_GetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, out_saveopt));
LIBCMO_EXPORT bool BMTexture_SetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, saveopt));
LIBCMO_EXPORT bool BMTexture_GetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VX_PIXELFORMAT, out_vfmt));
LIBCMO_EXPORT bool BMTexture_SetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VX_PIXELFORMAT, vfmt));
BMAP_EXPORT bool BMTexture_GetFileName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_filename));
BMAP_EXPORT bool BMTexture_LoadImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
BMAP_EXPORT bool BMTexture_SaveImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
BMAP_EXPORT bool BMTexture_GetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, out_saveopt));
BMAP_EXPORT bool BMTexture_SetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, saveopt));
BMAP_EXPORT bool BMTexture_GetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VX_PIXELFORMAT, out_vfmt));
BMAP_EXPORT bool BMTexture_SetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VX_PIXELFORMAT, vfmt));
#pragma endregion
#pragma region CKMaterial
LIBCMO_EXPORT bool BMMaterial_GetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
LIBCMO_EXPORT bool BMMaterial_SetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
LIBCMO_EXPORT bool BMMaterial_GetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
LIBCMO_EXPORT bool BMMaterial_SetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
LIBCMO_EXPORT bool BMMaterial_GetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
LIBCMO_EXPORT bool BMMaterial_SetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
LIBCMO_EXPORT bool BMMaterial_GetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
LIBCMO_EXPORT bool BMMaterial_SetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
LIBCMO_EXPORT bool BMMaterial_GetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
LIBCMO_EXPORT bool BMMaterial_SetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMMaterial_GetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMMaterial_SetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
LIBCMO_EXPORT bool BMMaterial_GetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_texid));
LIBCMO_EXPORT bool BMMaterial_SetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, texid));
LIBCMO_EXPORT bool BMMaterial_GetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, val));
BMAP_EXPORT bool BMMaterial_GetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_texid));
BMAP_EXPORT bool BMMaterial_SetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, texid));
BMAP_EXPORT bool BMMaterial_GetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, val));
LIBCMO_EXPORT bool BMMaterial_GetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_BLENDMODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_BLENDMODE, val));
LIBCMO_EXPORT bool BMMaterial_GetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
LIBCMO_EXPORT bool BMMaterial_GetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
LIBCMO_EXPORT bool BMMaterial_GetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_BLENDMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_BLENDMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, val));
LIBCMO_EXPORT bool BMMaterial_GetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
LIBCMO_EXPORT bool BMMaterial_GetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
LIBCMO_EXPORT bool BMMaterial_GetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXFILL_MODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXFILL_MODE, val));
LIBCMO_EXPORT bool BMMaterial_GetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXSHADE_MODE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXSHADE_MODE, val));
BMAP_EXPORT bool BMMaterial_GetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
BMAP_EXPORT bool BMMaterial_GetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
BMAP_EXPORT bool BMMaterial_GetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXFILL_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXFILL_MODE, val));
BMAP_EXPORT bool BMMaterial_GetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXSHADE_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXSHADE_MODE, val));
LIBCMO_EXPORT bool BMMaterial_GetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
LIBCMO_EXPORT bool BMMaterial_SetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
LIBCMO_EXPORT bool BMMaterial_GetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
LIBCMO_EXPORT bool BMMaterial_SetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
LIBCMO_EXPORT bool BMMaterial_GetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
LIBCMO_EXPORT bool BMMaterial_SetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
LIBCMO_EXPORT bool BMMaterial_GetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
LIBCMO_EXPORT bool BMMaterial_SetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
LIBCMO_EXPORT bool BMMaterial_GetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
LIBCMO_EXPORT bool BMMaterial_SetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
LIBCMO_EXPORT bool BMMaterial_GetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKBYTE, out_val));
LIBCMO_EXPORT bool BMMaterial_SetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKBYTE, val));
LIBCMO_EXPORT bool BMMaterial_GetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
LIBCMO_EXPORT bool BMMaterial_SetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
LIBCMO_EXPORT bool BMMaterial_GetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
LIBCMO_EXPORT bool BMMaterial_SetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
BMAP_EXPORT bool BMMaterial_GetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKBYTE, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKBYTE, val));
BMAP_EXPORT bool BMMaterial_GetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
BMAP_EXPORT bool BMMaterial_GetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
BMAP_EXPORT bool BMMaterial_SetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
#pragma endregion
#pragma region CKMesh
LIBCMO_EXPORT bool BMMesh_GetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXMESH_LITMODE, out_mode));
LIBCMO_EXPORT bool BMMesh_SetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXMESH_LITMODE, mode));
BMAP_EXPORT bool BMMesh_GetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXMESH_LITMODE, out_mode));
BMAP_EXPORT bool BMMesh_SetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXMESH_LITMODE, mode));
LIBCMO_EXPORT bool BMMesh_GetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMMesh_SetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMesh_GetVertexPositions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
LIBCMO_EXPORT bool BMMesh_GetVertexNormals(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
LIBCMO_EXPORT bool BMMesh_GetVertexUVs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
BMAP_EXPORT bool BMMesh_GetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetVertexPositions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMesh_GetVertexNormals(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMesh_GetVertexUVs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
LIBCMO_EXPORT bool BMMesh_GetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMMesh_SetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMesh_GetFaceIndices(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
LIBCMO_EXPORT bool BMMesh_GetFaceMaterialSlotIndexs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
BMAP_EXPORT bool BMMesh_GetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetFaceIndices(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
BMAP_EXPORT bool BMMesh_GetFaceMaterialSlotIndexs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
LIBCMO_EXPORT bool BMMesh_GetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
LIBCMO_EXPORT bool BMMesh_SetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
LIBCMO_EXPORT bool BMMesh_GetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_mtlid));
LIBCMO_EXPORT bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_IN(LibCmo::CK2::CK_ID, mtlid));
BMAP_EXPORT bool BMMesh_GetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_mtlid));
BMAP_EXPORT bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_IN(LibCmo::CK2::CK_ID, mtlid));
#pragma endregion
#pragma region CK3dEntity
BMAP_EXPORT bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat));
BMAP_EXPORT bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat));
BMAP_EXPORT bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid));
BMAP_EXPORT bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid));
BMAP_EXPORT bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible));
BMAP_EXPORT bool BM3dEntity_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible));
#pragma endregion
#pragma region CK3dObject
LIBCMO_EXPORT bool BM3dObject_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat));
LIBCMO_EXPORT bool BM3dObject_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat));
LIBCMO_EXPORT bool BM3dObject_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid));
LIBCMO_EXPORT bool BM3dObject_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid));
LIBCMO_EXPORT bool BM3dObject_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible));
LIBCMO_EXPORT bool BM3dObject_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible));
// nothing
#pragma endregion
#pragma region CKLight
BMAP_EXPORT bool BMLight_GetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXLIGHT_TYPE, out_val));
BMAP_EXPORT bool BMLight_SetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXLIGHT_TYPE, val));
BMAP_EXPORT bool BMLight_GetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMLight_SetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMLight_GetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
#pragma endregion
#pragma region CKTargetLight
// nothing
#pragma endregion

View File

@ -2,6 +2,247 @@
namespace BMap {
#pragma region BMfile
BMFile::BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_loader) :
m_IsInitError(false), m_IsLoader(is_loader), m_HasLoaded(false), m_HasSaved(false), m_Context(nullptr) {
m_Context = new LibCmo::CK2::CKContext();
// binding callback with lambda wrapper.
// check whether callback is nullptr.
m_IsInitError = m_IsInitError || (raw_callback == nullptr);
if (raw_callback != nullptr) {
m_Context->SetOutputCallback([raw_callback](LibCmo::CKSTRING strl) -> void {
raw_callback(strl);
});
}
// set temp folder and texture folder
auto pm = m_Context->GetPathManager();
m_IsInitError = m_IsInitError || !pm->AddPath(texture_folder);
m_IsInitError = m_IsInitError || !pm->SetTempFolder(temp_folder);
// set encoding
LibCmo::XContainer::XArray<LibCmo::XContainer::XString> cache;
for (LibCmo::CKDWORD i = 0; i < encoding_count; ++i) {
if (encodings[i] != nullptr)
cache.emplace_back(encodings[i]);
}
m_Context->SetEncoding(cache);
m_IsInitError = m_IsInitError || !m_Context->IsValidEncoding();
// set default texture save mode is external
m_Context->SetGlobalImagesSaveOptions(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL);
// set default file write mode is whole compressed
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
}
BMFile::~BMFile() {
delete m_Context;
}
#pragma region Safe Check Function
bool BMFile::IsInitError() {
return m_IsInitError;
}
bool BMFile::CanExecLoad() {
// no error, is loader, no prev load
return (!m_IsInitError && m_IsLoader && !m_HasLoaded);
}
bool BMFile::CanExecSave() {
// no error, is saver, no prev save
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
bool BMFile::CanExecLoaderVisitor() {
// no error, is loader, has loaded
return (!m_IsInitError && m_IsLoader && m_HasLoaded);
}
bool BMFile::CanExecSaverVisitor() {
// no error, is saver, not saveed yet
// same as CanExecSave
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
#pragma endregion
#pragma region Help Function
bool BMFile::Load(LibCmo::CKSTRING filename) {
if (!CanExecLoad()) return false;
// create temp ckfile and load
LibCmo::CK2::CKFileReader reader(m_Context);
LibCmo::CK2::CKERROR err = reader.DeepLoad(filename);
// detect error
if (err != LibCmo::CK2::CKERROR::CKERR_OK) {
// failed. clear document and return false
m_Context->ClearAll();
return false;
}
// sync data list to our list
m_ObjGroups.clear();
m_Obj3dObjects.clear();
m_ObjMeshes.clear();
m_ObjMaterials.clear();
m_ObjTextures.clear();
m_ObjTargetLights.clear();
for (const auto& fileobj : reader.GetFileObjects()) {
if (fileobj.ObjPtr == nullptr) continue;
switch (fileobj.ObjectCid) {
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
m_ObjGroups.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
m_Obj3dObjects.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
m_ObjMeshes.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
m_ObjMaterials.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
m_ObjTextures.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT:
m_ObjTargetLights.emplace_back(fileobj.CreatedObjectId);
break;
default:
break; // skip unknow objects
}
}
m_HasLoaded = true;
return true;
}
bool BMFile::Save(LibCmo::CKSTRING filename, LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, LibCmo::CKINT compress_level) {
if (!CanExecSave()) return false;
// create temp writer
LibCmo::CK2::CKFileWriter writer(m_Context);
// fill object data
for (const auto& id : m_ObjGroups) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_Obj3dObjects) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMeshes) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMaterials) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjTextures) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id :m_ObjTargetLights) {
writer.AddSavedObject(m_Context->GetObject(id));
}
// set global texture save mode
m_Context->SetGlobalImagesSaveOptions(texture_save_opt);
// set compress level
if (use_compress) {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
m_Context->SetCompressionLevel(compress_level);
} else {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED);
}
// save to file and detect error
LibCmo::CK2::CKERROR err = writer.Save(filename);
// return with error detect.
m_HasSaved = true;
return err == LibCmo::CK2::CKERROR::CKERR_OK;
}
LibCmo::CK2::ObjImpls::CKObject* BMFile::GetObjectPtr(LibCmo::CK2::CK_ID objid) {
// we fetch object from CKContext to get better performance
LibCmo::CK2::ObjImpls::CKObject* obj = m_Context->GetObject(objid);
// however, we can not directly return the pointer fetched fron CKContext.
// BMFile only provide limited type visiting, we must make sure it provided ID also is existed in out stored list.
// so we check its type here. if type is not matched, we reset it to nullptr.
if (obj != nullptr) {
switch (obj->GetClassID()) {
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
case LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT:
break; // okey. do nothing
default:
// this object should not be exposed to outside, reset it to nullptr
obj = nullptr;
break;
}
}
// return result
return obj;
}
#pragma endregion
#pragma region Visitor
LibCmo::CKDWORD BMFile::CommonGetObjectCount(std::vector<LibCmo::CK2::CK_ID>& container) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return static_cast<LibCmo::CKDWORD>(container.size());
}
LibCmo::CK2::CK_ID BMFile::CommonGetObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CKDWORD idx) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return container[idx];
}
LibCmo::CK2::CK_ID BMFile::CommonCreateObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CK2::CK_CLASSID cid) {
// only available in saver
if (!CanExecSaverVisitor()) return 0;
// try create object and get its pointer
LibCmo::CK2::ObjImpls::CKObject* obj = m_Context->CreateObject(cid, nullptr);
// check creation validation
if (obj == nullptr) return 0;
// if success, write its id and emplace its id into list
LibCmo::CK2::CK_ID objid = obj->GetID();
container.emplace_back(objid);
return objid;
}
LibCmo::CKDWORD BMFile::GetGroupCount() { return CommonGetObjectCount(m_ObjGroups); }
LibCmo::CK2::CK_ID BMFile::GetGroup(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjGroups, idx); }
LibCmo::CK2::CK_ID BMFile::CreateGroup() { return CommonCreateObject(m_ObjGroups, LibCmo::CK2::CK_CLASSID::CKCID_GROUP); }
LibCmo::CKDWORD BMFile::Get3dObjectCount() { return CommonGetObjectCount(m_Obj3dObjects); }
LibCmo::CK2::CK_ID BMFile::Get3dObject(LibCmo::CKDWORD idx) { return CommonGetObject(m_Obj3dObjects, idx); }
LibCmo::CK2::CK_ID BMFile::Create3dObject() { return CommonCreateObject(m_Obj3dObjects, LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT); }
LibCmo::CKDWORD BMFile::GetMeshCount() { return CommonGetObjectCount(m_ObjMeshes); }
LibCmo::CK2::CK_ID BMFile::GetMesh(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMeshes, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMesh() { return CommonCreateObject(m_ObjMeshes, LibCmo::CK2::CK_CLASSID::CKCID_MESH); }
LibCmo::CKDWORD BMFile::GetMaterialCount() { return CommonGetObjectCount(m_ObjMaterials); }
LibCmo::CK2::CK_ID BMFile::GetMaterial(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMaterials, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMaterial() { return CommonCreateObject(m_ObjMaterials, LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL); }
LibCmo::CKDWORD BMFile::GetTextureCount() { return CommonGetObjectCount(m_ObjTextures); }
LibCmo::CK2::CK_ID BMFile::GetTexture(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTextures, idx); }
LibCmo::CK2::CK_ID BMFile::CreateTexture() { return CommonCreateObject(m_ObjTextures, LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE); }
LibCmo::CKDWORD BMFile::GetTargetLightCount() { return CommonGetObjectCount(m_ObjTargetLights); }
LibCmo::CK2::CK_ID BMFile::GetTargetLight(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTargetLights, idx); }
LibCmo::CK2::CK_ID BMFile::CreateTargetLight() { return CommonCreateObject(m_ObjTargetLights, LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT); }
#pragma endregion
#pragma endregion
#pragma region BMMeshTransition
BMMeshTransition::TransitionVertex::TransitionVertex(
@ -229,146 +470,4 @@ namespace BMap {
#pragma endregion
#pragma region BMfile
BMFile::BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_loader) :
m_IsInitError(false), m_IsLoader(is_loader), m_HasLoaded(false), m_HasSaved(false), m_Context(nullptr) {
m_Context = new LibCmo::CK2::CKContext();
// binding callback with lambda wrapper.
// check whether callback is nullptr.
m_IsInitError = m_IsInitError || (raw_callback == nullptr);
if (raw_callback != nullptr) {
m_Context->SetOutputCallback([raw_callback](LibCmo::CKSTRING strl) -> void {
raw_callback(strl);
});
}
// set temp folder and texture folder
auto pm = m_Context->GetPathManager();
m_IsInitError = m_IsInitError || !pm->AddPath(texture_folder);
m_IsInitError = m_IsInitError || !pm->SetTempFolder(temp_folder);
// set encoding
LibCmo::XContainer::XArray<LibCmo::XContainer::XString> cache;
for (LibCmo::CKDWORD i = 0; i < encoding_count; ++i) {
if (encodings[i] != nullptr)
cache.emplace_back(encodings[i]);
}
m_Context->SetEncoding(cache);
// set default texture save mode is external
m_Context->SetGlobalImagesSaveOptions(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL);
// set default file write mode is whole compressed
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
}
BMFile::~BMFile() {
delete m_Context;
}
bool BMFile::Load(LibCmo::CKSTRING filename) {
if (!CanExecLoad()) return false;
// create temp ckfile and load
LibCmo::CK2::CKFileReader reader(m_Context);
LibCmo::CK2::CKERROR err = reader.DeepLoad(filename);
// detect error
if (err != LibCmo::CK2::CKERROR::CKERR_OK) {
// failed. clear document and return false
m_Context->ClearAll();
return false;
}
// sync data list to our list
m_ObjGroups.clear();
m_Obj3dObjects.clear();
m_ObjMeshs.clear();
m_ObjMaterials.clear();
m_ObjTextures.clear();
for (const auto& fileobj : reader.GetFileObjects()) {
if (fileobj.ObjPtr == nullptr) continue;
switch (fileobj.ObjectCid) {
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
m_ObjGroups.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
m_Obj3dObjects.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
m_ObjMeshs.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
m_ObjMaterials.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
m_ObjTextures.emplace_back(fileobj.CreatedObjectId);
break;
}
}
m_HasLoaded = true;
return true;
}
bool BMFile::Save(LibCmo::CKSTRING filename, LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, LibCmo::CKINT compress_level) {
if (!CanExecSave()) return false;
// create temp writer
LibCmo::CK2::CKFileWriter writer(m_Context);
// fill object data
for (const auto& id : m_ObjGroups) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_Obj3dObjects) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMeshs) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMaterials) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjTextures) {
writer.AddSavedObject(m_Context->GetObject(id));
}
// set global texture save mode
m_Context->SetGlobalImagesSaveOptions(texture_save_opt);
// set compress level
if (use_compress) {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
m_Context->SetCompressionLevel(compress_level);
} else {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED);
}
// save to file and detect error
LibCmo::CK2::CKERROR err = writer.Save(filename);
// return with error detect.
m_HasSaved = true;
return err == LibCmo::CK2::CKERROR::CKERR_OK;
}
LibCmo::CKDWORD BMFile::GetGroupCount() { return CommonGetObjectCount(m_ObjGroups); }
LibCmo::CK2::CK_ID BMFile::GetGroup(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjGroups, idx); }
LibCmo::CK2::CK_ID BMFile::CreateGroup() { return CommonCreateObject(m_ObjGroups, LibCmo::CK2::CK_CLASSID::CKCID_GROUP); }
LibCmo::CKDWORD BMFile::Get3dObjectCount() { return CommonGetObjectCount(m_Obj3dObjects); }
LibCmo::CK2::CK_ID BMFile::Get3dObject(LibCmo::CKDWORD idx) { return CommonGetObject(m_Obj3dObjects, idx); }
LibCmo::CK2::CK_ID BMFile::Create3dObject() { return CommonCreateObject(m_Obj3dObjects, LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT); }
LibCmo::CKDWORD BMFile::GetMeshCount() { return CommonGetObjectCount(m_ObjMeshs); }
LibCmo::CK2::CK_ID BMFile::GetMesh(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMeshs, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMesh() { return CommonCreateObject(m_ObjMeshs, LibCmo::CK2::CK_CLASSID::CKCID_MESH); }
LibCmo::CKDWORD BMFile::GetMaterialCount() { return CommonGetObjectCount(m_ObjMaterials); }
LibCmo::CK2::CK_ID BMFile::GetMaterial(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMaterials, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMaterial() { return CommonCreateObject(m_ObjMaterials, LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL); }
LibCmo::CKDWORD BMFile::GetTextureCount() { return CommonGetObjectCount(m_ObjTextures); }
LibCmo::CK2::CK_ID BMFile::GetTexture(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTextures, idx); }
LibCmo::CK2::CK_ID BMFile::CreateTexture() { return CommonCreateObject(m_ObjTextures, LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE); }
#pragma endregion
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <VTUserAll.hpp>
#include <VTAll.hpp>
#include <vector>
#include <cstdint>
#include <cinttypes>
@ -14,95 +14,97 @@ namespace BMap {
public:
BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_reader);
~BMFile();
LIBCMO_DISABLE_COPY_MOVE(BMFile);
YYCC_DEL_CLS_COPY_MOVE(BMFile);
// ===== safe visit functions =====
// ===== Safe Check Function =====
/**
Safe Visit Function will make sure this class is visited with safe mode.
These function will block all other functions if this class init failed.
Or, block any more operations if this class has loaded or saved once. In this time you only can free this class
/*
Safe Check Function will make sure this class is visited in safe mode.
Some of them are exposed to outside to report current status of this class, for example, whether there is a issue when initialize this class.
And some of them are used by internal functions to make sure there is a safe environment to execute corresponding functions.
For example, #Load function will use #CanExecLoad to detect whether it can execute loading process.
*/
public:
bool IsInitError() {
return m_IsInitError;
}
private:
bool CanExecLoad() {
// no error, is loader, no prev load
return (!m_IsInitError && m_IsLoader && !m_HasLoaded);
}
bool CanExecSave() {
// no error, is saver, no prev save
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
bool CanExecLoaderVisitor() {
// no error, is loader, has loaded
return (!m_IsInitError && m_IsLoader && m_HasLoaded);
}
bool CanExecSaverVisitor() {
// no error, is saver, not saveed yet
// same as CanExecSave
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
/**
* @brief Check whether there is an error when initializing this class.
* @details
* This class is exposed for outside code to check.
* Internal code should use one of following 4 private check functions to check environment.
* @return True if there is an error when initializing this class.
*/
bool IsInitError();
private:
/**
* @brief True if an error occurs when initializing this class.
* @brief Check whether it's okey to execute #Load function.
* @return True if it is okey.
*/
bool m_IsInitError;
bool CanExecLoad();
/**
* @brief True if this class is a reader.
* @brief Check whether it's okey to execute #Save function.
* @return True if it is okey.
*/
bool m_IsLoader;
bool CanExecSave();
/**
* @brief True if this class has read. Only valid when this class is reader.
* @brief Check whether it's okey to execute Loader-related function.
* @details
* Due to implementation, saving file and loading file are use the same class, BMFile to represent.
* So obviously you can visit loader-related function in a saver.
* This operation is illegal. So we need block these operation.
* This is what this function does. Provide the condition which raise blocking.
* @return True if it is okey.
*/
bool m_HasLoaded;
bool CanExecLoaderVisitor();
/**
* @brief True if this class has written. Only valid when this class is writer.
* @brief Check whether it's okey to execute Saver-related function.
* @return True if it is okey.
* @see CanExecLoaderVisitor
*/
bool m_HasSaved;
bool CanExecSaverVisitor();
// ===== help functions =====
private:
bool m_IsInitError; /**< True if an error occurs when initializing this class. */
bool m_IsLoader; /**< True if this class is a reader. */
bool m_HasLoaded; /**< True if this class has read. It's undefined behavior when visiting this variable if this class is not reader. */
bool m_HasSaved; /**< True if this class has written. It's undefined behavior when visiting this variable if this class is not writer. */
// ===== Help Function =====
public:
/**
* @brief Load document to this class.
* @param[in] filename The path to file.
* @return True if no error, otherwise false.
*/
bool Load(LibCmo::CKSTRING filename);
/**
* @brief Save current class into document.
* @param[in] filename The path to file.
* @param[in] texture_save_opt Global texture save option
* @param[in] use_compress True if use compression when saving.
* @param[in] compress_level The compress level if you choose using compression in file.
* @return
*/
bool Save(LibCmo::CKSTRING filename, LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, LibCmo::CKINT compress_level);
LibCmo::CK2::ObjImpls::CKObject* GetObjectPtr(LibCmo::CK2::CK_ID objid) {
return m_Context->GetObject(objid);;
}
/**
* @brief Get object pointer from given ID.
* @details
* This function is specially exposed to outside for detecting whether given ID is valid in BMFile.
* Also used by BMMeshTransition to get essential objects.
* @param[in] objid The ID of object.
* @return The pointer to given ID represented object. nullptr if not found.
*/
LibCmo::CK2::ObjImpls::CKObject* GetObjectPtr(LibCmo::CK2::CK_ID objid);
// ===== visitors =====
// ===== Visitor =====
private:
LibCmo::CKDWORD CommonGetObjectCount(std::vector<LibCmo::CK2::CK_ID>& container) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return static_cast<LibCmo::CKDWORD>(container.size());
}
LibCmo::CK2::CK_ID CommonGetObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CKDWORD idx) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return container[idx];
}
LibCmo::CK2::CK_ID CommonCreateObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CK2::CK_CLASSID cid) {
// only available in saver
if (!CanExecSaverVisitor()) return 0;
LibCmo::CKDWORD CommonGetObjectCount(std::vector<LibCmo::CK2::CK_ID>& container);
LibCmo::CK2::CK_ID CommonGetObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CommonCreateObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CK2::CK_CLASSID cid);
// try create object and get its pointer
LibCmo::CK2::ObjImpls::CKObject* obj = m_Context->CreateObject(cid, nullptr);
// check creation validation
if (obj == nullptr) return 0;
// if success, write its id and emplace its id into list
LibCmo::CK2::CK_ID objid = obj->GetID();
container.emplace_back(objid);
return objid;
}
public:
LibCmo::CKDWORD GetGroupCount();
LibCmo::CK2::CK_ID GetGroup(LibCmo::CKDWORD idx);
@ -119,15 +121,19 @@ namespace BMap {
LibCmo::CKDWORD GetTextureCount();
LibCmo::CK2::CK_ID GetTexture(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateTexture();
LibCmo::CKDWORD GetTargetLightCount();
LibCmo::CK2::CK_ID GetTargetLight(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateTargetLight();
private:
LibCmo::CK2::CKContext* m_Context;
std::vector<LibCmo::CK2::CK_ID> m_ObjGroups;
std::vector<LibCmo::CK2::CK_ID> m_Obj3dObjects;
std::vector<LibCmo::CK2::CK_ID> m_ObjMeshs;
std::vector<LibCmo::CK2::CK_ID> m_ObjMeshes;
std::vector<LibCmo::CK2::CK_ID> m_ObjMaterials;
std::vector<LibCmo::CK2::CK_ID> m_ObjTextures;
std::vector<LibCmo::CK2::CK_ID> m_ObjTargetLights;
};
@ -154,7 +160,7 @@ namespace BMap {
public:
BMMeshTransition();
~BMMeshTransition();
LIBCMO_DISABLE_COPY_MOVE(BMMeshTransition);
YYCC_DEL_CLS_COPY_MOVE(BMMeshTransition);
bool PrepareVertexCount(LibCmo::CKDWORD count);
LibCmo::VxMath::VxVector3* PrepareVertex();

View File

@ -1,188 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{0f0a8b98-35d7-4b8e-af0a-041b1bd80fd2}</ProjectGuid>
<RootNamespace>BMap</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_EXPORTING;LIBCMO_BUILD_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;../IronPad;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>zlibwapi.lib;LibCmo.lib;IronPad.lib;Dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ZLIB_PATH)\contrib\vstudio\vc14\x86\ZlibDllReleaseWithoutAsm;$(SolutionDir)out\$(Platform)\$(Configuration)\LibCmo;$(SolutionDir)out\$(Platform)\$(Configuration)\IronPad;</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_EXPORTING;LIBCMO_BUILD_RELEASE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;../IronPad;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>zlibwapi.lib;LibCmo.lib;IronPad.lib;Dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ZLIB_PATH)\contrib\vstudio\vc14\x86\ZlibDllReleaseWithoutAsm;$(SolutionDir)out\$(Platform)\$(Configuration)\LibCmo;$(SolutionDir)out\$(Platform)\$(Configuration)\IronPad;</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_EXPORTING;LIBCMO_BUILD_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;../IronPad;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>zlibwapi.lib;LibCmo.lib;IronPad.lib;Dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ZLIB_PATH)\contrib\vstudio\vc14\x64\ZlibDllReleaseWithoutAsm;$(SolutionDir)out\$(Platform)\$(Configuration)\LibCmo;$(SolutionDir)out\$(Platform)\$(Configuration)\IronPad;</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_EXPORTING;LIBCMO_BUILD_RELEASE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;../IronPad;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>zlibwapi.lib;LibCmo.lib;IronPad.lib;Dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ZLIB_PATH)\contrib\vstudio\vc14\x64\ZlibDllReleaseWithoutAsm;$(SolutionDir)out\$(Platform)\$(Configuration)\LibCmo;$(SolutionDir)out\$(Platform)\$(Configuration)\IronPad;</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="BMap.hpp" />
<ClInclude Include="BMExports.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="BMap.cpp" />
<ClCompile Include="BMExports.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headers">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BMap.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="BMExports.hpp">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BMap.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="BMExports.cpp">
<Filter>Sources</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,65 +1,55 @@
cmake_minimum_required(VERSION 3.12)
project(BMap LANGUAGES CXX)
# add libcmo if not existed
if (NOT TARGET LibCmo)
add_subdirectory("../LibCmo" "LibCmo.out")
endif ()
# add ironpad if not existed
if (NOT TARGET IronPad)
add_subdirectory("../IronPad" "IronPad.out")
endif ()
# hide all function in default
# fix imported library PIC issue (i don't know why. just make it works)
set_target_properties(LibCmo
PROPERTIES
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON
)
set_target_properties(IronPad
PROPERTIES
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON
)
# setup sources
set(bmap_headers ".")
set(bmap_sources
BMap.cpp
BMExports.cpp
)
# generate shared library
add_library(BMap
SHARED
${bmap_sources}
)
target_link_libraries(BMap
# Create shared library
add_library(BMap SHARED "")
# Setup sources
target_sources(BMap
PRIVATE
LibCmo
IronPad
BMap.cpp
BMExports.cpp
)
# Setup headers
target_sources(BMap
PRIVATE
FILE_SET HEADERS
FILES
BMap.hpp
BMExports.hpp
)
# Setup header infomation
target_include_directories(BMap
PRIVATE
${bmap_headers}
"${CMAKE_CURRENT_LIST_DIR}"
)
# set project standard
# Setup linked library infomation
target_link_libraries(BMap
PRIVATE
YYCC::YYCCommonplace
LibCmo
)
# Setup C++ standard
set_target_properties(BMap
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# set default visibility to hidden
set_target_properties(BMap
PROPERTIES
CXX_VISIBILITY_PRESET hidden
)
# add export used macro flag
# Setup project macros
target_compile_definitions(BMap
PUBLIC
LIBCMO_EXPORTING
# Enable export macro
PRIVATE
BMAP_EXPORTING
# Order Unicode charset for private using
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
# Order build as UTF-8 in MSVC
target_compile_options(BMap
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install BMap only on Release mode
install(TARGETS BMap
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

398
BMapBindings/BMapSharp/.gitignore vendored Normal file
View File

@ -0,0 +1,398 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BMapSharp", "BMapSharp\BMapSharp.csproj", "{604F426A-EC91-4E17-BE58-74565B24946C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BMapSharpTestbench", "BMapSharpTestbench\BMapSharpTestbench.csproj", "{3490D77F-119B-48EF-AA0B-E715EBE80DAA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{604F426A-EC91-4E17-BE58-74565B24946C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{604F426A-EC91-4E17-BE58-74565B24946C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{604F426A-EC91-4E17-BE58-74565B24946C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{604F426A-EC91-4E17-BE58-74565B24946C}.Release|Any CPU.Build.0 = Release|Any CPU
{3490D77F-119B-48EF-AA0B-E715EBE80DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3490D77F-119B-48EF-AA0B-E715EBE80DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3490D77F-119B-48EF-AA0B-E715EBE80DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3490D77F-119B-48EF-AA0B-E715EBE80DAA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>BMapSharp</PackageId>
<Version>1.0.0</Version>
<Authors>yyc12345</Authors>
<Company>BearKidsTeam</Company>
</PropertyGroup>
<PropertyGroup Condition="$([System.OperatingSystem]::IsWindows())">
<DefineConstants>BMAP_OS_WINDOWS</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([System.OperatingSystem]::IsLinux()) Or $([System.OperatingSystem]::IsFreeBSD())">
<DefineConstants>BMAP_OS_LINUX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([System.OperatingSystem]::IsMacOS())">
<DefineConstants>BMAP_OS_MACOS</DefineConstants>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,617 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BMapSharp.VirtoolsTypes;
namespace BMapSharp.BMapWrapper {
/// <summary>
/// The guard of native BMap environment.
/// This class initialize native BMap environment when constructing and free it when destructing.
/// </summary>
internal sealed class BMapGuard : SafeHandle {
private static readonly IntPtr MAGIC_HANDLE = (IntPtr)61;
internal BMapGuard() : base(Utils.INVALID_PTR, true) {
BMapException.ThrowIfFailed(BMap.BMInit());
this.handle = MAGIC_HANDLE;
}
public override bool IsInvalid => this.handle == Utils.INVALID_PTR;
protected override bool ReleaseHandle() {
return BMap.BMDispose();
}
}
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>
internal static readonly uint INVALID_CKID = 0u;
/// <summary>
/// The function used as callback for BMap.
/// It just writes the data in console.
/// </summary>
internal static void BMapSharpCallback(string 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
}
// 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;
}
public override bool IsInvalid => this.handle == Utils.INVALID_PTR;
protected override bool ReleaseHandle() => throw new NotImplementedException();
internal bool isValid() => this.handle != Utils.INVALID_PTR;
internal IntPtr getPointer() => this.handle;
#region IEquatable
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;
}
public override int GetHashCode() => this.handle.GetHashCode();
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 Misc
public override string ToString() => this.handle.ToString();
#endregion
}
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;
}
public override bool IsInvalid => this.handle == Utils.INVALID_PTR;
protected override bool ReleaseHandle() => throw new NotImplementedException();
private readonly uint 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;
#region IEquatable
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);
}
public override int GetHashCode() => HashCode.Combine(this.handle, m_CKID);
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);
#endregion
#region Misc
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(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
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(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(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(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 BM3dEntity : BMObject {
internal BM3dEntity(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
public VxMatrix GetWorldMatrix() => getGenericValue<VxMatrix>(BMap.BM3dEntity_GetWorldMatrix);
public void SetWorldMatrix(VxMatrix mat) => setGenericValue<VxMatrix>(BMap.BM3dEntity_SetWorldMatrix, mat);
public BMMesh GetCurrentMesh() {
BMapException.ThrowIfFailed(BMap.BM3dEntity_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.BM3dEntity_SetCurrentMesh(getPointer(), getCKID(), meshid));
}
public bool GetVisibility() => getGenericValue<bool>(BMap.BM3dEntity_GetVisibility);
public void SetVisibility(bool visb) => setGenericValue<bool>(BMap.BM3dEntity_SetVisibility, visb);
}
public class BM3dObject : BM3dEntity {
internal BM3dObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
}
public class BMLight : BM3dEntity {
internal BMLight(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
// Name `GetType` is conflict with C# base class function name.
// So we add a `Light` prefix for it.
public VXLIGHT_TYPE GetLightType() => getGenericValue<VXLIGHT_TYPE>(BMap.BMLight_GetType);
public void SetLightType(VXLIGHT_TYPE val) => setGenericValue<VXLIGHT_TYPE>(BMap.BMLight_SetType, val);
public VxColor GetColor() => getGenericValue<VxColor>(BMap.BMLight_GetColor);
public void SetColor(VxColor col) => setGenericValue<VxColor>(BMap.BMLight_SetColor, col);
public float GetConstantAttenuation() => getGenericValue<float>(BMap.BMLight_GetConstantAttenuation);
public void SetConstantAttenuation(float val) => setGenericValue<float>(BMap.BMLight_SetConstantAttenuation, val);
public float GetLinearAttenuation() => getGenericValue<float>(BMap.BMLight_GetLinearAttenuation);
public void SetLinearAttenuation(float val) => setGenericValue<float>(BMap.BMLight_SetLinearAttenuation, val);
public float GetQuadraticAttenuation() => getGenericValue<float>(BMap.BMLight_GetQuadraticAttenuation);
public void SetQuadraticAttenuation(float val) => setGenericValue<float>(BMap.BMLight_SetQuadraticAttenuation, val);
public float GetRange() => getGenericValue<float>(BMap.BMLight_GetRange);
public void SetRange(float val) => setGenericValue<float>(BMap.BMLight_SetRange, val);
public float GetHotSpot() => getGenericValue<float>(BMap.BMLight_GetHotSpot);
public void SetHotSpot(float val) => setGenericValue<float>(BMap.BMLight_SetHotSpot, val);
public float GetFalloff() => getGenericValue<float>(BMap.BMLight_GetFalloff);
public void SetFalloff(float val) => setGenericValue<float>(BMap.BMLight_SetFalloff, val);
public float GetFalloffShape() => getGenericValue<float>(BMap.BMLight_GetFalloffShape);
public void SetFalloffShape(float val) => setGenericValue<float>(BMap.BMLight_SetFalloffShape, val);
}
public class BMTargetLight : BMLight {
internal BMTargetLight(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { }
}
public class BMGroup : BMObject {
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) {
BMapException.ThrowIfFailed(BMap.BMFile_Load(
file_name, temp_folder, texture_folder,
Utils.BMapSharpCallback,
(uint)encodings.Length, encodings,
out IntPtr out_file
));
return out_file;
}
protected override bool ReleaseHandle() {
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)) { }
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;
}
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(fct_obj(this.getPointer(), i, out uint out_id));
yield return fct_crt(this.getPointer(), out_id);
}
}
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 uint GetTargetLightCount() =>
getCKObjectCount(BMap.BMFile_GetTargetLightCount);
public IEnumerable<BMTargetLight> GetTargetLights() =>
getCKObjects<BMTargetLight>(BMap.BMFile_GetTargetLightCount, BMap.BMFile_GetTargetLight, (bmf, id) => new BMTargetLight(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;
}
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
));
}
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 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 BMTargetLight CreateTargetLight() => createCKObject<BMTargetLight>(BMap.BMFile_CreateTargetLight, (bmf, id) => new BMTargetLight(bmf, id));
}
public sealed class BMMeshTrans : AbstractPointer {
private static IntPtr allocateHandle() {
BMapException.ThrowIfFailed(BMap.BMMeshTrans_New(out IntPtr out_trans));
return out_trans;
}
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 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 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

@ -0,0 +1,311 @@
using System;
using System.Runtime.InteropServices;
using System.Numerics;
namespace BMapSharp.VirtoolsTypes {
// NOTE: Structures defined in there is only served for marshaling.
// You should not use them in hash set or anything else,
// because they do not have proper hash function and compare function.
// You should use the managed type generated by them instead.
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct VxVector2 {
[MarshalAs(UnmanagedType.R4)]
public float X, Y;
public VxVector2(float _x = 0.0f, float _y = 0.0f) {
X = _x; Y = _y;
}
public VxVector2(Vector2 vec) {
FromManaged(vec);
}
public void FromManaged(Vector2 vec) {
X = vec.X; Y = vec.Y;
}
public Vector2 ToManaged() {
return new Vector2(X, Y);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct VxVector3 {
[MarshalAs(UnmanagedType.R4)]
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;
}
public VxVector3(Vector3 vec) {
FromManaged(vec);
}
public void FromManaged(Vector3 vec) {
X = vec.X; Y = vec.Y; Z = vec.Z;
}
public Vector3 ToManaged() {
return new Vector3(X, Y, Z);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct VxColor {
[MarshalAs(UnmanagedType.R4)]
public float R, G, B, A;
public VxColor(float _r, float _g, float _b, float _a) {
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;
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; A = 1.0f;
Regulate();
}
public Vector3 ToManagedRGB() {
return new Vector3(R, G, B);
}
public void FromDword(uint val) {
B = (val & 0xFFu) / 255.0f;
val >>= 8;
G = (val & 0xFFu) / 255.0f;
val >>= 8;
R = (val & 0xFFu) / 255.0f;
val >>= 8;
A = (val & 0xFFu) / 255.0f;
}
public uint ToDword() {
// regulate self first
Regulate();
// build result
uint val = 0u;
val |= (uint)(A * 255.0f);
val <<= 8;
val |= (uint)(R * 255.0f);
val <<= 8;
val |= (uint)(G * 255.0f);
val <<= 8;
val |= (uint)(B * 255.0f);
return val;
}
public static float ClampFactor(float factor) {
return System.Math.Clamp(factor, 0.0f, 1.0f);
}
public void Regulate() {
A = ClampFactor(A);
R = ClampFactor(R);
G = ClampFactor(G);
B = ClampFactor(B);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct VxMatrix {
[MarshalAs(UnmanagedType.R4)]
public float M11, M12, M13, M14;
[MarshalAs(UnmanagedType.R4)]
public float M21, M22, M23, M24;
[MarshalAs(UnmanagedType.R4)]
public float M31, M32, M33, M34;
[MarshalAs(UnmanagedType.R4)]
public float M41, M42, M43, M44;
public VxMatrix(float m11 = 1.0f, float m12 = 0.0f, float m13 = 0.0f, float m14 = 0.0f,
float m21 = 0.0f, float m22 = 1.0f, float m23 = 0.0f, float m24 = 0.0f,
float m31 = 0.0f, float m32 = 0.0f, float m33 = 1.0f, float m34 = 0.0f,
float m41 = 0.0f, float m42 = 0.0f, float m43 = 0.0f, float m44 = 1.0f) {
M11 = m11; M12 = m12; M13 = m13; M14 = m14;
M21 = m21; M22 = m22; M23 = m23; M24 = m24;
M31 = m31; M32 = m32; M33 = m33; M34 = m34;
M41 = m41; M42 = m42; M43 = m43; M44 = m44;
}
public void Reset() {
M11 = 1.0f; M12 = 0.0f; M13 = 0.0f; M14 = 0.0f;
M21 = 0.0f; M22 = 1.0f; M23 = 0.0f; M24 = 0.0f;
M31 = 0.0f; M32 = 0.0f; M33 = 1.0f; M34 = 0.0f;
M41 = 0.0f; M42 = 0.0f; M43 = 0.0f; M44 = 1.0f;
}
public void FromManaged(Matrix4x4 mat) {
M11 = mat.M11; M12 = mat.M12; M13 = mat.M13; M14 = mat.M14;
M21 = mat.M21; M22 = mat.M22; M23 = mat.M23; M24 = mat.M24;
M31 = mat.M31; M32 = mat.M32; M33 = mat.M33; M34 = mat.M34;
M41 = mat.M41; M42 = mat.M42; M43 = mat.M43; M44 = mat.M44;
}
public Matrix4x4 ToManaged() {
return new Matrix4x4(
M11, M12, M13, M14,
M21, M22, M23, M24,
M31, M32, M33, M34,
M41, M42, M43, M44
);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct CKFaceIndices {
[MarshalAs(UnmanagedType.U4)]
public uint I1, I2, I3;
public CKFaceIndices(uint i1 = 0u, uint i2 = 0u, uint i3 = 0u) {
I1 = i1;
I2 = i2;
I3 = i3;
}
}
[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. */
CKTEXTURE_IMAGEFORMAT = 2, /**< Save using format specified. The bitmap data will be converted to the specified format by the correspondant bitmap plugin and saved inside file. */
CKTEXTURE_USEGLOBAL = 3, /**< Use Global settings, that is the settings given with CKContext::SetGlobalImagesSaveOptions. (Not valid when using CKContext::SetImagesSaveOptions). */
CKTEXTURE_INCLUDEORIGINALFILE = 4, /**< Insert original image file inside CMO file. The bitmap file that was used originally for the texture or sprite will be append to the composition file and extracted when the file is loaded. */
}
public enum VX_PIXELFORMAT : uint {
UNKNOWN_PF = 0, /**< Unknown pixel format */
_32_ARGB8888 = 1, /**< 32-bit ARGB pixel format with alpha */
_32_RGB888 = 2, /**< 32-bit RGB pixel format without alpha */
_24_RGB888 = 3, /**< 24-bit RGB pixel format */
_16_RGB565 = 4, /**< 16-bit RGB pixel format */
_16_RGB555 = 5, /**< 16-bit RGB pixel format (5 bits per color) */
_16_ARGB1555 = 6, /**< 16-bit ARGB pixel format (5 bits per color + 1 bit for alpha) */
_16_ARGB4444 = 7, /**< 16-bit ARGB pixel format (4 bits per color) */
_8_RGB332 = 8, /**< 8-bit RGB pixel format */
_8_ARGB2222 = 9, /**< 8-bit ARGB pixel format */
_32_ABGR8888 = 10, /**< 32-bit ABGR pixel format */
_32_RGBA8888 = 11, /**< 32-bit RGBA pixel format */
_32_BGRA8888 = 12, /**< 32-bit BGRA pixel format */
_32_BGR888 = 13, /**< 32-bit BGR pixel format */
_24_BGR888 = 14, /**< 24-bit BGR pixel format */
_16_BGR565 = 15, /**< 16-bit BGR pixel format */
_16_BGR555 = 16, /**< 16-bit BGR pixel format (5 bits per color) */
_16_ABGR1555 = 17, /**< 16-bit ABGR pixel format (5 bits per color + 1 bit for alpha) */
_16_ABGR4444 = 18, /**< 16-bit ABGR pixel format (4 bits per color) */
_DXT1 = 19, /**< S3/DirectX Texture Compression 1 */
_DXT2 = 20, /**< S3/DirectX Texture Compression 2 */
_DXT3 = 21, /**< S3/DirectX Texture Compression 3 */
_DXT4 = 22, /**< S3/DirectX Texture Compression 4 */
_DXT5 = 23, /**< S3/DirectX Texture Compression 5 */
_16_V8U8 = 24, /**< 16-bit Bump Map format format (8 bits per color) */
_32_V16U16 = 25, /**< 32-bit Bump Map format format (16 bits per color) */
_16_L6V5U5 = 26, /**< 16-bit Bump Map format format with luminance */
_32_X8L8V8U8 = 27, /**< 32-bit Bump Map format format with luminance */
_8_ABGR8888_CLUT = 28, /**< 8 bits indexed CLUT (ABGR) */
_8_ARGB8888_CLUT = 29, /**< 8 bits indexed CLUT (ARGB) */
_4_ABGR8888_CLUT = 30, /**< 4 bits indexed CLUT (ABGR) */
_4_ARGB8888_CLUT = 31, /**< 4 bits indexed CLUT (ARGB) */
}
public enum VXLIGHT_TYPE : uint {
VX_LIGHTPOINT = 1, /**< The Light is a point of light */
VX_LIGHTSPOT = 2, /**< The light is a spotlight */
VX_LIGHTDIREC = 3, /**< The light is directional light : Lights comes from an infinite point so only direction of light can be given */
// VX_LIGHTPARA = 4UL, /**< Obsolete, do not use */
}
public enum VXTEXTURE_BLENDMODE : uint {
VXTEXTUREBLEND_DECAL = 1, /**< Texture replace any material information */
VXTEXTUREBLEND_MODULATE = 2, /**< Texture and material are combine. Alpha information of the texture replace material alpha component. */
VXTEXTUREBLEND_DECALALPHA = 3, /**< Alpha information in the texture specify how material and texture are combined. Alpha information of the texture replace material alpha component. */
VXTEXTUREBLEND_MODULATEALPHA = 4, /**< Alpha information in the texture specify how material and texture are combined */
VXTEXTUREBLEND_DECALMASK = 5,
VXTEXTUREBLEND_MODULATEMASK = 6,
VXTEXTUREBLEND_COPY = 7, /**< Equivalent to DECAL */
VXTEXTUREBLEND_ADD = 8,
VXTEXTUREBLEND_DOTPRODUCT3 = 9, /**< Perform a Dot Product 3 between texture (normal map) and a referential vector given in VXRENDERSTATE_TEXTUREFACTOR. */
VXTEXTUREBLEND_MAX = 10,
}
public enum VXTEXTURE_FILTERMODE : uint {
VXTEXTUREFILTER_NEAREST = 1, /**< No Filter */
VXTEXTUREFILTER_LINEAR = 2, /**< Bilinear Interpolation */
VXTEXTUREFILTER_MIPNEAREST = 3, /**< Mip mapping */
VXTEXTUREFILTER_MIPLINEAR = 4, /**< Mip Mapping with Bilinear interpolation */
VXTEXTUREFILTER_LINEARMIPNEAREST = 5, /**< Mip Mapping with Bilinear interpolation between mipmap levels. */
VXTEXTUREFILTER_LINEARMIPLINEAR = 6, /**< Trilinear Filtering */
VXTEXTUREFILTER_ANISOTROPIC = 7, /**< Anisotropic filtering */
}
public enum VXTEXTURE_ADDRESSMODE : uint {
VXTEXTURE_ADDRESSWRAP = 1, /**< Default mesh wrap mode is used (see CKMesh::SetWrapMode) */
VXTEXTURE_ADDRESSMIRROR = 2, /**< Texture coordinates outside the range [0..1] are flipped evenly. */
VXTEXTURE_ADDRESSCLAMP = 3, /**< Texture coordinates greater than 1.0 are set to 1.0, and values less than 0.0 are set to 0.0. */
VXTEXTURE_ADDRESSBORDER = 4, /**< When texture coordinates are greater than 1.0 or less than 0.0 texture is set to a color defined in CKMaterial::SetTextureBorderColor. */
VXTEXTURE_ADDRESSMIRRORONCE = 5, /**< */
}
public enum VXBLEND_MODE : uint {
VXBLEND_ZERO = 1, /**< Blend factor is (0, 0, 0, 0). */
VXBLEND_ONE = 2, /**< Blend factor is (1, 1, 1, 1). */
VXBLEND_SRCCOLOR = 3, /**< Blend factor is (Rs, Gs, Bs, As). */
VXBLEND_INVSRCCOLOR = 4, /**< Blend factor is (1-Rs, 1-Gs, 1-Bs, 1-As). */
VXBLEND_SRCALPHA = 5, /**< Blend factor is (As, As, As, As). */
VXBLEND_INVSRCALPHA = 6, /**< Blend factor is (1-As, 1-As, 1-As, 1-As). */
VXBLEND_DESTALPHA = 7, /**< Blend factor is (Ad, Ad, Ad, Ad). */
VXBLEND_INVDESTALPHA = 8, /**< Blend factor is (1-Ad, 1-Ad, 1-Ad, 1-Ad). */
VXBLEND_DESTCOLOR = 9, /**< Blend factor is (Rd, Gd, Bd, Ad). */
VXBLEND_INVDESTCOLOR = 10, /**< Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad). */
VXBLEND_SRCALPHASAT = 11, /**< Blend factor is (f, f, f, 1); f = min(As, 1-Ad). */
// VXBLEND_BOTHSRCALPHA = 12, /**< Source blend factor is (As, As, As, As) and destination blend factor is (1-As, 1-As, 1-As, 1-As) */
// VXBLEND_BOTHINVSRCALPHA = 13, /**< Source blend factor is (1-As, 1-As, 1-As, 1-As) and destination blend factor is (As, As, As, As) */
}
public enum VXFILL_MODE : uint {
VXFILL_POINT = 1, /**< Vertices rendering */
VXFILL_WIREFRAME = 2, /**< Edges rendering */
VXFILL_SOLID = 3, /**< Face rendering */
}
public enum VXSHADE_MODE : uint {
VXSHADE_FLAT = 1, /**< Flat Shading */
VXSHADE_GOURAUD = 2, /**< Gouraud Shading */
VXSHADE_PHONG = 3, /**< Phong Shading (Not yet supported by most implementation) */
}
public enum VXCMPFUNC : uint {
VXCMP_NEVER = 1, /**< Always fail the test. */
VXCMP_LESS = 2, /**< Accept if value if less than current value. */
VXCMP_EQUAL = 3, /**< Accept if value if equal than current value. */
VXCMP_LESSEQUAL = 4, /**< Accept if value if less or equal than current value. */
VXCMP_GREATER = 5, /**< Accept if value if greater than current value. */
VXCMP_NOTEQUAL = 6, /**< Accept if value if different than current value. */
VXCMP_GREATEREQUAL = 7, /**< Accept if value if greater or equal current value. */
VXCMP_ALWAYS = 8, /**< Always accept the test. */
}
public enum VXMESH_LITMODE : uint {
VX_PRELITMESH = 0, /**< Lighting use color information store with vertices */
VX_LITMESH = 1, /**< Lighting is done by renderer using normals and face material information. */
}
}

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

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\BMapSharp\BMapSharp.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,219 @@
using BMapSharp.BMapWrapper;
using System;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.CommandLine;
namespace BMapSharpTestbench {
internal class Program {
static void Main(string[] args) {
// Parse arguments
var resolved_args = ResolveArguments(args);
if (resolved_args is null) {
// just silent quit
Environment.Exit(0);
}
// 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 = resolved_args.mFileName; // "LightCameraTest.nmo";
string temp_folder = resolved_args.mTempFolder; // "Temp";
string texture_folder = resolved_args.mTextureFolder; // "F:\\Ballance\\Ballance\\Textures";
string[] encodings = resolved_args.mEncodings; // ["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);
}
class BMapSharpArguments {
public string mFileName;
public string mTempFolder;
public string mTextureFolder;
public string[] mEncodings;
}
static BMapSharpArguments ResolveArguments(string[] args) {
// define arguments
var fileNameOpt = new Option<string>
("--file-path", "The path to input Virtools file.");
fileNameOpt.IsRequired = true;
var tempFolderOpt = new Option<string>
("--temp-dir", "The temp folder used by BMap.");
tempFolderOpt.IsRequired = true;
var textureFolderOpt = new Option<string>
("--texture-dir", "The texture folder containing Ballance texture resources.");
textureFolderOpt.IsRequired = true;
var encodingsOpt = new Option<IEnumerable<string>>
("--encodings", "The encodings used to parse the names stroed in input Virtools file.");
encodingsOpt.IsRequired = true;
encodingsOpt.Arity = ArgumentArity.OneOrMore;
encodingsOpt.AllowMultipleArgumentsPerToken = true;
// init root command
var rootCommand = new RootCommand("The testbench of BMapSharp.");
rootCommand.Add(fileNameOpt);
rootCommand.Add(tempFolderOpt);
rootCommand.Add(textureFolderOpt);
rootCommand.Add(encodingsOpt);
// init result container
BMapSharpArguments ret = new BMapSharpArguments();
// set handler
rootCommand.SetHandler((context) => {
ret.mFileName = context.ParseResult.GetValueForOption(fileNameOpt);
ret.mTempFolder = context.ParseResult.GetValueForOption(tempFolderOpt);
ret.mTextureFolder = context.ParseResult.GetValueForOption(textureFolderOpt);
ret.mEncodings = context.ParseResult.GetValueForOption(encodingsOpt).ToArray();
context.ExitCode = 61;
});
// execute root command and return value.
if (rootCommand.Invoke(args) != 61) return null;
return ret;
}
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("===== Target Lights =====");
foreach (var lit in reader.GetTargetLights()) {
Console.WriteLine(lit.GetName());
Console.WriteLine($"\tVisibility: {lit.GetVisibility()}");
Console.WriteLine($"\tMatrix: {lit.GetWorldMatrix().ToManaged()}");
Console.WriteLine($"Type: {lit.GetLightType()}");
Console.WriteLine($"Color: {lit.GetColor().ToManagedRGBA()}");
Console.WriteLine($"Constant Attenuation: {lit.GetConstantAttenuation()}");
Console.WriteLine($"Linear Attenuation: {lit.GetLinearAttenuation()}");
Console.WriteLine($"Quadratic Attenuation: {lit.GetQuadraticAttenuation()}");
Console.WriteLine($"Range: {lit.GetRange()}");
Console.WriteLine($"Hot Spot: {lit.GetHotSpot()}");
Console.WriteLine($"Falloff: {lit.GetFalloff()}");
Console.WriteLine($"Falloff Shape: {lit.GetFalloffShape()}");
}
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

@ -0,0 +1,9 @@
# BMapSharp
The core of BMapSharp project is placed within `BMapSharp` subdirectory. This directory also contain a testbench project of `BMapSharp`, called `BMapSharpTestbench`. You can build it and do basic test for `BMapSharp`.
The native BMap library should be placed together with managed `BMapSharp` dynamic library. I use gitignore file to filter all native binary so you need put them manually. The native BMap library must be named as `BMap.dll` (in Windows), `BMap.so` (in Linux or BSD), or `BMap.dylib` (in macOS). If you still can not load BMap or your system is not listed above, you should name it as `BMap.bin`.
The most content of `VirtoolsTypes.cs` is generated by EnumsMigration, and the most content of `BMap.cs` is generated by BMapBindings. You should watch these file changes if corresponding C++ code or structures are changed.
Since BMap 0.3.0, testbench use command line arguments, instead of hardcode variables in code, as the arguments of BMap. It is convenient that debug BMapSharp without any modification of source code. For a brief instruction, you may need to launch BMapSharpTestbench in following command (just an example. you can modify it as you wished): `dotnet run -- --file-path "LightCameraTest.nmo" --temp-dir "Temp" --texture-dir "F:/Ballance/Ballance/Textures" --encodings cp1252 gb2312`.

View File

@ -9,9 +9,6 @@
*.dylib
*.bin
# Ignore testbench file.
testbench.py
# -------------------- Python --------------------
# Byte-compiled / optimized / DLL files
__pycache__/

View File

@ -78,12 +78,13 @@ elif sys.platform.startswith('darwin'):
else:
_g_BMapLibName = "BMap.bin"
_g_BMapLibPath: str = os.path.join(os.path.dirname(__file__), _g_BMapLibName)
_g_BMapModule: ctypes.CDLL | None = None
try:
_g_BMapModule = ctypes.cdll.LoadLibrary(
os.path.join(os.path.dirname(__file__), _g_BMapLibName)
)
_g_BMapModule = ctypes.cdll.LoadLibrary(_g_BMapLibPath)
except:
print(f'Fail to load native BMap dynamic library file "{_g_BMapLibPath}".')
_g_BMapModule = None
def is_bmap_available() -> bool:
@ -107,6 +108,8 @@ def _create_bmap_func(fct_name: str, fct_params: list[typing.Any]) -> typing.Cal
#region Function Defines
##### GENERATED FUNCTIONS BEGIN #####
## BMInit
# @return True if no error, otherwise False.
BMInit = _create_bmap_func('BMInit', [])
@ -224,6 +227,22 @@ BMFile_GetTexture = _create_bmap_func('BMFile_GetTexture', [bm_void_p, bm_CKDWOR
# @param out_id[out] Type: LibCmo::CK2::CK_ID. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMFile_CreateTexture = _create_bmap_func('BMFile_CreateTexture', [bm_void_p, bm_CKID_p])
## BMFile_GetTargetLightCount
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param out_count[out] Type: LibCmo::CKDWORD. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMFile_GetTargetLightCount = _create_bmap_func('BMFile_GetTargetLightCount', [bm_void_p, bm_CKDWORD_p])
## BMFile_GetTargetLight
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param idx[in] Type: LibCmo::CKDWORD.
# @param out_id[out] Type: LibCmo::CK2::CK_ID. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMFile_GetTargetLight = _create_bmap_func('BMFile_GetTargetLight', [bm_void_p, bm_CKDWORD, bm_CKID_p])
## BMFile_CreateTargetLight
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param out_id[out] Type: LibCmo::CK2::CK_ID. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMFile_CreateTargetLight = _create_bmap_func('BMFile_CreateTargetLight', [bm_void_p, bm_CKID_p])
## BMMeshTrans_New
# @param out_trans[out] Type: BMap::BMMeshTransition*. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
@ -744,42 +763,151 @@ BMMesh_GetMaterialSlot = _create_bmap_func('BMMesh_GetMaterialSlot', [bm_void_p,
# @param mtlid[in] Type: LibCmo::CK2::CK_ID.
# @return True if no error, otherwise False.
BMMesh_SetMaterialSlot = _create_bmap_func('BMMesh_SetMaterialSlot', [bm_void_p, bm_CKID, bm_CKDWORD, bm_CKID])
## BM3dObject_GetWorldMatrix
## BM3dEntity_GetWorldMatrix
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_mat[out] Type: LibCmo::VxMath::VxMatrix. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BM3dObject_GetWorldMatrix = _create_bmap_func('BM3dObject_GetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix_p])
## BM3dObject_SetWorldMatrix
BM3dEntity_GetWorldMatrix = _create_bmap_func('BM3dEntity_GetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix_p])
## BM3dEntity_SetWorldMatrix
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param mat[in] Type: LibCmo::VxMath::VxMatrix.
# @return True if no error, otherwise False.
BM3dObject_SetWorldMatrix = _create_bmap_func('BM3dObject_SetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix])
## BM3dObject_GetCurrentMesh
BM3dEntity_SetWorldMatrix = _create_bmap_func('BM3dEntity_SetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix])
## BM3dEntity_GetCurrentMesh
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_meshid[out] Type: LibCmo::CK2::CK_ID. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BM3dObject_GetCurrentMesh = _create_bmap_func('BM3dObject_GetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID_p])
## BM3dObject_SetCurrentMesh
BM3dEntity_GetCurrentMesh = _create_bmap_func('BM3dEntity_GetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID_p])
## BM3dEntity_SetCurrentMesh
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param meshid[in] Type: LibCmo::CK2::CK_ID.
# @return True if no error, otherwise False.
BM3dObject_SetCurrentMesh = _create_bmap_func('BM3dObject_SetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID])
## BM3dObject_GetVisibility
BM3dEntity_SetCurrentMesh = _create_bmap_func('BM3dEntity_SetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID])
## BM3dEntity_GetVisibility
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_isVisible[out] Type: bool. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BM3dObject_GetVisibility = _create_bmap_func('BM3dObject_GetVisibility', [bm_void_p, bm_CKID, bm_bool_p])
## BM3dObject_SetVisibility
BM3dEntity_GetVisibility = _create_bmap_func('BM3dEntity_GetVisibility', [bm_void_p, bm_CKID, bm_bool_p])
## BM3dEntity_SetVisibility
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param is_visible[in] Type: bool.
# @return True if no error, otherwise False.
BM3dObject_SetVisibility = _create_bmap_func('BM3dObject_SetVisibility', [bm_void_p, bm_CKID, bm_bool])
BM3dEntity_SetVisibility = _create_bmap_func('BM3dEntity_SetVisibility', [bm_void_p, bm_CKID, bm_bool])
## BMLight_GetType
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::VxMath::VXLIGHT_TYPE. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetType = _create_bmap_func('BMLight_GetType', [bm_void_p, bm_CKID, bm_enum_p])
## BMLight_SetType
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::VxMath::VXLIGHT_TYPE.
# @return True if no error, otherwise False.
BMLight_SetType = _create_bmap_func('BMLight_SetType', [bm_void_p, bm_CKID, bm_enum])
## BMLight_GetColor
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::VxMath::VxColor. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetColor = _create_bmap_func('BMLight_GetColor', [bm_void_p, bm_CKID, bm_VxColor_p])
## BMLight_SetColor
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param col[in] Type: LibCmo::VxMath::VxColor.
# @return True if no error, otherwise False.
BMLight_SetColor = _create_bmap_func('BMLight_SetColor', [bm_void_p, bm_CKID, bm_VxColor])
## BMLight_GetConstantAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetConstantAttenuation = _create_bmap_func('BMLight_GetConstantAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetConstantAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetConstantAttenuation = _create_bmap_func('BMLight_SetConstantAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetLinearAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetLinearAttenuation = _create_bmap_func('BMLight_GetLinearAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetLinearAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetLinearAttenuation = _create_bmap_func('BMLight_SetLinearAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetQuadraticAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetQuadraticAttenuation = _create_bmap_func('BMLight_GetQuadraticAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetQuadraticAttenuation
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetQuadraticAttenuation = _create_bmap_func('BMLight_SetQuadraticAttenuation', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetRange
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetRange = _create_bmap_func('BMLight_GetRange', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetRange
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetRange = _create_bmap_func('BMLight_SetRange', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetHotSpot
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetHotSpot = _create_bmap_func('BMLight_GetHotSpot', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetHotSpot
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetHotSpot = _create_bmap_func('BMLight_SetHotSpot', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetFalloff
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetFalloff = _create_bmap_func('BMLight_GetFalloff', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetFalloff
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetFalloff = _create_bmap_func('BMLight_SetFalloff', [bm_void_p, bm_CKID, bm_CKFLOAT])
## BMLight_GetFalloffShape
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param out_val[out] Type: LibCmo::CKFLOAT. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False.
BMLight_GetFalloffShape = _create_bmap_func('BMLight_GetFalloffShape', [bm_void_p, bm_CKID, bm_CKFLOAT_p])
## BMLight_SetFalloffShape
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile.
# @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param val[in] Type: LibCmo::CKFLOAT.
# @return True if no error, otherwise False.
BMLight_SetFalloffShape = _create_bmap_func('BMLight_SetFalloffShape', [bm_void_p, bm_CKID, bm_CKFLOAT])
##### GENERATED FUNCTIONS END #####
#endregion

File diff suppressed because it is too large Load Diff

View File

@ -221,6 +221,15 @@ class VX_PIXELFORMAT(enum.IntEnum):
_4_ABGR8888_CLUT = 30 ##< 4 bits indexed CLUT (ABGR)
_4_ARGB8888_CLUT = 31 ##< 4 bits indexed CLUT (ARGB)
class VXLIGHT_TYPE(enum.IntEnum):
"""!
Light type
"""
VX_LIGHTPOINT = 1 ##< The Light is a point of light
VX_LIGHTSPOT = 2 ##< The light is a spotlight
VX_LIGHTDIREC = 3 ##< The light is directional light : Lights comes from an infinite point so only direction of light can be given
#VX_LIGHTPARA = 4 ##< Obsolete, do not use
class VXTEXTURE_BLENDMODE(enum.IntEnum):
"""!
Blend Mode Flags

View File

@ -1,5 +1,9 @@
# PyBMap
The real scripts are placed in sub PyBMap folder. This folder is served for testbench scripts placing. Place any testbench files (e.g. `testbench.py`) in there what you want and don't sumbit them (`testbench.py` is explicitly excluded by gitignore file).
The real scripts are placed in sub PyBMap folder. This folder is served for testbench scripts placing. You can run `testbench.py` to do a basic test for PyBMap but you may need some essential files to run this testbench which were written in `testbench.py`.
The native BMap library should be placed in sub PyBMap folder, and I have used gitignore file to filter them. The native BMap library must be named as `BMap.dll` (in Windows), `BMap.so` (in Linux or BSD), or `BMap.dylib` (in macOS). If you still can not load BMap or your system is not listed above, you should name it as `BMap.bin`.
Please note the most content of `virtools_types.py` are generated by EnumsMigration sub-project. Additionally the most content of `bmap.py` is generated by BMapBindings. So if some structs are updated, do not forget checking these files.
Since BMap 0.3.0, testbench use command line arguments, instead of hardcode variables in code, as the arguments of BMap. It is convenient that debug BMapSharp without any modification of source code. For a brief instruction, you may need to launch BMapSharpTestbench in following command (just an example. you can modify it as you wished): `py testbench.py --file-path "LightCameraTest.nmo" --temp-dir "Temp" --texture-dir "F:/Ballance/Ballance/Textures" --encodings cp1252 gb2312`.

View File

@ -0,0 +1,178 @@
import os
import argparse
import PyBMap.bmap_wrapper as bmap
def main(file_name: str, temp_folder: str, texture_folder: str, encodings: tuple[str, ...]) -> None:
input(f'Python PID is {os.getpid()}. Waiting for debugger, press any key to continue...')
# file_name: str = 'LightCameraTest.nmo'
# temp_folder: str = 'Temp'
# texture_folder: str = 'F:\\Ballance\\Ballance\\Textures'
# encodings: tuple[str, ...] = ('cp1252', )
with bmap.BMFileReader(file_name, temp_folder, texture_folder, encodings) as reader:
test_common(reader)
test_equatable(reader)
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('===== 3dObjects =====')
# for obj in reader.get_3dobjects():
# print(obj.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('===== 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('===== Target Lights =====')
for lit in reader.get_target_lights():
print(lit.get_name())
print(f'\tVisibility: {lit.get_visibility()}')
print(f'\tMatrix: {lit.get_world_matrix().to_const()}')
print(f'\tType: {lit.get_type()}')
print(f'\tColor: {lit.get_color().to_const_rgba()}')
print(f'\tConstant Attenuation: {lit.get_constant_attenuation()}')
print(f'\tLinear Attenuation: {lit.get_linear_attenuation()}')
print(f'\tQuadratic Attenuation: {lit.get_quadratic_attenuation()}')
print(f'\tRange: {lit.get_range()}')
print(f'\tHot Spot: {lit.get_hot_spot()}')
print(f'\tFalloff: {lit.get_falloff()}')
print(f'\tFalloff Shape: {lit.get_falloff_shape()}')
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__':
# parse argument
parser = argparse.ArgumentParser(
prog='PyBMap Testbench',
description='The testbench of PyBMap.'
)
parser.add_argument(
'--file-path',
action='store', dest='file_path', required=True,
help='The path to input Virtools file.'
)
parser.add_argument(
'--temp-dir',
action='store', dest='temp_dir', required=True,
help='The temp folder used by BMap.'
)
parser.add_argument(
'--texture-dir',
action='store', dest='texture_dir', required=True,
help='The texture folder containing Ballance texture resources.'
)
parser.add_argument(
'--encodings',
action='extend', nargs='+', dest='encodings', required=True,
help='The encodings used to parse the names stroed in input Virtools file.'
)
args = parser.parse_args()
# run main function
main(args.file_path, args.temp_dir, args.texture_dir, tuple(args.encodings))

View File

@ -0,0 +1,7 @@
@PACKAGE_INIT@
# Include targets file
include("${CMAKE_CURRENT_LIST_DIR}/LibCmoTargets.cmake")
check_required_components(LibCmo)

6
CMake/VTVersion.hpp.in Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#define LIBCMO_VER_MAJOR @PROJECT_VERSION_MAJOR@
#define LIBCMO_VER_MINOR @PROJECT_VERSION_MINOR@
#define LIBCMO_VER_PATCH @PROJECT_VERSION_PATCH@
#define LIBCMO_VER_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"

View File

@ -0,0 +1,9 @@
if (WIN32)
# In Windows, we should not import Iconv.
# Send a notice to programmer.
message("Windows environment detected, skip finding Iconv!")
else ()
# In non-Windows, we simply import Iconv from CMake preset.
# It will produce Iconv::Iconv target for including and linking.
find_package(Iconv REQUIRED)
endif ()

View File

@ -0,0 +1,14 @@
# Check stb path variable
if (NOT DEFINED STB_IMAGE_PATH)
message(FATAL_ERROR "You must set STB_IMAGE_PATH variable to the root directory of std-image repository.")
endif()
# Add library
add_library(stb-image INTERFACE IMPORTED)
# Add alias for it
add_library(stb::stb-image ALIAS stb-image)
# Setup header files
set_target_properties(stb-image PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${STB_IMAGE_PATH}"
)

View File

@ -0,0 +1,15 @@
# Check YYCC path environment variable
if (NOT DEFINED YYCC_PATH)
message(FATAL_ERROR "You must set YYCC_PATH variable to one of YYCC CMake distribution installation path.")
endif()
# Find YYCC library
# It will produce YYCC::YYCCommonplace target for including and linking.
#
# 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)

View File

@ -0,0 +1,34 @@
if (WIN32)
# In Windows, we use custom way to import ZLib.
# Before using this CMake file in Windows, you should do following steps first.
# 1. Get ZLib repository: https://github.com/madler/zlib
# 2. Navigate to `contrib/vstudio` and choose a proper Visual Studio project according to your environment.
# 3. Open project file and build. Then you will get the built binary.
# 4. The directory binary located is the argument you should passed to ZLIB_BINARY_PATH, for example: `contrib/vstudio/vc14/x64/ZlibDllRelease`
# Check ZLib path variable
if (NOT DEFINED ZLIB_HEADER_PATH)
message(FATAL_ERROR "You must set ZLIB_HEADER_PATH to the root directory of ZLib repository.")
endif()
if (NOT DEFINED ZLIB_BINARY_PATH)
message(FATAL_ERROR "You must set ZLIB_BINARY_PATH to the directory where include binary built by contributed Visual Studio project.")
endif()
# Add imported library
add_library(ZLIB INTERFACE IMPORTED)
# Add alias for it to let it has the same behavior with CMake imported ZLib.
add_library(ZLIB::ZLIB ALIAS ZLIB)
# Setup header files
set_target_properties(ZLIB PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${ZLIB_HEADER_PATH}"
)
# Setup lib files
set_target_properties(ZLIB PROPERTIES
INTERFACE_LINK_LIBRARIES
"${ZLIB_BINARY_PATH}/zlibwapi.lib"
)
else ()
# In non-Windows, we simply import ZLib from CMake preset.
# It will produce ZLIB::ZLIB target for including and linking.
find_package(ZLIB REQUIRED)
endif ()

77
CMakeLists.txt Normal file
View File

@ -0,0 +1,77 @@
cmake_minimum_required(VERSION 3.23)
project(NeMo
VERSION 0.3.0
LANGUAGES CXX
)
# Provide options
option(NEMO_BUILD_UNVIRT "Build Unvirt, the console interface operator of LibCmo." ON)
option(NEMO_BUILD_BMAP "Build BMap, the example use of LibCmo which can read and write Ballance game map." OFF)
option(NEMO_BUILD_DOC "Build document of LibCmo and all related stuff." OFF)
# Setup install path from CMake provided install path for convenient use.
include(GNUInstallDirs)
set(NEMO_INSTALL_INCLUDE_PATH ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH
"Public header install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
set(NEMO_INSTALL_LIB_PATH ${CMAKE_INSTALL_LIBDIR} CACHE PATH
"Library install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
set(NEMO_INSTALL_BIN_PATH ${CMAKE_INSTALL_BINDIR} CACHE PATH
"Binary install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
set(NEMO_INSTALL_DOC_PATH ${CMAKE_INSTALL_DOCDIR} CACHE PATH
"Non-arch doc install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
# Import essential packages
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_zlib.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_iconv.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_yycc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_stb.cmake)
# If we are not in Windows environment, and we need to build shared library BMap,
# we should enable PIC (position independent code), otherwise build process will fail.
# Also we should let all symbols in final dll be hidden (not exported) in default.
# Because we only want export functions we ordered.
if ((NOT WIN32) AND NEMO_BUILD_BMAP)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_POSITION_INDEPENDENT_CODE True)
endif ()
# Import build targets
add_subdirectory(LibCmo)
if (NEMO_BUILD_UNVIRT)
add_subdirectory(Unvirt)
endif ()
if (NEMO_BUILD_BMAP)
add_subdirectory(BMap)
endif ()
if (NEMO_BUILD_DOC)
add_subdirectory(Documents)
endif ()
# Install target and package
# Install target
install(EXPORT LibCmoTargets
FILE LibCmoTargets.cmake
NAMESPACE NeMo::
DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Package configuration file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
LibCmoConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY SameMinorVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/LibCmoConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
INSTALL_DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Copy package files to install destination
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfigVersion.cmake"
DESTINATION
${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)

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

@ -1,12 +1,286 @@
import java.io.OutputStreamWriter;
import java.util.Vector;
import java.util.stream.Collectors;
public class CSharpWriter {
/**
* The class represent the C# type corresponding to extracted variable type.
*/
private static class CsInteropType {
public CsInteropType() {
mMarshalAs = null;
mCsType = null;
}
/**
* The argument of MarshalAsAttribute constructor. In generation, this field
* should be used like this: "[MarshalAs(THIS)]" (for parameter) or "[return:
* MarshalAs(THIS)]" (for return value).
*/
public String mMarshalAs;
/**
* The C# type used in interop function declaration for corresponding parameter.
*/
public String mCsType;
}
/**
* C# specified function which get C# used interop MarshalAs constructor
* arguments and C# type used in interop function declaration.
*
* @param vt The instance of {@linkplain VariableType} for fetching interop
* type.
* @return The corresponding interop type of given variable type.
*/
private static CsInteropType getCsInteropType(ExpFctParamDecl paramdecl) {
// get essential variable type properties first
VariableType vt = paramdecl.mVarType;
String vt_base_type = vt.getBaseType();
int vt_pointer_level = vt.getPointerLevel();
// create return value
CsInteropType ret = new CsInteropType();
// 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.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = \"" + direction_cookie + "\"";
// ret.mMarshalAs = "UnmanagedType.LPUTF8Str";
ret.mCsType = "string";
break;
case 1:
ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler), MarshalCookie = \"" + direction_cookie + "\"";
ret.mCsType = "string[]";
break;
}
break;
case "CKDWORD":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U4";
ret.mCsType = "uint";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CKWORD":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U2";
ret.mCsType = "ushort";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CKINT":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.I4";
ret.mCsType = "int";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "bool":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U1";
ret.mCsType = "bool";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CKFLOAT":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.R4";
ret.mCsType = "float";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CKBYTE":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U1";
ret.mCsType = "byte";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CK_ID":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.U4";
ret.mCsType = "uint";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "NakedOutputCallback":
// callback actually is a function pointer
// so it only allow base type without any pointer level.
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.FunctionPtr";
ret.mCsType = "OutputCallback";
}
break;
case "BMFile":
// In any case, BMFile only should be raw pointer
if (vt_pointer_level != 0) {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "BMMeshTransition":
// In any case, BMMeshTransition only should be raw pointer
if (vt_pointer_level != 0) {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "VxVector3":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.Struct";
ret.mCsType = "VxVector3";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "VxVector2":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.Struct";
ret.mCsType = "VxVector2";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "VxColor":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.Struct";
ret.mCsType = "VxColor";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "VxMatrix":
if (vt_pointer_level == 0) {
ret.mMarshalAs = "UnmanagedType.Struct";
ret.mCsType = "VxMatrix";
} else {
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
case "CK_TEXTURE_SAVEOPTIONS":
case "VX_PIXELFORMAT":
case "VXLIGHT_TYPE":
case "VXTEXTURE_BLENDMODE":
case "VXTEXTURE_FILTERMODE":
case "VXTEXTURE_ADDRESSMODE":
case "VXBLEND_MODE":
case "VXFILL_MODE":
case "VXSHADE_MODE":
case "VXCMPFUNC":
case "VXMESH_LITMODE":
// 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 = vt_base_type;
} else {
// for pointer type, use IntPtr instead.
ret.mMarshalAs = "UnmanagedType.SysInt";
ret.mCsType = "IntPtr";
}
break;
}
// check whether we successfully get result
if (ret.mMarshalAs == null || ret.mCsType == null) {
throw new IllegalArgumentException("Unexpected type: " + vt.toCType());
}
// return value
return ret;
}
public static void writeCSharpCode(Vector<ExpFctDecl> data) throws Exception {
OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.cs");
writer.write("// WIP");
IndentHelper helper = new IndentHelper(writer);
// write function decls
for (ExpFctDecl fctdecl : data) {
// write annotation
// summary (just plain function name)
helper.printf("/// <summary>%s</summary>", fctdecl.mFctName);
// parameter list
for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) {
helper.printf("/// <param name=\"%s\">Type: %s. %s%s</param>", paramdecl.mVarName,
paramdecl.mVarType.toCType(), (paramdecl.mIsInput ? "" : "This is OUT parameter. "),
paramdecl.mVarDesc);
}
// return value
helper.puts("/// <returns>True if no error, otherwise False.</returns>");
// write real function declaration
// first, write DllImportAttribute
helper.printf(
"[DllImport(g_DllName, EntryPoint = \"%s\", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]",
fctdecl.mFctName);
// second, write return value MarshalAsAttribute
helper.printf("[return: MarshalAs(UnmanagedType.U1)]");
// then, before we write function body, we need origanize its parameter list
// first
Vector<String> cs_param_list = new Vector<String>();
for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) {
// create string builder
StringBuilder sb = new StringBuilder();
// push in out symbol
if (paramdecl.mIsInput) {
sb.append("[In, ");
} else {
sb.append("[Out, ");
}
// get interop type now
CsInteropType interop_type = getCsInteropType(paramdecl);
// push MarshalAsAttribute
sb.append("MarshalAs(");
sb.append(interop_type.mMarshalAs);
sb.append(")] ");
// push out keyword if parameter is out parameter
if (!paramdecl.mIsInput) {
sb.append("out ");
}
// push parameter cs type
sb.append(interop_type.mCsType);
sb.append(" ");
// push parameter name
sb.append(paramdecl.mVarName);
// insert built string into list
cs_param_list.add(sb.toString());
}
// join built parameter list and output real function declaration
helper.printf("internal static extern bool %s(%s);", fctdecl.mFctName,
cs_param_list.stream().collect(Collectors.joining(", ")));
}
writer.close();
}
}

View File

@ -1,28 +1,28 @@
import java.io.FileInputStream;
//import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
//import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
public class CommonHelper {
public static InputStreamReader openReader(String filename) throws Exception {
FileInputStream fs = new FileInputStream(filename);
return new InputStreamReader(fs, StandardCharsets.UTF_8);
}
// public static InputStreamReader openReader(String filename) throws Exception {
// FileInputStream fs = new FileInputStream(filename);
// return new InputStreamReader(fs, StandardCharsets.UTF_8);
// }
public static OutputStreamWriter openWriter(String filename) throws Exception {
FileOutputStream fs = new FileOutputStream(filename);
return new OutputStreamWriter(fs, StandardCharsets.UTF_8);
}
public static void writeSnippet(OutputStreamWriter writer, String snippet_path) throws Exception {
// open snippet
InputStreamReader reader = openReader(snippet_path);
// write into writer
reader.transferTo(writer);
reader.close();
}
// public static void writeSnippet(OutputStreamWriter writer, String snippet_path) throws Exception {
// // open snippet
// InputStreamReader reader = openReader(snippet_path);
// // write into writer
// reader.transferTo(writer);
// reader.close();
// }
public static String getDoxygenInOutStr(boolean isInput) {
return isInput ? "in" : "out";

View File

@ -1,16 +1,29 @@
import java.util.Vector;
/**
* The class represent an export BMap function.
*/
public class ExpFctDecl {
/**
* The name of this function.
*/
public String mFctName;
/**
* The return value type of this function.
*/
public VariableType mFctRetType;
/**
* The parameters (arguments) list of this function. Each items are
* {@linkplain ExpFctParamDecl} and represent parameter one by one from left to
* right.
*/
public Vector<ExpFctParamDecl> mFctParams;
public ExpFctDecl() {
mFctName = "";
mFctRetType = new VariableType();
mFctParams = new Vector<ExpFctParamDecl>();
}
}
}

View File

@ -1,16 +1,48 @@
/**
* The class represent a single parameter (argument) of function. This class
* usually is the member of {@linkplain ExpFctDecl}.
*/
public class ExpFctParamDecl {
/**
* The type of this parameter.
*/
public VariableType mVarType;
/**
* The name of this parameter.
*/
public String mVarName;
/**
* True if this paramter is marked as input parameter, otherwise false.
* <p>
* Input parameter and output paramter is commonly used in C/C++ code. By using
* this feature, each function can receive multiple arguments and return
* multiple arguments without defining a struct to hold it.
* <p>
* The type of input parameter is itself. However, the type of output parameter
* is the pointer of itself. So you may need get its pointer type when
* processing output paramter, especially for the scenario that the target
* language do not support explicit output parameter keyword.
*/
public boolean mIsInput;
/**
* The description of this parameter.
* <p>
* This description is generated by this program. It will indicate the
* underlying C++ type to tell end user how to treat this paramter because some
* target languages' native calling style can not represent these detail.
* <p>
* In this program, this field must be written as a annotation of corresponding
* function.
*/
public String mVarDesc;
public ExpFctParamDecl() {
mVarType = new VariableType();
mVarName = "";
mVarDesc = "";
mIsInput = true;
}
}

View File

@ -1,7 +1,7 @@
lexer grammar ExpFctsLexer;
// keywords
EXPFCTS_EXPORT: 'LIBCMO_EXPORT' ;
EXPFCTS_EXPORT: 'BMAP_EXPORT' ;
EXPFCTS_FILE_DECL: 'BMPARAM_FILE_DECL' ;
EXPFCTS_MESHTRANS_DECL: 'BMPARAM_MESHTRANS_DECL' ;
EXPFCTS_OBJECT_DECL: 'BMPARAM_OBJECT_DECL' ;

View File

@ -9,7 +9,10 @@ with open(src_file, 'r', encoding='utf-8') as fsrc:
fulltext: str = fsrc.read()
# do findall and write into file
with open(dst_file, 'w', encoding='utf-8') as fdst:
for item in re.findall('^LIBCMO_EXPORT[^;]+;', fulltext, re.MULTILINE):
# We should not only match BMAP_EXPORT,
# because it may match the defination of BMAP_EXPORT.
# So we add a bool at head because all BMap functions return bool.
for item in re.findall('^BMAP_EXPORT[ \\t]+bool[ \\t]+[^;]+;', fulltext, re.MULTILINE):
fdst.write(item)
fdst.write('\n')

View File

@ -28,6 +28,7 @@ public class PythonWriter {
cache.put("VxMatrix", "VxMatrix");
cache.put("CK_TEXTURE_SAVEOPTIONS", "enum");
cache.put("VX_PIXELFORMAT", "enum");
cache.put("VXLIGHT_TYPE", "enum");
cache.put("VXTEXTURE_BLENDMODE", "enum");
cache.put("VXTEXTURE_FILTERMODE", "enum");
cache.put("VXTEXTURE_ADDRESSMODE", "enum");
@ -39,19 +40,29 @@ public class PythonWriter {
return Collections.unmodifiableMap(cache);
}
public static String pythonTypeGetter(ExpFctParamDecl paramdecl) {
private static String pythonTypeGetter(ExpFctParamDecl paramdecl) throws IllegalArgumentException {
VariableType vt = paramdecl.mVarType;
if (!paramdecl.mIsInput) {
vt = vt.getPointerOfThis();
}
// create string builder for build final type string
StringBuilder sb = new StringBuilder();
// add type prefix
sb.append("bm_");
sb.append(g_CppTypeMap.get(vt.getBaseType()));
// try getting cpp type from base type
String cpp_type = g_CppTypeMap.get(vt.getBaseType());
if (cpp_type == null) {
throw new IllegalArgumentException("Unexpected type: " + vt.toCType());
}
// assign cpp type
sb.append(cpp_type);
// add pointer suffix
if (vt.isPointer()) {
sb.append("_");
sb.append(String.join("", Collections.nCopies(vt.getPointerLevel(), "p")));
}
// return built type string.
return sb.toString();
}
@ -59,15 +70,7 @@ public class PythonWriter {
OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.py");
IndentHelper helper = new IndentHelper(writer);
// write snippet
CommonHelper.writeSnippet(writer, "snippets/header.py");
// write function decls
helper.puts("");
helper.puts("#region Function Defines");
helper.puts("");
for (ExpFctDecl fctdecl : data) {
// write annotation
// function name
@ -87,10 +90,6 @@ public class PythonWriter {
.stream().map(value -> pythonTypeGetter(value)).collect(Collectors.joining(", ")));
}
helper.puts("");
helper.puts("#endregion");
helper.puts("");
writer.close();
}

View File

@ -2,28 +2,51 @@ import java.util.Collections;
import java.util.Vector;
import java.util.stream.Collectors;
/**
* The class represent the type of each parameters and function return value.
*/
public class VariableType {
/**
* The base type of this variable which remove all ending stars. Each item is a
* part of namespace string. If no namespace, this Vector will only have one
* item.
* The base type of this variable removing all ending stars (remove all pointer
* levels) Each item in this a part of namespace and the last one must be the
* type itself (without any namespace restriction). If no namespace restriction
* for this type, this Vector will only have one item.
* <p>
* For end user, it is enough that knowing the last item is type itself.
*/
private Vector<String> mBaseType;
/**
* The pointer level of this type. It is equal with the count of stars.
* The pointer level of this type. It is equal to the count of trailing star of
* this field in C style representation.
*/
private int mPointerLevel;
/**
* Construct an empty varible type. This is commonly used constructor.
*/
public VariableType() {
mBaseType = new Vector<String>();
mPointerLevel = 0;
}
/**
* The constructor used for cloning self. This constructor is only can be used
* by self.
*
* @param base_type The hierarchy of the variable type.
* @param pointer_level The pointer level of new created variable type.
*/
private VariableType(Vector<String> base_type, int pointer_level) {
mBaseType = (Vector<String>) base_type.clone();
mPointerLevel = pointer_level;
}
/**
* Set this variable type with a type string in C/C++ style. For example
* "NSTest::NSTest2::MyType**".
*
* @param ctype The type string in C/C++ style.
*/
public void fromCType(String ctype) {
if (ctype.isEmpty())
throw new IllegalArgumentException("empty string can not be parsed.");
@ -43,7 +66,7 @@ public class VariableType {
namepart = ctype.substring(0, star_pos);
mPointerLevel = len - star_pos;
}
// resolve name part
mBaseType.clear();
for (String item : namepart.split("::")) {
@ -51,31 +74,78 @@ public class VariableType {
}
}
/**
* Build a type string represented by this variable type in C/C++ style.
*
* @return The type string in C/C++ style.
*/
public String toCType() {
return mBaseType.stream().collect(Collectors.joining("::"))
+ String.join("", Collections.nCopies(mPointerLevel, "*"));
}
/**
* Get the base type of this variable type without any namespace. It just simply
* get the last entry in type hierarchy.
*
* @return The base type string without namespace prefix.
*/
public String getBaseType() {
return mBaseType.lastElement();
}
/**
* Check whether this variable type is a pointer. This function just check
* whether the pointer level of this variavle type is zero.
*
* @return True if it is pointer, otherwise false.
*/
public boolean isPointer() {
return mPointerLevel != 0;
}
/**
* Return the pointer level of this variable type. You can simply assume the
* pointer level is equal to the count of trailing star.
*
* @return The pointer level integer. Zero means that this type is not a
* pointer.
*/
public int getPointerLevel() {
return mPointerLevel;
}
/**
* Return the clone of the type hierarchy of this variable type.
* <p>
* It is rarely used. This only should be used when you need the namespace
* hierarchy of this variable type.
*
* @return The clone of current variable type hierarchy.
*/
public Vector<String> getBaseTypeHierarchy() {
return (Vector<String>) mBaseType.clone();
}
/**
* Check whether this type is a valid one. It actually check whether type
* hierarchy include at least one entry.
*
* @return True if no problem of this type, otherwise false.
*/
public boolean isValid() {
return mBaseType.size() != 0;
}
/**
* Return a new created variable type which is the pointer of this variable
* type.
* <p>
* In internal implementation, it just create a clone of current variable type
* with the increase of pointer level by 1.
*
* @return The new created pointer type of this variable type.
*/
public VariableType getPointerOfThis() {
return new VariableType(mBaseType, mPointerLevel + 1);
}

View File

@ -1,106 +0,0 @@
import ctypes, os, sys, typing
#region Type Defines
class BMapException(Exception):
"""
The exception thrown by BMap bindings.
"""
pass
bm_CKSTRING = ctypes.c_char_p
bm_CKSTRING_p = ctypes.POINTER(bm_CKSTRING)
bm_CKDWORD = ctypes.c_uint32
bm_CKDWORD_p = ctypes.POINTER(bm_CKDWORD)
bm_CKDWORD_pp = ctypes.POINTER(bm_CKDWORD_p)
bm_CKWORD = ctypes.c_uint16
bm_CKWORD_p = ctypes.POINTER(bm_CKWORD)
bm_CKWORD_pp = ctypes.POINTER(bm_CKWORD_p)
bm_CKID = ctypes.c_uint32
bm_CKID_p = ctypes.POINTER(bm_CKID)
bm_CKID_pp = ctypes.POINTER(bm_CKID_p)
bm_CKFLOAT = ctypes.c_float
bm_CKFLOAT_p = ctypes.POINTER(bm_CKFLOAT)
bm_CKINT = ctypes.c_int32
bm_CKBYTE = ctypes.c_uint8
bm_CKBYTE_p = ctypes.POINTER(bm_CKBYTE)
bm_enum = bm_CKDWORD
bm_enum_p = ctypes.POINTER(bm_enum)
bm_bool = ctypes.c_bool
bm_bool_p = ctypes.POINTER(bm_bool)
bm_void_p = ctypes.c_void_p
bm_void_pp = ctypes.POINTER(ctypes.c_void_p)
bm_callback = ctypes.CFUNCTYPE(None, bm_CKSTRING)
class bm_VxVector2(ctypes.Structure):
_fields_ = [
('x', bm_CKFLOAT),
('y', bm_CKFLOAT),
]
bm_VxVector2_p = ctypes.POINTER(bm_VxVector2)
bm_VxVector2_pp = ctypes.POINTER(bm_VxVector2_p)
class bm_VxVector3(ctypes.Structure):
_fields_ = [
('x', bm_CKFLOAT),
('y', bm_CKFLOAT),
('z', bm_CKFLOAT),
]
bm_VxVector3_p = ctypes.POINTER(bm_VxVector3)
bm_VxVector3_pp = ctypes.POINTER(bm_VxVector3_p)
class bm_VxColor(ctypes.Structure):
_fields_ = [
('r', bm_CKFLOAT),
('g', bm_CKFLOAT),
('b', bm_CKFLOAT),
('a', bm_CKFLOAT),
]
bm_VxColor_p = ctypes.POINTER(bm_VxColor)
class bm_VxMatrix(ctypes.Structure):
_fields_ = list(
(f'i{idx}', bm_CKFLOAT) for idx in range(16)
)
bm_VxMatrix_p = ctypes.POINTER(bm_VxMatrix)
#endregion
#region BMap Loader
_g_BMapLibName: str
if sys.platform.startswith('win32') or sys.platform.startswith('cygwin'):
_g_BMapLibName = "BMap.dll"
elif sys.platform.startswith('linux') or sys.platform.startswith('freebsd'):
_g_BMapLibName = "BMap.so"
elif sys.platform.startswith('darwin'):
_g_BMapLibName = "BMap.dylib"
else:
_g_BMapLibName = "BMap.bin"
_g_BMapModule: ctypes.CDLL | None = None
try:
_g_BMapModule = ctypes.cdll.LoadLibrary(
os.path.join(os.path.dirname(__file__), _g_BMapLibName)
)
except:
_g_BMapModule = None
def is_bmap_available() -> bool:
return _g_BMapModule is not None
def _bmap_error_check(result: bool, func, args):
if not result:
raise BMapException("BMap operation failed.")
return result
def _create_bmap_func(fct_name: str, fct_params: list[typing.Any]) -> typing.Callable[..., bm_bool]:
if _g_BMapModule is None: return None
cache: typing.Callable[..., bm_bool] = getattr(_g_BMapModule, fct_name)
cache.argtypes = fct_params
cache.restype = bm_bool
cache.errcheck = _bmap_error_check
return cache
#endregion

View File

@ -2,7 +2,7 @@
dest/*
!dest/*.gitkeep
# Antlr output
# ===== ANTLR Output =====
*.interp
*.tokens
@ -10,6 +10,7 @@ CKGeneralLexer*.java
CKEnumsParser*.java
CKDefinesParser*.java
# ===== Eclipse Java =====
# Eclipse projects
.classpath
.project

View File

@ -0,0 +1,168 @@
import java.io.OutputStreamWriter;
/**
* Write enum declarations and accessible value into CSharp format.
*/
public class CSharpWriter {
// =========== C# Enum Declaration Writer ===========
/**
* Get corredponding C# underlying type of given enum.
* <p>
* This is C# specific function.
*
* @param canUnsigned The parameter stored in Enum_t that indicate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
private static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "uint" : "int";
}
/**
* Internal real enum declaration writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CSharp);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
// write flasg attribute if it is
if (enum_t.mUseFlags) {
indent.puts("[Flags]");
}
indent.printf("public enum %s : %s {", enum_t.mEnumName, getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
/**
* Write an enum declaration collection into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum declaration into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create collection from single enum
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== C# Enum Accessible Value Writer ===========
/**
* Internal real enum accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CSharp);
// write enum collections
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf(
"public static readonly System.Collections.Generic.Dictionary<%s, string> %s = new System.Collections.Generic.Dictionary<%s, string>() {",
enum_t.mEnumName, enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ %s.%s, \"%s\" },", enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum accessible value collection into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create a collection with single enum.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col);
fs.close();
}
}

View File

@ -1,28 +0,0 @@
import java.io.OutputStreamWriter;
import java.util.stream.Collectors;
/**
* The nameof values writer for CK_CLASSID.
*/
public class ClassidWriter {
public static void writeAccVal(String filename, EnumsHelper.Enum_t classids) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
indent.puts("const CkClassidReflectionArray CK_CLASSID {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : classids.mEntries) {
EnumsHelper.EnumEntryWithHierarchy_t specialized = (EnumsHelper.EnumEntryWithHierarchy_t) entry;
String hierarchy = specialized.mHierarchy.stream().map(value -> value.mEntryName)
.collect(Collectors.joining("\", \""));
indent.printf("{ LibCmo::CK2::CK_CLASSID::%s, { { \"%s\" } } },", entry.mEntryName, hierarchy);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -4,7 +4,6 @@ import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.antlr.v4.runtime.*;
@ -110,17 +109,6 @@ public class CommonHelper {
return numstr.replaceFirst("[ulUL]+$", "");
}
/**
* Get underlying type of enum.
*
* @param canUnsigned The parameter stored in Enum_t that indiccate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
public static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "CKDWORD" : "CKINT";
}
// =========== Parts ===========
enum CKParts {
@ -128,7 +116,7 @@ public class CommonHelper {
}
enum LangType {
CPP, Python
Cpp, Python, CSharp
}
public static String getCKPartsNamespace(CKParts parts) {

View File

@ -0,0 +1,273 @@
import java.io.OutputStreamWriter;
import java.util.stream.Collectors;
/**
* Write enum declarations and accessible value into C++ format.
*/
public class CppWriter {
// =========== C++ Enum Declaration Writer ===========
/**
* Get corredponding C++ underlying type of given enum.
* <p>
* This is C++ specific function.
*
* @param canUnsigned The parameter stored in Enum_t that indicate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
private static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "CKDWORD" : "CKINT";
}
/**
* Internal real enum declarations writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
indent.printf("enum class %s : %s {", enum_t.mEnumName, getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum collection into given file.
* <p>
* Actually this is a wrapper of internal enum collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum into given file.
* <p>
* Actually this is a wrapper of internal enum collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create an collection from single enum declaration
// for suit the argument requirement of real writer.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== C++ Enum Accessible Value Writer ===========
/**
* Internal real enum collection accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @param parts The part of these enum declarations. It will indicate the
* namespace where find given enum collection.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog,
CommonHelper.CKParts parts) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct GeneralReflection { const char8_t* mName; };");
indent.puts("// template<typename _Ty, std::enable_if_t<std::is_enum_v<_Ty>, int> = 0>");
indent.puts("// using GeneralReflectionArray = std::vector<std::pair<_Ty, GeneralReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
// write declarations
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
indent.printf("extern const GeneralReflectionArray<LibCmo::%s::%s> %s;",
CommonHelper.getCKPartsNamespace(parts), enum_t.mEnumName, enum_t.mEnumName);
}
indent.puts("");
indent.puts("");
indent.puts("");
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("const GeneralReflectionArray<LibCmo::%s::%s> %s {", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ LibCmo::%s::%s::%s, { u8\"%s\" } },", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum collection accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum collection accessible value
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @param parts The part of these enum declarations.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog, CommonHelper.CKParts parts)
throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog, parts);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum collection accessible value
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @param parts The part of these enum declarations.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
// create a enum collection to fulfill the requirement of internal writer.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col, parts);
fs.close();
}
// =========== Specialized C++ Enum Accessible Value Writer ===========
// Only accessible value part of CERROR and CK_CLASSID need to be specialized.
// The enum self do not need special treat. Just write them normally.
/**
* Specialized CKERROR accessible value writer.
* <p>
* The declaration of CKERROR do not need special treat. It is okey to use
* common writer.
*
* @param filename The name of written file.
* @param errors The {@linkplain EnumsHelper.Enum_t} instance storing CKERROR.
* @throws Exception
*/
public static void writeCkErrorAccVal(String filename, EnumsHelper.Enum_t errors) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct CkErrorReflection { const char8_t* mName; const char8_t* mDescription; };");
indent.puts("// using CkErrorReflectionArray = std::vector<std::pair<LibCmo::CK2::CKERROR, CkErrorReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
// write implementation
indent.puts("const CkErrorReflectionArray CKERROR {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : errors.mEntries) {
String comment = CommonHelper.escapeString(entry.mEntryComment);
if (comment == null)
comment = "";
indent.printf("{ LibCmo::CK2::CKERROR::%s, { u8\"%s\", u8\"%s\" } },", entry.mEntryName, entry.mEntryName,
comment);
}
indent.dec();
indent.puts("};");
writer.close();
}
/**
* Specialized CK_CLASSID accessible value writer.
* <p>
* The declaration of CK_CLASSID do not need special treat. It is okey to use
* common writer.
*
* @param filename The name of written file.
* @param classids The {@linkplain EnumsHelper.Enum_t} instance storing
* CK_CLASSID.
* @throws Exception
*/
public static void writeCkClassidAccVal(String filename, EnumsHelper.Enum_t classids) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct CkClassidReflection { std::vector<const char8_t*> mHierarchy; };");
indent.puts("// using CkClassidReflectionArray = std::vector<std::pair<LibCmo::CK2::CK_CLASSID, CkClassidReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
indent.puts("const CkClassidReflectionArray CK_CLASSID {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : classids.mEntries) {
EnumsHelper.EnumEntryWithHierarchy_t specialized = (EnumsHelper.EnumEntryWithHierarchy_t) entry;
String hierarchy = specialized.mHierarchy.stream().map(value -> value.mEntryName)
.collect(Collectors.joining("\", u8\""));
indent.printf("{ LibCmo::CK2::CK_CLASSID::%s, { { u8\"%s\" } } },", entry.mEntryName, hierarchy);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -1,26 +0,0 @@
import java.io.OutputStreamWriter;
/**
* The nameof values writer for CKERROR
*/
public class ErrorsWriter {
public static void writeAccVal(String filename, EnumsHelper.Enum_t errors) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
indent.puts("const CkErrorReflectionArray CKERROR {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : errors.mEntries) {
String comment = CommonHelper.escapeString(entry.mEntryComment);
if (comment == null)
comment = "";
indent.printf("{ LibCmo::CK2::CKERROR::%s, { \"%s\", \"%s\" } },", entry.mEntryName, entry.mEntryName,
comment);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -1,212 +0,0 @@
import java.io.OutputStreamWriter;
import java.util.Locale;
/**
* Generic Enum Writer. Including Data Type Defination and Nameof Values.
*/
public class GeneralWriter {
public static void writeEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
indent.printf("enum class %s : %s {", enum_t.mEnumName,
CommonHelper.getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeEnums(fs, prog);
fs.close();
}
public static void writeEnum(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writeEnums(writer, col);
}
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeEnum(fs, _enum);
fs.close();
}
public static void writeAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog,
CommonHelper.CKParts parts) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
// write decls
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
indent.printf("extern const GeneralReflectionArray<LibCmo::%s::%s> %s;",
CommonHelper.getCKPartsNamespace(parts), enum_t.mEnumName, enum_t.mEnumName);
}
indent.puts("");
indent.puts("");
indent.puts("");
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("const GeneralReflectionArray<LibCmo::%s::%s> %s {", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ LibCmo::%s::%s::%s, {\"%s\"} },", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog, CommonHelper.CKParts parts)
throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeAccVals(fs, prog, parts);
fs.close();
}
public static void writeAccVal(OutputStreamWriter writer, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writeAccVals(writer, col, parts);
}
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeAccVal(fs, _enum, parts);
fs.close();
}
public static void writePyEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum start
indent.printf("class %s(enum.IntEnum):", enum_t.mEnumName);
indent.inc();
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s = auto()", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s", enumEntry_t.mEntryName,
CommonHelper.convertToPythonNumber(enumEntry_t.mEntryValue));
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// enum tail
indent.dec();
}
}
public static void writePyEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyEnums(fs, prog);
fs.close();
}
public static void writePyEnum(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writePyEnums(writer, col);
}
public static void writePyEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyEnum(fs, _enum);
fs.close();
}
private static String extractHumanReadableEntryName(String entry_name) {
// remove first part (any content before underline '_')
entry_name = entry_name.replaceFirst("^[a-zA-Z0-9]+_", "");
// lower all chars except first char
if (entry_name.length() < 1)
return entry_name;
else
return entry_name.substring(0, 1) + entry_name.substring(1).toLowerCase(Locale.ROOT);
}
public static void writePyAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("g_Annotation_%s: dict[int, EnumAnnotation] = {", enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
String comment = "";
if (enumEntry_t.mEntryComment != null) {
comment = CommonHelper.escapeString(enumEntry_t.mEntryComment);
}
indent.printf("%s.%s.value: EnumAnnotation(\"%s\", \"%s\"),", enum_t.mEnumName, enumEntry_t.mEntryName,
extractHumanReadableEntryName(enumEntry_t.mEntryName), comment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
public static void writePyAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyAccVals(fs, prog);
fs.close();
}
public static void writePyAccVal(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writePyAccVals(writer, col);
}
public static void writePyAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyAccVal(fs, _enum);
fs.close();
}
}

View File

@ -8,7 +8,8 @@ public class IndentHelper {
// set indent chars
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
mIndentChars = CommonHelper.getIndentString(true);
break;
case Python:
@ -67,7 +68,8 @@ public class IndentHelper {
return;
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
puts("/**");
mWriter.write(System.lineSeparator());
@ -100,7 +102,8 @@ public class IndentHelper {
mWriter.write(mIndentChars);
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
mWriter.write(String.format("/**< %s */", CommonHelper.removeEol(comment)));
break;
case Python:

View File

@ -1,10 +1,21 @@
import java.io.OutputStreamWriter;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class MainRunner {
/**
* Extract an enums collection from given file.
* <p>
* This function is the most commonly used function for extracting enums.
* <p>
* This function is used for a file which only contain enum declarations. This
* is not suit for extracting CKERROR and CK_CLASSID. For these declarations,
* please use their specialized extractor as described following.
*
* @param infile The file for reading.
* @return An {@linkplain EnumsHelper.EnumCollection_t} instance.
* @throws Exception
*/
private static EnumsHelper.EnumCollection_t getEnumsCollection(String infile) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -20,6 +31,21 @@ public class MainRunner {
return worker.getEnums();
}
/**
* Extract a series of "#define" syntax as an enum.
* <p>
* This function will assume that given file only contain C++ "#define" syntax.
* After reading it, it will re-organize it as an enum and return. This only is
* used by CKERROR now. But it suit for more scenarios if there are something
* like CKERROR in future.
*
* @param infile The file for reading.
* @param assignedEnumName The desired name of organized enum instance.
* Contemporary this field should always be "CKERROR"
* because no one else is using it.
* @return An {@linkplain EnumsHelper.Enum_t} instance.
* @throws Exception
*/
private static EnumsHelper.Enum_t organiseDefines(String infile, String assignedEnumName) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -38,6 +64,22 @@ public class MainRunner {
return result;
}
/**
* Extract a series of macro define as an enum, considering its indent to build
* hierarchy.
* <p>
* This is specialized enum extractor of CK_CLASSID. The given file should use a
* series "#define" syntax to describe enum, and use Tab as the indent before
* each "#define" syntax to indicate its hierarchy.
*
* @param infile The file for reading.
* @return An {@linkplain EnumsHelper.Enum_t} instance. Actually it is an
* instance to {@linkplain EnumsHelper.Enum_t} whose entries is
* {@linkplain EnumsHelper.EnumEntryWithHierarchy_t}, the child class of
* {@linkplain EnumsHelper.EnumEntry_t} (the entry type of common
* {@linkplain EnumsHelper.Enum_t}) with extra hierarchy infos.
* @throws Exception
*/
private static EnumsHelper.Enum_t organiseClassid(String infile) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -59,57 +101,82 @@ public class MainRunner {
public static void main(String[] args) throws Exception {
// =========== CKERROR ===========
EnumsHelper.Enum_t ckerror = organiseDefines("src/CKError.txt", "CKERROR");
GeneralWriter.writeEnum("dest/CKError.hpp", ckerror);
GeneralWriter.writePyEnum("dest/CKError.py", ckerror);
ErrorsWriter.writeAccVal("dest/CKError.AccVal.hpp", ckerror);
GeneralWriter.writePyAccVal("dest/CKError.AccVal.py", ckerror);
EnumsHelper.Enum_t ckerror = organiseDefines("src/CKERROR.txt", "CKERROR");
CppWriter.writeEnum("dest/CKERROR.hpp", ckerror);
PythonWriter.writeEnum("dest/CKERROR.py", ckerror);
CSharpWriter.writeEnum("dest/CKERROR.cs", ckerror);
CppWriter.writeCkErrorAccVal("dest/CKERROR.AccVal.hpp", ckerror);
PythonWriter.writeAccVal("dest/CKERROR.AccVal.py", ckerror);
CSharpWriter.writeAccVal("dest/CKERROR.AccVal.cs", ckerror);
// =========== CK_CLASSID ===========
EnumsHelper.Enum_t classid = organiseClassid("src/CK_CLASSID.txt");
GeneralWriter.writeEnum("dest/CK_CLASSID.hpp", classid);
GeneralWriter.writePyEnum("dest/CK_CLASSID.py", classid);
ClassidWriter.writeAccVal("dest/CK_CLASSID.AccVal.hpp", classid);
GeneralWriter.writePyAccVal("dest/CK_CLASSID.AccVal.py", classid);
CppWriter.writeEnum("dest/CK_CLASSID.hpp", classid);
PythonWriter.writeEnum("dest/CK_CLASSID.py", classid);
CSharpWriter.writeEnum("dest/CK_CLASSID.cs", classid);
CppWriter.writeCkClassidAccVal("dest/CK_CLASSID.AccVal.hpp", classid);
PythonWriter.writeAccVal("dest/CK_CLASSID.AccVal.py", classid);
// =========== Define2 ===========
// Define2 do not need values.
// Define2 do not need annotation output.
// Because they are CKStateChunk used value which are not exposed to outside.
EnumsHelper.EnumCollection_t def2 = getEnumsCollection("src/Defines2.txt");
GeneralWriter.writeEnums("dest/CK_CLASSID.hpp", def2);
GeneralWriter.writePyEnums("dest/CK_CLASSID.py", def2);
CppWriter.writeEnums("dest/Defines2.hpp", def2);
PythonWriter.writeEnums("dest/Defines2.py", def2);
CSharpWriter.writeEnums("dest/Defines2.cs", def2);
// =========== Combined enums ===========
EnumsHelper.EnumCollection_t ck2Enums = getEnumsCollection("src/CKEnums.txt"),
vxEnums = getEnumsCollection("src/VxEnums.txt");
GeneralWriter.writeEnums("dest/CKEnums.hpp", ck2Enums);
GeneralWriter.writePyEnums("dest/CKEnums.py", ck2Enums);
GeneralWriter.writeAccVals("dest/CKEnums.AccVal.hpp", ck2Enums, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVals("dest/CKEnums.AccVal.py", ck2Enums);
GeneralWriter.writeEnums("dest/VxEnums.hpp", vxEnums);
GeneralWriter.writePyEnums("dest/VxEnums.py", vxEnums);
GeneralWriter.writeAccVals("dest/VxEnums.AccVal.hpp", vxEnums, CommonHelper.CKParts.VxMath);
GeneralWriter.writePyAccVals("dest/VxEnums.AccVal.py", vxEnums);
CppWriter.writeEnums("dest/CKEnums.hpp", ck2Enums);
PythonWriter.writeEnums("dest/CKEnums.py", ck2Enums);
CSharpWriter.writeEnums("dest/CKEnums.cs", ck2Enums);
CppWriter.writeAccVals("dest/CKEnums.AccVal.hpp", ck2Enums, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVals("dest/CKEnums.AccVal.py", ck2Enums);
CSharpWriter.writeAccVals("dest/CKEnums.AccVal.cs", ck2Enums);
CppWriter.writeEnums("dest/VxEnums.hpp", vxEnums);
PythonWriter.writeEnums("dest/VxEnums.py", vxEnums);
CSharpWriter.writeEnums("dest/VxEnums.cs", vxEnums);
CppWriter.writeAccVals("dest/VxEnums.AccVal.hpp", vxEnums, CommonHelper.CKParts.VxMath);
PythonWriter.writeAccVals("dest/VxEnums.AccVal.py", vxEnums);
CSharpWriter.writeAccVals("dest/VxEnums.AccVal.cs", vxEnums);
// =========== Single enums ===========
EnumsHelper.Enum_t single;
single = organiseDefines("src/CK_STATECHUNK_CHUNKVERSION.txt", "CK_STATECHUNK_CHUNKVERSION");
GeneralWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.hpp", single);
GeneralWriter.writePyEnum("dest/CK_STATECHUNK_CHUNKVERSION.py", single);
GeneralWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.py", single);
CppWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.hpp", single);
PythonWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.py", single);
CSharpWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.cs", single);
CppWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.cs", single);
single = organiseDefines("src/CK_STATECHUNK_DATAVERSION.txt", "CK_STATECHUNK_DATAVERSION");
GeneralWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.hpp", single);
GeneralWriter.writePyEnum("dest/CK_STATECHUNK_DATAVERSION.py", single);
GeneralWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.py", single);
CppWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.hpp", single);
PythonWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.py", single);
CSharpWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.cs", single);
CppWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.cs", single);
single = organiseDefines("src/CK_BITMAPDATA_FLAGS.txt", "CK_BITMAPDATA_FLAGS");
GeneralWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.hpp", single);
GeneralWriter.writePyEnum("dest/CK_BITMAPDATA_FLAGS.py", single);
GeneralWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.py", single);
CppWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.hpp", single);
PythonWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.py", single);
CSharpWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.cs", single);
CppWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.cs", single);
single = organiseDefines("src/CK_CAMERA_PROJECTION.txt", "CK_CAMERA_PROJECTION");
CppWriter.writeEnum("dest/CK_CAMERA_PROJECTION.hpp", single);
PythonWriter.writeEnum("dest/CK_CAMERA_PROJECTION.py", single);
CSharpWriter.writeEnum("dest/CK_CAMERA_PROJECTION.cs", single);
CppWriter.writeAccVal("dest/CK_CAMERA_PROJECTION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_CAMERA_PROJECTION.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_CAMERA_PROJECTION.AccVal.cs", single);
// print message.
System.out.println("DONE!");

View File

@ -0,0 +1,185 @@
import java.io.OutputStreamWriter;
import java.util.Locale;
/**
* Write enum declarations and accessible value into Python format.
*/
public class PythonWriter {
// =========== Python Enum Declaration Writer ===========
/**
* Internal real enum declaration writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum start
indent.printf("class %s(enum.IntEnum):", enum_t.mEnumName);
indent.inc();
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s = auto()", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s", enumEntry_t.mEntryName,
CommonHelper.convertToPythonNumber(enumEntry_t.mEntryValue));
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// enum tail
indent.dec();
}
}
/**
* Write an enum declaration collection into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum declaration into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create collection from single enum
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== Python Enum Accessible Value Writer ===========
/**
* Try generate human readable name from enum entry name.
* <p>
* This function is only served for Python code generation.
* <p>
* As you noticed, almost entries of CK enums are fully capital and splitted by
* underline. This is really not good for human reading, especially those who
* are not programmer. So this function will try give these programmer-oriented
* entry name a human readable name as its display name. However, this extract
* method is not perfect. It simply do some split and replacement so the
* generated content may still not good for reader.
*
* @param entry_name The name of enum entry
* @return A human readable entry name. No guaranteen that return value is must
* human readable.
*/
private static String extractHumanReadableEntryName(String entry_name) {
// remove first part (any content before underline '_')
entry_name = entry_name.replaceFirst("^[a-zA-Z0-9]+_", "");
// lower all chars except first char
if (entry_name.length() < 1)
return entry_name;
else
return entry_name.substring(0, 1) + entry_name.substring(1).toLowerCase(Locale.ROOT);
}
/**
* Internal real enum accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("g_Annotation_%s: dict[int, EnumAnnotation] = {", enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
String comment = "";
if (enumEntry_t.mEntryComment != null) {
comment = CommonHelper.escapeString(enumEntry_t.mEntryComment);
}
indent.printf("%s.%s.value: EnumAnnotation(\"%s\", \"%s\"),", enum_t.mEnumName, enumEntry_t.mEntryName,
extractHumanReadableEntryName(enumEntry_t.mEntryName), comment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
/**
* Write an enum accessible value collection into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create a collection with single enum.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col);
fs.close();
}
}

View File

@ -1,6 +1,10 @@
# Code Gen
# Enums Migration
A helper program to generate some definations.
A helper program to migrate existing Virtools enum declarations into other formats.
Original Virtools SDK have various enum declarations. All of them are defined as C format and their formation are not uniform. This sub-project will use laxer and parser to recognize these diverse declarations, extract them as a series of uniform Java data struct and output them as C++ code (as C++ enum class syntax for LibCmo using), Python code (for PyBMap using), and C# code (for BMapSharp using).
The steps processing existing enum declaration is called migration as this sub-project name told.
```
antlr4 CKGeneralLexer.g4

View File

@ -0,0 +1,4 @@
#define CK_PERSPECTIVEPROJECTION 1
#define CK_ORTHOGRAPHICPROJECTION 2

View File

@ -41,6 +41,25 @@ typedef enum VX_PIXELFORMAT {
_4_ARGB8888_CLUT = 31 // 4 bits indexed CLUT (ARGB)
} VX_PIXELFORMAT;
/******************************************************************
{filename:VXLIGHT_TYPE}
Summary: Light type.
Remarks:
+ Used by CKLight::SetType to specify the type of a light.
See also: CKLight::SetType,CKLight::GetType
******************************************************************/
typedef enum VXLIGHT_TYPE
{
VX_LIGHTPOINT = 1UL, // The Light is a point of light
VX_LIGHTSPOT = 2UL, // The light is a spotlight
VX_LIGHTDIREC = 3UL, // The light is directional light : Lights comes from an infinite point so only direction of light can be given
VX_LIGHTPARA = 4UL // Obsolete, do not use
} VXLIGHT_TYPE;
/*****************************************************************
{filename:VXTEXTURE_BLENDMODE}
Summary: Blend Mode Flags

2
CodeGen/UniversalEncoding/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Result
*.cpp

View File

@ -0,0 +1,98 @@
Encoding Alias Code Page Iconv Identifier
ascii 646, us-ascii 437 ASCII
big5 big5-tw, csbig5 950 BIG5
big5hkscs big5-hkscs, hkscs BIG5-HKSCS
cp037 IBM037, IBM039 037
cp273 273, IBM273, csIBM273
cp424 EBCDIC-CP-HE, IBM424
cp437 437, IBM437 437
cp500 EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500 500
cp720 720
cp737 737
cp775 IBM775 775
cp850 850, IBM850 850 CP850
cp852 852, IBM852 852
cp855 855, IBM855 855
cp856
cp857 857, IBM857 857
cp858 858, IBM858 858
cp860 860, IBM860 860
cp861 861, CP-IS, IBM861 861
cp862 862, IBM862 862 CP862
cp863 863, IBM863 863
cp864 IBM864 864
cp865 865, IBM865 865
cp866 866, IBM866 866 CP866
cp869 869, CP-GR, IBM869 869
cp874 874 CP874
cp875 875
cp932 932, ms932, mskanji, ms-kanji, windows-31j 932 CP932
cp949 949, ms949, uhc 949 CP949
cp950 950, ms950 950 CP950
cp1006
cp1026 ibm1026 1026
cp1125 1125, ibm1125, cp866u, ruscii
cp1140 ibm1140 1140
cp1250 windows-1250 1250 CP1250
cp1251 windows-1251 1251 CP1251
cp1252 windows-1252 1252 CP1252
cp1253 windows-1253 1253 CP1253
cp1254 windows-1254 1254 CP1254
cp1255 windows-1255 1255 CP1255
cp1256 windows-1256 1256 CP1256
cp1257 windows-1257 1257 CP1257
cp1258 windows-1258 1258 CP1258
euc_jp eucjp, ujis, u-jis 20932 EUC-JP
euc_jis_2004 jisx0213, eucjis2004
euc_jisx0213 eucjisx0213
euc_kr euckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 51949 EUC-KR
gb2312 chinese, csiso58gb231280, euc-cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso-ir-58 936 CP936
gbk 936, cp936, ms936 936 GBK
gb18030 gb18030-2000 54936 GB18030
hz hzgb, hz-gb, hz-gb-2312 52936 HZ
iso2022_jp csiso2022jp, iso2022jp, iso-2022-jp 50220 ISO-2022-JP
iso2022_jp_1 iso2022jp-1, iso-2022-jp-1 ISO-2022-JP-1
iso2022_jp_2 iso2022jp-2, iso-2022-jp-2 ISO-2022-JP-2
iso2022_jp_2004 iso2022jp-2004, iso-2022-jp-2004
iso2022_jp_3 iso2022jp-3, iso-2022-jp-3
iso2022_jp_ext iso2022jp-ext, iso-2022-jp-ext
iso2022_kr csiso2022kr, iso2022kr, iso-2022-kr 50225 ISO-2022-KR
latin_1 iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1 28591 ISO-8859-1
iso8859_2 iso-8859-2, latin2, L2 28592 ISO-8859-2
iso8859_3 iso-8859-3, latin3, L3 28593 ISO-8859-3
iso8859_4 iso-8859-4, latin4, L4 28594 ISO-8859-4
iso8859_5 iso-8859-5, cyrillic 28595 ISO-8859-5
iso8859_6 iso-8859-6, arabic 28596 ISO-8859-6
iso8859_7 iso-8859-7, greek, greek8 28597 ISO-8859-7
iso8859_8 iso-8859-8, hebrew 28598 ISO-8859-8
iso8859_9 iso-8859-9, latin5, L5 28599 ISO-8859-9
iso8859_10 iso-8859-10, latin6, L6 ISO-8859-10
iso8859_11 iso-8859-11, thai ISO-8859-11
iso8859_13 iso-8859-13, latin7, L7 28603 ISO-8859-13
iso8859_14 iso-8859-14, latin8, L8 ISO-8859-14
iso8859_15 iso-8859-15, latin9, L9 28605 ISO-8859-15
iso8859_16 iso-8859-16, latin10, L10 ISO-8859-16
johab cp1361, ms1361 1361 JOHAB
koi8_r
koi8_t KOI8-T
koi8_u
kz1048 kz_1048, strk1048_2002, rk1048
mac_cyrillic maccyrillic 10007 MacCyrillic
mac_greek macgreek 10006 MacGreek
mac_iceland maciceland 10079 MacIceland
mac_latin2 maclatin2, maccentraleurope, mac_centeuro
mac_roman macroman, macintosh MacRoman
mac_turkish macturkish 10081 MacTurkish
ptcp154 csptcp154, pt154, cp154, cyrillic-asian PT154
shift_jis csshiftjis, shiftjis, sjis, s_jis 932 SHIFT_JIS
shift_jis_2004 shiftjis2004, sjis_2004, sjis2004
shift_jisx0213 shiftjisx0213, sjisx0213, s_jisx0213
utf_32 U32, utf32 UTF-32
utf_32_be UTF-32BE UTF-32BE
utf_32_le UTF-32LE UTF-32LE
utf_16 U16, utf16 UTF16
utf_16_be UTF-16BE UTF-16BE
utf_16_le UTF-16LE UTF-16LE
utf_7 U7, unicode-1-1-utf-7 65000 UTF-7
utf_8 U8, UTF, utf8, utf-8, cp65001 65001 UTF-8
utf_8_sig
1 Encoding Alias Code Page Iconv Identifier
2 ascii 646, us-ascii 437 ASCII
3 big5 big5-tw, csbig5 950 BIG5
4 big5hkscs big5-hkscs, hkscs BIG5-HKSCS
5 cp037 IBM037, IBM039 037
6 cp273 273, IBM273, csIBM273
7 cp424 EBCDIC-CP-HE, IBM424
8 cp437 437, IBM437 437
9 cp500 EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500 500
10 cp720 720
11 cp737 737
12 cp775 IBM775 775
13 cp850 850, IBM850 850 CP850
14 cp852 852, IBM852 852
15 cp855 855, IBM855 855
16 cp856
17 cp857 857, IBM857 857
18 cp858 858, IBM858 858
19 cp860 860, IBM860 860
20 cp861 861, CP-IS, IBM861 861
21 cp862 862, IBM862 862 CP862
22 cp863 863, IBM863 863
23 cp864 IBM864 864
24 cp865 865, IBM865 865
25 cp866 866, IBM866 866 CP866
26 cp869 869, CP-GR, IBM869 869
27 cp874 874 CP874
28 cp875 875
29 cp932 932, ms932, mskanji, ms-kanji, windows-31j 932 CP932
30 cp949 949, ms949, uhc 949 CP949
31 cp950 950, ms950 950 CP950
32 cp1006
33 cp1026 ibm1026 1026
34 cp1125 1125, ibm1125, cp866u, ruscii
35 cp1140 ibm1140 1140
36 cp1250 windows-1250 1250 CP1250
37 cp1251 windows-1251 1251 CP1251
38 cp1252 windows-1252 1252 CP1252
39 cp1253 windows-1253 1253 CP1253
40 cp1254 windows-1254 1254 CP1254
41 cp1255 windows-1255 1255 CP1255
42 cp1256 windows-1256 1256 CP1256
43 cp1257 windows-1257 1257 CP1257
44 cp1258 windows-1258 1258 CP1258
45 euc_jp eucjp, ujis, u-jis 20932 EUC-JP
46 euc_jis_2004 jisx0213, eucjis2004
47 euc_jisx0213 eucjisx0213
48 euc_kr euckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 51949 EUC-KR
49 gb2312 chinese, csiso58gb231280, euc-cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso-ir-58 936 CP936
50 gbk 936, cp936, ms936 936 GBK
51 gb18030 gb18030-2000 54936 GB18030
52 hz hzgb, hz-gb, hz-gb-2312 52936 HZ
53 iso2022_jp csiso2022jp, iso2022jp, iso-2022-jp 50220 ISO-2022-JP
54 iso2022_jp_1 iso2022jp-1, iso-2022-jp-1 ISO-2022-JP-1
55 iso2022_jp_2 iso2022jp-2, iso-2022-jp-2 ISO-2022-JP-2
56 iso2022_jp_2004 iso2022jp-2004, iso-2022-jp-2004
57 iso2022_jp_3 iso2022jp-3, iso-2022-jp-3
58 iso2022_jp_ext iso2022jp-ext, iso-2022-jp-ext
59 iso2022_kr csiso2022kr, iso2022kr, iso-2022-kr 50225 ISO-2022-KR
60 latin_1 iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1 28591 ISO-8859-1
61 iso8859_2 iso-8859-2, latin2, L2 28592 ISO-8859-2
62 iso8859_3 iso-8859-3, latin3, L3 28593 ISO-8859-3
63 iso8859_4 iso-8859-4, latin4, L4 28594 ISO-8859-4
64 iso8859_5 iso-8859-5, cyrillic 28595 ISO-8859-5
65 iso8859_6 iso-8859-6, arabic 28596 ISO-8859-6
66 iso8859_7 iso-8859-7, greek, greek8 28597 ISO-8859-7
67 iso8859_8 iso-8859-8, hebrew 28598 ISO-8859-8
68 iso8859_9 iso-8859-9, latin5, L5 28599 ISO-8859-9
69 iso8859_10 iso-8859-10, latin6, L6 ISO-8859-10
70 iso8859_11 iso-8859-11, thai ISO-8859-11
71 iso8859_13 iso-8859-13, latin7, L7 28603 ISO-8859-13
72 iso8859_14 iso-8859-14, latin8, L8 ISO-8859-14
73 iso8859_15 iso-8859-15, latin9, L9 28605 ISO-8859-15
74 iso8859_16 iso-8859-16, latin10, L10 ISO-8859-16
75 johab cp1361, ms1361 1361 JOHAB
76 koi8_r
77 koi8_t KOI8-T
78 koi8_u
79 kz1048 kz_1048, strk1048_2002, rk1048
80 mac_cyrillic maccyrillic 10007 MacCyrillic
81 mac_greek macgreek 10006 MacGreek
82 mac_iceland maciceland 10079 MacIceland
83 mac_latin2 maclatin2, maccentraleurope, mac_centeuro
84 mac_roman macroman, macintosh MacRoman
85 mac_turkish macturkish 10081 MacTurkish
86 ptcp154 csptcp154, pt154, cp154, cyrillic-asian PT154
87 shift_jis csshiftjis, shiftjis, sjis, s_jis 932 SHIFT_JIS
88 shift_jis_2004 shiftjis2004, sjis_2004, sjis2004
89 shift_jisx0213 shiftjisx0213, sjisx0213, s_jisx0213
90 utf_32 U32, utf32 UTF-32
91 utf_32_be UTF-32BE UTF-32BE
92 utf_32_le UTF-32LE UTF-32LE
93 utf_16 U16, utf16 UTF16
94 utf_16_be UTF-16BE UTF-16BE
95 utf_16_le UTF-16LE UTF-16LE
96 utf_7 U7, unicode-1-1-utf-7 65000 UTF-7
97 utf_8 U8, UTF, utf8, utf-8, cp65001 65001 UTF-8
98 utf_8_sig

View File

@ -0,0 +1,63 @@
import typing
import io
import os
class LanguageToken:
m_Name: str
m_Alias: tuple[str, ...]
m_CodePage: str | None
m_IconvCode: str | None
def __init__(self, name: str, alias: typing.Iterator[str], code_page: str, iconv_code: str):
self.m_Name = name.lower()
self.m_Alias = tuple(map(lambda x: x.lower(), alias))
self.m_CodePage = None if code_page == '' else code_page
self.m_IconvCode = None if iconv_code == '' else iconv_code
def extract_data(fs: io.TextIOWrapper) -> tuple[str, ...]:
# remove first line to remove table header
return fs.readlines()[1:]
def extract_token(csv_data: tuple[str, ...]) -> tuple[LanguageToken, ...]:
ret: list[LanguageToken] = []
for line in csv_data:
line = line.strip('\n')
line_sp = line.split('\t')
alias_sp = filter(lambda x: x != '', map(lambda x: x.strip(), line_sp[1].split(',')))
ret.append(LanguageToken(line_sp[0], alias_sp, line_sp[2], line_sp[3]))
return tuple(ret)
def write_alias_map(fs: io.TextIOWrapper, data: tuple[LanguageToken, ...]) -> None:
fs.write('static const std::map<std::u8string, std::u8string> c_AliasMap {\n')
for i in data:
for j in i.m_Alias:
fs.write(f'\t{{ u8"{j}", u8"{i.m_Name}" }},\n')
fs.write('};\n')
def write_win_cp_map(fs: io.TextIOWrapper, data: tuple[LanguageToken, ...]) -> None:
fs.write('static const std::map<std::u8string, UINT> c_WinCPMap {\n')
for i in data:
if i.m_CodePage is not None:
fs.write(f'\t{{ u8"{i.m_Name}", static_cast<UINT>({i.m_CodePage}u) }},\n')
fs.write('};\n')
def write_iconv_map(fs: io.TextIOWrapper, data: tuple[LanguageToken, ...]) -> None:
fs.write('static const std::map<std::u8string, std::string> c_IconvMap {\n')
for i in data:
if i.m_IconvCode is not None:
fs.write(f'\t{{ u8"{i.m_Name}", "{i.m_IconvCode}" }},\n')
fs.write('};\n')
if __name__ == '__main__':
# get file path
self_path: str = os.path.dirname(__file__)
csv_file: str = os.path.join(self_path, 'EncodingTable.csv')
cpp_file: str = os.path.join(self_path, 'EncodingTable.cpp')
# process files
with open(csv_file, 'r', encoding='utf-8') as fr:
with open(cpp_file, 'w', encoding='utf-8') as fw:
data = extract_data(fr)
token = extract_token(data)
write_alias_map(fw, token)
write_win_cp_map(fw, token)
write_iconv_map(fw, token)

View File

@ -1,3 +1,3 @@
# Result
*.hpp
VxTypes.hpp
VxTypes.cpp

View File

@ -0,0 +1,3 @@
# Vector Generator
Vector types (LibCmo::VxMath::VxVector3 and etc) and Vector-like types (LibCmo::VxMath::VxColor and etc) nearly have similar declaration except slight differences (basically is the count of factors). Manually writing these declarations is boring and easy to cause potential invisible bugs. So we use a Python script to generate these declarations batchly to prevent any defects indroduced above.

View File

@ -0,0 +1,178 @@
{% import 'VxTypes.shared.jinja' as shared %}
{#
For friend operator overload, we do not need add CLASSNAME:: prefix for it.
Because they are not a part of that class.
#}
#pragma region {{ sname }}
{# Ctor type 1 - Default ctor -#}
{{ sname }}::{{ sname }}() : {{- shared.initialize_list_builder(svars, False) -}} {} {% if not is_vector %}// SET YOUR CUSTOM INIT{% endif %}
{#- Ctor type 2 - User specified ctor #}
{{ sname }}::{{ sname }}({{- shared.argument_list_builder(svars) -}}) : {{- shared.initialize_list_builder(svars, True) -}} {}
{#- Offset operator #}
CKFLOAT& {{ sname }}::operator[](size_t i) {
switch (i) {
{%- for item in svars %}
case {{ loop.index0 }}: return {{ item }};
{%- endfor %}
default: throw LogicException("Invalid index for {{ sname }}::operator[].");
}
}
const CKFLOAT& {{ sname }}::operator[](size_t i) const {
switch (i) {
{%- for item in svars %}
case {{ loop.index0 }}: return {{ item }};
{%- endfor %}
default: throw LogicException("Invalid index for {{ sname }}::operator[].");
}
}
{#- Equal operator #}
bool {{ sname }}::operator==(const {{ sname }}& rhs) const {
return (
{%- for item in svars -%}
{{ item }} == rhs.{{ item }} {%- if not loop.last %} && {% endif %}
{%- endfor -%}
);
}
{#- Spaceship operator #}
auto {{ sname }}::operator<=>(const {{ sname }}& rhs) const {
{%- for item in svars[:-1] %}
if (auto cmp = {{ item }} <=> rhs.{{ item }}; cmp != 0) return cmp;
{%- endfor %}
return {{ svars[-1] }} <=> rhs.{{ svars[-1] }};
}
{#- BEGIN VECTOR SPECIFIC #}
{%- if is_vector %}
{#- Add, minus operators #}
{#- Unary operators #}
{{ sname }} {{ sname }}::operator+() const {
return *this;
}
{{ sname }} {{ sname }}::operator-() const {
return {{ sname }}(
{%- for item in svars -%}
-{{ item }} {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{#- Additive operators #}
{{ sname }}& {{ sname }}::operator+=(const {{ sname }}& rhs) {
{%- for item in svars %}
{{ item }} += rhs.{{ item }};
{%- endfor %}
return *this;
}
{{ sname }} operator+(const {{ sname }}& lhs, const {{ sname }}& rhs) {
return {{ sname }}(
{%- for item in svars -%}
lhs.{{ item }} + rhs.{{ item }} {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{{ sname }}& {{ sname }}::operator-=(const {{ sname }}& rhs) {
{%- for item in svars %}
{{ item }} -= rhs.{{ item }};
{%- endfor %}
return *this;
}
{{ sname }} operator-(const {{ sname }}& lhs, const {{ sname }}& rhs) {
return {{ sname }}(
{%- for item in svars -%}
lhs.{{ item }} - rhs.{{ item }} {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{#- Mul operator #}
{{ sname }}& {{ sname }}::operator*=(CKFLOAT rhs) {
{%- for item in svars %}
{{ item }} *= rhs;
{%- endfor %}
return *this;
}
{{ sname }} operator*(const {{ sname }}& lhs, CKFLOAT rhs) {
return {{ sname }}(
{%- for item in svars -%}
lhs.{{ item }} * rhs {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{{ sname }} operator*(CKFLOAT lhs, const {{ sname }}& rhs) {
return {{ sname }}(
{%- for item in svars -%}
lhs * rhs.{{ item }} {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
CKFLOAT operator*(const {{ sname }}& lhs, const {{ sname }}& rhs) {
return (
{%- for item in svars -%}
lhs.{{ item }} * rhs.{{ item }} {%- if not loop.last %} + {% endif %}
{%- endfor -%}
);
}
{#- Div operator #}
{{ sname }}& {{ sname }}::operator/=(CKFLOAT rhs) {
if (rhs == 0.0f) return *this;
{%- for item in svars %}
{{ item }} /= rhs;
{%- endfor %}
return *this;
}
{{ sname }} operator/(const {{ sname }}& lhs, CKFLOAT rhs) {
if (rhs == 0.0f) return {{ sname }}();
else return {{ sname }}(
{%- for item in svars -%}
lhs.{{ item }} / rhs {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{#- Length functions #}
CKFLOAT {{ sname }}::SquaredLength() const {
return (
{%- for item in svars -%}
{{ item }} * {{ item }} {%- if not loop.last %} + {% endif %}
{%- endfor -%}
);
}
CKFLOAT {{ sname }}::Length() const {
return std::sqrt(SquaredLength());
}
{#- Normalize functions #}
void {{ sname }}::Normalized() {
CKFLOAT len = Length();
if (len == 0.0f) return;
{%- for item in svars %}
{{ item }} /= len;
{%- endfor %}
}
{{ sname }} {{ sname }}::Normalize() const {
CKFLOAT len = Length();
if (len == 0.0f) return {{ sname }}();
else return {{ sname }}(
{%- for item in svars -%}
{{ item }} / len {%- if not loop.last %}, {% endif %}
{%- endfor -%}
);
}
{%- endif %}
{#- END VECTOR SPECIFIC #}
{#- User custom region #}
/* ===== BEGIN USER CUSTOM ===== */
/* ===== END USER CUSTOM ===== */
#pragma endregion

View File

@ -0,0 +1,65 @@
{% import 'VxTypes.shared.jinja' as shared %}
struct {{ sname }} {
{#- Variable declaration #}
CKFLOAT {{ ", ".join(svars) }};
{#- Ctor type 1 - Default ctor #}
{{ sname }}();
{#- Ctor type 2 - User specified ctor #}
{{ sname }}({{- shared.argument_list_builder(svars) -}});
{#- Default copy ctor, move ctor, copy assigner, move assigner #}
YYCC_DEF_CLS_COPY_MOVE({{ sname }});
{#- Offset operator #}
CKFLOAT& operator[](size_t i);
const CKFLOAT& operator[](size_t i) const;
{#- Equal operator #}
bool operator==(const {{ sname }}& rhs) const;
{#- Spaceship operator #}
auto operator<=>(const {{ sname }}& rhs) const;
{#- BEGIN VECTOR SPECIFIC #}
{%- if is_vector %}
{#- Add, minus operators #}
{#- Unary operators #}
{{ sname }} operator+() const;
{{ sname }} operator-() const;
{#- Additive operators #}
{{ sname }}& operator+=(const {{ sname }}& rhs);
friend {{ sname }} operator+(const {{ sname }}& lhs, const {{ sname }}& rhs);
{{ sname }}& operator-=(const {{ sname }}& rhs);
friend {{ sname }} operator-(const {{ sname }}& lhs, const {{ sname }}& rhs);
{#- Mul operator #}
{{ sname }}& operator*=(CKFLOAT rhs);
friend {{ sname }} operator*(const {{ sname }}& lhs, CKFLOAT rhs);
friend {{ sname }} operator*(CKFLOAT lhs, const {{ sname }}& rhs);
friend CKFLOAT operator*(const {{ sname }}& lhs, const {{ sname }}& rhs);
{#- Div operator #}
{{ sname }}& operator/=(CKFLOAT rhs);
friend {{ sname }} operator/(const {{ sname }}& lhs, CKFLOAT rhs);
{#- Length functions #}
CKFLOAT SquaredLength() const;
CKFLOAT Length() const;
{#- Normalize functions #}
void Normalized();
{{ sname }} Normalize() const;
{%- endif %}
{#- END VECTOR SPECIFIC #}
{#- User custom region #}
/* ===== BEGIN USER CUSTOM ===== */
/* ===== END USER CUSTOM ===== */
};

View File

@ -0,0 +1,21 @@
{#
The macro to generate C++ ctor argument list
It produce like this: `CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w`
#}
{% macro argument_list_builder(svars) %}
{%- for item in svars -%}
CKFLOAT _{{- item -}}{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
{% endmacro %}
{#
The macro to generate C++ ctor initialize list
It produce like this: `x(0.0f), y(0.0f), z(0.0f), w(0.0f)`
or this: `x(_x), y(_y), z(_z), w(_w)`
according to user request.
#}
{% macro initialize_list_builder(svars, is_user) %}
{%- for item in svars -%}
{{- item -}}({%- if is_user -%}_{{- item -}}{%- else -%}0.0f{%- endif -%}){%- if not loop.last %}, {% endif -%}
{%- endfor -%}
{% endmacro %}

View File

@ -0,0 +1,63 @@
import os
import io
import typing
import jinja2
g_HppTemplateFile: str = 'VxTypes.hpp.jinja'
g_CppTemplateFile: str = 'VxTypes.cpp.jinja'
g_ResultHppFile: str = 'VxTypes.hpp'
g_ResultCppFile: str = 'VxTypes.cpp'
def get_root_directory() -> str:
return os.path.dirname(__file__)
class TemplateRender:
m_Loader: jinja2.BaseLoader
m_Environment: jinja2.Environment
m_HppTemplate: jinja2.Template
m_CppTemplate: jinja2.Template
m_OutputHpp: io.TextIOWrapper
m_OutputCpp: io.TextIOWrapper
def __init__(self, output_hpp_path: str, output_cpp_path: str) -> None:
self.m_Loader = jinja2.FileSystemLoader(get_root_directory())
self.m_Environment = jinja2.Environment(loader=self.m_Loader)
self.m_HppTemplate = self.m_Environment.get_template(g_HppTemplateFile)
self.m_CppTemplate = self.m_Environment.get_template(g_CppTemplateFile)
self.m_OutputHpp = open(os.path.join(get_root_directory(), output_hpp_path), 'w', encoding='utf-8')
self.m_OutputCpp = open(os.path.join(get_root_directory(), output_cpp_path), 'w', encoding='utf-8')
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.m_OutputHpp.close()
self.m_OutputCpp.close()
def __render(self, sname: str, is_vector: bool, svars: tuple[str]) -> None:
template_argument: dict[str, typing.Any] = {
'sname': sname,
'is_vector': is_vector,
'svars': svars
}
self.m_OutputHpp.write(self.m_HppTemplate.render(**template_argument))
self.m_OutputCpp.write(self.m_CppTemplate.render(**template_argument))
def render_vector(self, sname: str, svars: tuple[str]) -> None:
self.__render(sname, True, svars)
def render_others(self, sname: str, svars: tuple[str]) -> None:
self.__render(sname, False, svars)
if __name__ == '__main__':
with TemplateRender(g_ResultHppFile, g_ResultCppFile) as render:
render.render_vector('VxVector2', ('x', 'y', ))
render.render_vector('VxVector3', ('x', 'y', 'z', ))
render.render_vector('VxVector4', ('x', 'y', 'z', 'w', ))
render.render_others('VxQuaternion', ('x', 'y', 'z', 'w', ))
render.render_others('VxColor', ('r', 'g', 'b', 'a', ))

View File

@ -1,159 +0,0 @@
def GetTmplDecl(svars: tuple[str]) -> str:
return f'CKFLOAT {", ".join(svars)};'
def GetTmplCtor1(sname: str, svars: tuple[str]) -> str:
return f'{sname}() : {", ".join(map(lambda x: f"{x}(0.0f)", svars))} {{}}'
def GetTmplCtor2(sname: str, svars: tuple[str]) -> str:
return f'{sname}({", ".join(map(lambda x: f"CKFLOAT _{x}", svars))}) : {", ".join(map(lambda x: f"{x}(_{x})", svars))} {{}}'
def GetTmplCopyCtor(sname: str, svars: tuple[str]) -> str:
return f'{sname}(const {sname}& rhs) : {", ".join(map(lambda x: f"{x}(rhs.{x})", svars))} {{}}'
def GetTmplMoveCtor(sname: str, svars: tuple[str]) -> str:
return f'{sname}({sname}&& rhs) : {", ".join(map(lambda x: f"{x}(rhs.{x})", svars))} {{}}'
def GetTmplOperAssignCopy(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\t{sname}& operator=(const {sname}& rhs) {{
\t\t{sp.join(map(lambda x: f'{x} = rhs.{x};', svars))}
\t\treturn *this;
\t}}"""
def GetTmplOperAssignMove(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\t{sname}& operator=({sname}&& rhs) {{
\t\t{sp.join(map(lambda x: f'{x} = rhs.{x};', svars))}
\t\treturn *this;
\t}}"""
def GetTmplOperOffset(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t\t'
return f"""\tCKFLOAT& operator[](size_t i) {{
\t\tswitch (i) {{
\t\t\t{sp.join(map(lambda x: f'case {x}: return {svars[x]};', range(len(svars))))}
\t\t\tdefault: return {svars[0]};
\t\t}}
\t}}
\tconst CKFLOAT& operator[](size_t i) const {{
\t\tswitch (i) {{
\t\t\t{sp.join(map(lambda x: f'case {x}: return {svars[x]};', range(len(svars))))}
\t\t\tdefault: return {svars[0]};
\t\t}}
\t}}"""
def GetTmplOperAddMinus(sname: str, svars: tuple[str], oper: str) -> str:
sp: str = '\n\t\t'
return f"""\t{sname}& operator{oper}=(const {sname}& rhs) {{
\t\t{sp.join(map(lambda x: f'{x} {oper}= rhs.{x};', svars))}
\t\treturn *this;
\t}}
\tfriend {sname} operator{oper}(const {sname}& lhs, const {sname}& rhs) {{
\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} {oper} rhs.{x}', svars))});
\t}}"""
def GetTmplOperMul(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\t{sname}& operator*=(CKFLOAT rhs) {{
\t\t{sp.join(map(lambda x: f'{x} *= rhs;', svars))}
\t\treturn *this;
\t}}
\tfriend {sname} operator*(const {sname}& lhs, CKFLOAT rhs) {{
\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} * rhs', svars))});
\t}}
\tfriend {sname} operator*(CKFLOAT lhs, const {sname}& rhs) {{
\t\treturn {sname}({', '.join(map(lambda x: f'lhs * rhs.{x}', svars))});
\t}}
\tfriend CKFLOAT operator*(const {sname}& lhs, const {sname}& rhs) {{
\t\treturn ({' + '.join(map(lambda x: f'lhs.{x} * rhs.{x}', svars))});
\t}}"""
def GetTmplOperDiv(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\t{sname}& operator/=(CKFLOAT rhs) {{
\t\tif (rhs == 0.0f) return *this;
\t\t{sp.join(map(lambda x: f'{x} /= rhs;', svars))}
\t\treturn *this;
\t}}
\tfriend {sname} operator/(const {sname}& lhs, CKFLOAT rhs) {{
\t\tif (rhs == 0.0f) return {sname}({', '.join(map(lambda x: '0.0f', range(len(svars))))});
\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} / rhs', svars))});
\t}}"""
def GetTmplOperEqual(sname: str, svars: tuple[str]) -> str:
return f"""\tbool operator==(const {sname}& rhs) const {{
\t\treturn ({' && '.join(map(lambda x: f'{x} == rhs.{x}', svars))});
\t}}"""
def GetTmplOperSpaceship(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\tauto operator<=>(const {sname}& rhs) const {{
\t\t{sp.join(map(lambda x: f'if (auto cmp = {x} <=> rhs.{x}; cmp != 0) return cmp;', svars[:-1]))}
\t\treturn {svars[-1]} <=> rhs.{svars[-1]};
\t}}"""
def GetTmplLength(sname: str, svars: tuple[str]) -> str:
return f"""\tCKFLOAT SquaredLength() const {{
\t\treturn ({' + '.join(map(lambda x: f'{x} * {x}', svars))});
\t}}
\tCKFLOAT Length() const {{
\t\treturn std::sqrt(SquaredLength());
\t}}"""
def GetTmplNormalize(sname: str, svars: tuple[str]) -> str:
sp: str = '\n\t\t'
return f"""\tvoid Normalized() {{
\t\tCKFLOAT len = Length();
\t\tif (len == 0.0f) return;
\t\t{sp.join(map(lambda x: f'{x} /= len;', svars))}
\t}}
\t{sname} Normalize() const {{
\t\tCKFLOAT len = Length();
\t\tif (len == 0.0f) return {sname}();
\t\treturn {sname}({', '.join(map(lambda x: f'{x} / len', svars))});
\t}}"""
def GetTmplVector(sname: str, svars: tuple[str]) -> str:
return f"""
struct {sname} {{
\t{GetTmplDecl(svars)}
\t{GetTmplCtor1(sname, svars)}
\t{GetTmplCtor2(sname, svars)}
\tLIBCMO_DEFAULT_COPY_MOVE({sname});
{GetTmplOperOffset(sname, svars)}
{GetTmplOperAddMinus(sname, svars, '+')}
{GetTmplOperAddMinus(sname, svars, '-')}
{GetTmplOperMul(sname, svars)}
{GetTmplOperDiv(sname, svars)}
{GetTmplOperEqual(sname, svars)}
{GetTmplLength(sname, svars)}
{GetTmplNormalize(sname, svars)}
}};
"""
def GetTmplOthers(sname: str, svars: tuple[str]) -> str:
return f"""
struct {sname} {{
\t{GetTmplDecl(svars)}
\t{GetTmplCtor1(sname, svars)} // set your custom init.
\t{GetTmplCtor2(sname, svars)}
\tLIBCMO_DEFAULT_COPY_MOVE({sname});
{GetTmplOperOffset(sname, svars)}
{GetTmplOperEqual(sname, svars)}
}};
"""
# use LIBCMO_DEFAULT_COPY_MOVE instead of these outputs.
#\t{GetTmplCopyCtor(sname, svars)}
#\t{GetTmplMoveCtor(sname, svars)}
#{GetTmplOperAssignCopy(sname, svars)}
#{GetTmplOperAssignMove(sname, svars)}
if __name__ == '__main__':
with open('VxTypes.hpp', 'w', encoding='utf-8') as fs:
fs.write(GetTmplVector('VxVector2', ('x', 'y', )))
fs.write(GetTmplVector('VxVector3', ('x', 'y', 'z', )))
fs.write(GetTmplVector('VxVector4', ('x', 'y', 'z', 'w', )))
fs.write(GetTmplOthers('VxQuaternion', ('x', 'y', 'z', 'w', )))
fs.write(GetTmplOthers('VxColor', ('r', 'g', 'b', 'a', )))

19
Documents/CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
# Configure Doxygen config file
configure_file(
${CMAKE_CURRENT_LIST_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
# Add custom target
add_custom_target (NeMoDocuments
doxygen ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating LibCmo documentation" VERBATIM
)
# Install built documentation
install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
DESTINATION ${NEMO_INSTALL_DOC_PATH}
)

2778
Documents/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
cmake_minimum_required(VERSION 3.12)
project(IronPad LANGUAGES CXX)
# add libcmo if not existed
if (NOT TARGET LibCmo)
add_subdirectory("../LibCmo" "LibCmo.out")
endif ()
# setup sources
set(ironpad_headers ".")
set(ironpad_src IronPad.cpp)
# create static library
add_library(IronPad
STATIC
${ironpad_src}
)
target_link_libraries(IronPad
PRIVATE
LibCmo
)
target_include_directories(IronPad
PUBLIC
${ironpad_headers}
)
# set project standard
set_target_properties(IronPad
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)

View File

@ -1,334 +0,0 @@
#include "IronPad.hpp"
// only include these header on windows.
// in other words, include these header when ironpad enabled.
#if defined(IRONPAD_ENABLED)
#include <Windows.h>
#include <DbgHelp.h>
#include <filesystem>
#include <cstdarg>
#include <cstdio>
#endif
namespace IronPad {
#if defined(IRONPAD_ENABLED)
/**
* @brief true if the exception handler already registered.
* This variable is served for singleton.
*/
static bool g_IsRegistered = false;
/**
* @brief true if a exception handler is running.
* This variable is served for blocking possible infinity recursive exception handling.
*/
static bool g_IsProcessing = false;
/**
* @brief The backup of original exception handler.
*/
LPTOP_LEVEL_EXCEPTION_FILTER g_ProcBackup;
#pragma region Exception Handler Detail
static HMODULE GetCurrentModule() {
// Reference: https://stackoverflow.com/questions/557081/how-do-i-get-the-hmodule-for-the-currently-executing-code
HMODULE hModule = NULL;
GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, // get address and do not inc ref counter.
(LPCWSTR)GetCurrentModule,
&hModule);
return hModule;
}
static const char* UExceptionGetCodeName(DWORD code) {
switch (code) {
case EXCEPTION_ACCESS_VIOLATION:
return "access violation";
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return "array index out of bound";
case EXCEPTION_BREAKPOINT:
return "breakpoint reached";
case EXCEPTION_DATATYPE_MISALIGNMENT:
return "misaligned data access";
case EXCEPTION_FLT_DENORMAL_OPERAND:
return "operand had denormal value";
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return "floating-point division by zero";
case EXCEPTION_FLT_INEXACT_RESULT:
return "no decimal fraction representation for value";
case EXCEPTION_FLT_INVALID_OPERATION:
return "invalid floating-point operation";
case EXCEPTION_FLT_OVERFLOW:
return "floating-point overflow";
case EXCEPTION_FLT_STACK_CHECK:
return "floating-point stack corruption";
case EXCEPTION_FLT_UNDERFLOW:
return "floating-point underflow";
case EXCEPTION_ILLEGAL_INSTRUCTION:
return "illegal instruction";
case EXCEPTION_IN_PAGE_ERROR:
return "inaccessible page";
case EXCEPTION_INT_DIVIDE_BY_ZERO:
return "integer division by zero";
case EXCEPTION_INT_OVERFLOW:
return "integer overflow";
case EXCEPTION_INVALID_DISPOSITION:
return "documentation says this should never happen";
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return "can't continue after a noncontinuable exception";
case EXCEPTION_PRIV_INSTRUCTION:
return "attempted to execute a privileged instruction";
case EXCEPTION_SINGLE_STEP:
return "one instruction has been executed";
case EXCEPTION_STACK_OVERFLOW:
return "stack overflow";
default:
return "unknown exception";
}
}
static void UExceptionFormat(std::FILE* fs, const char* fmt, ...) {
// write to file
va_list arg1;
va_start(arg1, fmt);
std::vfprintf(fs, fmt, arg1);
va_end(arg1);
// write to stdout
va_list arg2;
va_start(arg2, fmt);
std::vfprintf(stdout, fmt, arg2);
va_end(arg2);
}
static void UExceptionPrint(std::FILE* fs, const char* strl) {
// write to file
std::fputs(strl, fs);
// write to stdout
std::fputs(strl, stdout);
}
static void UExceptionBacktrace(FILE* fs, LPCONTEXT context, int maxdepth) {
// setup loading symbol options
SymSetOptions(SymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); // lazy load symbol, and load line number.
// setup handle
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
// init symbol
if (!SymInitialize(process, 0, TRUE)) {
// fail to load. return
UExceptionPrint(fs, "Lost symbol file!\n");
return;
}
// ========== CORE DUMP ==========
// prepare frame. setup correct fields
// references:
// https://github.com/rust-lang/backtrace-rs/blob/9ed25b581cfd2ee60e5a3b9054fd023bf6dced90/src/backtrace/dbghelp.rs
// https://sourceforge.net/p/predef/wiki/Architectures/
DWORD machine_type = 0;
STACKFRAME64 frame;
memset(&frame, 0, sizeof(frame));
#if defined(_M_IX86) || defined(__i386__)
// x86
machine_type = IMAGE_FILE_MACHINE_I386;
frame.AddrPC.Offset = context->Eip;
frame.AddrStack.Offset = context->Esp;
frame.AddrFrame.Offset = context->Ebp;
#elif defined(_M_AMD64) || defined(__amd64__)
// amd64
machine_type = IMAGE_FILE_MACHINE_AMD64;
frame.AddrPC.Offset = context->Rip;
frame.AddrStack.Offset = context->Rsp;
frame.AddrFrame.Offset = context->Rbp;
#elif defined(_M_ARM) || defined(__arm__)
// arm (32bit)
machine_type = IMAGE_FILE_MACHINE_ARMNT;
frame.AddrPC.Offset = context->Pc;
frame.AddrStack.Offset = context->Sp;
frame.AddrFrame.Offset = context->R11;
#elif defined(_M_ARM64) || defined(__aarch64__)
// arm64
machine_type = IMAGE_FILE_MACHINE_ARM64;
frame.AddrPC.Offset = context->Pc;
frame.AddrStack.Offset = context->Sp;
frame.AddrFrame.Offset = context->DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp;
#else
#error "Unsupported platform"
//IA-64 anybody?
#endif
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrFrame.Mode = AddrModeFlat;
// other variables
char module_name_raw[MAX_PATH];
// stack walker
while (StackWalk64(machine_type, process, thread, &frame, context,
0, SymFunctionTableAccess64, SymGetModuleBase64, 0)) {
// depth breaker
--maxdepth;
if (maxdepth < 0) {
UExceptionPrint(fs, "...\n"); // indicate there are some frames not listed
break;
}
// get module name
DWORD64 module_base = SymGetModuleBase64(process, frame.AddrPC.Offset);
const char* module_name = "[unknown module]";
if (module_base && GetModuleFileNameA((HINSTANCE)module_base, module_name_raw, MAX_PATH)) {
module_name = module_name_raw;
}
// get source file and line
const char* source_file = "[unknow_source_file]";
DWORD64 source_file_line = 0;
DWORD dwDisplacement;
IMAGEHLP_LINE64 winline;
winline.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &dwDisplacement, &winline)) {
source_file = winline.FileName;
source_file_line = winline.LineNumber;
}
// write to file
UExceptionFormat(fs, "0x%016llx(rel: 0x%016llx)[%s]\t%s#%llu\n",
frame.AddrPC.Offset, frame.AddrPC.Offset - module_base, module_name,
source_file, source_file_line
);
}
// ========== END CORE DUMP ==========
// free symbol
SymCleanup(process);
}
static void UExceptionCoreDump(LPCWSTR filename, LPEXCEPTION_POINTERS info) {
// open file and write
HANDLE hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exception_info;
exception_info.ThreadId = GetCurrentThreadId();
exception_info.ExceptionPointers = info;
exception_info.ClientPointers = TRUE;
MiniDumpWriteDump(
GetCurrentProcess(), GetCurrentProcessId(), hFile,
MiniDumpNormal,
&exception_info,
NULL, NULL
);
CloseHandle(hFile);
}
}
static LONG WINAPI UExceptionImpl(LPEXCEPTION_POINTERS info) {
// detect loop calling
if (g_IsProcessing) {
goto end_proc;
}
// start process
g_IsProcessing = true;
{
// get main folder first
std::filesystem::path ironpad_path;
WCHAR module_path[MAX_PATH];
std::memset(module_path, 0, sizeof(module_path));
if (GetModuleFileNameW(GetCurrentModule(), module_path, MAX_PATH) == 0) {
goto failed;
}
ironpad_path = module_path;
ironpad_path = ironpad_path.parent_path();
// create 2 filename
auto logfilename = ironpad_path / "IronPad.log";
auto dmpfilename = ironpad_path / "IronPad.dmp";
std::fputc('\n', stdout);
std::fprintf(stdout, "Exception Log: %s\n", logfilename.string().c_str());
std::fprintf(stdout, "Exception Coredump: %s\n", dmpfilename.string().c_str());
// output log file
{
std::FILE* fs = _wfopen(logfilename.wstring().c_str(), L"w");
if (fs == nullptr) {
goto failed;
}
// record exception type first
PEXCEPTION_RECORD rec = info->ExceptionRecord;
fprintf(fs, "Unhandled exception occured at 0x%08p: %s (%lu).\n",
rec->ExceptionAddress,
UExceptionGetCodeName(rec->ExceptionCode),
rec->ExceptionCode
);
// special proc for 2 exceptions
if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || rec->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) {
if (rec->NumberParameters >= 2) {
const char* op =
rec->ExceptionInformation[0] == 0 ? "read" :
rec->ExceptionInformation[0] == 1 ? "written" : "executed";
fprintf(fs, "The data at memory address 0x%016" PRIxPTR " could not be %s.\n",
rec->ExceptionInformation[1], op);
}
}
// output stacktrace
UExceptionBacktrace(fs, info->ContextRecord, 1024);
std::fclose(fs);
}
// output minidump
{
UExceptionCoreDump(dmpfilename.wstring().c_str(), info);
}
}
// end process
failed:
g_IsProcessing = false;
// if backup proc can be run, run it
// otherwise directly return.
end_proc:
if (g_ProcBackup != nullptr) {
return g_ProcBackup(info);
} else {
return EXCEPTION_CONTINUE_SEARCH;
}
}
#pragma endregion
void IronPadRegister() {
if (g_IsRegistered) return;
g_ProcBackup = SetUnhandledExceptionFilter(UExceptionImpl);
g_IsRegistered = true;
}
void IronPadUnregister() {
if (!g_IsRegistered) return;
SetUnhandledExceptionFilter(g_ProcBackup);
g_IsRegistered = false;
}
#else
// blank implement
void IronPadRegister() {}
void IronPadUnregister() {}
#endif
}

View File

@ -1,26 +0,0 @@
#pragma once
// only include VTUtils to get essential macro
#include <VTUtils.hpp>
#if defined(LIBCMO_BUILD_RELEASE) && defined(LIBCMO_OS_WIN32)
#define IRONPAD_ENABLED 1
#endif
// Debug IronPad used. Force enable IronPad.
//#define IRONPAD_ENABLED 1
namespace IronPad {
/**
* @brief Register IronPad.
* @detail This function frequently called at the start of program.
*/
void IronPadRegister();
/**
* @brief Unregiister IronPad
* @detail This function frequently called at the end of program.
*/
void IronPadUnregister();
}

View File

@ -1,186 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{a6454164-2153-45ae-bdb8-19c77014e0cc}</ProjectGuid>
<RootNamespace>IronPad</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\LibRef.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_BUILD_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_BUILD_RELEASE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_BUILD_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LIBCMO_BUILD_RELEASE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../LibCmo;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="IronPad.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="IronPad.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headers">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="IronPad.hpp">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="IronPad.cpp">
<Filter>Sources</Filter>
</ClCompile>
</ItemGroup>
</Project>

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

@ -1,6 +1,6 @@
#pragma once
#include "../VTAll.hpp"
#include "../VTInternal.hpp"
namespace LibCmo::CK2 {
@ -26,7 +26,7 @@ namespace LibCmo::CK2 {
CKBitmapSlot() :
m_ImageData(), m_FileName() {}
~CKBitmapSlot() {}
LIBCMO_DEFAULT_COPY_MOVE(CKBitmapSlot);
YYCC_DEF_CLS_COPY_MOVE(CKBitmapSlot);
VxMath::VxImageDescEx m_ImageData;
XContainer::XString m_FileName;
@ -36,7 +36,7 @@ namespace LibCmo::CK2 {
public:
CKBitmapData(CKContext* ctx);
~CKBitmapData();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapData);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapData);
#pragma region RW Funcs
@ -60,48 +60,48 @@ namespace LibCmo::CK2 {
/**
* @brief Create a black image with full alpha in specified slot.
* @param Width[in] Image width
* @param Height[in] Image height
* @param Slot[in] The slot placing image.
* @param[in] Width Image width
* @param[in] Height Image height
* @param[in] Slot The slot placing image.
* @return True if creating success.
*/
bool CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
/**
* @brief Load image into specified slot.
* @param filename[in] The file name of loading image.
* @param slot[in] The slot placing loaded image.
* @param[in] filename The file name of loading image.
* @param[in] slot The slot placing loaded image.
* @return True if load successfully.
*/
bool LoadImage(CKSTRING filename, CKDWORD slot);
/**
* @brief Save image for specified slot.
* @param filename[in] The file name of saving image.
* @param slot[in] The slot will be saved.
* @param isForceThisFmt[in] True to use this class specified format to save image. Otherwise use the format evaluated by the image file name.
* @param[in] filename The file name of saving image.
* @param[in] slot The slot will be saved.
* @param[in] isForceThisFmt True to use this class specified format to save image. Otherwise use the format evaluated by the image file name.
* @return True if success.
*/
bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false);
/**
* @brief Get specified slot image descriptor.
* @param slot[in] The slot to get.
* @param[in] slot The slot to get.
* @return The descriptor. nullptr if failed.
*/
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
/**
* @brief Release specified slot image.
* @param slot[in] The slot to free.
* @param[in] slot The slot to free.
*/
void ReleaseImage(CKDWORD slot);
/**
* @brief Set associated file name for specified slot.
* @param slot[in] The slot to set.
* @param filename[in] The associated file name.
* @param[in] slot The slot to set.
* @param[in] filename The associated file name.
*/
bool SetSlotFileName(CKDWORD slot, CKSTRING filename);
/**
* @brief Get associated file name for specified slot.
* @param slot[in] The slot to get.
* @param[in] slot The slot to get.
* @return The file name. nullptr if failed.
*/
CKSTRING GetSlotFileName(CKDWORD slot) const;
@ -132,7 +132,7 @@ namespace LibCmo::CK2 {
void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opts);
/**
@brief Enables or disables the color key transparency.
@param Transparency[in] TRUE activates transparency, FALSE disables it.
@param[in] Transparency TRUE activates transparency, FALSE disables it.
@remark
+ 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically
@ -149,7 +149,7 @@ namespace LibCmo::CK2 {
bool IsTransparent() const;
/**
@brief Sets the transparent color.
@param Color[in] A 32 bit ARGB transparent color.
@param[in] Color A 32 bit ARGB transparent color.
@remark
+ 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically
@ -168,7 +168,7 @@ namespace LibCmo::CK2 {
CKDWORD GetTransparentColor() const;
/**
@brief Sets pick threshold value.
@param pt[in] Pick threshold value to be set.
@param[in] pt Pick threshold value to be set.
@remark
+ The pick threshold is used when picking object with
transparent textures.

View File

@ -26,7 +26,7 @@ namespace LibCmo::CK2 {
m_OutputCallback(nullptr) {
// setup save format
m_GlobalImagesSaveFormat.m_Ext.SetExt("bmp");
m_GlobalImagesSaveFormat.m_Ext.SetExt(u8"bmp");
// setup managers
m_ObjectManager = new MgrImpls::CKObjectManager(this);
@ -42,6 +42,8 @@ namespace LibCmo::CK2 {
for (auto& mgrptr : m_ManagerList) {
delete mgrptr;
}
// free encoding
this->ClearEncoding();
}
#pragma endregion
@ -252,23 +254,17 @@ namespace LibCmo::CK2 {
void CKContext::OutputToConsole(CKSTRING str) {
if (m_OutputCallback == nullptr) return;
if (str == nullptr) return;
m_OutputCallback(str);
}
void CKContext::OutputToConsoleEx(CKSTRING fmt, ...) {
if (m_OutputCallback == nullptr) return;
if (fmt == nullptr) return;
va_list argptr;
va_start(argptr, fmt);
XContainer::XString result;
int count = std::vsnprintf(nullptr, 0, fmt, argptr);
result.resize(count);
// count + 1 for NUL terminator. but we don't need allocate space for it (resize with count). let it write into the reserved tail of std::string.
int write_result = std::vsnprintf(result.data(), count + 1, fmt, argptr);
if (write_result < 0 || write_result > count) return;
XContainer::XString result(YYCC::StringHelper::VPrintf(fmt, argptr));
va_end(argptr);
// use c_str(), not XContainer::NSXString::ToCKSTRING because we want make sure this paramter is not nullptr.
@ -284,48 +280,71 @@ namespace LibCmo::CK2 {
#pragma region Encoding utilities
void CKContext::GetUtf8String(const XContainer::XString& native_name, XContainer::XString& u8_name) {
bool success = false;
bool CKContext::GetUTF8String(const std::string& native_name, XContainer::XString& u8_name) {
bool conv_success = false, has_valid_token = false;
for (const auto& token : this->m_NameEncoding) {
success = LibCmo::EncodingHelper::GetUtf8VirtoolsName(native_name, u8_name, token);
if (success) break;
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
has_valid_token = true;
conv_success = EncodingHelper::ToUTF8(native_name, u8_name, token);
if (conv_success) break;
}
// fallback
if (!success) {
u8_name = native_name;
this->OutputToConsole("Error when converting to UTF8 string.");
// fallback if failed.
if (!conv_success) {
if (!has_valid_token) {
throw RuntimeException("Try to get UTF8 string from ordinary string in CKContext but giving empty encoding candidate.");
} else {
u8_name.clear();
this->OutputToConsole(u8"Error when converting to UTF8 string from ordinary string. The string will leave to blank.");
}
}
// return value
return conv_success;
}
void CKContext::GetNativeString(const XContainer::XString& u8_name, XContainer::XString& native_name) {
bool success = false;
bool CKContext::GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name) {
bool conv_success = false, has_valid_token = false;
for (const auto& token : this->m_NameEncoding) {
success = LibCmo::EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, token);
if (success) break;
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
has_valid_token = true;
conv_success = EncodingHelper::ToOrdinary(u8_name, native_name, token);
if (conv_success) break;
}
// fallback
if (!success) {
native_name = u8_name;
this->OutputToConsole("Error when converting to native string.");
// fallback if failed.
if (!conv_success) {
if (!has_valid_token) {
throw RuntimeException("Try to get ordinary string from UTF8 string in CKContext but giving empty encoding candidate.");
} else {
native_name.clear();
this->OutputToConsole(u8"Error when converting to ordinary string from UTF8 string. The string will leave to blank.");
}
}
// return value
return conv_success;
}
void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_series) {
void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_seq) {
// free all current series
for (const auto& encoding : this->m_NameEncoding) {
LibCmo::EncodingHelper::DestroyEncodingToken(encoding);
this->ClearEncoding();
// add new encoding
for (const auto& encoding_str : encoding_seq) {
this->m_NameEncoding.emplace_back(LibCmo::EncodingHelper::CreateEncodingToken(encoding_str));
}
}
void CKContext::ClearEncoding() {
for (const auto& token : this->m_NameEncoding) {
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
LibCmo::EncodingHelper::DestroyEncodingToken(token);
}
this->m_NameEncoding.clear();
// add new encoding
for (const auto& encoding_str : encoding_series) {
this->m_NameEncoding.push_back(LibCmo::EncodingHelper::CreateEncodingToken(encoding_str));
}
}
bool CKContext::IsValidEncoding() {
for (const auto& token : this->m_NameEncoding) {
if (token != EncodingHelper::INVALID_ENCODING_TOKEN) return true;
}
return false;
}
#pragma endregion

View File

@ -1,6 +1,6 @@
#pragma once
#include "../VTAll.hpp"
#include "../VTInternal.hpp"
#include <map>
#include <deque>
#include <functional>
@ -21,7 +21,7 @@ namespace LibCmo::CK2 {
public:
CKContext();
~CKContext();
LIBCMO_DISABLE_COPY_MOVE(CKContext);
YYCC_DEL_CLS_COPY_MOVE(CKContext);
// ========== Engine runtime ==========
public:
@ -100,18 +100,77 @@ namespace LibCmo::CK2 {
// ========== Encoding utilities ==========
public:
void GetUtf8String(const XContainer::XString& native_name, XContainer::XString& u8_name);
void GetNativeString(const XContainer::XString& u8_name, XContainer::XString& native_name);
/**
* @brief Convert given ordinary string to UTF8 string.
* @param[in] native_name The input ordinary string.
* @param[out] u8_name The output UTF8 string.
* @return True if convertion is success, otherwise false.
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
* @remarks
* The encoding of ordinary is specified by encoding sequence.
* If we fail to do convertion, the result will leave to blank and output a message to CKContext.
* However, if you use this function with blank encoding sequence, it will raise exception.
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
*/
bool GetUTF8String(const std::string& native_name, XContainer::XString& u8_name);
/**
* @brief Convert given UTF8 string to ordinary string.
* @param[in] u8_name The input UTF8 string.
* @param[out] native_name The output ordinary string.
* @return True if convertion is success, otherwise false.
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
* @remarks
* The encoding of ordinary is specified by encoding sequence.
* If we fail to do convertion, the result will leave to blank and output a message to CKContext.
* However, if you use this function with blank encoding sequence, it will raise exception.
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
*/
bool GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name);
/**
* @brief Set the encoding sequence.
* @param[in] encoding_series The encoding name in this sequence.
* @remarks
* \li The order in encoding sequence is important. The encoding name with lower index will be used for convertion first.
* \li Encoding sequence will be used for performing GetUTF8String() and GetOrdinaryString().
* We will try using it to do convertion from top to bottom (if one failed we will continue trying to use next one to do convertion).
*/
void SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_series);
/**
* @brief Clear specified encoding sequence.
*/
void ClearEncoding();
/**
* @brief Check whether current encoding sequence at least has one valid encoding for convertion.
* @return True if it is, otherwise false.
*/
bool IsValidEncoding();
protected:
XContainer::XArray<EncodingHelper::ENCODING_TOKEN> m_NameEncoding;
XContainer::XArray<EncodingHelper::EncodingToken> m_NameEncoding;
// ========== Print utilities ==========
public:
/**
* @brief The callback prototype.
* @details It accept a CKSTRING representing the string need to be printed.
* The passed CKSTRING is guaranteen that it can not be nullptr.
*/
using OutputCallback = std::function<void(CKSTRING)>;
/**
* @brief Output plain message.
* @param[in] str Plain message. nullptr is allowed but not suggested.
*/
void OutputToConsole(CKSTRING str);
/**
* @brief Output message with given format.
* @param[in] fmt The format string. nullptr is allowed but not suggested.
* @param[in] ... The arguments of format string.
*/
void OutputToConsoleEx(CKSTRING fmt, ...);
/**
* @brief Set the callback for message printing.
* @param[in] cb The function pointer to callback. nullptr to remove callback.
*/
void SetOutputCallback(OutputCallback cb);
protected:

View File

@ -5,9 +5,9 @@
namespace LibCmo::CK2 {
#pragma region Preregistred Managers
#pragma region Preregistred Manager GUIDs
// Virtools Managers GUID second data is 0
// Virtools Managers GUID second DWORD must be 0
constexpr const CKDWORD OBJECT_MANAGER_GUID1 = 0x7cbb3b91;
constexpr const CKDWORD ATTRIBUTE_MANAGER_GUID1 = 0x3d242466;
@ -26,31 +26,31 @@ namespace LibCmo::CK2 {
constexpr const CKDWORD PATH_MANAGER_GUID1 = 0x15fd54b9;
constexpr const CKDWORD VARIABLE_MANAGER_GUID1 = 0x98cc3cc9;
constexpr const CKGUID OBJECT_MANAGER_GUID{ OBJECT_MANAGER_GUID1 ,0 };
constexpr const CKGUID ATTRIBUTE_MANAGER_GUID{ ATTRIBUTE_MANAGER_GUID1, 0 };
constexpr const CKGUID MESSAGE_MANAGER_GUID{ MESSAGE_MANAGER_GUID1 ,0 };
constexpr const CKGUID TIME_MANAGER_GUID{ TIME_MANAGER_GUID1 ,0 };
constexpr const CKGUID SOUND_MANAGER_GUID{ SOUND_MANAGER_GUID1 ,0 };
constexpr const CKGUID MIDI_MANAGER_GUID{ MIDI_MANAGER_GUID1 ,0 };
constexpr const CKGUID INPUT_MANAGER_GUID{ INPUT_MANAGER_GUID1 ,0 };
constexpr const CKGUID BEHAVIOR_MANAGER_GUID{ BEHAVIOR_MANAGER_GUID1 ,0 };
constexpr const CKGUID FLOOR_MANAGER_GUID{ FLOOR_MANAGER_GUID1 ,0 };
constexpr const CKGUID COLLISION_MANAGER_GUID{ COLLISION_MANAGER_GUID1 ,0 };
constexpr const CKGUID GRID_MANAGER_GUID{ GRID_MANAGER_GUID1 ,0 };
constexpr const CKGUID INTERFACE_MANAGER_GUID{ INTERFACE_MANAGER_GUID1 ,0 };
constexpr const CKGUID RENDER_MANAGER_GUID{ RENDER_MANAGER_GUID1 ,0 };
constexpr const CKGUID PARAMETER_MANAGER_GUID{ PARAMETER_MANAGER_GUID1 ,0 };
constexpr const CKGUID PATH_MANAGER_GUID{ PATH_MANAGER_GUID1 ,0 };
constexpr const CKGUID VARIABLE_MANAGER_GUID{ VARIABLE_MANAGER_GUID1 ,0 };
constexpr const CKGUID OBJECT_MANAGER_GUID { OBJECT_MANAGER_GUID1, 0 };
constexpr const CKGUID ATTRIBUTE_MANAGER_GUID { ATTRIBUTE_MANAGER_GUID1, 0 };
constexpr const CKGUID MESSAGE_MANAGER_GUID { MESSAGE_MANAGER_GUID1, 0 };
constexpr const CKGUID TIME_MANAGER_GUID { TIME_MANAGER_GUID1, 0 };
constexpr const CKGUID SOUND_MANAGER_GUID { SOUND_MANAGER_GUID1, 0 };
constexpr const CKGUID MIDI_MANAGER_GUID { MIDI_MANAGER_GUID1, 0 };
constexpr const CKGUID INPUT_MANAGER_GUID { INPUT_MANAGER_GUID1, 0 };
constexpr const CKGUID BEHAVIOR_MANAGER_GUID { BEHAVIOR_MANAGER_GUID1, 0 };
constexpr const CKGUID FLOOR_MANAGER_GUID { FLOOR_MANAGER_GUID1, 0 };
constexpr const CKGUID COLLISION_MANAGER_GUID { COLLISION_MANAGER_GUID1, 0 };
constexpr const CKGUID GRID_MANAGER_GUID { GRID_MANAGER_GUID1, 0 };
constexpr const CKGUID INTERFACE_MANAGER_GUID { INTERFACE_MANAGER_GUID1, 0 };
constexpr const CKGUID RENDER_MANAGER_GUID { RENDER_MANAGER_GUID1, 0 };
constexpr const CKGUID PARAMETER_MANAGER_GUID { PARAMETER_MANAGER_GUID1, 0 };
constexpr const CKGUID PATH_MANAGER_GUID { PATH_MANAGER_GUID1, 0 };
constexpr const CKGUID VARIABLE_MANAGER_GUID { VARIABLE_MANAGER_GUID1, 0 };
#pragma endregion
#pragma region Misc Constant
#pragma region Misc Constant Variables
/**
* @brief The identifier of Virtools file.
*/
constexpr const CKCHAR CKNEMOFI[] = "Nemo Fi";
constexpr const CKCHAR CKNEMOFI[] = u8"Nemo Fi";
/**
* @brief Current Version of CK Engine (Day/Month/Year)
*/
@ -65,8 +65,7 @@ namespace LibCmo::CK2 {
#pragma endregion
#pragma region Common Used Struct
// a stupid forward decl to remove something
/**
* @brief Storage class for filename extensions
*/
@ -97,10 +96,10 @@ namespace LibCmo::CK2 {
void SetExt(CKSTRING s) {
if (s == nullptr) {
m_Data[0] = '\0';
m_Data[0] = u8'\0';
} else {
if (s[0] == '.') ++s; // skip dot
size_t len = std::strlen(s);
if (s[0] == u8'.') ++s; // skip dot
CKDWORD len = CKStrLen(s);
if (len > (c_DataLen - 1)) len = c_DataLen - 1;
std::memcpy(m_Data, s, len);
}
@ -122,13 +121,13 @@ namespace LibCmo::CK2 {
static constexpr size_t c_DataLen = 4u;
CKCHAR m_Data[c_DataLen];
};
/**
* The struct describe the bitmap handler's infomation,
* including its GUID and supported file extension.
* This struct also will store some parameters related to bitmap handler,
* such as jpeg compress level and etc. But currently there are no
* such parameters.
* @brief Bitmap readers image description
* @details
* The struct describe the bitmap handler's infomation, including its GUID and supported file extension.
* This struct also will store some parameters related to bitmap handler, such as jpeg compress level and etc.
* But currently there are no such parameters.
*/
class CKBitmapProperties {
public:
@ -136,12 +135,34 @@ namespace LibCmo::CK2 {
m_ReaderGuid(), m_Ext() {}
CKBitmapProperties(const CKGUID& guid, CKSTRING ext) :
m_ReaderGuid(guid), m_Ext(ext) {}
LIBCMO_DEFAULT_COPY_MOVE(CKBitmapProperties);
YYCC_DEF_CLS_COPY_MOVE(CKBitmapProperties);
CKGUID m_ReaderGuid; /**< CKGUID that uniquely identifies the reader that created this properties structure */
CKFileExtension m_Ext; /**< File Extension of the image being described by this structure */
};
/**
* @brief Light Structure passed to CKRasterizerContext::SetLight()
* @details
* This struct is a part of CKRasterizer.
* I put it in there just for the convenience of CKLight.
*/
struct CKLightData {
VxMath::VXLIGHT_TYPE m_Type; /**< Point, Spot, Directionnal */
VxMath::VxColor m_Diffuse; /**< Diffuse Color */
VxMath::VxColor m_Specular; /**< Specular Color (Unused...) */
VxMath::VxColor m_Ambient; /**< Ambient Color (Unused...) */
VxMath::VxVector3 m_Position; /**< World Position */
VxMath::VxVector3 m_Direction; /**< Direction */
CKFLOAT m_Range; /**< Range */
CKFLOAT m_Falloff;
CKFLOAT m_Attenuation0;
CKFLOAT m_Attenuation1;
CKFLOAT m_Attenuation2;
CKFLOAT m_InnerSpotCone; /**< Only for spot lights */
CKFLOAT m_OuterSpotCone; /**< Only for spot lights */
};
#pragma endregion

View File

@ -256,4 +256,9 @@ namespace LibCmo::CK2 {
CKBITMAPDATA_DYNAMIC = 64,
};
enum class CK_CAMERA_PROJECTION : CKDWORD {
CK_PERSPECTIVEPROJECTION = 1,
CK_ORTHOGRAPHICPROJECTION = 2,
};
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "../VTAll.hpp"
#include "../VTInternal.hpp"
namespace LibCmo::XContainer {
using XIntArray = XArray<CKINT>;
@ -40,13 +40,13 @@ namespace LibCmo::CK2 {
~CKBufferParser() {
if (this->m_NeedManualFree) delete[](this->m_MemBegin);
}
LIBCMO_DISABLE_COPY_MOVE(CKBufferParser);
YYCC_DEL_CLS_COPY_MOVE(CKBufferParser);
const void* GetPtr(CKINT extraoff = 0) { return (this->m_MemBegin + m_MemPos + extraoff); }
void* GetMutablePtr(CKINT extraoff = 0) { return (this->m_MemBegin + m_MemPos + extraoff); }
void* GetBase(void) { return this->m_MemBegin; }
CKDWORD GetSize(void) { return this->m_MemSize; }
CKDWORD GetCursor(void) { return this->m_MemPos; }
void* GetBase() { return this->m_MemBegin; }
CKDWORD GetSize() { return this->m_MemSize; }
CKDWORD GetCursor() { return this->m_MemPos; }
void MoveCursor(CKINT off) { this->m_MemPos += off; }
void SetCursor(CKDWORD off) { this->m_MemPos = off; }
void Read(void* data, CKDWORD data_size) {
@ -67,7 +67,6 @@ namespace LibCmo::CK2 {
}
};
#pragma pack(push)
#pragma pack(1)
struct CKRawFileInfo {
CKBYTE NeMo[8];
@ -87,7 +86,7 @@ namespace LibCmo::CK2 {
CKDWORD ProductBuild;
CKDWORD Hdr1UnPackSize;
};
#pragma pack(pop)
#pragma pack()
class CKFileInfo {
public:
@ -97,7 +96,7 @@ namespace LibCmo::CK2 {
ObjectCount(0u), ManagerCount(0u), MaxIDSaved(0u), Crc(0u),
Hdr1PackSize(0u), Hdr1UnPackSize(0u), DataPackSize(0u), DataUnPackSize(0u) {}
~CKFileInfo() {}
LIBCMO_DEFAULT_COPY_MOVE(CKFileInfo);
YYCC_DEF_CLS_COPY_MOVE(CKFileInfo);
CKDWORD ProductVersion; /**< Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) */
CKDWORD ProductBuild; /**< Virtools Build Number. */
@ -156,7 +155,7 @@ namespace LibCmo::CK2 {
CKFilePluginDependencies() :
m_PluginCategory(CK_PLUGIN_TYPE::CKPLUGIN_MANAGER_DLL), m_Guids() {}
~CKFilePluginDependencies() {}
LIBCMO_DEFAULT_COPY_MOVE(CKFilePluginDependencies);
YYCC_DEF_CLS_COPY_MOVE(CKFilePluginDependencies);
CK_PLUGIN_TYPE m_PluginCategory;
XContainer::XArray<CKGUID> m_Guids;
@ -188,7 +187,7 @@ namespace LibCmo::CK2 {
public:
CKFileReader(CKContext* ctx);
~CKFileReader();
LIBCMO_DISABLE_COPY_MOVE(CKFileReader);
YYCC_DEL_CLS_COPY_MOVE(CKFileReader);
// ========== Loading ==========
CKERROR ShallowLoad(CKSTRING u8_filename);
@ -211,7 +210,7 @@ namespace LibCmo::CK2 {
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */
/**
* @brief List of files that should be inserted in the CMO file.
* @remark Each item is just file name, not the full path to file.
* @remarks Each item is just file name, not the full path to file.
*/
XContainer::XArray<XContainer::XString> m_IncludedFiles;
CKFileInfo m_FileInfo; /**< Headers summary */
@ -229,7 +228,7 @@ namespace LibCmo::CK2 {
CKFileWriter(CKContext* ctx);
CKFileWriter(CKContext* ctx, CKFileReader* reader, bool is_shallow);
~CKFileWriter();
LIBCMO_DISABLE_COPY_MOVE(CKFileWriter);
YYCC_DEL_CLS_COPY_MOVE(CKFileWriter);
// ========== Saving Preparing ==========
bool AddSavedObject(ObjImpls::CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
@ -242,37 +241,36 @@ namespace LibCmo::CK2 {
protected:
/**
* @brief A helper function to check whether given file can be written.
* @param filename[in] The name of file to be wriiten
* @param[in] filename The name of file to be wriiten
* @return CKERROR::CK_OK if can write.
*/
CKERROR PrepareFile(CKSTRING filename);
/**
* @brief Internal used Object Adder.
*
* @details
* This function is used by AddSavedObject() and Copy from reader constructor.
* This function accept a object pointer, and try adding them.
* This function accept an object pointer, and try adding them.
* And set m_IncludedFiles and m_ObjectsHashTable properly.
*
* @param obj The pointer to added object.
* @param flags The flag used when saving this object.
* @param[in] obj The pointer to added object.
* @param[in] flags The flag used when saving this object.
* @return True if success.
*/
bool InternalObjectAdder(ObjImpls::CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
protected:
bool m_Done; /**< True if this writer is already written into file. A written CKFileWriter can no be written again. */
bool m_Done; /**< True if this writer is already written into file. A written CKFileWriter can no be written again. */
/**
* @brief True if this writer is not allowed to add objects.
* @remark
* + This field should be false in default.
* + This field usually be set when importing from reader.
* @remarks
* \li This field should be false in default.
* \li This field usually be set when importing from reader.
*/
bool m_DisableAddingObject;
/**
* @brief True if this writer is not allowed to add files.
* @remark
* + This field should be false in default.
* + This field usually be set when importing from reader.
* @remarks
* \li This field should be false in default.
* \li This field usually be set when importing from reader.
*/
bool m_DisableAddingFile;
@ -282,7 +280,7 @@ namespace LibCmo::CK2 {
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
/**
* @brief List of files that should be inserted in the CMO file.
* @remark Each item is the full path to file.
* @remarks Each item is the full path to file.
*/
XContainer::XArray<XContainer::XString> m_IncludedFiles;
XContainer::XHashTable<CK_ID, CKDWORD> m_ObjectsHashTable; /**< A Object ID to save index hash table. */

View File

@ -323,12 +323,12 @@ namespace LibCmo::CK2 {
CKFileVisitor::CKFileVisitor(CKFileReader* reader) :
m_IsReader(true), m_Reader(reader), m_Writer(nullptr), m_Ctx(reader->m_Ctx) {
if (reader == nullptr) LIBCMO_PANIC("Reader is nullptr.");
if (reader == nullptr) throw LogicException("Reader is nullptr.");
}
CKFileVisitor::CKFileVisitor(CKFileWriter* writer) :
m_IsReader(false), m_Reader(nullptr), m_Writer(writer), m_Ctx(writer->m_Ctx) {
if (writer == nullptr) LIBCMO_PANIC("Writer is nullptr.");
if (writer == nullptr) throw LogicException("Writer is nullptr.");
}
CKFileVisitor::CKFileVisitor(const CKFileVisitor& rhs) :

View File

@ -18,12 +18,14 @@ namespace LibCmo::CK2 {
CKERROR CKFileReader::ShallowLoad(CKSTRING u8_filename) {
// check document status
if (this->m_Done) return CKERROR::CKERR_CANCELLED;
// check CKContext encoding sequence
if (!this->m_Ctx->IsValidEncoding()) return CKERROR::CKERR_CANCELLED;
// check file and open memory
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename));
if (!mappedFile->IsValid()) {
this->m_Ctx->OutputToConsoleEx("Fail to create Memory File for \"%s\".", u8_filename);
this->m_Ctx->OutputToConsoleEx(u8"Fail to create Memory File for \"%s\".", u8_filename);
return CKERROR::CKERR_INVALIDFILE;
}
@ -35,6 +37,8 @@ namespace LibCmo::CK2 {
if (err != CKERROR::CKERR_OK) return err;
// other data will be free automatically
// set done flag and return
this->m_Done = true;
return CKERROR::CKERR_OK;
}
@ -42,7 +46,7 @@ namespace LibCmo::CK2 {
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->SetCursor(ParserPtr->GetCursor());
XContainer::XString name_conv;
std::string name_conv;
// ========== read header ==========
// check header size
@ -85,20 +89,49 @@ namespace LibCmo::CK2 {
// reset crc field of header
rawHeader.Crc = 0u;
// compute crc
// Compute and check CRC in theory (< Virtools 4.0)
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, CKSizeof(CKRawFileInfo), 0u);
parser->SetCursor(sizeof(CKRawFileInfo));
parser->SetCursor(CKSizeof(CKRawFileInfo));
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
// MARK:
// If the CRC check failed, there is another way to compute CRC. (>= Virtools 4.0)
// This is a patch for Dassault stupid programmer.
//
// After Virtools 4.0, Dassault use a new way to compute the CRC of file.
// Dassault introduces a new class called CKMemoryBufferWriter which use file and memory map to handle big file properly.
// This algorithm splits the whole data body into 8 MB chunks and calculate them one by one to avoid instantaneous memory occupation.
// However, there is a bug in virtual function CKMemoryBufferWriter::ComputeCRC.
// It takes `PreviousCRC` as argument but never use it in function.
// In this function, the start value of CRC compution is hardcoded 0.
// So, although Dassault programmer try to compute CRC for file header, header part and daat part in code, it actually only compute CRC for data part!
// I 100% sure this is the mistake of Dassault stupid programmer and this bug cause more horrible result.
//
// In Virtools 2.1, engine will check CRC of file first. If no matched CRC, engine will reject loading file.
// So the obvious result is that we can not load file saved by Virtools 4.0 in Virtools 2.1.
// But this is not the point which makes me indignant.
// The real weird point is that we can use Virtools 3.5 to open file saved by Virtools 4.0, but why?
// After some researches, I found that the programmer of Dassault totally removed CRC check when loading file, since some version which I don't know, to suppress this bug!
// This is totally cheat and commercial-oriented behavior!
// I guess Dassault programmer also found that they can not load new created file in old Virtools.
// But they didn't find out what cause this bug, and just directly remove the whole of CRC checker to resolve this bug!
// I can't believe that this thing happens on such official software.
// This is the point which makes me indignant.
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, 0u);
// Both CRC compute methods are failed. This file may be really broken.
// Report exception directly.
if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole(u8"Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
}
}
// reset cursor
parser->SetCursor(sizeof(CKRawFileInfo));
parser->SetCursor(CKSizeof(CKRawFileInfo));
// compare size to decide wheher use compress feature
if (this->m_FileInfo.Hdr1PackSize != this->m_FileInfo.Hdr1UnPackSize) {
@ -129,7 +162,8 @@ namespace LibCmo::CK2 {
if (namelen != 0) {
name_conv.resize(namelen);
parser->Read(name_conv.data(), namelen);
m_Ctx->GetUtf8String(name_conv, fileobj.Name);
if (!m_Ctx->GetUTF8String(name_conv, fileobj.Name))
m_Ctx->OutputToConsole(u8"Fail to get UTF8 name for CKObject when reading file header. Some objects name will leave to blank.");
} else {
XContainer::NSXString::FromCKSTRING(fileobj.Name, nullptr);
}
@ -184,7 +218,7 @@ namespace LibCmo::CK2 {
if (this->m_FileInfo.FileVersion >= 8) {
// file ver >= 8, use header offset
// because it have compress feature
ParserPtr->SetCursor(this->m_FileInfo.Hdr1PackSize + sizeof(CKRawFileInfo));
ParserPtr->SetCursor(this->m_FileInfo.Hdr1PackSize + CKSizeof(CKRawFileInfo));
} else {
// otherwise, sync with current parser.
ParserPtr->SetCursor(parser->GetCursor());
@ -197,11 +231,11 @@ namespace LibCmo::CK2 {
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->SetCursor(ParserPtr->GetCursor());
XContainer::XString name_conv;
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) {
@ -219,7 +253,7 @@ namespace LibCmo::CK2 {
0u
);
if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error.");
this->m_Ctx->OutputToConsole(u8"Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR;
}
@ -307,7 +341,8 @@ namespace LibCmo::CK2 {
// read filename
if (filenamelen != 0) {
parser->Read(name_conv.data(), filenamelen);
m_Ctx->GetUtf8String(name_conv, file);
if (!m_Ctx->GetUTF8String(name_conv, file))
m_Ctx->OutputToConsole(u8"Fail to get UTF8 name for included file when reading file body. Some included files may be stripped.");
}
// read file body length
@ -316,12 +351,12 @@ namespace LibCmo::CK2 {
// read file body
XContainer::XString tempfilename = m_Ctx->GetPathManager()->GetTempFilePath(file.c_str());
FILE* fp = EncodingHelper::U8FOpen(tempfilename.c_str(), "wb");
FILE* fp = YYCC::IOHelper::UTF8FOpen(tempfilename.c_str(), u8"wb");
if (fp != nullptr) {
std::fwrite(parser->GetPtr(), sizeof(CKBYTE), filebodylen, fp);
std::fclose(fp);
} else {
m_Ctx->OutputToConsoleEx("Fail to open temp file: %s", tempfilename.c_str());
m_Ctx->OutputToConsoleEx(u8"Fail to open temp file: %s", tempfilename.c_str());
}
// move to next
@ -335,6 +370,8 @@ namespace LibCmo::CK2 {
CKERROR CKFileReader::DeepLoad(CKSTRING u8_filename) {
// check document status
if (this->m_Done) return CKERROR::CKERR_CANCELLED;
// check CKContext encoding sequence
if (!this->m_Ctx->IsValidEncoding()) return CKERROR::CKERR_CANCELLED;
// ========== prepare work ==========
CKERROR err = CKERROR::CKERR_OK;
@ -342,6 +379,8 @@ namespace LibCmo::CK2 {
// get shallow document first
err = this->ShallowLoad(u8_filename);
if (err != CKERROR::CKERR_OK) return err;
// reset done flag because we need further processing
this->m_Done = false;
// ========== create object first ==========
for (auto& obj : this->m_FileObjects) {
@ -387,6 +426,10 @@ namespace LibCmo::CK2 {
}
// ========== finalize work ==========
// set done flag and return
this->m_Done = true;
return CKERROR::CKERR_OK;
}

View File

@ -12,9 +12,11 @@ namespace LibCmo::CK2 {
CKERROR CKFileWriter::Save(CKSTRING u8_filename) {
// check document status
if (this->m_Done) return CKERROR::CKERR_CANCELLED;
// check CKContext encoding sequence
if (!this->m_Ctx->IsValidEncoding()) return CKERROR::CKERR_CANCELLED;
// encoding conv helper
XContainer::XString name_conv;
std::string name_conv;
// try detect filename legality
CKERROR err = PrepareFile(u8_filename);
@ -89,7 +91,8 @@ namespace LibCmo::CK2 {
sumHdrObjSize += 4 * CKSizeof(CKDWORD);
if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) {
// += Name size
m_Ctx->GetNativeString(obj.Name, name_conv);
if (!m_Ctx->GetOrdinaryString(obj.Name, name_conv))
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for CKObject name when computing the size of saved file. It may cause application crash or saved file has blank object name.");
sumHdrObjSize += static_cast<CKDWORD>(name_conv.size());
}
@ -176,7 +179,8 @@ namespace LibCmo::CK2 {
if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) {
// if have name, write it
m_Ctx->GetNativeString(obj.Name, name_conv);
if (!m_Ctx->GetOrdinaryString(obj.Name, name_conv))
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for CKObject name when saving file. Some objects may be saved with blank name.");
CKDWORD namelen = static_cast<CKDWORD>(name_conv.size());
hdrparser->Write(&namelen);
hdrparser->Write(name_conv.data(), namelen);
@ -212,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());
@ -259,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());
@ -299,7 +303,7 @@ namespace LibCmo::CK2 {
// ========== Open File & Write Essential Data ==========
// open file and test
FILE* fs = EncodingHelper::U8FOpen(u8_filename, "wb");
FILE* fs = YYCC::IOHelper::UTF8FOpen(u8_filename, u8"wb");
if (fs == nullptr) return CKERROR::CKERR_CANTWRITETOFILE;
// write small header + header + data
std::fwrite(&rawHeader, sizeof(CKRawFileInfo), 1, fs);
@ -316,7 +320,8 @@ namespace LibCmo::CK2 {
m_Ctx->GetPathManager()->GetFileName(filename);
// write filename
m_Ctx->GetNativeString(filename, name_conv);
if (!m_Ctx->GetOrdinaryString(filename, name_conv))
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for included file when saving file. Some included files may not be saved correctly.");
CKDWORD filenamelen = static_cast<CKDWORD>(name_conv.size());
std::fwrite(&filenamelen, sizeof(CKDWORD), 1, fs);
std::fwrite(name_conv.data(), sizeof(CKBYTE), filenamelen, fs);
@ -336,7 +341,7 @@ namespace LibCmo::CK2 {
std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs);
// report error
m_Ctx->OutputToConsoleEx("Fail to open temp file: %" PRI_CKSTRING, fentry.c_str());
m_Ctx->OutputToConsoleEx(u8"Fail to open temp file: %" PRI_CKSTRING, fentry.c_str());
}
// release mapped file
@ -347,6 +352,8 @@ namespace LibCmo::CK2 {
// close file
std::fclose(fs);
// set done flag and return
this->m_Done = true;
return CKERROR::CKERR_OK;
}
@ -356,7 +363,7 @@ namespace LibCmo::CK2 {
// try open file to check whether we can write it.
CKERROR err;
FILE* tryfile = EncodingHelper::U8FOpen(filename, "ab");
FILE* tryfile = YYCC::IOHelper::UTF8FOpen(filename, u8"ab");
if (tryfile == nullptr) {
err = CKERROR::CKERR_CANTWRITETOFILE;
} else {

View File

@ -1,5 +1,5 @@
#include "../VTUtils.hpp"
#if defined(LIBCMO_OS_WIN32)
#if YYCC_OS == YYCC_OS_WINDOWS
#define ZLIB_WINAPI
#endif
#include <zconf.h>
@ -20,44 +20,63 @@
#include "ObjImpls/CKTexture.hpp"
#include "ObjImpls/CKMaterial.hpp"
#include "ObjImpls/CKMesh.hpp"
#include "ObjImpls/CKLight.hpp"
#include "ObjImpls/CKTargetLight.hpp"
#include "ObjImpls/CKCamera.hpp"
#include "ObjImpls/CKTargetCamera.hpp"
namespace LibCmo::CK2 {
#pragma region Compression utilities
#pragma region Compression Utilities
void* CKPackData(const void* Data, CKDWORD size, CKDWORD& NewSize, CKINT compressionlevel) {
uLong boundary = compressBound(static_cast<uLong>(size));
CKBYTE* DestBuffer = new CKBYTE[boundary];
// check argument
if (Data == nullptr && size != 0u)
throw LogicException("Data passed in CKPackData should not be nullptr.");
// get boundary and allocate buffer.
uLong boundary = compressBound(static_cast<uLong>(size));
std::unique_ptr<CKBYTE[]> DestBuffer(new CKBYTE[boundary]);
// do compress
uLongf _destLen = static_cast<uLongf>(boundary);
if (compress2(
reinterpret_cast<Bytef*>(DestBuffer), &_destLen,
reinterpret_cast<Bytef*>(DestBuffer.get()), &_destLen,
static_cast<const Bytef*>(Data), static_cast<uLong>(size),
static_cast<int>(compressionlevel)) != Z_OK) {
NewSize = 0;
delete[] DestBuffer;
// failed
NewSize = 0u;
return nullptr;
}
NewSize = static_cast<CKDWORD>(_destLen);
return DestBuffer;
return DestBuffer.release();
}
void* CKUnPackData(CKDWORD DestSize, const void* SrcBuffer, CKDWORD SrcSize) {
CKBYTE* DestBuffer = new CKBYTE[DestSize];
// check argument
if (SrcBuffer == nullptr && SrcSize != 0u)
throw LogicException("Data passed in CKUnPackData should not be nullptr.");
// allocate buffer
std::unique_ptr<CKBYTE[]> DestBuffer(new CKBYTE[DestSize]);
uLongf cache = DestSize;
if (uncompress(
reinterpret_cast<Bytef*>(DestBuffer), &cache,
reinterpret_cast<Bytef*>(DestBuffer.get()), &cache,
static_cast<const Bytef*>(SrcBuffer), static_cast<uLong>(SrcSize)) != Z_OK) {
delete[] DestBuffer;
return nullptr;
}
return DestBuffer;
return DestBuffer.release();
}
CKDWORD CKComputeDataCRC(const void* data, CKDWORD size, CKDWORD PreviousCRC) {
// check argument
if (data == nullptr && size != 0u)
throw LogicException("Data passed in CKComputeDataCRC should not be nullptr.");
// compute
return static_cast<CKDWORD>(adler32(
static_cast<uLong>(PreviousCRC),
static_cast<const Bytef*>(data),
@ -69,42 +88,50 @@ namespace LibCmo::CK2 {
#pragma region String Utilities
bool CKStrEqual(CKSTRING str1, CKSTRING str2) {
template<bool bCaseSenstive>
static bool InternalStrEqual(CKSTRING str1, CKSTRING str2) {
if (str1 == nullptr) {
if (str2 == nullptr) return true;
else return false;
} else {
if (str2 == nullptr) return false;
else {
return std::strcmp(str1, str2) == 0;
}
}
}
bool CKStrEqualI(CKSTRING str1, CKSTRING str2) {
if (str1 == nullptr) {
if (str2 == nullptr) return true;
else return false;
} else {
if (str2 == nullptr) return false;
else {
// do real cmp
size_t i = 0;
while (str1[i] != '\0' && str2[i] != '\0') {
if (std::tolower(str1[i]) != std::tolower(str2[i])) return false;
// do real compare
while (*str1 != u8'\0' && *str2 != u8'\0') {
// compare char
if constexpr (bCaseSenstive) {
if (*str1 != *str2) return false;
} else {
if (std::tolower(*str1) != std::tolower(*str2)) return false;
}
// inc step
++str1;
++str2;
}
// !XOR the result, if both of them is zero, return true(1)
return !((str1[i] != '\0') ^ (str2[i] != '\0'));
// if both of them is zero, return true, otherwise false.
return *str1 == u8'\0' && *str2 == u8'\0';
}
}
}
bool CKStrEqual(CKSTRING str1, CKSTRING str2) {
return InternalStrEqual<true>(str1, str2);
}
bool CKStrEqualI(CKSTRING str1, CKSTRING str2) {
return InternalStrEqual<false>(str1, str2);
}
bool CKStrEmpty(CKSTRING strl) {
if (strl == nullptr) return true;
return strl[0] == '\0';
return strl[0] == u8'\0';
}
CKDWORD CKStrLen(CKSTRING strl) {
if (strl == nullptr) return 0u;
size_t len = std::strlen(YYCC::EncodingHelper::ToOrdinary(strl));
if (len > static_cast<size_t>(std::numeric_limits<CKDWORD>::max()))
throw RuntimeException("Exceed maximum value when cast size_t to CKDWORD.");
return static_cast<CKDWORD>(len);
}
#pragma endregion
@ -112,7 +139,7 @@ namespace LibCmo::CK2 {
#pragma region CKClass Registration
static XContainer::XArray<CKClassDesc> g_CKClassInfo;
static bool GetClassIdIndex(CK_CLASSID cid, size_t& intcid) {
intcid = static_cast<size_t>(cid);
if (intcid >= g_CKClassInfo.size()) return false;
@ -123,7 +150,7 @@ namespace LibCmo::CK2 {
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo) {
size_t idxListener, idxListenTo;
if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo)) return;
XContainer::NSXBitArray::Set(g_CKClassInfo[idxListener].ToBeNotify, static_cast<CKDWORD>(idxListenTo));
}
@ -173,8 +200,8 @@ namespace LibCmo::CK2 {
CKSTRING CKClassIDToString(CK_CLASSID cid) {
const CKClassDesc* desc = CKGetClassDesc(cid);
if (desc == nullptr) return "Undefined Type";
else return desc->NameFct();
if (desc == nullptr) return u8"Undefined Type";
return desc->NameFct();
}
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
@ -233,18 +260,18 @@ namespace LibCmo::CK2 {
This relation is represented in ToBeNotify, a pure relation without any inhertance hierarchy.
Ok, now we assume A have children AA, B also have children BB.
Because B is a businessman, so his children BB also is a bussinessman.
Because B is a businessman, so his children BB also is a businessman.
B and BB have the same goods so A can buy his stuff from both of B and BB.
This is the first step executed by ComputeParentsNotifyTable().
In this step, the function expand existing business relations to all possible business relations (expand to businessman's children)
Image there is a candy store, C. Because AA still is a kids.
So AA want to buy something from C. Now C is in his ToBeNotify.
Additionally, A, the parent of AA, force AA to buy something from B, just for A himself.
For AA, he does not need want to buy something from B, but his parent A order he to do.
This is the second step executed by ComputeParentsNotifyTable().
For AA, his parent's relations also need to be merged after he processed his relations with C like I introduced previously.
Now, AA have a full business list writing all trades he can do.
This is represented as CommonToBeNotify.
In this time, AA's ToBeNotify only have C, but his CommonToBeNotify have B, BB and C.
@ -254,7 +281,7 @@ namespace LibCmo::CK2 {
Because a full trades list are created from A side.
The better solution is just ask the guest: do you want to buy something from me?
This operation will fill ToNotify and is implemented at ComputeHierarchyTable().
At the end of this story,
All bussiness man can use ToNofity to see whom they want to sell something to.
And all buyer can use CommonToBeNofity to check who they can buy something from.
@ -267,7 +294,7 @@ namespace LibCmo::CK2 {
// find direct parent
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
if (!parent.IsValid) LIBCMO_PANIC("No such CK_CLASSID.");
if (!parent.IsValid) throw LogicException("No such CK_CLASSID.");
// if it is not self inheritance, call recursively
if (desc.Self != desc.Parent) {
@ -281,26 +308,26 @@ namespace LibCmo::CK2 {
// set derivation level
desc.DerivationLevel = parent.DerivationLevel + 1;
// set done
desc.Done = true;
}
static void ComputeParentsNotifyTable(CKClassDesc& desc) {
// if it has done, do not process it again.
if (desc.Done) return;
// find direct parent
CKClassDesc& parent = g_CKClassInfo[static_cast<size_t>(desc.Parent)];
if (!parent.IsValid) LIBCMO_PANIC("No such CK_CLASSID.");
if (!parent.IsValid) throw LogicException("No such CK_CLASSID.");
// if it is not self inheritance, call recursively
if (desc.Self != desc.Parent) {
ComputeParentsNotifyTable(parent);
}
// add all children of ToBeNofity list
for (CKDWORD idx = 0; idx < desc.ToBeNotify.size(); ++idx) {
if (!XContainer::NSXBitArray::IsSet(desc.ToBeNotify, idx))
if (!XContainer::NSXBitArray::IsSet(desc.ToBeNotify, idx))
continue;
CKClassDesc& target = g_CKClassInfo[idx];
@ -352,7 +379,7 @@ namespace LibCmo::CK2 {
if (!item.IsValid || item.RegisterFct == nullptr) continue;
item.RegisterFct();
}
// ===== Build Notify Hierarchy =====
// set array first
for (auto& item : g_CKClassInfo) {
@ -398,13 +425,13 @@ CKClassRegister(cid, parentCid, \
nullptr, \
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
[]() -> CKSTRING { return strName; });
[]() -> CKSTRING { return u8 ## strName; });
#define EasyClassRegWithNotify(clsname, cid, parentCid, strName, notifyCids) \
CKClassRegister(cid, parentCid, \
[]() -> void { NeedNotificationWrapper(cid, notifyCids); }, \
[](CKContext* ctx, CK_ID id, CKSTRING name) -> ObjImpls::CKObject* { return new clsname(ctx, id, name); }, \
[](CKContext* ctx, ObjImpls::CKObject* obj) -> void { delete obj; }, \
[]() -> CKSTRING { return strName; });
[]() -> CKSTRING { return u8 ## strName; });
EasyClassReg(ObjImpls::CKObject, CK_CLASSID::CKCID_OBJECT, CK_CLASSID::CKCID_OBJECT, "Basic Object");
EasyClassReg(ObjImpls::CKSceneObject, CK_CLASSID::CKCID_SCENEOBJECT, CK_CLASSID::CKCID_OBJECT, "Scene Object");
@ -416,6 +443,10 @@ CKClassRegister(cid, parentCid, \
EasyClassReg(ObjImpls::CKTexture, CK_CLASSID::CKCID_TEXTURE, CK_CLASSID::CKCID_BEOBJECT, "Texture");
EasyClassRegWithNotify(ObjImpls::CKMaterial, CK_CLASSID::CKCID_MATERIAL, CK_CLASSID::CKCID_BEOBJECT, "Material", { CK_CLASSID::CKCID_TEXTURE });
EasyClassRegWithNotify(ObjImpls::CKMesh, CK_CLASSID::CKCID_MESH, CK_CLASSID::CKCID_BEOBJECT, "Mesh", { CK_CLASSID::CKCID_MATERIAL });
EasyClassReg(ObjImpls::CKLight, CK_CLASSID::CKCID_LIGHT, CK_CLASSID::CKCID_3DENTITY, "Light");
EasyClassReg(ObjImpls::CKCamera, CK_CLASSID::CKCID_CAMERA, CK_CLASSID::CKCID_3DENTITY, "Camera");
EasyClassRegWithNotify(ObjImpls::CKTargetLight, CK_CLASSID::CKCID_TARGETLIGHT, CK_CLASSID::CKCID_LIGHT, "Target Light", { CK_CLASSID::CKCID_3DENTITY });
EasyClassRegWithNotify(ObjImpls::CKTargetCamera, CK_CLASSID::CKCID_TARGETCAMERA, CK_CLASSID::CKCID_CAMERA, "Target Camera", { CK_CLASSID::CKCID_3DENTITY });
#undef EasyClassReg
#undef EasyClassRegWithNotify
@ -426,7 +457,7 @@ CKClassRegister(cid, parentCid, \
}
CKERROR CKShutdown() {
// free class indo
// free class infos
g_CKClassInfo.clear();
return CKERROR::CKERR_OK;

View File

@ -3,6 +3,7 @@
#include "CKTypes.hpp"
#include "../XContainer/XTypes.hpp"
#include <functional>
#include <memory>
namespace LibCmo::CK2 {
@ -10,87 +11,114 @@ namespace LibCmo::CK2 {
/**
* @brief Compress a buffer
* @param[in] Data A pointer to the buffer to coompress
* @param[in] Data A pointer to the buffer to compress. nullptr is not allowed.
* @param[in] size Size of the source buffer.
* @param[out] NewSize A reference that will be filled with the size of the compressed buffer. 0 if failed.
* @param[in] compressionlevel 0-9
* @param[in] compressionlevel 0-9 Greater level smaller result size.
* @return
* A pointer to the compressed buffer. nullptr if failed.
* The return pointer should be freed by `delete[]` manually.
* @remark
* The return pointer should be freed by \c delete[] manually.
* @remarks
* The size of allocated return value may greater than the passed value of NewSize.
* NewSize only indicate the size of the part storing useful data in return value.
* @see CKUnPackData, CKComputeDataCRC
* @exception LogicException Raised if given buffer is nullptr and size is not equal to zero.
* @see CKUnPackData(), CKComputeDataCRC()
*/
void* CKPackData(const void* Data, CKDWORD size, CKDWORD& NewSize, CKINT compressionlevel);
/**
* @brief Decompress a buffer
* @param[in] DestSize Expected size of the decompressed buffer.
* @param[in] SrcBuffer Compressed buffer.
* @param[in] SrcBuffer Compressed buffer. nullptr is not allowed.
* @param[in] SrcSize Size of the compressed buffer.
* @return
* A pointer to the decompressed buffer or nullptr if there was a error.
* The return pointer should be freed by `delete[]` manually.
* @see CKPackData, CKComputeDataCRC
* The return pointer should be freed by \c delete[] manually.
* @exception LogicException Raised if given buffer is nullptr and size is not equal to zero.
* @see CKPackData(), CKComputeDataCRC()
*/
void* CKUnPackData(CKDWORD DestSize, const void* SrcBuffer, CKDWORD SrcSize);
/**
* @brief Computes a CRC for a buffer.
* @param[in] data A pointer to the buffer to create a CRC for.
* @param[in] data A pointer to the buffer to create a CRC for. nullptr is not allowed.
* @param[in] size Size of the source buffer.
* @param[in] PreviousCRC
* The first time a CRC is computed this value should be 0,
* but it can be use to compute a single CRC for a several buffers
* by using the currently computed CRC for previous buffers in this value.
* @return CRC of the buffer.
* @see CKPackData, CKUnPackData
* @exception LogicException Raised if given buffer is nullptr and size is not equal to zero.
* @see CKPackData(), CKUnPackData()
*/
CKDWORD CKComputeDataCRC(const void* data, CKDWORD size, CKDWORD PreviousCRC = 0);
// ========== String Utilities ==========
/**
* @brief Check whether 2 string is equal. Case senstive.
* @param str1[in] String 1
* @param str2[in] String 2
* @return True if 2 string is equal.
* @see CKStrIEqual
* @brief Check whether two string is equal. Case senstive.
* @param[in] str1 First string. nullptr is allowed but not suggested.
* @param[in] str2 Second string. nullptr is allowed but not suggested.
* @return True if two string is equal, otherwise false.
* @remarks
* nullptr string is not equal to any other string.
* However two nullptr string is equal.
* @see CKStrEqualI()
*/
bool CKStrEqual(CKSTRING str1, CKSTRING str2);
/**
* @brief Check whther 2 string is equal. Case insenstive.
* @param str1
* @param str2
* @return True if 2 string is equal.
* @see CKStrEqual
* @brief Check whther two string is equal. Case insenstive.
* @param[in] str1 First string. nullptr is allowed but not suggested.
* @param[in] str2 Second string. nullptr is allowed but not suggested.
* @return True if two string is equal, otherwise false.
* @remarks
* nullptr string is not equal to any other string.
* However two nullptr string is equal.
* @see CKStrEqual()
*/
bool CKStrEqualI(CKSTRING str1, CKSTRING str2);
/**
* @brief Check whether string is empty
* @param strl
* @return True if string is empty.
* @param[in] strl String for checking. nullptr is allowed but not suggested.
* @return True if string is empty, otherwise false.
* @remarks nullptr string is seen as empty string.
*/
bool CKStrEmpty(CKSTRING strl);
/**
* @brief Get the length of given string.
* @param[in] strl String for getting length. nullptr is allowed but not suggested.
* @return String length in UTF8 code unit.
* @remarks nullptr string will return 0 instead.
* @exception RuntimeException Raised if the length of string exceed the maximum value of CKDWORD.
*/
CKDWORD CKStrLen(CKSTRING strl);
// ========== Class registration utilities ==========
/// @brief Function pointer which do extra stuff when registry this class.
using CKClassRegisterFct = std::function<void()>;
/// @brief Function pointer which create ObjImpls::CKObject pointer by given CKContext, CK_ID and name.
using CKClassCreationFct = std::function<ObjImpls::CKObject* (CKContext*, CK_ID, CKSTRING)>;
/// @brief Function pointer which free given ObjImpls::CKObject pointer.
using CKClassReleaseFct = std::function<void(CKContext*, ObjImpls::CKObject*)>;
/// @brief Function pointer which return the name of class.
using CKClassNameFct = std::function<CKSTRING()>;
//using CKClassDependenciesFct = std::function<CKSTRING(CKINT, CKINT)>;
//using CKClassDependenciesCountFct = std::function<CKINT(CKINT)>;
/**
* @brief The representation of a registered class.
*/
struct CKClassDesc {
// Variables used when building class hierarchy table
bool IsValid; /**< True if this CKClassDesc is a valid one. Because CK_CLASSID may not be consecutive. */
bool Done;
// Initialized upon class registration
CK_CLASSID Self;
CK_CLASSID Parent; // Class Identifier of parent class
CKClassRegisterFct RegisterFct; // Pointer to Class Specific Registration function
CKClassCreationFct CreationFct; // Pointer to Class instance creation function
CKClassReleaseFct ReleaseFct; // Pointer to Class instance release function
CKClassNameFct NameFct; // Pointer to Class name function
bool Done; /**< Temporary variable indicating this item has been processed when creating table. */
// Variables initialized upon class registration
CK_CLASSID Self; /**< Class identifier of self */
CK_CLASSID Parent; /**< Class identifier of parent class */
CKClassRegisterFct RegisterFct; /**< Function pointer which do extra stuff when registry this class. */
CKClassCreationFct CreationFct; /**< Function pointer which create ObjImpls::CKObject pointer by given CKContext, CK_ID and name. */
CKClassReleaseFct ReleaseFct; /**< Function pointer which free given ObjImpls::CKObject pointer. */
CKClassNameFct NameFct; /**< Function pointer which return the name of class. */
//CKClassDependenciesFct DependsFct; // Pointer to Class dependencies function (Copy,delete,replace...)
//CKClassDependenciesCountFct DependsCountFct; // Pointer to Class dependencies Count function (Copy,delete,replace...)
@ -102,13 +130,13 @@ namespace LibCmo::CK2 {
//CKDWORD DefaultSaveDependencies;
//CKGUID Parameter; // Associated parameter GUID
// Initialized when building class hierarchy table
CKINT DerivationLevel; // O => CKObject , etc..
XContainer::XBitArray Parents; // Bit Mask of parents classes
XContainer::XBitArray Children; // Bit Mask of children classes
XContainer::XBitArray ToBeNotify; // User specified notify list, only for current class. If any deleted objects match class id in this XBitArray, notify the host of this XBitArray.
XContainer::XBitArray CommonToBeNotify; // Same as ToBeNotify, but merging all parents' notify list.
XContainer::XBitArray ToNotify; // The ClassID to notify when an object of this class is deleted (inverse of ToBeNotify)
// Variables initialized after building class hierarchy table
CKINT DerivationLevel; /**< How many parent level it has. 0 for CKObject, etc.. */
XContainer::XBitArray Parents; /**< Bit Mask of parents classes */
XContainer::XBitArray Children; /**< Bit Mask of children classes */
XContainer::XBitArray ToBeNotify; /**< User specified notify list, only for current class. If any deleted objects match class id in this XBitArray, notify the host of this XBitArray. */
XContainer::XBitArray CommonToBeNotify; /**< Same as ToBeNotify, but merging all parents' notify list. */
XContainer::XBitArray ToNotify; /**< The ClassID to notify when an object of this class is deleted (inverse of ToBeNotify) */
CKClassDesc() :
IsValid(false),
@ -118,44 +146,114 @@ namespace LibCmo::CK2 {
DerivationLevel(0),
Parents(), Children(), ToBeNotify(), CommonToBeNotify()
{}
LIBCMO_DEFAULT_COPY_MOVE(CKClassDesc);
YYCC_DEF_CLS_COPY_MOVE(CKClassDesc);
};
// ========== CKClass Registration ==========
/**
* @brief Order that first class id will be notified when deleting object whose class id is second argument
* @param[in] listener The id of class will be notified.
* @param[in] listenTo The id of class which first argument interested in.
* @remarks If one of given class ids is invalid, this function simply return and do nothing.
*/
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo);
/**
* @brief Get an usable class id for registration.
* @details This function is usually used by plugin to registering classes.
* Because all embedded Virtools classes has constant class id.
* @return An usable class id for registration.
*/
CK_CLASSID CKClassGetNewIdentifier();
/**
* @brief Register a new class.
* @param[in] cid The id of this class.
* @param[in] parentCid The id of parent class.
* @param[in] regFct Pointer to class specific registration function which do extra stuff when registry this class.
* @param[in] createFct Pointer to class instance creation function
* @param[in] relFct Pointer to class instance release function
* @param[in] nameFct Pointer to class name function
*/
void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid,
CKClassRegisterFct regFct, CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct);
// ========== Class Hierarchy Management ==========
/**
* @brief Get total count of registered classes.
* @return The total count of registered classes.
*/
CKDWORD CKGetClassCount();
/**
* @brief Get the class description struct by given class id.
* @param[in] cid Class id for fetching.
* @return The pointer to corresponding class description.
* If given class id is invalid, this function will return nullptr.
* According to this, caller can utilize this function to validate class id.
*/
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
/**
* @brief Get the name representation of given class id.
* @param[in] cid Class id for fetching.
* @return The name of given class id.
* If given class id is invalid, it return a predefined name.
*/
CKSTRING CKClassIDToString(CK_CLASSID cid);
/**
* @brief Check whether first class is second class' child class.
* @param[in] child The id of first class assumed as child class.
* @param[in] parent The id of second class assumed as parent class.
* @return True if relation is satisfied, otherwise false.
* If one of given class ids is invalid, this function always return false.
*/
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent);
/**
* @brief Get the parent class id of given class id.
* @param[in] child The id to class which need to find parent class.
* @return The parent class id.
* If given class id is invalid, this function always return the class id of CKObject.
*/
CK_CLASSID CKGetParentClassID(CK_CLASSID child);
/**
* @brief Get the cloest common parent of given two classes.
* @param[in] cid1 The id of first class finding common parent.
* @param[in] cid2 The id of second class finding common parent.
* @return The cloest common parent class id.
*/
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2);
/**
* @brief Check whether 'listener' need notified by the deletion of 'deletedObjCid'
* @param listener
* @param deletedObjCid
* @return true if need notify
* @brief Check whether object whose class id is first argument, need to be notified when the objects whose class id is second argument, is deleting.
* @param[in] listener The class id of checking whether need to be notified.
* @param[in] deletedObjCid The class id of deleting object.
* @return True if it need to be notified, otherwise false.
* If the class id of checking is invalid, this function always return false.
*/
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid);
/**
* @brief Get all object cid need to be notified when 'delObjCids' matched objects are deleting.
* @param delObjCids
* @param cidCount
* @return
* @brief Get all class ids need to be notified when objects whose class id included in \c delObjCids are deleting.
* @param[in] delObjCids The bit array representing class ids which need to be queried.
* @return The queried bit array representing class ids need to be notified.
* @see CKIsNeedNotify()
*/
XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids);
// ========== Initializations functions ==========
// ========== Initializations Functions ==========
/**
* @brief Initialize CK engine.
* @details You must call this function before anything.
* @return Error code about initializing.
* @see CKShutdown()
*/
CKERROR CKStartUp();
/**
* @brief Shutdown CK engine.
* @details You must call this function after you have done all things.
* @return Error code about shutdown.
* @see CKStartUp()
*/
CKERROR CKShutdown();
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "../VTAll.hpp"
#include "../VTInternal.hpp"
#include <memory>
#include <functional>
#include <type_traits>
@ -54,9 +54,9 @@ namespace LibCmo::CK2 {
LockedReadBufferDeleter() : m_Host(nullptr), m_ConsumedSize(0) {}
LockedReadBufferDeleter(CKStateChunk* host, CKDWORD init_size) :
m_Host(host), m_ConsumedSize(init_size) {}
LIBCMO_DEFAULT_COPY_MOVE(LockedReadBufferDeleter);
YYCC_DEF_CLS_COPY_MOVE(LockedReadBufferDeleter);
void operator()(LIBCMO_UNUSED const void* buf);
void operator()(const void* /*buf*/);
void SetConsumedSize(CKDWORD newsize);
private:
CKStateChunk* m_Host;
@ -68,9 +68,9 @@ namespace LibCmo::CK2 {
LockedWriteBufferDeleter() : m_Host(nullptr), m_ConsumedSize(0) {}
LockedWriteBufferDeleter(CKStateChunk* host, CKDWORD init_size) :
m_Host(host), m_ConsumedSize(init_size) {}
LIBCMO_DEFAULT_COPY_MOVE(LockedWriteBufferDeleter);
YYCC_DEF_CLS_COPY_MOVE(LockedWriteBufferDeleter);
void operator()(LIBCMO_UNUSED const void* buf);
void operator()(const void* /*buf*/);
void SetConsumedSize(CKDWORD newsize);
private:
CKStateChunk* m_Host;
@ -82,7 +82,7 @@ namespace LibCmo::CK2 {
BufferDeleter() : m_Host(nullptr), m_BufSize(0) {}
BufferDeleter(CKStateChunk* host, CKDWORD bufsize) :
m_Host(host), m_BufSize(bufsize) {}
LIBCMO_DEFAULT_COPY_MOVE(BufferDeleter);
YYCC_DEF_CLS_COPY_MOVE(BufferDeleter);
void operator()(const void* buf);
CKDWORD GetBufferSize() const;
@ -265,8 +265,8 @@ namespace LibCmo::CK2 {
#pragma region Read Function
public:
void StartRead(void);
void StopRead(void);
void StartRead();
void StopRead();
/* ========== Identifier Functions ==========*/
@ -556,7 +556,7 @@ namespace LibCmo::CK2 {
/*
* Actually this function mix various functions, including CloseChunk(), UpdateSize() and etc.
*/
void StopWrite(void);
void StopWrite();
/* ========== Identifier Functions ==========*/

View File

@ -101,7 +101,7 @@ namespace LibCmo::CK2 {
#pragma region Self Used Data Struct
void CKStateChunk::LockedReadBufferDeleter::operator()(LIBCMO_UNUSED const void* buf) {
void CKStateChunk::LockedReadBufferDeleter::operator()(const void* /*buf*/) {
if (m_Host == nullptr) return;
m_Host->UnLockReadBuffer(m_ConsumedSize);
}
@ -110,7 +110,7 @@ namespace LibCmo::CK2 {
m_ConsumedSize = newsize;
}
void CKStateChunk::LockedWriteBufferDeleter::operator()(LIBCMO_UNUSED const void* buf) {
void CKStateChunk::LockedWriteBufferDeleter::operator()(const void* /*buf*/) {
if (m_Host == nullptr) return;
m_Host->UnLockWriteBuffer(m_ConsumedSize);
}
@ -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

@ -4,7 +4,7 @@
namespace LibCmo::CK2 {
void CKStateChunk::StartRead(void) {
void CKStateChunk::StartRead() {
if (this->m_Parser.m_Status != CKStateChunkStatus::IDLE) return;
this->m_Parser.m_CurrentPos = 0u;
@ -13,7 +13,7 @@ namespace LibCmo::CK2 {
this->m_Parser.m_Status = CKStateChunkStatus::READ;
}
void CKStateChunk::StopRead(void) {
void CKStateChunk::StopRead() {
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return;
this->m_Parser.m_CurrentPos = 0u;
@ -71,7 +71,7 @@ namespace LibCmo::CK2 {
return true;
} else {
// failed, report to context
m_BindContext->OutputToConsoleEx("CKStateChunk::LockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
m_BindContext->OutputToConsoleEx(u8"CKStateChunk::LockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false;
}
}
@ -88,7 +88,7 @@ namespace LibCmo::CK2 {
return true;
} else {
// failed, report to context
m_BindContext->OutputToConsoleEx("CKStateChunk::UnLockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
m_BindContext->OutputToConsoleEx(u8"CKStateChunk::UnLockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false;
}
}
@ -140,7 +140,7 @@ namespace LibCmo::CK2 {
// MARK: the written string has NULL terminal.
// strByteSize also include NULL terminal,
// so we need minus 1 when resizing (not ReadByteData, because we still need read NULL terminal to skip it.)
XContainer::XString cache;
std::string cache;
cache.resize(strByteSize - 1);
if (!this->ReadByteData(cache.data(), strByteSize)) {
strl->clear();
@ -148,7 +148,13 @@ namespace LibCmo::CK2 {
}
// convert encoding
m_BindContext->GetUtf8String(cache, *strl);
if (!m_BindContext->GetUTF8String(cache, *strl)) {
m_BindContext->OutputToConsole(u8"Fail to get UTF8 string when reading CKStateChunk. Some objects may be loaded incorrectly.");
strl->clear();
return false;
}
// okey
return true;
}
@ -214,7 +220,7 @@ namespace LibCmo::CK2 {
return true;
}
//CKStateChunk* CKStateChunk::ReadSubChunk(void) {
//CKStateChunk* CKStateChunk::ReadSubChunk() {
// CKStateChunk* subchunk = nullptr;
// // get size and do a enough space check

View File

@ -32,7 +32,7 @@ namespace LibCmo::CK2 {
this->m_Parser.m_Status = CKStateChunkStatus::WRITE;
}
void CKStateChunk::StopWrite(void) {
void CKStateChunk::StopWrite() {
if (this->m_Parser.m_Status != CKStateChunkStatus::WRITE) return;
// update buffer size
@ -86,7 +86,7 @@ namespace LibCmo::CK2 {
*ppData = this->m_pData + this->m_Parser.m_CurrentPos;
return true;
} else {
m_BindContext->OutputToConsoleEx("CKStateChunk::LockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
m_BindContext->OutputToConsoleEx(u8"CKStateChunk::LockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false;
}
}
@ -100,7 +100,7 @@ namespace LibCmo::CK2 {
this->m_Parser.m_CurrentPos += size_in_dword;
return true;
} else {
m_BindContext->OutputToConsoleEx("CKStateChunk::UnLockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
m_BindContext->OutputToConsoleEx(u8"CKStateChunk::UnLockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false;
}
}
@ -137,8 +137,9 @@ namespace LibCmo::CK2 {
if (strl == nullptr) return false;
// convert encoding
XContainer::XString cache;
m_BindContext->GetNativeString(*strl, cache);
std::string cache;
if (!m_BindContext->GetOrdinaryString(*strl, cache))
m_BindContext->OutputToConsole(u8"Fail to get ordinary string when saving CKStateChunk. Some objects may be saved incorrectly.");
if (cache.empty()) {
// write zero string

View File

@ -12,83 +12,88 @@
namespace LibCmo {
// Types.
// These types is general types used in every module.
// These types are general types used in every module.
// So we declare them in LibCmo, not LibCmo::CK2 to make sure every module can use it.
/**
* @brief General Const String Type. Encoding Unrelated.
* @brief The representation of constant UTF8 string pointer.
*/
using CKSTRING = const char*;
using CKSTRING = const char8_t*;
/**
* @brief Changeble CKSTRING.
* @brief The representation of mutable CKSTRING (UTF8 string pointer).
* @see CKSTRING
*/
using CKMUTSTRING = char*;
using CKMUTSTRING = char8_t*;
/**
* @brief The Representation of Single Character (1 byte). Encoding Unrelated.
* @remark
* + Only used with string process.
* + For memory representation and moving, use CKBYTE instead.
* @see CKBYTE
* @brief The representation of single UTF8 code unit (1 byte).
* @remarks
* \li Only used with string process.
* \li For memory representation and operating, use CKBYTE instead.
* @see CKSTRING, CKBYTE
*/
using CKCHAR = char;
using CKCHAR = char8_t;
/**
* @brief Always Represent a Byte (1 byte, unsigned). Platform Independent.
* @remark
* + This type should only be used when representing memory data or position.
* + If you want to represent a char, or a sequence of chars, use CKCHAR instead.
* @brief Platform independent representation of a byte (1 byte, unsigned).
* @remarks
* \li This type should only be used when representing memory data or position.
* \li If you want to represent a character code unit, or a sequence of chars, use CKCHAR instead.
* @see CKCHAR
*/
using CKBYTE = uint8_t;
/**
* @brief Always Represent a WORD (2 byte, unsigned). Platform Independent.
* @brief Platform independent representation of a WORD (2 byte, unsigned).
*/
using CKWORD = uint16_t;
/**
* @brief Always Represent a DWORD (4 byte, unsigned). Platform Independent.
* @brief Platform independent representation of a DWORD (4 byte, unsigned).
* @see CKINT
*/
using CKDWORD = uint32_t;
/**
* @brief Always Represent a QWORD (8 byte, unsigned). Platform Independent.
* @brief Platform independent representation of a QWORD (8 byte, unsigned).
*/
using CKQWORD = uint64_t;
/**
* @brief The Int type used in LibCmo.
* @remark
* + All 'int' type in original Virtools SDK should be replaced with CKINT in this project if needed.
* + This type also can be seen as the equvalent of signed CKDWORD.
* @brief Platform independent representation of \c int.
* @remarks
* \li All \c int type presented in original Virtools SDK should be replaced by this type, CKINT, in this project if needed.
* \li This type also can be seen as the equvalent of signed CKDWORD.
* @see CKDWORD
*/
using CKINT = int32_t;
/**
* @brief Always Represent a float (32 bit). Platform Independent.
* @brief Platform independent representation of a float (32 bit floating point type).
*/
using CKFLOAT = float;
/**
* @brief Always Represent a double (64 bit). Platform Independent.
* @brief Platform independent representation of a double (64 bit floating point type).
*/
using CKDOUBLE = double;
/**
* @brief Represent a x86 Platform Pointer.
* @brief Platform independent representation of a x86 pointer.
* @remark
* + This type only can be used when replacing pointer in old Virtools struct / class.
* + Due to Virtools shitty design, in some cases we need read data with x86 memory layout from file.
* So we use this type to replace native pointer in struct existed in Virtools SDK to make sure this
* program can run perfectly on x64 and more architectures.
* + A example can be found in CKTexture::Load().
* \li This type only should be used when replacing pointer in old Virtools struct / class.
* \li Due to Virtools shitty design, in some cases we need read data with x86 memory layout from file.
* So we use this type to replace native pointer in struct existed in Virtools SDK
* to make sure this program can run perfectly on x64 and more architectures.
* \li A example usage can be found in CK2::ObjImpls::CKTexture::Load().
*/
using CKPTR = uint32_t;
// Format constants for the std::fprintf family of functions
// Format macro for \c std::printf family of functions
#define PRI_CKSTRING "s"
#define PRI_CKCHAR "c"
#define CKBYTE_C(v) UINT8_C(v)
#define CKWORD_C(v) UINT16_C(v)
#define CKDWORD_C(v) UINT32_C(v)
#define CKQWORD_C(v) UINT64_C(v)
#define PRIuCKBYTE PRIu8
#define PRIuCKWORD PRIu16
#define PRIuCKDWORD PRIu32
@ -104,6 +109,8 @@ namespace LibCmo {
#define PRIXCKDWORD PRIX32
#define PRIXCKQWORD PRIX64
#define CKINT_C(v) INT32_C(v)
#define PRIiCKINT PRIi32
#define PRIfCKFLOAT "f"
@ -113,33 +120,46 @@ namespace LibCmo {
#define PRIxCKPTR PRIx32
#define PRIXCKPTR PRIX32
/*
The convenient sizeof which return CKDWORD, not size_t.
/**
* @brief The convenient sizeof macro which return \c CKDWORD instead of \c size_t.
* @details This macro is frequently used in LibCmo.
* Because LibCmo use \c CKDWORD, not \c size_t everywhere.
*/
#define CKSizeof(_Ty) (static_cast<LibCmo::CKDWORD>(sizeof(_Ty)))
#define CKSizeof(_Ty) (static_cast<::LibCmo::CKDWORD>(sizeof(_Ty)))
}
// ========== CK2 Section ==========
/**
* @brief The CK2 part of LibCmo. The main part of LibCmo.
* @details
* This namespace include most implementations of LibCmo,
* including important CKContext, CKStateChunk and etc.
*/
namespace LibCmo::CK2 {
/**
@brief Unique Identifier for all Objects instanciated in a given CKContext
@remarks
+ Each instance of CKObject and derived classes are automatically given a global unique
ID at creation time. This ID can be accessed through the CKObject::GetID method.
It is safer, though a bit slower, to reference object through their global ID than through
a direct pointer reference. In any case the referenced object may be deleted even though
the client object has a ID for it. The client object should verify that the referenced object
still exists when used with the CKGetObject function.
+ The global ID for an instance remains unique and unchanged through a application session, but there
is no garanty that this ID will be the same when a level is saved and loaded back again.
@see CKObject::GetID, CKContext::GetObject
* @brief Unique identifier for all CK2 objects instantiated in CKContext
* @remarks
* \li Each instance of ObjImpls::CKObject and derived classes are automatically given a global unique ID at creation time.
* This ID can be accessed through the ObjImpls::CKObject::GetID() method.
* It is safer, though a bit slower, to reference object through their global ID than through a direct pointer.
* In some cases the referenced object may be deleted even though the client has a object ID for it.
* The client should verify that the referenced object still exists when used via CKContext::GetObject().
* \li The global ID for an instance remains unique and unchanged through a application session,
* but there is no guarateen that this ID will be the same when a level is saved and loaded back again.
* @see ObjImpls::CKObject::GetID(), CKContext::GetObject()
*/
using CK_ID = CKDWORD;
/**
* @brief The enumeration of all CK2 errors
* @details
* Some CK2, Vx, XContainer functions will try to return a error code to indicate
* whether given operation has been done successfully.
*/
enum class CKERROR : CKINT {
CKERR_OK = 0, /**< Operation successful */
CKERR_INVALIDPARAMETER = -1, /**< One of the parameter passed to the function was invalid */
@ -195,14 +215,16 @@ namespace LibCmo::CK2 {
};
/**
@brief Per Class Unique Identifier.
@remark
+ Each class derived from the CKObject class has a unique class ID.
+ This ID can be accessed through each instance of these classes, with the
CKObject::GetClassID method.
+ This class ID is used internally for various matching operations, like matching behaviors on
objects, etc..
@see CKObject::GetClassID, CKIsChildClassOf, Class Identifiers
* @brief Unique class identifier.
* @remarks
* \li Each class derived from the ObjImpls::CKObject class has a unique class ID.
* \li This ID can be accessed through each instance of these classes, with the ObjImpls::CKObject::GetClassID() method.
* \li This class ID is used internally for various matching operations, like matching behaviors on objects, etc..
* \li Identifiers listed in there is CK2 builtin class identifier list.
* In original Virtools SDK, user can use plugin mechanism to register more class identifier in runtime.
* Virtools only guarateen that identifiers listed in there must correspond with its real meaning.
* However, there is no guarateen that IDs not listed in there will be the same when Virtools engine quit and initialized back again.
* @see ObjImpls::CKObject::GetClassID(), CKIsChildClassOf()
*/
enum class CK_CLASSID : CKINT {
CKCID_OBJECT = 1,
@ -289,8 +311,10 @@ namespace LibCmo::CK2 {
#define PRIiCLASSID PRIiCKINT
// ========== Class List ==========
// We declare these classes in there to make sure that
// following code can refer their pointer type safely.
// Objects and derivated classes
namespace ObjImpls {
class CKObject;
class CKInterfaceObjectManager;
@ -345,7 +369,7 @@ namespace LibCmo::CK2 {
class CKGrid;
}
//---- Misc
// Misc
class CKBehaviorPrototype;
class CKMessage;
class CK2dCurvePoint;
@ -362,7 +386,7 @@ namespace LibCmo::CK2 {
class CKFileExtension;
class CKVertexBuffer;
//--- Managers
// Managers
namespace MgrImpls {
class CKBaseManager;
class CKObjectManager;
@ -379,13 +403,14 @@ namespace LibCmo::CK2 {
class CKPluginManager;
}
// Data Handlers
namespace DataHandlers {
class CKBitmapHandler;
class CKMovieHandler;
class CKSoundHandler;
}
//--- Important classes
// Important classes (rewritten hugely)
class CKContext;
class CKStateChunk;
class CKFileReader;
@ -393,32 +418,34 @@ namespace LibCmo::CK2 {
class CKFileVisitor;
/**
@brief Global Unique Identifier Struture.
@remark
+ Guids are used to uniquely identify plugins,operation types, parameter types and behavior prototypes.
+ Its defined as
```
typedef struct CKGUID {
union {
struct { CKDWORD d1,d2; };
CKDWORD d[2];
};
};
```
+ Comparison operators are defined so CKGUIDS can be compared with
==, != , <, > operators.
@see Pre-Registred Parameter Types, ParameterOperation Types
* @brief Global unique identifier struture.
* @remarks
* \li Guids are used to uniquely identify plugins, operation types, parameter types and behavior prototypes.
* \li Comparison operators are defined so CKGUID can be compared with ==, != , <, > operators.
* \li It's defined as following code
* \code
* typedef struct CKGUID {
* union {
* struct { CKDWORD d1,d2; };
* CKDWORD d[2];
* };
* };
* \endcode
*/
struct CKGUID {
CKDWORD d1, d2;
constexpr CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) : d1(gd1), d2(gd2) {}
CKGUID(const CKGUID& rhs) : d1(rhs.d1), d2(rhs.d2) {}
CKGUID(CKGUID&& rhs) : d1(rhs.d1), d2(rhs.d2) {}
CKGUID& operator=(const CKGUID& rhs) {
this->d1 = rhs.d1;
this->d2 = rhs.d2;
return *this;
}
CKGUID& operator=(CKGUID&& rhs) {
this->d1 = rhs.d1;
this->d2 = rhs.d2;
return *this;
}

View File

@ -1,6 +1,6 @@
#include "CKBitmapHandler.hpp"
#include "stb_image.h"
#include "stb_image_write.h"
#include <stb_image.h>
#include <stb_image_write.h>
namespace LibCmo::CK2::DataHandlers {
@ -135,7 +135,7 @@ namespace LibCmo::CK2::DataHandlers {
static bool StbReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) {
if (u8filename == nullptr || read_image == nullptr) return false;
FILE* fs = EncodingHelper::U8FOpen(u8filename, "rb");
FILE* fs = YYCC::IOHelper::UTF8FOpen(u8filename, u8"rb");
if (fs == nullptr) return false;
// read data
@ -210,7 +210,7 @@ namespace LibCmo::CK2::DataHandlers {
static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, bool save_alpha, SaveOperation oper) {
if (u8filename == nullptr || write_image == nullptr) return false;
if (!write_image->IsValid()) return false;
FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb");
FILE* fs = YYCC::IOHelper::UTF8FOpen(u8filename, u8"wb");
if (fs == nullptr) return false;
// allocate buffer and convert data from ARGB to RGBA or RGB
@ -285,7 +285,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapBMPHandler
static const CKBitmapProperties g_BMPProperties(CKGUID(0xBCA97223u, 0x48578BCAu), "Bmp");
static const CKBitmapProperties g_BMPProperties(CKGUID(0xBCA97223u, 0x48578BCAu), u8"Bmp");
CKBitmapBMPHandler::CKBitmapBMPHandler() :
CKBitmapHandler() {}
@ -330,7 +330,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapTGAHandler
static const CKBitmapProperties g_TGAProperties(CKGUID(0x585C7216u, 0x33302657u), "Tga");
static const CKBitmapProperties g_TGAProperties(CKGUID(0x585C7216u, 0x33302657u), u8"Tga");
CKBitmapTGAHandler::CKBitmapTGAHandler() :
CKBitmapHandler() {}
@ -372,7 +372,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapJPGHandler
// MARK: this GUID is gotten from Virtools 3.5 Plugins.
static const CKBitmapProperties g_JPGProperties(CKGUID(0x4AE51AC4u, 0x04587D76u), "jpg");
static const CKBitmapProperties g_JPGProperties(CKGUID(0x4AE51AC4u, 0x04587D76u), u8"jpg");
// MARK: this quality is gotten from default value of virtools.
constexpr int g_JPGDefaultQuality = 75;
@ -416,7 +416,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapPNGHandler
// MARK: this GUID is gotten from Virtools 3.5 Plugins.
static const CKBitmapProperties g_PNGProperties(CKGUID(0x02D45C7Bu, 0x4AAC16ECu), "png");
static const CKBitmapProperties g_PNGProperties(CKGUID(0x02D45C7Bu, 0x4AAC16ECu), u8"png");
// MARK: this is compress level gotten from default value of virtools.
constexpr int g_PNGDefaultCompressLevel = 3;

View File

@ -1,6 +1,6 @@
#pragma once
#include "../../VTAll.hpp"
#include "../../VTInternal.hpp"
#include <memory>
#include <functional>
@ -30,7 +30,7 @@ namespace LibCmo::CK2::DataHandlers {
public:
CKBitmapHandler() {}
virtual ~CKBitmapHandler() {}
LIBCMO_DISABLE_COPY_MOVE(CKBitmapHandler);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapHandler);
/**
* @brief General CKBitmapHandler getter.
@ -102,7 +102,7 @@ namespace LibCmo::CK2::DataHandlers {
public:
CKBitmapBMPHandler();
virtual ~CKBitmapBMPHandler();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapBMPHandler);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapBMPHandler);
static const CKBitmapProperties& GetBitmapDefaultProperties();
@ -118,7 +118,7 @@ namespace LibCmo::CK2::DataHandlers {
public:
CKBitmapTGAHandler();
virtual ~CKBitmapTGAHandler();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapTGAHandler);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapTGAHandler);
static const CKBitmapProperties& GetBitmapDefaultProperties();
@ -134,7 +134,7 @@ namespace LibCmo::CK2::DataHandlers {
public:
CKBitmapJPGHandler();
virtual ~CKBitmapJPGHandler();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapJPGHandler);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapJPGHandler);
static const CKBitmapProperties& GetBitmapDefaultProperties();
@ -150,7 +150,7 @@ namespace LibCmo::CK2::DataHandlers {
public:
CKBitmapPNGHandler();
virtual ~CKBitmapPNGHandler();
LIBCMO_DISABLE_COPY_MOVE(CKBitmapPNGHandler);
YYCC_DEL_CLS_COPY_MOVE(CKBitmapPNGHandler);
static const CKBitmapProperties& GetBitmapDefaultProperties();

View File

@ -1,6 +1,6 @@
#pragma once
#include "../../VTAll.hpp"
#include "../../VTInternal.hpp"
/**
CKBaseManager virtual functions implementations help
@ -40,7 +40,7 @@ namespace LibCmo::CK2::MgrImpls {
XContainer::NSXString::FromCKSTRING(m_ManagerName, name);
}
virtual ~CKBaseManager() {}
LIBCMO_DISABLE_COPY_MOVE(CKBaseManager);
YYCC_DEL_CLS_COPY_MOVE(CKBaseManager);
/**
@brief Acces to Manager GUID
@ -90,7 +90,7 @@ namespace LibCmo::CK2::MgrImpls {
data for your manager.
@see CKStateChunk, LoadData
*/
virtual bool SaveData(LIBCMO_UNUSED CKStateChunk* chunk, LIBCMO_UNUSED CKFileVisitor* SavedFile) {
virtual bool SaveData([[maybe_unused]] CKStateChunk* chunk, [[maybe_unused]] CKFileVisitor* SavedFile) {
return false; // default value is false to indicate this manager do not need save any data.
}
/**
@ -102,7 +102,7 @@ namespace LibCmo::CK2::MgrImpls {
+ During a load operation, each manager is automatically called if there was a chunk saved in the file with SaveData.
@see CKStateChunk, SaveData
*/
virtual CKERROR LoadData(LIBCMO_UNUSED CKStateChunk* chunk, LIBCMO_UNUSED CKFileVisitor* LoadedFile) {
virtual CKERROR LoadData([[maybe_unused]] CKStateChunk* chunk, [[maybe_unused]] CKFileVisitor* LoadedFile) {
return CKERROR::CKERR_OK;
}
@ -138,7 +138,7 @@ namespace LibCmo::CK2::MgrImpls {
CKMANAGER_FUNC_OnSequenceToBeDeleted for this function to get called.
@see Main Virtools Events, CKContext::DestroyObjects, SequenceDeleted
*/
virtual CKERROR SequenceToBeDeleted(LIBCMO_UNUSED const CK_ID* objids, LIBCMO_UNUSED CKDWORD count) { return CKERROR::CKERR_OK; }
virtual CKERROR SequenceToBeDeleted([[maybe_unused]] const CK_ID* objids, [[maybe_unused]] CKDWORD count) { return CKERROR::CKERR_OK; }
/**
@brief Called after objects have been deleted.
@return CK_OK if successful or an error code otherwise.
@ -150,7 +150,7 @@ namespace LibCmo::CK2::MgrImpls {
CKMANAGER_FUNC_OnSequenceDeleted for this function to get called.
@see Main Virtools Events, CKContext::DestroyObjects, SequenceToBeDeleted
*/
virtual CKERROR SequenceDeleted(LIBCMO_UNUSED const CK_ID* objids, LIBCMO_UNUSED CKDWORD count) { return CKERROR::CKERR_OK; }
virtual CKERROR SequenceDeleted([[maybe_unused]] const CK_ID* objids, [[maybe_unused]] CKDWORD count) { return CKERROR::CKERR_OK; }
protected:

View File

@ -5,7 +5,7 @@
namespace LibCmo::CK2::MgrImpls {
CKObjectManager::CKObjectManager(CKContext* ctx) :
CKBaseManager(ctx, OBJECT_MANAGER_GUID, "Object Manager"),
CKBaseManager(ctx, OBJECT_MANAGER_GUID, u8"Object Manager"),
m_ObjectsList(), m_ReturnedObjectOffsets(), m_ObjectCount(0),
m_GroupGlobalIndex(), m_SceneGlobalIndex(),
m_ObjectsListByClass(CKGetClassCount()) {}
@ -20,6 +20,7 @@ namespace LibCmo::CK2::MgrImpls {
// get description first
const CKClassDesc* desc = CKGetClassDesc(cls);
// if no description, return directly to reject creating object.
if (desc == nullptr) return nullptr;
// allocate a CK_ID first
@ -60,13 +61,10 @@ namespace LibCmo::CK2::MgrImpls {
void CKObjectManager::InternalDestroy(ObjImpls::CKObject* obj) {
// find desc by classid
// if really we can not find it, we only can delete it directly.
const CKClassDesc* desc = CKGetClassDesc(obj->GetClassID());
if (desc == nullptr) {
delete obj;
return;
}
// a create CKObject instance definitely can find corresponding desc.
// if not, throw exception.
if (desc == nullptr) throw LogicException("Invalid CK_CLASSID");
// free it
desc->ReleaseFct(m_Context, obj);
}
@ -88,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

@ -1,6 +1,6 @@
#pragma once
#include "../../VTAll.hpp"
#include "../../VTInternal.hpp"
#include "CKBaseManager.hpp"
#include <deque>
@ -10,7 +10,7 @@ namespace LibCmo::CK2::MgrImpls {
public:
CKObjectManager(CKContext* ctx);
virtual ~CKObjectManager();
LIBCMO_DISABLE_COPY_MOVE(CKObjectManager);
YYCC_DEL_CLS_COPY_MOVE(CKObjectManager);
// ========== Objects Management ==========

View File

@ -2,20 +2,16 @@
namespace LibCmo::CK2::MgrImpls {
#if defined(LIBCMO_OS_WIN32)
static wchar_t g_UniqueFolder[] = L"LibCmo";
#else
static char g_UniqueFolder[] = "LibCmo";
#endif
static constexpr char8_t g_UniqueFolder[] = u8"LibCmo";
CKPathManager::CKPathManager(CKContext* ctx) :
CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager"),
CKBaseManager(ctx, PATH_MANAGER_GUID, u8"Path Manager"),
m_TempFolder(), m_ExtraPathes() {
// preset for temp folder
// todo: add current CKContext pointer as the part of temp path.
// thus multiple CKContext can work.
m_TempFolder = std::filesystem::temp_directory_path();
m_TempFolder /= g_UniqueFolder;
m_TempFolder /= std::filesystem::path(g_UniqueFolder);
std::filesystem::create_directories(m_TempFolder);
}
@ -24,8 +20,7 @@ namespace LibCmo::CK2::MgrImpls {
bool CKPathManager::SetTempFolder(CKSTRING u8_temp) {
if (u8_temp == nullptr) return false;
std::filesystem::path cache;
EncodingHelper::U8PathToStdPath(cache, u8_temp);
std::filesystem::path cache(u8_temp);
if (std::filesystem::is_directory(cache)) {
m_TempFolder = cache;
return true;
@ -35,28 +30,22 @@ namespace LibCmo::CK2::MgrImpls {
}
XContainer::XString CKPathManager::GetTempFolder() {
XContainer::XString result;
EncodingHelper::StdPathToU8Path(result, this->m_TempFolder);
return result;
return this->m_TempFolder.u8string();
}
XContainer::XString CKPathManager::GetTempFilePath(CKSTRING u8_filename) {
if (u8_filename == nullptr) return XContainer::XString();
std::filesystem::path stdfilename;
EncodingHelper::U8PathToStdPath(stdfilename, u8_filename);
std::filesystem::path stdfilename(u8_filename);
auto realfile = this->m_TempFolder / stdfilename;
XContainer::XString result;
EncodingHelper::StdPathToU8Path(result, realfile);
return result;
return realfile.u8string();
}
bool CKPathManager::AddPath(CKSTRING u8path) {
if (u8path == nullptr) return false;
std::filesystem::path newpath;
EncodingHelper::U8PathToStdPath(newpath, u8path);
std::filesystem::path newpath(u8path);
if (std::filesystem::is_directory(newpath)) {
m_ExtraPathes.emplace_back(std::move(newpath));
return true;
@ -70,8 +59,7 @@ namespace LibCmo::CK2::MgrImpls {
}
bool CKPathManager::ResolveFileName(XContainer::XString& u8_filename) {
std::filesystem::path filepath;
EncodingHelper::U8PathToStdPath(filepath, u8_filename.c_str());
std::filesystem::path filepath(u8_filename);
// if it is absolute path, return it directly
if (filepath.is_absolute()) {
@ -81,7 +69,7 @@ namespace LibCmo::CK2::MgrImpls {
// test in temp folder
auto tempfile = m_TempFolder / filepath;
if (std::filesystem::is_regular_file(tempfile)) {
EncodingHelper::StdPathToU8Path(u8_filename, tempfile);
u8_filename = tempfile.u8string();
return true;
}
@ -90,7 +78,7 @@ namespace LibCmo::CK2::MgrImpls {
auto combinedpath = extrapath / filepath;
if (std::filesystem::is_regular_file(combinedpath)) {
// this is correct
EncodingHelper::StdPathToU8Path(u8_filename, combinedpath);
u8_filename = combinedpath.u8string();
return true;
}
}
@ -100,19 +88,17 @@ namespace LibCmo::CK2::MgrImpls {
}
void CKPathManager::GetFileName(XContainer::XString& u8path) {
std::filesystem::path filepath;
EncodingHelper::U8PathToStdPath(filepath, u8path.c_str());
std::filesystem::path filepath(u8path);
auto result = filepath.filename();
EncodingHelper::StdPathToU8Path(u8path, result);
u8path = result.u8string();
}
void CKPathManager::GetExtension(XContainer::XString& u8path) {
std::filesystem::path filepath;
EncodingHelper::U8PathToStdPath(filepath, u8path.c_str());
std::filesystem::path filepath(u8path);
auto result = filepath.extension();
EncodingHelper::StdPathToU8Path(u8path, result);
u8path = result.u8string();
}
}

Some files were not shown because too many files have changed in this diff Show More