Skip to content

Commit 20ed280

Browse files
committed
Add some minor comments, logging and move classes around
1 parent b179401 commit 20ed280

1 file changed

Lines changed: 129 additions & 118 deletions

File tree

io_scene_a3d/BattleMapBlenderImporter.py

Lines changed: 129 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -32,120 +32,6 @@
3232
from .A3DBlenderImporter import A3DBlenderImporter
3333
from .BlenderMaterialUtils import addImageTextureToMaterial, decodeIntColorToTuple
3434

35-
class Prop:
36-
def __init__(self):
37-
self.objects = []
38-
self.mainObject = None
39-
40-
def loadModel(self, modelPath):
41-
fileExtension = modelPath.split(".")[-1]
42-
if fileExtension == "a3d":
43-
modelData = A3D()
44-
with open(modelPath, "rb") as file: modelData.read(file)
45-
46-
# Import the model
47-
modelImporter = A3DBlenderImporter(modelData, None, reset_empty_transform=False, try_import_textures=False)
48-
self.objects = modelImporter.importData()
49-
elif fileExtension == "3ds":
50-
bpy.ops.import_scene.max3ds(filepath=modelPath, use_apply_transform=False)
51-
for ob in bpy.context.selectable_objects:
52-
# The imported objects are added to the active collection, remove them
53-
bpy.context.collection.objects.unlink(ob)
54-
55-
# Correct the origin XXX: this does not work for all cases, investigate more
56-
ob.animation_data_clear()
57-
x, y, z = -ob.location.x, -ob.location.y, -ob.location.z
58-
objectOrigin = Matrix.Translation((x, y, z))
59-
ob.data.transform(objectOrigin)
60-
ob.location = (0.0, 0.0, 0.0)
61-
62-
self.objects.append(ob)
63-
else:
64-
raise RuntimeError(f"Unknown model file extension: {fileExtension}")
65-
66-
# Identify the main parent object
67-
for ob in self.objects:
68-
if ob.parent == None: self.mainObject = ob
69-
if self.mainObject == None:
70-
raise RuntimeError(f"Unable to find the parent object for: {modelPath}")
71-
72-
def loadSprite(self, propInfo):
73-
spriteInfo = propInfo["sprite"]
74-
75-
# Create a plane we can use for the sprite
76-
me = bpy.data.meshes.new(propInfo["name"])
77-
78-
# bm = bmesh.new()
79-
# bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=spriteInfo["scale"]*100)
80-
# bm.to_mesh(me)
81-
# bm.free()
82-
83-
ob = bpy.data.objects.new(me.name, me)
84-
85-
# Assign data
86-
ob.scale = (spriteInfo["width"], 1.0, spriteInfo["height"]) #XXX: this should involve spriteInfo["scale"] probably?
87-
spriteOrigin = Matrix.Translation((0.0, spriteInfo["originY"], 0.0))
88-
me.transform(spriteOrigin)
89-
90-
# Finalise
91-
self.objects.append(ob)
92-
self.mainObject = ob
93-
94-
class PropLibrary:
95-
propGroups = {}
96-
def __init__(self, directory):
97-
self.directory = directory
98-
self.libraryInfo = {}
99-
100-
# Load library info
101-
with open(f"{self.directory}/library.json", "r") as file: self.libraryInfo = load(file)
102-
print(f"Loaded prop library: " + self.libraryInfo["name"])
103-
104-
def getProp(self, propName, groupName):
105-
# Create the prop group if it's not already loaded
106-
if not groupName in self.propGroups:
107-
self.propGroups[groupName] = {}
108-
109-
# Load the prop if it's not already loaded
110-
if not propName in self.propGroups[groupName]:
111-
# Find the prop group
112-
groupInfo = None
113-
for group in self.libraryInfo["groups"]:
114-
if group["name"] == groupName:
115-
groupInfo = group
116-
break
117-
if groupInfo == None:
118-
raise RuntimeError(f"Unable to find prop group with name {groupName} in " + self.libraryInfo["name"])
119-
120-
# Find the prop
121-
propInfo = None
122-
for prop in groupInfo["props"]:
123-
if prop["name"] == propName:
124-
propInfo = prop
125-
break
126-
if propInfo == None:
127-
raise RuntimeError(f"Unable to find prop with name {propName} in {groupName} from " + self.libraryInfo["name"])
128-
129-
# Create the prop
130-
prop = Prop()
131-
meshInfo = propInfo["mesh"]
132-
spriteInfo = propInfo["sprite"]
133-
if meshInfo != None:
134-
modelPath = f"{self.directory}/" + meshInfo["file"]
135-
prop.loadModel(modelPath)
136-
elif spriteInfo != None:
137-
prop.loadSprite(propInfo)
138-
else:
139-
#XXX: Uhhhhhh, empty prop?
140-
pass
141-
self.propGroups[groupName][propName] = prop
142-
143-
return self.propGroups[groupName][propName]
144-
145-
def getTexture(self, textureName):
146-
im = load_image(textureName, self.directory)
147-
return im
148-
14935
class BattleMapBlenderImporter:
15036
# Allows subsequent map loads to be faster
15137
libraryCache = {}
@@ -170,12 +56,16 @@ def importData(self):
17056
ma = self.createBlenderMaterial(materialData)
17157
self.materials[materialData.ID] = ma
17258

