rename BM3dEntity to BM3dObject in BMap. continue writing python bmao binding. fix doc

This commit is contained in:
yyc12345 2023-11-05 10:44:11 +08:00
parent 2000a6ad9b
commit fcd1fa81db
7 changed files with 155 additions and 40 deletions

View File

@ -820,7 +820,7 @@ bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCm
#pragma region CK3dObject #pragma region CK3dObject
bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat)) { bool BM3dObject_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
if (obj == nullptr) return false; if (obj == nullptr) return false;
@ -828,7 +828,7 @@ bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(L
return true; return true;
} }
bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat)) { bool BM3dObject_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
if (obj == nullptr) return false; if (obj == nullptr) return false;
@ -836,7 +836,7 @@ bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(Li
return true; return true;
} }
bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid)) { bool BM3dObject_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
if (obj == nullptr) return false; if (obj == nullptr) return false;
@ -844,7 +844,7 @@ bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(L
return true; return true;
} }
bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid)) { bool BM3dObject_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
auto meshobj = CheckCKMesh(bmfile, meshid); auto meshobj = CheckCKMesh(bmfile, meshid);
if (obj == nullptr /*|| meshobj == nullptr*/) return false; //allow nullptr assign if (obj == nullptr /*|| meshobj == nullptr*/) return false; //allow nullptr assign
@ -853,7 +853,7 @@ bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(Li
return true; return true;
} }
bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible)) { bool BM3dObject_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
if (obj == nullptr) return false; if (obj == nullptr) return false;
@ -861,7 +861,7 @@ bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bo
return true; return true;
} }
bool BM3dEntity_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible)) { bool BM3dObject_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible)) {
auto obj = CheckCK3dObject(bmfile, objid); auto obj = CheckCK3dObject(bmfile, objid);
if (obj == nullptr) return false; if (obj == nullptr) return false;

View File

@ -239,11 +239,11 @@ LIBCMO_EXPORT bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BM
#pragma region CK3dObject #pragma region CK3dObject
LIBCMO_EXPORT bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat)); LIBCMO_EXPORT bool BM3dObject_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat));
LIBCMO_EXPORT bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat)); LIBCMO_EXPORT bool BM3dObject_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat));
LIBCMO_EXPORT bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid)); LIBCMO_EXPORT bool BM3dObject_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid));
LIBCMO_EXPORT bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid)); LIBCMO_EXPORT bool BM3dObject_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid));
LIBCMO_EXPORT bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible)); LIBCMO_EXPORT bool BM3dObject_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible));
LIBCMO_EXPORT bool BM3dEntity_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible)); LIBCMO_EXPORT bool BM3dObject_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible));
#pragma endregion #pragma endregion

View File

