From cd2d408618037ad3ff4d4f2068e6c8f4e77ee116 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Mon, 6 Nov 2023 10:47:49 +0800 Subject: [PATCH] finish MeshTransition & BMTexture bindings in pybmap --- BMapBindings/PyBMap/bmap_wrapper.py | 184 ++++++++++++++++++++++++-- BMapBindings/PyBMap/virtools_types.py | 47 +++++++ 2 files changed, 220 insertions(+), 11 deletions(-) diff --git a/BMapBindings/PyBMap/bmap_wrapper.py b/BMapBindings/PyBMap/bmap_wrapper.py index ffde1b7..895c2a7 100644 --- a/BMapBindings/PyBMap/bmap_wrapper.py +++ b/BMapBindings/PyBMap/bmap_wrapper.py @@ -107,7 +107,39 @@ class BMObject(_AbstractCKObject): bmap.BMObject_SetName(self._get_pointer(), self._get_ckid(), name) class BMTexture(BMObject): - pass + def get_file_name(self) -> str | None: + filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING() + bmap.BMTexture_GetFileName(self._get_pointer(), self._get_ckid(), ctypes.byref(filename)) + if filename.value is None: + return None + else: + return filename.value.decode(g_BMapEncoding) + + def load_image(self, filepath: str) -> None: + filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING(filepath.encode(g_BMapEncoding)) + bmap.BMTexture_LoadImage(self._get_pointer(), self._get_ckid(), filename) + + def save_image(self, filepath: str) -> None: + filename: bmap.bm_CKSTRING = bmap.bm_CKSTRING(filepath.encode(g_BMapEncoding)) + bmap.BMTexture_SaveImage(self._get_pointer(), self._get_ckid(), filename) + + def get_save_options(self) -> virtools_types.CK_TEXTURE_SAVEOPTIONS: + opt: bmap.bm_enum = bmap.bm_enum() + bmap.BMTexture_GetSaveOptions(self._get_pointer(), self._get_ckid(), ctypes.byref(opt)) + return virtools_types.CK_TEXTURE_SAVEOPTIONS(opt.value) + + def set_save_options(self, opt_: virtools_types.CK_TEXTURE_SAVEOPTIONS) -> None: + opt: bmap.bm_enum = bmap.bm_enum(opt_.value) + bmap.BMTexture_SetSaveOptions(self._get_pointer(), self._get_ckid(), opt) + + def get_video_format(self) -> virtools_types.VX_PIXELFORMAT: + fmt: bmap.bm_enum = bmap.bm_enum() + bmap.BMTexture_GetVideoFormat(self._get_pointer(), self._get_ckid(), ctypes.byref(fmt)) + return virtools_types.VX_PIXELFORMAT(fmt.value) + + def set_video_format(self, fmt_: virtools_types.VX_PIXELFORMAT) -> None: + fmt: bmap.bm_enum = bmap.bm_enum(fmt_.value) + bmap.BMTexture_SetVideoFormat(self._get_pointer(), self._get_ckid(), fmt) class BMMaterial(BMObject): pass @@ -116,16 +148,18 @@ class BMMesh(BMObject): pass class BM3dObject(BMObject): - def get_world_matrix(self) -> virtools_types.ConstVxMatrix: + def get_world_matrix(self) -> virtools_types.VxMatrix: 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)) + ret: virtools_types.VxMatrix = virtools_types.VxMatrix() + ret.from_const(tuple(flat[i] for i in range(16))) + return ret - def set_world_matrix(self, mat: virtools_types.ConstVxMatrix) -> None: + def set_world_matrix(self, mat: virtools_types.VxMatrix) -> None: # star syntax expand the tuple as the argument. - mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix(*mat) + mat: bmap.bm_VxMatrix = bmap.bm_VxMatrix(*(mat.to_const())) bmap.BM3dObject_SetWorldMatrix(self._get_pointer(), self._get_ckid(), mat) def get_current_mesh(self) -> BMMesh | None: @@ -157,15 +191,18 @@ class BMGroup(BMObject): def add_object(self, member: BM3dObject) -> None: bmap.BMGroup_AddObject(self._get_pointer(), self._get_ckid(), member._get_ckid()) - def iterate_objects(self) -> typing.Iterator[BM3dObject]: - # get count + def get_object_count(self) -> int: csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD() bmap.BMGroup_GetObjectCount(self._get_pointer(), self._get_ckid(), ctypes.byref(csize)) + return csize.value + + def iterate_objects(self) -> typing.Iterator[BM3dObject]: + csize: int = self.get_object_count() # iterate list cidx: bmap.bm_CKDWORD = bmap.bm_CKDWORD() retid: bmap.bm_CKID = bmap.bm_CKID() - for i in range(csize.value): + for i in range(csize): cidx.value = i bmap.BMGroup_GetObject(self._get_pointer(), self._get_ckid(), cidx, ctypes.byref(retid)) # return visitor @@ -203,23 +240,31 @@ class BMFileReader(_AbstractPointer): bmap.BMFile_Free(self._get_pointer()) self._set_pointer(g_InvalidPtr) + def __get_ckobject_count(self, + count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bool]) -> int: + # get size + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD() + count_getter(self._get_pointer(), ctypes.byref(csize)) + return csize.value + def __iterate_ckobjects(self, class_type: type[TCKObj], count_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD_p], bool], obj_getter: typing.Callable[[bmap.bm_void_p, bmap.bm_CKDWORD, bmap.bm_CKID_p], bool]) -> typing.Iterator[TCKObj]: # get size first - csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD() - count_getter(self._get_pointer(), ctypes.byref(csize)) + csize: int = self.__get_ckobject_count(count_getter) # iterate list cidx: bmap.bm_CKDWORD = bmap.bm_CKDWORD() retid: bmap.bm_CKID = bmap.bm_CKID() - for i in range(csize.value): + for i in range(csize): cidx.value = i obj_getter(self._get_pointer(), cidx, ctypes.byref(retid)) # yield return constructed obj visitor yield class_type(self._get_pointer(), retid) + def get_texture_count(self) -> int: + return self.__get_ckobject_count(bmap.BMFile_GetTextureCount) def iterate_textures(self) -> typing.Iterator[BMTexture]: return self.__iterate_ckobjects( BMTexture, @@ -227,6 +272,8 @@ class BMFileReader(_AbstractPointer): bmap.BMFile_GetTexture ) + def get_material_count(self) -> int: + return self.__get_ckobject_count(bmap.BMFile_GetMaterialCount) def iterate_materials(self) -> typing.Iterator[BMMaterial]: return self.__iterate_ckobjects( BMMaterial, @@ -234,6 +281,8 @@ class BMFileReader(_AbstractPointer): bmap.BMFile_GetMaterial ) + def get_mesh_count(self) -> int: + return self.__get_ckobject_count(bmap.BMFile_GetMeshCount) def iterate_meshs(self) -> typing.Iterator[BMMesh]: return self.__iterate_ckobjects( BMMesh, @@ -241,6 +290,8 @@ class BMFileReader(_AbstractPointer): bmap.BMFile_GetMesh ) + def get_3dobject_count(self) -> int: + return self.__get_ckobject_count(bmap.BMFile_Get3dObjectCount) def iterate_3dobjects(self) -> typing.Iterator[BM3dObject]: return self.__iterate_ckobjects( BM3dObject, @@ -248,6 +299,8 @@ class BMFileReader(_AbstractPointer): bmap.BMFile_Get3dObject ) + def get_group_count(self) -> int: + return self.__get_ckobject_count(bmap.BMFile_GetGroupCount) def iterate_groups(self) -> typing.Iterator[BMGroup]: return self.__iterate_ckobjects( BMGroup, @@ -349,5 +402,114 @@ class BMMeshTrans(_AbstractPointer): if self._is_valid(): bmap.BMMeshTrans_Delete(self._get_pointer()) self._set_pointer(g_InvalidPtr) + + def parse(self, bmfile: BMFileWriter, objmesh: BMMesh) -> None: + bmap.BMMeshTrans_Parse(self._get_pointer(), bmfile._get_pointer(), objmesh._get_ckid()) + + def prepare_vertex(self, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None: + # prepare count first + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count) + bmap.BMMeshTrans_PrepareVertexCount(self._get_pointer(), csize) + # get raw pointer and conv to float ptr for convenient visit + raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p() + bmap.BMMeshTrans_PrepareVertex(self._get_pointer(), ctypes.byref(raw_vector)) + raw_float: bmap.bm_CKFLOAT_p = ctypes.cast(raw_vector, bmap.bm_CKFLOAT_p) + # iterate iterator and set + idx: int = 0 + for _ in range(count): + uservector: virtools_types.VxVector3 = next(itor) + raw_float[idx] = uservector.x + raw_float[idx + 1] = uservector.y + raw_float[idx + 2] = uservector.z + idx += 3 + def prepare_normal(self, count: int, itor: typing.Iterator[virtools_types.VxVector3]) -> None: + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count) + bmap.BMMeshTrans_PrepareNormalCount(self._get_pointer(), csize) + + raw_vector: bmap.bm_VxVector3_p = bmap.bm_VxVector3_p() + bmap.BMMeshTrans_PrepareNormal(self._get_pointer(), ctypes.byref(raw_vector)) + raw_float: bmap.bm_CKFLOAT_p = ctypes.cast(raw_vector, bmap.bm_CKFLOAT_p) + + idx: int = 0 + for _ in range(count): + uservector: virtools_types.VxVector3 = next(itor) + raw_float[idx] = uservector.x + raw_float[idx + 1] = uservector.y + raw_float[idx + 2] = uservector.z + idx += 3 + + def prepare_uv(self, count: int, itor: typing.Iterator[virtools_types.VxVector2]) -> None: + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count) + bmap.BMMeshTrans_PrepareUVCount(self._get_pointer(), csize) + + raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p() + bmap.BMMeshTrans_PrepareUV(self._get_pointer(), ctypes.byref(raw_vector)) + raw_float: bmap.bm_CKFLOAT_p = ctypes.cast(raw_vector, bmap.bm_CKFLOAT_p) + + idx: int = 0 + for _ in range(count): + uservector: virtools_types.VxVector2 = next(itor) + raw_float[idx] = uservector.x + raw_float[idx + 1] = uservector.y + idx += 2 + + def prepare_mtl_slot(self, count: int, itor: typing.Iterator[BMMaterial | None]) -> None: + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count) + bmap.BMMeshTrans_PrepareMtlSlotCount(self._get_pointer(), csize) + + raw_ckid: bmap.bm_CKID_p = bmap.bm_CKID_p() + bmap.BMMeshTrans_PrepareMtlSlot(self._get_pointer(), ctypes.byref(raw_ckid)) + + idx: int = 0 + for _ in range(count): + usermtl: BMMaterial = next(itor) + if usermtl is None: + raw_ckid[idx] = g_InvalidCKID + else: + raw_ckid[idx] = usermtl._get_ckid().value + idx += 1 + + def prepare_face(self, + count: int, + vec_idx: typing.Iterator[int], + nml_idx: typing.Iterator[int], + uv_idx: typing.Iterator[int], + mtl_idx: typing.Iterator[int]) -> None: + """ + The count of `vec_idx`, `nml_idx`, `uv_idx` must equal with `3 * count`. + And `mtl_idx`'s length must equal with `count`. + """ + # prepare face size + csize: bmap.bm_CKDWORD = bmap.bm_CKDWORD(count) + bmap.BMMeshTrans_PrepareFaceCount(self._get_pointer(), csize) + + # get 4 raw pointer for following assign + raw_vec_idx: bmap.bm_CKDWORD_p = bmap.bm_CKDWORD_p() + raw_nml_idx: bmap.bm_CKDWORD_p = bmap.bm_CKDWORD_p() + raw_uv_idx: bmap.bm_CKDWORD_p = bmap.bm_CKDWORD_p() + raw_mtl_idx: bmap.bm_CKDWORD_p = bmap.bm_CKDWORD_p() + bmap.BMMeshTrans_PrepareFaceVertexIndices(self._get_pointer(), ctypes.byref(raw_vec_idx)) + bmap.BMMeshTrans_PrepareFaceNormalIndices(self._get_pointer(), ctypes.byref(raw_nml_idx)) + bmap.BMMeshTrans_PrepareFaceUVIndices(self._get_pointer(), ctypes.byref(raw_uv_idx)) + bmap.BMMeshTrans_PrepareFaceMtlSlot(self._get_pointer(), ctypes.byref(raw_mtl_idx)) + + # iterate and assign + idx3: int = 0 + idx1: int = 0 + for _ in range(count): + raw_vec_idx[idx3] = next(vec_idx) + raw_vec_idx[idx3 + 1] = next(vec_idx) + raw_vec_idx[idx3 + 2] = next(vec_idx) + raw_nml_idx[idx3] = next(nml_idx) + raw_nml_idx[idx3 + 1] = next(nml_idx) + raw_nml_idx[idx3 + 2] = next(nml_idx) + raw_uv_idx[idx3] = next(uv_idx) + raw_uv_idx[idx3 + 1] = next(uv_idx) + raw_uv_idx[idx3 + 2] = next(uv_idx) + idx3 += 3 + + raw_mtl_idx[idx1] = next(mtl_idx) + idx1 += 1 + #endregion diff --git a/BMapBindings/PyBMap/virtools_types.py b/BMapBindings/PyBMap/virtools_types.py index bbfd7c8..e75094e 100644 --- a/BMapBindings/PyBMap/virtools_types.py +++ b/BMapBindings/PyBMap/virtools_types.py @@ -131,6 +131,53 @@ class VxMatrix(): 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 CK_TEXTURE_SAVEOPTIONS(enum.IntEnum): + """! + Specify the way textures or sprites will be saved + """ + 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. + +class VX_PIXELFORMAT(enum.IntEnum): + """! + Pixel format types. + """ + 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) class VXTEXTURE_BLENDMODE(enum.IntEnum): """!