59+
# Static geometry
17360
propObjects = []
17461
if self.import_static_geom:
17562
# Load props
17663
for propData in self.mapData.staticGeometry:
17764
ob = self.getBlenderProp(propData)
17865
propObjects.append(ob)
66+
print(f"Loaded {len(propObjects)} prop objects")
67+
68+
# Collision geometry
17969
collisionObjects = []
18070
if self.import_collision_geom:
18171
# Load collision meshes
@@ -189,21 +79,25 @@ def importData(self):
18979
collisionObjects += collisionTriangleObjects
19080
collisionObjects += collisionPlaneObjects
19181
collisionObjects += collisionBoxObjects
82+
print(f"Loaded {len(collisionObjects)} collision objects")
83+
84+
# Spawn points
19285
spawnPointObjects = []
19386
if self.import_spawn_points:
19487
# Create spawn points
19588
for spawnPointData in self.mapData.spawnPoints:
19689
ob = self.createBlenderSpawnPoint(spawnPointData)
19790
spawnPointObjects.append(ob)
91+
print(f"Loaded {len(spawnPointObjects)} spawn points")
19892

19993
# Create container object to store all our objects
20094
objects = propObjects + collisionObjects + spawnPointObjects
20195
mapOB = bpy.data.objects.new("BattleMap", None)
202-
mapOB.empty_display_size = 100
96+
mapOB.empty_display_size = 100 # Alternativa use a x100 scale
20397
mapOB.scale = (self.map_scale_factor, self.map_scale_factor, self.map_scale_factor)
20498
objects.append(mapOB)
20599

206-
# Create empty objects to house each type of object
100+
# Create empty objects to group each type of object
207101
if self.import_static_geom:
208102
groupOB = bpy.data.objects.new("StaticGeometry", None)
209103
groupOB.parent = mapOB
@@ -223,6 +117,7 @@ def importData(self):
223117
for ob in spawnPointObjects:
224118
ob.parent = groupOB
225119

120+
# Lighting data
226121
if self.import_lightmapdata:
227122
# Create a sun light object
228123
li = bpy.data.lights.new("DirectionalLight", "SUN")
@@ -252,14 +147,15 @@ def getPropLibrary(self, libraryName):
252147
# First check if we've already loaded the required prop library
253148
if not libraryName in self.libraryCache:
254149
# Load the proplib
255-
libraryPath = f"{self.propLibrarySourcePath}/{libraryName}" # XXX: Get platform agnostic way of doing this
150+
libraryPath = f"{self.propLibrarySourcePath}/{libraryName}"
256151
library = PropLibrary(libraryPath)
257152
self.libraryCache[libraryName] = library
258153

259154
return self.libraryCache[libraryName]
260155

261156
def tryLoadTexture(self, textureName, libraryName):
262157
if libraryName == None:
158+
# For some reason Remaster proplib is alwaus marked as None? This is not true for the ny2024 remaster prop lib though
263159
libraryName = "Remaster"
264160

265161
propLibrary = self.getPropLibrary(libraryName)
@@ -302,6 +198,7 @@ def getBlenderProp(self, propData):
302198
# Material
303199
ma = self.materials[propData.materialID]
304200
if len(propOB.data.materials) != 0:
201+
# Create a duplicate mesh object if it needs a different material, XXX: could probably cache these to reuse datablocks
305202
if propOB.data.materials[0] != ma:
306203
propOB.data = propOB.data.copy()
307204
propOB.data.materials[0] = ma
@@ -430,4 +327,118 @@ def createBlenderMaterial(self, materialData):
430327
else:
431328
pass # Unknown shader
432329