@ -76,7 +76,7 @@ def is_bmap_available() -> bool:
return _g_BMapModule is not None return _g_BMapModule is not None
def _bmap_error_check(result: bm_bool, func, args): def _bmap_error_check(result: bm_bool, func, args):
if not bm_bool.value: if not result:
raise BMapException("BMap operation failed.") raise BMapException("BMap operation failed.")
return result return result
@ -714,42 +714,42 @@ BMMesh_GetMaterialSlot = _create_bmap_func('BMMesh_GetMaterialSlot', [bm_void_p,
# @param mtlid[in] Type: LibCmo::CK2::CK_ID. # @param mtlid[in] Type: LibCmo::CK2::CK_ID.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BMMesh_SetMaterialSlot = _create_bmap_func('BMMesh_SetMaterialSlot', [bm_void_p, bm_CKID, bm_CKDWORD, bm_CKID]) BMMesh_SetMaterialSlot = _create_bmap_func('BMMesh_SetMaterialSlot', [bm_void_p, bm_CKID, bm_CKDWORD, bm_CKID])
## BM3dEntity_GetWorldMatrix ## BM3dObject_GetWorldMatrix
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 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. # @param out_mat[out] Type: LibCmo::VxMath::VxMatrix. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_GetWorldMatrix = _create_bmap_func('BM3dEntity_GetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix_p]) BM3dObject_GetWorldMatrix = _create_bmap_func('BM3dObject_GetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix_p])
## BM3dEntity_SetWorldMatrix ## BM3dObject_SetWorldMatrix
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param mat[in] Type: LibCmo::VxMath::VxMatrix. # @param mat[in] Type: LibCmo::VxMath::VxMatrix.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_SetWorldMatrix = _create_bmap_func('BM3dEntity_SetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix]) BM3dObject_SetWorldMatrix = _create_bmap_func('BM3dObject_SetWorldMatrix', [bm_void_p, bm_CKID, bm_VxMatrix])
## BM3dEntity_GetCurrentMesh ## BM3dObject_GetCurrentMesh
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 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. # @param out_meshid[out] Type: LibCmo::CK2::CK_ID. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_GetCurrentMesh = _create_bmap_func('BM3dEntity_GetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID_p]) BM3dObject_GetCurrentMesh = _create_bmap_func('BM3dObject_GetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID_p])
## BM3dEntity_SetCurrentMesh ## BM3dObject_SetCurrentMesh
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param meshid[in] Type: LibCmo::CK2::CK_ID. # @param meshid[in] Type: LibCmo::CK2::CK_ID.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_SetCurrentMesh = _create_bmap_func('BM3dEntity_SetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID]) BM3dObject_SetCurrentMesh = _create_bmap_func('BM3dObject_SetCurrentMesh', [bm_void_p, bm_CKID, bm_CKID])
## BM3dEntity_GetVisibility ## BM3dObject_GetVisibility
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 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. # @param out_isVisible[out] Type: bool. Use ctypes.byref(data) pass it.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_GetVisibility = _create_bmap_func('BM3dEntity_GetVisibility', [bm_void_p, bm_CKID, bm_bool_p]) BM3dObject_GetVisibility = _create_bmap_func('BM3dObject_GetVisibility', [bm_void_p, bm_CKID, bm_bool_p])
## BM3dEntity_SetVisibility ## BM3dObject_SetVisibility
# @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @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 objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing.
# @param is_visible[in] Type: bool. # @param is_visible[in] Type: bool.
# @return True if no error, otherwise False. # @return True if no error, otherwise False.
BM3dEntity_SetVisibility = _create_bmap_func('BM3dEntity_SetVisibility', [bm_void_p, bm_CKID, bm_bool]) BM3dObject_SetVisibility = _create_bmap_func('BM3dObject_SetVisibility', [bm_void_p, bm_CKID, bm_bool])
#endregion #endregion

View File

@ -3,6 +3,7 @@ from . import bmap, virtools_types
#region Basic Class Defines #region Basic Class Defines
g_InvalidCKID: int = 0
g_BMapEncoding: str = "utf-8" g_BMapEncoding: str = "utf-8"
class _AbstractPointer(): class _AbstractPointer():
@ -70,26 +71,81 @@ if is_bmap_available():
#region Real Type Defines #region Real Type Defines
"""!
BMFileReader, BMFileWriter, and BMMeshTrans can be create by given constructor.
But they must be destroyed by calling dispose(). Otherwise it may cause memory leak.
You also can use python `with` statement to achieve this automatically.
BMObject, BMTexture, BMMaterial, BMMesh, and BM3dObject should NOT be constructed from given constructor.
They must be obtained from BMFileReader, BMFileWriter, and BMMeshTrans.
Thus BMObject, BMTexture, BMMaterial, BMMesh, and BM3dObject also do not need to free
because these resources are sotred in BMFileReader, BMFileWriter, and BMMeshTrans.
We just provide them as a visitor.
"""
class BMFileReader(_AbstractPointer): class BMFileReader(_AbstractPointer):
pass def __init__(self, file_name: str, temp_folder: str, texture_folder: str, encodings: tuple[str]):
# write with `with` syntax pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.dispose()
def dispose(self) -> None:
if self.is_valid():
bmap.BMFile_Free(self._get_pointer())
class BMFileWriter(_AbstractPointer): class BMFileWriter(_AbstractPointer):
pass def __init__(self, temp_folder: str, texture_folder: str, encodings: tuple[str]):
# write with `with` syntax pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.dispose()
def save(self, file_name: str, compress_level: int) -> None:
pass
def dispose(self) -> None:
if self.is_valid():
bmap.BMFile_Free(self._get_pointer())
class BMMeshTrans(_AbstractPointer): class BMMeshTrans(_AbstractPointer):
pass def __init__(self):
# write with `with` syntax ptr: bmap.bm_void_p = bmap.bm_void_p()
bmap.BMMeshTrans_New(ctypes.byref(ptr))
_AbstractPointer.__init__(ptr)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.dispose()
def dispose(self) -> None:
if self.is_valid():
bmap.BMMeshTrans_Delete(self._get_pointer())
class BMObject(_AbstractCKObject): class BMObject(_AbstractCKObject):
def get_name(self) -> str: def get_name(self) -> str | None:
name: bmap.bm_CKSTRING = bmap.bm_CKSTRING() name: bmap.bm_CKSTRING = bmap.bm_CKSTRING()
bmap.BMObject_GetName(self._get_pointer(), self._get_ckid(), ctypes.byref(name)) bmap.BMObject_GetName(self._get_pointer(), self._get_ckid(), ctypes.byref(name))
return name.value.decode(g_BMapEncoding) if name.value is None:
return None
else:
return name.value.decode(g_BMapEncoding)
def set_name(self, name: str) -> None: def set_name(self, name: str | None) -> None:
name: bmap.bm_CKSTRING = bmap.bm_CKSTRING(name.encode(g_BMapEncoding)) name: bmap.bm_CKSTRING
if name is None:
name = bmap.bm_CKSTRING(0)
else:
name = bmap.bm_CKSTRING(name.encode(g_BMapEncoding))
bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name) bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name)
class BMGroup(BMObject): class BMGroup(BMObject):
@ -105,6 +161,41 @@ class BMMesh(BMObject):
pass pass
class BM3dObject(BMObject): class BM3dObject(BMObject):
pass def get_world_matrix(self) -> virtools_types.ConstVxMatrix:
mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix()
bmap.BM3dObject_GetWorldMatrix(self._get_pointer(), self._get_ckid(), ctypes.byref(mat))
# use cast & pointer to get matrix data conveniently
flat: bmap.bm_CKFLOAT_p = ctypes.cast(ctypes.byref(mat), bmap.bm_CKFLOAT_p)
return tuple(flat[i] for i in range(16))
def set_world_matrix(self, mat: virtools_types.ConstVxMatrix) -> None:
# star syntax expand the tuple as the argument.
mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix(*mat)
bmap.BM3dObject_SetWorldMatrix(self._get_pointer(), self._get_ckid(), mat)
def get_current_mesh(self) -> BMMesh | None:
ckid: bmap.bm_CKID = bmap.bm_CKID()
bmap.BM3dObject_GetCurrentMesh(self._get_pointer(), self._get_ckid(), ctypes.byref(ckid))
if ckid.value == g_InvalidCKID:
return None
else:
return BMMesh(self._get_pointer(), ckid)
def set_current_mesh(self, mesh: BMMesh | None) -> None:
ckid: bmap.bm_CKID
if mesh is None:
ckid = bmap.bm_CKID(g_InvalidCKID)
else:
ckid = bmap.bm_CKID(mesh._get_ckid())
bmap.BM3dObject_SetCurrentMesh(self._get_pointer(), self._get_ckid(), ckid)
def get_visibility(self) -> bool:
visb: bmap.bm_bool = bmap.bm_bool()
bmap.BM3dObject_GetVisibility(self._get_pointer(), self._get_ckid(), ctypes.byref(visb))
return visb.value
def set_visibility(self, visb_: bool) -> None:
visb: bmap.bm_bool = bmap.bm_bool(visb_)
bmap.BM3dObject_SetVisibility(self._get_pointer(), self._get_ckid(), visb)
#endregion #endregion

