mirror of
https://github.com/MapMakersAndProgrammers/io_scene_a3d.git
synced 2025-10-26 09:59:11 -07:00
Compare commits
2 Commits
refresh
...
mapmodelsa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
542a4c9298 | ||
|
|
b07596676d |
@@ -1,6 +1,10 @@
|
||||
# io_scene_a3d
|
||||
Blender plugin to import the proprietary model format `A3D` used by the game [Tanki Online](https://tankionline.com/en/) from [Alternativa Games](https://alternativa.games/), it is not compatible with older the formats used by the flash based Alternativa3D engine (see [this plugin by Davide Jones](https://github.com/davidejones/alternativa3d_tools) instead). The plugin can also import Tanki Online binary format maps: `map.bin`, both legacy maps and remaster maps work.
|
||||
|
||||
## Legal
|
||||
Any ripped assets are subject to the Tanki Online [Fan Content Guidelines](https://en.tankiwiki.com/Creating_Fan_Content_Guide) and must only be used for producing fan content like fan art.
|
||||
> Using original models, maps, or other in-game assets outside the scope of Tanki Online gameplay or fan art is not allowed.
|
||||
|
||||
## Installation
|
||||
### Requirements: Blender version 4.2+
|
||||
### Optional: io_scene_3ds plugin for importing legacy maps (non remaster)
|
||||
@@ -43,4 +47,4 @@ The plugin also supports `lightmapdata` files that come with remaster maps, thes
|
||||
- Lightprobes (not imported)
|
||||
|
||||
## File format
|
||||
Check the wiki for file format documentation.
|
||||
Check the wiki for file format documentation.
|
||||
|
||||
@@ -36,8 +36,9 @@ class BattleMapBlenderImporter:
|
||||
# Allows subsequent map loads to be faster
|
||||
libraryCache = {}
|
||||
|
||||
def __init__(self, mapData, lightmapData, propLibrarySourcePath, map_scale_factor=0.01, import_static_geom=True, import_collision_geom=False, import_spawn_points=False, import_lightmapdata=False):
|
||||
def __init__(self, mapData, mapDirectory, lightmapData, propLibrarySourcePath, map_scale_factor=0.01, import_static_geom=True, import_collision_geom=False, import_spawn_points=False, import_lightmapdata=False):
|
||||
self.mapData = mapData
|
||||
self.mapDirectory = mapDirectory
|
||||
self.lightmapData = lightmapData
|
||||
self.propLibrarySourcePath = propLibrarySourcePath
|
||||
self.map_scale_factor = map_scale_factor
|
||||
@@ -51,6 +52,7 @@ class BattleMapBlenderImporter:
|
||||
self.collisionBoxMesh = None
|
||||
|
||||
self.materials = {}
|
||||
self.modelsA3D = {}
|
||||
|
||||
def importData(self):
|
||||
print("Importing BattleMap data into blender")
|
||||
@@ -172,8 +174,11 @@ class BattleMapBlenderImporter:
|
||||
|
||||
def tryLoadTexture(self, textureName, libraryName):
|
||||
if libraryName == None:
|
||||
# For some reason Remaster proplib is alwaus marked as None? This is not true for the ny2024 remaster prop lib though
|
||||
# For some reason Remaster proplib is always marked as None? This is not true for the ny2024 remaster prop lib though
|
||||
libraryName = "Remaster"
|
||||
elif libraryName == "":
|
||||
# This is only true for a material that is using the atlas in case of models.a3d
|
||||
return None
|
||||
|
||||
propLibrary = self.getPropLibrary(libraryName)
|
||||
texture = propLibrary.getTexture(f"{textureName}.webp")
|
||||
@@ -182,10 +187,33 @@ class BattleMapBlenderImporter:
|
||||
'''
|
||||
Blender data builders
|
||||
'''
|
||||
def getPropFromModelsA3D(self, propName):
|
||||
if len(self.modelsA3D) == 0:
|
||||
# Load models.a3d
|
||||
modelData = A3D()
|
||||
try:
|
||||
with open(f"{self.mapDirectory}/models.a3d", "rb") as f: modelData.read(f)
|
||||
except: return None
|
||||
modelImporter = A3DBlenderImporter(modelData, None, reset_empty_transform=False, try_import_textures=False)
|
||||
modelObjects = modelImporter.importData()
|
||||
|
||||
# Create props
|
||||
for ob in modelObjects:
|
||||
prop = Prop()
|
||||
prop.createFromObject(ob)
|
||||
self.modelsA3D[ob.name] = prop
|
||||
|
||||
return self.modelsA3D[propName]
|
||||
|
||||
def getBlenderProp(self, propData):
|
||||
# Load prop
|
||||
propLibrary = self.getPropLibrary(propData.libraryName)
|
||||
prop = propLibrary.getProp(propData.name, propData.groupName)
|
||||
prop = None
|
||||
if propData.libraryName == "":
|
||||
# Load prop from models.a3d first, we prefer it over the library where possible
|
||||
prop = self.getPropFromModelsA3D(propData.name)
|
||||
if prop == None:
|
||||
# Load prop through libraries if we can't find it in models.a3d
|
||||
propLibrary = self.getPropLibrary(propData.libraryName)
|
||||
prop = propLibrary.getProp(propData.name, propData.groupName)
|
||||
propOB = prop.mainObject.copy() # We want to use a copy of the prop object
|
||||
|
||||
# Assign data
|
||||
@@ -390,6 +418,10 @@ class Prop:
|
||||
self.objects = []
|
||||
self.mainObject = None
|
||||
|
||||
def createFromObject(self, ob):
|
||||
self.objects.append(ob)
|
||||
self.mainObject = ob
|
||||
|
||||
def loadModel(self, modelPath):
|
||||
fileExtension = modelPath.split(".")[-1].lower()
|
||||
if fileExtension == "a3d":
|
||||
|
||||
@@ -182,7 +182,7 @@ class ImportBattleMap(Operator, ImportHelper):
|
||||
preferences = context.preferences.addons[__package__].preferences
|
||||
if not isdir(preferences.propLibrarySourcePath):
|
||||
raise RuntimeError("Please set a valid prop library folder in addon properties!")
|
||||
mapImporter = BattleMapBlenderImporter(mapData, lightmapData, preferences.propLibrarySourcePath, self.map_scale_factor, self.import_static_geom, self.import_collision_geom, self.import_spawn_points, self.import_lightmapdata)
|
||||
mapImporter = BattleMapBlenderImporter(mapData, self.directory, lightmapData, preferences.propLibrarySourcePath, self.map_scale_factor, self.import_static_geom, self.import_collision_geom, self.import_spawn_points, self.import_lightmapdata)
|
||||
objects = mapImporter.importData()
|
||||
|
||||
# Link objects
|
||||
|
||||
Reference in New Issue
Block a user