433-
return ma
330+
return ma
331+
332+
class PropLibrary:
333+
propGroups = {}
334+
def __init__(self, directory):
335+
self.directory = directory
336+
self.libraryInfo = {}
337+
338+
# Load library info
339+
with open(f"{self.directory}/library.json", "r") as file: self.libraryInfo = load(file)
340+
print(f"Loaded prop library: " + self.libraryInfo["name"])
341+
342+
def getProp(self, propName, groupName):
343+
# Create the prop group if it's not already loaded
344+
if not groupName in self.propGroups:
345+
self.propGroups[groupName] = {}
346+
347+
# Load the prop if it's not already loaded
348+
if not propName in self.propGroups[groupName]:
349+
# Find the prop group
350+
groupInfo = None
351+
for group in self.libraryInfo["groups"]:
352+
if group["name"] == groupName:
353+
groupInfo = group
354+
break
355+
if groupInfo == None:
356+
raise RuntimeError(f"Unable to find prop group with name {groupName} in " + self.libraryInfo["name"])
357+
358+
# Find the prop
359+
propInfo = None
360+
for prop in groupInfo["props"]:
361+
if prop["name"] == propName:
362+
propInfo = prop
363+
break
364+
if propInfo == None:
365+
raise RuntimeError(f"Unable to find prop with name {propName} in {groupName} from " + self.libraryInfo["name"])
366+
367+
# Create the prop
368+
prop = Prop()
369+
meshInfo = propInfo["mesh"]
370+
spriteInfo = propInfo["sprite"]
371+
if meshInfo != None:
372+
modelPath = f"{self.directory}/" + meshInfo["file"]
373+
prop.loadModel(modelPath)
374+
elif spriteInfo != None:
375+
prop.loadSprite(propInfo)
376+
else:
377+
#XXX: Uhhhhhh, empty prop?
378+
pass
379+
self.propGroups[groupName][propName] = prop
380+
381+
return self.propGroups[groupName][propName]
382+
383+
def getTexture(self, textureName):
384+
im = load_image(textureName, self.directory)
385+
return im
386+
387+
class Prop:
388+
def __init__(self):
389+
self.objects = []
390+
self.mainObject = None
391+
392+
def loadModel(self, modelPath):
393+
fileExtension = modelPath.split(".")[-1]
394+
if fileExtension == "a3d":
395+
modelData = A3D()
396+
with open(modelPath, "rb") as file: modelData.read(file)
397+
398+
# Import the model
399+
modelImporter = A3DBlenderImporter(modelData, None, reset_empty_transform=False, try_import_textures=False)
400+
self.objects = modelImporter.importData()
401+
elif fileExtension == "3ds":
402+
bpy.ops.import_scene.max3ds(filepath=modelPath, use_apply_transform=False)
403+
for ob in bpy.context.selectable_objects:
404+
# The imported objects are added to the active collection, remove them
405+
bpy.context.collection.objects.unlink(ob)
406+
407+
# Correct the origin XXX: this does not work for all cases, investigate more
408+
ob.animation_data_clear()
409+
x, y, z = -ob.location.x, -ob.location.y, -ob.location.z
410+
objectOrigin = Matrix.Translation((x, y, z))
411+
ob.data.transform(objectOrigin)
412+
ob.location = (0.0, 0.0, 0.0)
413+
414+
self.objects.append(ob)
415+
else:
416+
raise RuntimeError(f"Unknown model file extension: {fileExtension}")
417+
418+
# Identify the main parent object
419+
for ob in self.objects:
420+
if ob.parent == None: self.mainObject = ob
421+
if self.mainObject == None:
422+
raise RuntimeError(f"Unable to find the parent object for: {modelPath}")
423+
424+
def loadSprite(self, propInfo):
425+
spriteInfo = propInfo["sprite"]
426+
427+
# Create a plane we can use for the sprite
428+
me = bpy.data.meshes.new(propInfo["name"])
429+
430+
# bm = bmesh.new()
431+
# bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=spriteInfo["scale"]*100)
432+
# bm.to_mesh(me)
433+
# bm.free()
434+
435+
ob = bpy.data.objects.new(me.name, me)
436+
437+
# Assign data
438+
ob.scale = (spriteInfo["width"], 1.0, spriteInfo["height"]) #XXX: this should involve spriteInfo["scale"] probably?
439+
spriteOrigin = Matrix.Translation((0.0, spriteInfo["originY"], 0.0))
440+
me.transform(spriteOrigin)
441+
442+
# Finalise
443+
self.objects.append(ob)
444+
self.mainObject = ob

0 commit comments

Comments
 (0)