|
10 | 10 | from math import sin,cos |
11 | 11 | from mathutils import Vector, Matrix , Quaternion |
12 | 12 | import bmesh |
13 | | -from ..main.common import loc, show_message |
| 13 | +from ..main.common import * |
14 | 14 | from ..jsontool import JSONTool |
15 | 15 | from .phys_import import cp77_phys_import |
16 | 16 | from ..collisiontools.collisions import draw_box_collider, draw_capsule_collider, draw_convex_collider, draw_sphere_collider |
@@ -105,8 +105,9 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
105 | 105 | appearances.append('BASE_COMPONENTS_ONLY') |
106 | 106 |
|
107 | 107 | VS=[] |
| 108 | + vehicle_slots=None |
108 | 109 | for x in ent_components: |
109 | | - if 'name' in x.keys() and x['name']['$value']=='vehicle_slots': |
| 110 | + if 'name' in x.keys() and x['name']['$value']=='vehicle_slots' or x['name']['$value']=='slots': |
110 | 111 | VS.append(x) |
111 | 112 | if len(VS)>0: |
112 | 113 | vehicle_slots= VS[0]['slots'] |
@@ -199,7 +200,7 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
199 | 200 | #link it to the scene |
200 | 201 | coll_scene.children.link(ent_coll) |
201 | 202 | # tag it with some custom properties. |
202 | | - ent_coll['depotPath']=ent_name |
| 203 | + ent_coll['depotPath']=after |
203 | 204 |
|
204 | 205 |
|
205 | 206 | enum_items = [] |
@@ -251,11 +252,7 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
251 | 252 | ent_app_idx=i |
252 | 253 | app_name=a['appearanceName']['$value'] |
253 | 254 | continue |
254 | | - if a['name']['$value']==ent_default: |
255 | | - print('appearance matched, id = ',i) |
256 | | - ent_app_idx=i |
257 | | - app_name=a['appearanceName']['$value'] |
258 | | - continue |
| 255 | + |
259 | 256 |
|
260 | 257 | app_file = ent_apps[ent_app_idx]['appearanceResource']['DepotPath']['$value'] |
261 | 258 | appfilepath=os.path.join(path,app_file).replace('\\',os.sep)+'.json' |
@@ -285,8 +282,41 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
285 | 282 | if len(comps)==0: |
286 | 283 | print('falling back to rootchunk components...') |
287 | 284 | comps= ent_components |
| 285 | + |
| 286 | + for c in comps: |
| 287 | + if 'name' in c.keys() and c['name']['$value']=='vehicle_slots' or c['name']['$value']=='slot': |
| 288 | + VS.append(c) |
| 289 | + if 'rig' in c.keys(): |
| 290 | + rig_path = os.path.join(path, c['rig']['DepotPath']['$value']) |
| 291 | + ent_rigs.append(rig_path) |
| 292 | + if rig_path in ent_rigs: |
| 293 | + print(f"Rig found in app components: {c['rig']['DepotPath']['$value']}") |
| 294 | + if rig is None: |
| 295 | + rig_j=JSONTool.jsonload(rig_path+'.json', error_messages) |
| 296 | + if rig_j is not None: |
| 297 | + rig_j=rig_j['Data']['RootChunk'] |
| 298 | + print('rig json loaded') |
| 299 | + # get the armatures already in the model |
| 300 | + oldarms= [x for x in bpy.data.objects if 'Armature' in x.name] |
| 301 | + animpath=os.path.join(path,c['animations']['gameplay'][0]['animSet']['DepotPath']['$value']+'.glb') |
| 302 | + bpy.ops.io_scene_gltf.cp77(with_materials, filepath=animpath, scripting=True) |
| 303 | + # find the armature we just loaded |
| 304 | + arms=[x for x in bpy.data.objects if 'Armature' in x.name and x not in oldarms] |
| 305 | + rig=arms[0] |
| 306 | + bones=rig.pose.bones |
| 307 | + rig["animset"] = animpath |
| 308 | + rig["rig"] = rig_path |
| 309 | + rig["ent"] = ent_name + ".ent.json" |
| 310 | + print('anim rig loaded') |
| 311 | + else: |
| 312 | + print('another rig already loaded') |
| 313 | + if not vehicle_slots: |
| 314 | + if len(VS)>0: |
| 315 | + vehicle_slots= VS[0]['slots'] |
| 316 | + |
288 | 317 |
|
289 | 318 | for c in comps: |
| 319 | + vs_rot=None |
290 | 320 | if 'license_plate' in c['name']['$value']: |
291 | 321 | includes_license_plates = True |
292 | 322 | print('License plate component found:', c['name']['$value']) |
@@ -397,7 +427,7 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
397 | 427 | bindname=chunk_pt['Data']['bindName']['$value'] |
398 | 428 | # if it has a bindname of vehicle_slots, you may need to find the bone name in the vehicle slots in the root ent components |
399 | 429 | # this should have been loaded earlier, check for it in the vehicle slots if not just set to the slot value |
400 | | - if bindname=='vehicle_slots': |
| 430 | + if bindname=='vehicle_slots' or 'slots': |
401 | 431 | if vehicle_slots: |
402 | 432 | slotname=chunk_pt['Data']['slotName']['$value'] |
403 | 433 | for slot in vehicle_slots: |
@@ -460,12 +490,18 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
460 | 490 | bpy.context.view_layer.objects.active = obj |
461 | 491 | bpy.ops.constraint.childof_set_inverse(constraint="Child Of", owner='OBJECT') |
462 | 492 |
|
| 493 | + |
463 | 494 | # things like the tvs have a bindname but no slotname, bindname appears to point at the name of the main component, and its the only one with a transform applied |
464 | 495 | elif bindname: |
465 | 496 | #see if we can find a component that matches it |
466 | 497 | if bindname=='interior_02': |
467 | 498 | print('interior_02') |
468 | 499 | bindpt=[cmp for cmp in comps if cmp['name']['$value']==bindname] |
| 500 | + slotname= chunk_pt.get('Data').get('slotName').get('$value') |
| 501 | + if bindpt and slotname: |
| 502 | + # Have a bindpoint and a slotname, so we can use the local transform from the bindpoint |
| 503 | + print('bindpt and slotname found') |
| 504 | + |
469 | 505 | if bindpt and len(bindpt)==1: |
470 | 506 | if c['localTransform']['Position']['x']['Bits']==0 and c['localTransform']['Position']['y']['Bits']==0 and c['localTransform']['Position']['z']['Bits']==0 and 'localTransform' in bindpt[0]: |
471 | 507 | c['localTransform']['Position']=bindpt[0]['localTransform']['Position'] |
@@ -525,16 +561,42 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
525 | 561 | obj['bindname']=bindname |
526 | 562 | pt_trans=bones[bindname].head |
527 | 563 | pt_rot=bones[bindname].rotation_quaternion |
528 | | - |
529 | | - obj.location.x = obj.location.x+pt_trans[0] |
530 | | - obj.location.y = obj.location.y+pt_trans[1] |
531 | | - obj.location.z = obj.location.z+pt_trans[2] |
| 564 | + vs=[slot for slot in vehicle_slots if slot['slotName']['$value']==slotname] |
| 565 | + vs_rot=Quaternion([0,0,0,1]) |
| 566 | + vs_pos= Vector([0,0,0]) |
| 567 | + vs_scale=Vector([1,1,1]) |
| 568 | + if len(vs)>0: |
| 569 | + vs=vs[0] |
| 570 | + if 'relativeRotation' in vs.keys(): |
| 571 | + vs_rot[0]=vs['relativeRotation']['i'] |
| 572 | + vs_rot[1]=vs['relativeRotation']['j'] |
| 573 | + vs_rot[2]=vs['relativeRotation']['k'] |
| 574 | + vs_rot[3]=vs['relativeRotation']['r'] |
| 575 | + if 'relativePosition' in vs.keys(): |
| 576 | + vs_pos[0]=vs['relativePosition']['X'] |
| 577 | + vs_pos[1]=vs['relativePosition']['Y'] |
| 578 | + vs_pos[2]=vs['relativePosition']['Z'] |
| 579 | + #print('vs_rot = ',vs_rot) |
| 580 | + vs_mat=Matrix.LocRotScale(Vector([0,0,0]),vs_rot,vs_scale) |
| 581 | + pt_mat=Matrix.LocRotScale(Vector([0,0,0]),pt_rot,Vector(vs_scale)) |
| 582 | + vs_z_ang=vs_mat.to_euler().z |
| 583 | + pt_z_ang=pt_mat.to_euler().z |
| 584 | + |
| 585 | + obj.location.x = obj.location.x+pt_trans[0]+vs_pos[0] |
| 586 | + obj.location.y = obj.location.y+pt_trans[1]+vs_pos[1] |
| 587 | + obj.location.z = obj.location.z+pt_trans[2]+vs_pos[2] |
532 | 588 |
|
533 | 589 | obj.rotation_quaternion.x = btrans['Rotation']['i'] |
534 | 590 | obj.rotation_quaternion.y = btrans['Rotation']['j'] |
535 | 591 | obj.rotation_quaternion.z = btrans['Rotation']['k'] |
536 | 592 | obj.rotation_quaternion.w = btrans['Rotation']['r'] |
537 | | - # Apply child of constraints to them and set the inverse |
| 593 | + |
| 594 | + |
| 595 | + obj.rotation_quaternion=obj.rotation_quaternion*Quaternion(vs_rot) |
| 596 | + #obj.matrix_local= obj.matrix_local @ vs_mat |
| 597 | + #obj.matrix_world= pt_mat @ obj.matrix_world |
| 598 | + |
| 599 | + #Apply child of constraints to them and set the inverse |
538 | 600 | if 'fuel_cap' not in bindname: |
539 | 601 | co=obj.constraints.new(type='CHILD_OF') |
540 | 602 | co.target=rig |
@@ -593,11 +655,16 @@ def importEnt(with_materials, filepath='', appearances=[], exclude_meshes=[], in |
593 | 655 | obj.location.x = obj.location.x+x |
594 | 656 | obj.location.y = obj.location.y+y |
595 | 657 | obj.location.z = obj.location.z+z |
596 | | - if 'Orientation' in c['localTransform'].keys(): |
| 658 | + # shouldnt need the 0 check, pretty sure I've fuked up a default somewhere, but at this point I just want it to work. |
| 659 | + if 'Orientation' in c['localTransform'].keys() and (sum(obj.rotation_quaternion[:])<1.1 and sum(obj.rotation_quaternion[:])>0.9) or (sum(obj.rotation_quaternion[:])<0.1 and sum(obj.rotation_quaternion[:])>-0.1): |
| 660 | + lrot=get_rot(c['localTransform']) |
| 661 | + obj.rotation_quaternion = obj.rotation_quaternion * Quaternion(lrot) |
597 | 662 | obj.rotation_quaternion.x = c['localTransform']['Orientation']['i'] |
598 | 663 | obj.rotation_quaternion.y = c['localTransform']['Orientation']['j'] |
599 | 664 | obj.rotation_quaternion.z = c['localTransform']['Orientation']['k'] |
600 | 665 | obj.rotation_quaternion.w = c['localTransform']['Orientation']['r'] |
| 666 | + #if vs_rot: |
| 667 | + # obj.matrix_local = Matrix.LocRotScale(Vector(0,0,0),Quaternion(vs_rot),Vector(1,1,1)) @ |
601 | 668 | if 'scale' in c['localTransform'].keys(): |
602 | 669 | obj.scale.x = c['localTransform']['scale']['X'] |
603 | 670 | obj.scale.y = c['localTransform']['scale']['Y'] |
|
0 commit comments