View File

@ -82,6 +82,13 @@ class VxColor():
self.g = VxColor._clamp_factor(self.g) self.g = VxColor._clamp_factor(self.g)
self.b = VxColor._clamp_factor(self.b) self.b = VxColor._clamp_factor(self.b)
ConstVxMatrix = tuple[
float, float, float, float,
float, float, float, float,
float, float, float, float,
float, float, float, float
]
class VxMatrix(): class VxMatrix():
""" """
The Matrix representation. The Matrix representation.
@ -109,6 +116,22 @@ class VxMatrix():
self.__mData[2][2] = 1.0 self.__mData[2][2] = 1.0
self.__mData[3][3] = 1.0 self.__mData[3][3] = 1.0
def from_const(self, cm: ConstVxMatrix) -> None:
(
self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3],
self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3],
self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3],
self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]
) = cm
def to_const(self) -> ConstVxMatrix:
return (
self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3],
self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3],
self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3],
self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]
)
class VXTEXTURE_BLENDMODE(enum.IntEnum): class VXTEXTURE_BLENDMODE(enum.IntEnum):
"""! """!
Blend Mode Flags Blend Mode Flags

View File

@ -76,7 +76,7 @@ def is_bmap_available() -> bool:
return _g_BMapModule is not None return _g_BMapModule is not None
def _bmap_error_check(result: bm_bool, func, args): def _bmap_error_check(result: bm_bool, func, args):
if not bm_bool.value: if not result:
raise BMapException("BMap operation failed.") raise BMapException("BMap operation failed.")
return result return result

View File

@ -161,15 +161,16 @@
<tr> <tr>
<td><code>uint32 m_Identifier</code></td> <td><code>uint32 m_Identifier</code></td>
<td><code>uint32 m_NextIdentifier</code></td> <td><code>uint32 m_NextIdentifier</code></td>
<td><code>variable[] m_Payload</code></td> <td><code>uint32[] m_Payload</code></td>
</tr> </tr>
</table> </table>
<p> <p>
A single identifier area.<br /> A single identifier area.<br />
m_Identifier is the unique magic word of this identifier area for CKStateChunk locating this area.<br /> m_Identifier is the unique magic word of this identifier area for CKStateChunk locating this area.<br />
m_NextIdentifier point to the m_Identifier in next identifier area.<br /> m_NextIdentifier is a relative pointer. It point to the m_Identifier in next identifier area and is relative to the start of core data.<br />
Thus, the size of each identifier area can be simply computed by the absolute diff to adjacent m_NextIdentifier (<code>*m_pData[pos] - pos</code>)<br />
m_Payload is the data of this identifier area and can be read or written by various CKStateChunk read write functions.<br /> m_Payload is the data of this identifier area and can be read or written by various CKStateChunk read write functions.<br />
The size of each identifier area can be simply computed by the diff of m_NextIdentifier (<code>*m_pData[pos] - pos</code>) The minimum block size of m_Payload is uint32. It mean that all data must be aligned to uint32 boundary when saving.
</p> </p>
</td> </td>
<td> <td>