示例#1
0
文件: CMDL.hpp 项目: KalDragon/urde
    static bool Extract(const SpecBase& dataSpec,
                        PAKEntryReadStream& rs,
                        const hecl::ProjectPath& outPath,
                        PAKRouter<PAKBridge>& pakRouter,
                        const DNAMP1::PAK::Entry& entry,
                        bool,
                        std::function<void(const hecl::SystemChar*)>)
    {
        /* Check for RigPair */
        const PAKRouter<PAKBridge>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
        CINF cinf;
        CSKR cskr;
        std::pair<CSKR*,CINF*> loadRp(nullptr, nullptr);
        if (rp)
        {
            pakRouter.lookupAndReadDNA(rp->first, cskr);
            pakRouter.lookupAndReadDNA(rp->second, cinf);
            loadRp.first = &cskr;
            loadRp.second = &cinf;
        }

        /* Do extract */
        hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection();
        if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::Mesh))
            return false;
        DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_2, 4>
                (conn, rs, pakRouter, entry, dataSpec, loadRp);
        return conn.saveBlend();
    }
示例#2
0
文件: Pickup.hpp 项目: KalDragon/urde
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (particle)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle);
         ent->name = name + "_part";
     }
     if (model)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model);
         ent->name = name + "_model";
     }
     animationParameters.nameANCS(pakRouter, name + "_animp");
     actorParameters.nameIDs(pakRouter, name + "_actp");
 }
示例#3
0
文件: Midi.hpp 项目: KalDragon/urde
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (song)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(song);
         ent->name = name + "_song";
     }
 }
示例#4
0
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (unknown18)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown18);
         ent->name = name + "_unknown18";
     }
     if (model)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model);
         ent->name = name + "_model";
     }
     if (particle1)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1);
         ent->name = name + "_part1";
     }
     if (particle2)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2);
         ent->name = name + "_part2";
     }
     if (particle3)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3);
         ent->name = name + "_part3";
     }
     if (particle4)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4);
         ent->name = name + "_part4";
     }
     if (particle5)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5);
         ent->name = name + "_part5";
     }
     if (particle6)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6);
         ent->name = name + "_part6";
     }
     if (particle7)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7);
         ent->name = name + "_part7";
     }
     animationParameters.nameANCS(pakRouter, name + "_animp");
     actorParameters.nameIDs(pakRouter, name + "_actp");
 }
示例#5
0
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (dcln)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dcln);
         ent->name = name + "_dcln";
     }
     patternedInfo.nameIDs(pakRouter, name + "_patterned");
     actorParameters.nameIDs(pakRouter, name + "_actp");
 }
示例#6
0
文件: DCLN.cpp 项目: AxioDL/urde
bool DCLN::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
                   PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
                   std::function<void(const hecl::SystemChar*)> fileChanged) {
  DCLN dcln;
  dcln.read(rs);
  hecl::blender::Connection& conn = btok.getBlenderConnection();
  if (!conn.createBlend(outPath, hecl::blender::BlendType::ColMesh))
    return false;

  dcln.sendToBlender(conn, pakRouter.getBestEntryName(entry, false));
  return conn.saveBlend();
}
示例#7
0
UniqueID32 AnimationParameters::getCINF(PAKRouter<PAKBridge>& pakRouter) const
{
    if (!animationCharacterSet)
        return UniqueID32();
    const nod::Node* node;
    const PAK::Entry* ancsEnt = pakRouter.lookupEntry(animationCharacterSet, &node);
    ANCS ancs;
    {
        PAKEntryReadStream rs = ancsEnt->beginReadStream(*node);
        ancs.read(rs);
    }
    return ancs.characterSet.characters.at(character).cinf;
}
示例#8
0
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (wpsc1)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1);
         ent->name = name + "_wpsc1";
     }
     if (wpsc2)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2);
         ent->name = name + "_wpsc2";
     }
     if (wpsc3)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc3);
         ent->name = name + "_wpsc3";
     }
     if (particle1)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1);
         ent->name = name + "_part1";
     }
     if (particle2)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2);
         ent->name = name + "_part2";
     }
     if (particle3)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3);
         ent->name = name + "_part3";
     }
     if (particle4)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4);
         ent->name = name + "_part4";
     }
     patternedInfo.nameIDs(pakRouter, name + "_patterned");
     actorParameters.nameIDs(pakRouter, name + "_actp");
 }
示例#9
0
文件: MAPA.cpp 项目: AxioDL/urde
bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const hecl::ProjectPath& outPath,
                       PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force) {
  if (!force && outPath.isFile())
    return true;

  if (!conn.createBlend(outPath, hecl::blender::BlendType::MapArea))
    return false;
  hecl::blender::PyOutStream os = conn.beginPythonOut(true);

  os << "import bpy, bmesh\n"
        "from mathutils import Matrix\n"
        "\n"
        "bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n"
        "bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n"
        "bpy.types.Scene.retro_map_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0),"
        "('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
        "('VISIT', 'Visit', 'Visible after Visit', 2),"
        "('NEVER', 'Never', 'Never Visible', 3)],"
        "name='Retro: Map Visibility Mode')\n"
        "bpy.types.Object.retro_mapobj_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', "
        "0),"
        "('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
        "('VISIT', 'Visit', 'Visible after Door Visit', 2),"
        "('NEVER', 'Never', 'Never Visible', 3),"
        "('MAPSTATIONORVISIT2', 'Map Station or Visit 2', 'Visible after Map Station or Visit', 4)],"
        "name='Retro: Map Object Visibility Mode')\n"
        "\n"
        "for ar in bpy.context.screen.areas:\n"
        "    for sp in ar.spaces:\n"
        "        if sp.type == 'VIEW_3D':\n"
        "            sp.viewport_shade = 'SOLID'\n"
        "\n"
        "# Clear Scene\n"
        "for ob in bpy.data.objects:\n"
        "    if ob.type != 'CAMERA':\n"
        "        bpy.context.scene.objects.unlink(ob)\n"
        "        bpy.data.objects.remove(ob)\n"
        "\n"
        "def add_triangle(bm, verts):\n"
        "    verts = [bm.verts[vi] for vi in verts]\n"
        "    face = bm.faces.get(verts)\n"
        "    if face:\n"
        "        face = face.copy()\n"
        "        bm.verts.ensure_lookup_table()\n"
        "        face.normal_flip()\n"
        "    else:\n"
        "        bm.faces.new(verts)\n"
        "\n"
        "def add_border(bm, verts):\n"
        "    verts = [bm.verts[vi] for vi in verts]\n"
        "    edge = bm.edges.get(verts)\n"
        "    if not edge:\n"
        "        edge = bm.edges.new(verts)\n"
        "    edge.seam = True\n"
        "\n";

  os.format(
      "bpy.context.scene.name = 'MAPA_%s'\n"
      "bpy.context.scene.retro_map_vis_mode = '%s'\n",
      entry.id.toString().c_str(), RetroMapVisModes[mapa.header->visMode()]);

  /* Add empties representing MappableObjects */
  int moIdx = 0;
  for (const std::unique_ptr<MAPA::IMappableObject>& mo : mapa.mappableObjects) {
    if (mapa.version < 5) {
      const MAPA::MappableObjectMP1_2* moMP12 = static_cast<const MAPA::MappableObjectMP1_2*>(mo.get());
      zeus::simd_floats mtxF[3];
      for (int i = 0; i < 3; ++i)
        moMP12->transformMtx[i].simd.copy_to(mtxF[i]);
      os.format(
          "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
          "bpy.context.scene.objects.link(obj)\n"
          "obj.retro_mappable_type = %d\n"
          "obj.retro_mapobj_vis_mode = '%s'\n"
          "obj.retro_mappable_sclyid = '0x%08X'\n"
          "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
          "mtxd = mtx.decompose()\n"
          "obj.rotation_mode = 'QUATERNION'\n"
          "obj.location = mtxd[0]\n"
          "obj.rotation_quaternion = mtxd[1]\n"
          "obj.scale = mtxd[2]\n",
          moIdx, moMP12->type, RetroMapObjVisModes[moMP12->visMode], moMP12->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2],
          mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
      ++moIdx;
      continue;
    } else {
      const MAPA::MappableObjectMP3* moMP3 = static_cast<const MAPA::MappableObjectMP3*>(mo.get());
      zeus::simd_floats mtxF[3];
      for (int i = 0; i < 3; ++i)
        moMP3->transformMtx[i].simd.copy_to(mtxF[i]);
      os.format(
          "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
          "bpy.context.scene.objects.link(obj)\n"
          "obj.retro_mappable_type = %d\n"
          "obj.retro_mapobj_vis_mode = '%s'\n"
          "obj.retro_mappable_sclyid = '0x%08X'\n"
          "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
          "mtxd = mtx.decompose()\n"
          "obj.rotation_mode = 'QUATERNION'\n"
          "obj.location = mtxd[0]\n"
          "obj.rotation_quaternion = mtxd[1]\n"
          "obj.scale = mtxd[2]\n",
          moIdx, moMP3->type, RetroMapObjVisModes[moMP3->visMode], moMP3->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2],
          mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
      ++moIdx;
      continue;
    }
  }

  os << "# Begin bmesh\n"
        "bm = bmesh.new()\n"
        "\n";

  /* Read in verts */
  for (const atVec3f& vert : mapa.vertices) {
    zeus::simd_floats f(vert.simd);
    os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]);
  }
  os << "bm.verts.ensure_lookup_table()\n";

  /* Read in surfaces */
  for (const typename MAPA::Surface& surf : mapa.surfaces) {
    for (const typename MAPA::Surface::Primitive& prim : surf.primitives) {
      auto iit = prim.indices.cbegin();

      /* 3 Prim Verts to start */
      int c = 0;
      unsigned int primVerts[3] = {*iit++, *iit++, *iit++};

      if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) {
        atUint8 flip = 0;
        for (size_t v = 0; v < prim.indexCount - 2; ++v) {
          if (flip) {
            os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 2) % 3],
                      primVerts[(c + 1) % 3]);
          } else {
            os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 1) % 3],
                      primVerts[(c + 2) % 3]);
          }
          flip ^= 1;

          /* Break if done */
          if (iit == prim.indices.cend())
            break;

          bool peek = (v >= prim.indexCount - 3);

          /* Advance one prim vert */
          if (peek)
            primVerts[c % 3] = *iit;
          else
            primVerts[c % 3] = *iit++;
          ++c;
        }
      } else if (GX::Primitive(prim.type) == GX::TRIANGLES) {
        for (size_t v = 0; v < prim.indexCount; v += 3) {
          os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[0], primVerts[1], primVerts[2]);

          /* Break if done */
          if (v + 3 >= prim.indexCount)
            break;

          /* Advance 3 Prim Verts */
          for (int pv = 0; pv < 3; ++pv)
            primVerts[pv] = *iit++;
        }
      }
    }

    for (const typename MAPA::Surface::Border& border : surf.borders) {
      auto iit = border.indices.cbegin();
      for (size_t i = 0; i < border.indexCount - 1; ++i) {
        os.format("add_border(bm, (%u,%u))\n", *iit, *(iit + 1));
        ++iit;
      }
    }
  }

  os << "mesh = bpy.data.meshes.new('MAP')\n"
        "mesh.show_edge_seams = True\n"
        "obj = bpy.data.objects.new(mesh.name, mesh)\n"
        "bm.to_mesh(mesh)\n"
        "bpy.context.scene.objects.link(obj)\n"
        "bm.free()\n";

  const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id);
  const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::skIdentityMatrix4f;
  os.format(
      "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
      "mtxd = mtx.decompose()\n"
      "obj.rotation_mode = 'QUATERNION'\n"
      "obj.location = mtxd[0]\n"
      "obj.rotation_quaternion = mtxd[1]\n"
      "obj.scale = mtxd[2]\n",
      mtx[0][0], mtx[1][0], mtx[2][0], mtx[3][0], mtx[0][1], mtx[1][1], mtx[2][1], mtx[3][1], mtx[0][2], mtx[1][2],
      mtx[2][2], mtx[3][2]);

  /* World background */
  hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend");
  if (worldBlend.isFile())
    os.linkBackground("//../!world.blend", "World");

  os.centerView();
  os.close();
  conn.saveBlend();
  return true;
}
示例#10
0
文件: MREA.cpp 项目: KalDragon/urde
bool MREA::Extract(const SpecBase& dataSpec,
                   PAKEntryReadStream& rs,
                   const hecl::ProjectPath& outPath,
                   PAKRouter<PAKBridge>& pakRouter,
                   const PAK::Entry& entry,
                   bool force,
                   std::function<void(const hecl::SystemChar*)>)
{
    using RigPair = std::pair<CSKR*, CINF*>;
    RigPair dummy(nullptr, nullptr);

    hecl::ProjectPath mreaPath;
    if (pakRouter.isShared())
        /* Rename MREA for consistency */
        mreaPath = hecl::ProjectPath(outPath.getParentPath(), _S("!area.blend"));
    else
        /* We're not in a world pak, so lets keep the original name */
        mreaPath = outPath;

    if (!force && mreaPath.getPathType() == hecl::ProjectPath::Type::File)
        return true;

    /* Do extract */
    Header head;
    head.read(rs);
    rs.seekAlign32();

    /* MREA decompression stream */
    StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount);
    athena::io::FileWriter mreaDecompOut(pakRouter.getCooked(&entry).getWithExtension(_S(".decomp")).getAbsolutePath());
    head.write(mreaDecompOut);
    mreaDecompOut.seekAlign32();
    drs.writeDecompInfos(mreaDecompOut);
    mreaDecompOut.seekAlign32();
    drs.writeSecIdxs(mreaDecompOut);
    mreaDecompOut.seekAlign32();
    atUint64 decompLen = drs.length();
    mreaDecompOut.writeBytes(drs.readBytes(decompLen).get(), decompLen);
    mreaDecompOut.close();
    drs.seek(0, athena::Begin);


    /* Start up blender connection */
    hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection();
    if (!conn.createBlend(mreaPath, hecl::BlenderConnection::BlendType::Area))
        return false;

    /* Open Py Stream and read sections */
    hecl::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);
    os.format("import bpy\n"
              "import bmesh\n"
              "from mathutils import Vector\n"
              "\n"
              "bpy.context.scene.name = '%s'\n",
              pakRouter.getBestEntryName(entry).c_str());
    DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath());
    MaterialSet::RegisterMaterialProps(os);
    os << "# Clear Scene\n"
          "for ob in bpy.data.objects:\n"
          "    bpy.context.scene.objects.unlink(ob)\n"
          "    bpy.data.objects.remove(ob)\n"
          "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n"
          "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n"
          "\n";

    /* One shared material set for all meshes */
    os << "# Materials\n"
          "materials = []\n"
          "\n";
    MaterialSet matSet;
    atUint64 secStart = drs.position();
    matSet.read(drs);
    matSet.readToBlender(os, pakRouter, entry, 0);
    drs.seek(secStart + head.secSizes[0], athena::Begin);
    std::vector<DNACMDL::VertexAttributes> vertAttribs;
    DNACMDL::GetVertexAttributes(matSet, vertAttribs);

    /* Read mesh info */
    atUint32 curSec = 1;
    std::vector<atUint32> surfaceCounts;
    surfaceCounts.reserve(head.meshCount);
    for (atUint32 m=0 ; m<head.meshCount ; ++m)
    {
        /* Mesh header */
        MeshHeader mHeader;
        secStart = drs.position();
        mHeader.read(drs);
        drs.seek(secStart + head.secSizes[curSec++], athena::Begin);

        /* Surface count from here */
        secStart = drs.position();
        surfaceCounts.push_back(drs.readUint32Big());
        drs.seek(secStart + head.secSizes[curSec++], athena::Begin);

        /* Seek through AROT-relation sections */
        drs.seek(head.secSizes[curSec++], athena::Current);
        drs.seek(head.secSizes[curSec++], athena::Current);
    }

    /* Skip though WOBJs */
    auto secIdxIt = drs.beginSecIdxs();
    while (secIdxIt->first == FOURCC('WOBJ'))
        ++secIdxIt;

    /* Skip AROT */
    if (secIdxIt->first == FOURCC('ROCT'))
    {
        drs.seek(head.secSizes[curSec++], athena::Current);
        ++secIdxIt;
    }

    /* Skip AABB */
    if (secIdxIt->first == FOURCC('AABB'))
    {
        drs.seek(head.secSizes[curSec++], athena::Current);
        ++secIdxIt;
    }

    /* Now the meshes themselves */
    if (secIdxIt->first == FOURCC('GPUD'))
    {
        for (atUint32 m=0 ; m<head.meshCount ; ++m)
        {
            curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_3>
                          (os, drs, pakRouter, entry, dummy, true,
                           false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]);
        }
        ++secIdxIt;
    }

    /* Skip DEPS */
    if (secIdxIt->first == FOURCC('DEPS'))
    {
        drs.seek(head.secSizes[curSec++], athena::Current);
        ++secIdxIt;
    }

    /* Skip SOBJ (SCLY) */
    if (secIdxIt->first == FOURCC('SOBJ'))
    {
        for (atUint32 l=0 ; l<head.sclyLayerCount ; ++l)
            drs.seek(head.secSizes[curSec++], athena::Current);
        ++secIdxIt;
    }

    /* Skip SGEN */
    if (secIdxIt->first == FOURCC('SGEN'))
    {
        drs.seek(head.secSizes[curSec++], athena::Current);
        ++secIdxIt;
    }

    /* Read Collision Meshes */
    if (secIdxIt->first == FOURCC('COLI'))
    {
        DNAMP2::DeafBabe collision;
        secStart = drs.position();
        collision.read(drs);
        DNAMP2::DeafBabe::BlenderInit(os);
        collision.sendToBlender(os);
        drs.seek(secStart + head.secSizes[curSec++], athena::Begin);
        ++secIdxIt;
    }

    /* Read BABEDEAD Lights as Cycles emissives */
    if (secIdxIt->first == FOURCC('LITE'))
    {
        secStart = drs.position();
        ReadBabeDeadToBlender_3(os, drs);
        drs.seek(secStart + head.secSizes[curSec++], athena::Begin);
        ++secIdxIt;
    }

    /* Origins to center of mass */
    os << "bpy.context.scene.layers[1] = True\n"
          "bpy.ops.object.select_by_type(type='MESH')\n"
          "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n"
          "bpy.ops.object.select_all(action='DESELECT')\n"
          "bpy.context.scene.layers[1] = False\n";

    os.centerView();
    os.close();
    return conn.saveBlend();
}
示例#11
0
文件: ANCS.cpp 项目: AxioDL/urde
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
                       PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
                       std::function<void(const hecl::SystemChar*)> fileChanged, bool force) {
  /* Extract character CMDL/CSKR first */
  std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
  ancs.getCharacterResInfo(chResInfo);
  for (const auto& info : chResInfo) {
    const nod::Node* node;
    const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, false);
    if (cmdlE) {
      hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
      if (force || cmdlPath.isNone()) {
        cmdlPath.makeDirChain(false);
        if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
          return false;

        std::string bestName = pakRouter.getBestEntryName(*cmdlE);
        hecl::SystemStringConv bestNameView(bestName);
        fileChanged(bestNameView.c_str());

        typename ANCSDNA::CSKRType cskr;
        pakRouter.lookupAndReadDNA(info.cskr, cskr);
        typename ANCSDNA::CINFType cinf;
        pakRouter.lookupAndReadDNA(info.cinf, cinf);
        using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
        RigPair rigPair(&cskr, &cinf);

        PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
        DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>(
            conn, rs, pakRouter, *cmdlE, dataspec, rigPair);

        conn.saveBlend();
      }
    }
  }

  /* Extract attachment CMDL/CSKRs first */
  auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
  for (auto it = attRange.first; it != attRange.second; ++it) {
    auto cmdlid = it->second.first.second;

    const nod::Node* node;
    const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, &node, true, false);
    if (cmdlE) {
      hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
      if (force || cmdlPath.isNone()) {
        cmdlPath.makeDirChain(false);
        if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
          return false;

        std::string bestName = pakRouter.getBestEntryName(*cmdlE);
        hecl::SystemStringConv bestNameView(bestName);
        fileChanged(bestNameView.c_str());

        const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid);
        typename ANCSDNA::CSKRType cskr;
        pakRouter.lookupAndReadDNA(rp->first, cskr);
        typename ANCSDNA::CINFType cinf;
        pakRouter.lookupAndReadDNA(rp->second, cinf);
        using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
        RigPair rigPair(&cskr, &cinf);

        PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
        DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>(
            conn, rs, pakRouter, *cmdlE, dataspec, rigPair);

        conn.saveBlend();
      }
    }
  }

  std::string bestName = pakRouter.getBestEntryName(entry);
  hecl::SystemStringConv bestNameView(bestName);
  fileChanged(bestNameView.c_str());

  /* Establish ANCS blend */
  if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor))
    return false;

  std::string firstName;
  typename ANCSDNA::CINFType firstCinf;
  {
    hecl::blender::PyOutStream os = conn.beginPythonOut(true);

    os.format(
        "import bpy\n"
        "from mathutils import Vector\n"
        "bpy.context.scene.name = '%s'\n"
        "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
        "\n"
        "# Using 'Blender Game'\n"
        "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
        "\n"
        "# Clear Scene\n"
        "for ob in bpy.data.objects:\n"
        "    if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
        "        bpy.context.scene.objects.unlink(ob)\n"
        "        bpy.data.objects.remove(ob)\n"
        "\n"
        "actor_data = bpy.context.scene.hecl_sact_data\n"
        "arm_obj = None\n",
        pakRouter.getBestEntryName(entry).c_str());

    std::unordered_set<typename PAKRouter::IDType> cinfsDone;
    for (const auto& info : chResInfo) {
      /* Provide data to add-on */
      os.format(
          "actor_subtype = actor_data.subtypes.add()\n"
          "actor_subtype.name = '%s'\n\n",
          info.name.c_str());

      /* Build CINF if needed */
      if (cinfsDone.find(info.cinf) == cinfsDone.end()) {
        typename ANCSDNA::CINFType cinf;
        pakRouter.lookupAndReadDNA(info.cinf, cinf);
        cinf.sendCINFToBlender(os, info.cinf);
        if (cinfsDone.empty()) {
          firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf);
          firstCinf = cinf;
        }
        cinfsDone.insert(info.cinf);
      } else
        os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
      os << "actor_subtype.linked_armature = arm_obj.name\n";

      /* Link CMDL */
      const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, false);
      if (cmdlE) {
        hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
        os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);

        /* Attach CMDL to CINF */
        os << "if obj.name not in bpy.context.scene.objects:\n"
              "    bpy.context.scene.objects.link(obj)\n"
              "obj.parent = arm_obj\n"
              "obj.parent_type = 'ARMATURE'\n"
              "actor_subtype.linked_mesh = obj.name\n\n";
      }

      /* Link overlays */
      for (const auto& overlay : info.overlays) {
        os << "overlay = actor_subtype.overlays.add()\n";
        os.format("overlay.name = '%s'\n", overlay.first.c_str());

        /* Link CMDL */
        const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, false);
        if (cmdlE) {
          hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
          os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);

          /* Attach CMDL to CINF */
          os << "if obj.name not in bpy.context.scene.objects:\n"
                "    bpy.context.scene.objects.link(obj)\n"
                "obj.parent = arm_obj\n"
                "obj.parent_type = 'ARMATURE'\n"
                "overlay.linked_mesh = obj.name\n\n";
        }
      }
    }

    /* Link attachments */
    for (auto it = attRange.first; it != attRange.second; ++it) {
      os << "attachment = actor_data.attachments.add()\n";
      os.format("attachment.name = '%s'\n", it->second.second.c_str());

      auto cinfid = it->second.first.first;
      auto cmdlid = it->second.first.second;

      if (cinfid) {
        /* Build CINF if needed */
        if (cinfsDone.find(cinfid) == cinfsDone.end()) {
          typename ANCSDNA::CINFType cinf;
          pakRouter.lookupAndReadDNA(cinfid, cinf);
          cinf.sendCINFToBlender(os, cinfid);
          if (cinfsDone.empty()) {
            firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid);
            firstCinf = cinf;
          }
          cinfsDone.insert(cinfid);
        } else
          os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str());
        os << "attachment.linked_armature = arm_obj.name\n";
      }

      /* Link CMDL */
      const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, nullptr, true, false);
      if (cmdlE) {
        hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
        os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);

        /* Attach CMDL to CINF */
        os << "if obj.name not in bpy.context.scene.objects:\n"
              "    bpy.context.scene.objects.link(obj)\n"
              "obj.parent = arm_obj\n"
              "obj.parent_type = 'ARMATURE'\n"
              "attachment.linked_mesh = obj.name\n\n";
      }
    }
  }

  {
    hecl::blender::DataStream ds = conn.beginData();
    std::unordered_map<std::string, hecl::blender::Matrix3f> matrices = ds.getBoneMatrices(firstName);
    ds.close();
    DNAANIM::RigInverter<typename ANCSDNA::CINFType> inverter(firstCinf, matrices);

    hecl::blender::PyOutStream os = conn.beginPythonOut(true);
    os << "import bpy\n"
          "actor_data = bpy.context.scene.hecl_sact_data\n";

    /* Get animation primitives */
    std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
    ancs.getAnimationResInfo(&pakRouter, animResInfo);
    for (const auto& id : animResInfo) {
      typename ANCSDNA::ANIMType anim;
      if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) {
        os.format(
            "act = bpy.data.actions.new('%s')\n"
            "act.use_fake_user = True\n",
            id.second.name.c_str());
        anim.sendANIMToBlender(os, inverter, id.second.additive);
      }

      os.format(
          "actor_action = actor_data.actions.add()\n"
          "actor_action.name = '%s'\n",
          id.second.name.c_str());

      /* Extract EVNT if present */
      anim.extractEVNT(id.second, outPath, pakRouter, force);
    }
  }
  conn.saveBlend();
  return true;
}
示例#12
0
void Material::SectionPASS::constructNode(hecl::BlenderConnection::PyOutStream& out,
                                          const PAKRouter<PAKBridge>& pakRouter,
                                          const PAK::Entry& entry,
                                          const Material::ISection* prevSection,
                                          unsigned idx,
                                          unsigned& texMapIdx,
                                          unsigned& texMtxIdx,
                                          unsigned& kColorIdx) const
{
    /* Add Texture nodes */
    if (txtrId)
    {
        std::string texName = pakRouter.getBestEntryName(txtrId);
        const nod::Node* node;
        const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node);
        hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
        if (txtrPath.getPathType() == hecl::ProjectPath::Type::None)
        {
            PAKEntryReadStream rs = texEntry->beginReadStream(*node);
            TXTR::Extract(rs, txtrPath);
        }
        hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId);
        hecl::SystemUTF8View resPathView(resPath);
        out.format("if '%s' in bpy.data.textures:\n"
                   "    image = bpy.data.images['%s']\n"
                   "    texture = bpy.data.textures[image.name]\n"
                   "else:\n"
                   "    image = bpy.data.images.load('''//%s''')\n"
                   "    image.name = '%s'\n"
                   "    texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
                   "    texture.image = image\n"
                   "tex_maps.append(texture)\n"
                   "\n", texName.c_str(), texName.c_str(),
                   resPathView.str().c_str(), texName.c_str());
        if (uvAnim.size())
        {
            const UVAnimation& uva = uvAnim[0];
            DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx, texMapIdx++);
            DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals);
        }
        else
            DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++);
    }

    /* Special case for RFLV (environment UV mask) */
    if (Subtype(subtype.toUint32()) == Subtype::RFLV)
    {
        if (txtrId)
            out << "rflv_tex_node = texture_nodes[-1]\n";
        return;
    }

    /* Add PASS node */
    bool linkRAS = false;
    out << "prev_pnode = pnode\n"
           "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n";
    switch (Subtype(subtype.toUint32()))
    {
    case Subtype::DIFF:
    {
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n";
        if (txtrId)
        {
            out << "new_material.hecl_lightmap = texture.name\n"
                << "texture.image.use_fake_user = True\n";
        }
        linkRAS = true;
        break;
    }
    case Subtype::RIML:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n";
        if (idx == 0)
            linkRAS = true;
        break;
    case Subtype::BLOL:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n";
        if (idx == 0)
            linkRAS = true;
        break;
    case Subtype::BLOD:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n";
        if (idx == 0)
            linkRAS = true;
        break;
    case Subtype::CLR:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n";
        if (idx == 0)
            linkRAS = true;
        break;
    case Subtype::TRAN:
        if (flags.TRANInvert())
            out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRANInv']\n";
        else
            out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n";
        break;
    case Subtype::INCA:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n";
        break;
    case Subtype::RFLV:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n";
        break;
    case Subtype::RFLD:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n"
               "if rflv_tex_node:\n"
               "    new_nodetree.links.new(rflv_tex_node.outputs['Color'], pnode.inputs['Mask Color'])\n"
               "    new_nodetree.links.new(rflv_tex_node.outputs['Value'], pnode.inputs['Mask Alpha'])\n";
        break;
    case Subtype::LRLD:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n";
        break;
    case Subtype::LURD:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n";
        break;
    case Subtype::BLOI:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n";
        break;
    case Subtype::XRAY:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n";
        break;
    case Subtype::TOON:
        out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n";
        break;
    default: break;
    }
    out << "gridder.place_node(pnode, 2)\n";

    if (txtrId)
    {
        out << "new_nodetree.links.new(texture_nodes[-1].outputs['Color'], pnode.inputs['Tex Color'])\n"
               "new_nodetree.links.new(texture_nodes[-1].outputs['Value'], pnode.inputs['Tex Alpha'])\n";
    }

    if (linkRAS)
        out << "new_nodetree.links.new(material_node.outputs['Color'], pnode.inputs['Prev Color'])\n"
               "new_nodetree.links.new(material_node.outputs['Alpha'], pnode.inputs['Prev Alpha'])\n";
    else if (prevSection)
    {
        if (prevSection->m_type == ISection::Type::PASS &&
            Subtype(static_cast<const SectionPASS*>(prevSection)->subtype.toUint32()) != Subtype::RFLV)
            out << "new_nodetree.links.new(prev_pnode.outputs['Next Color'], pnode.inputs['Prev Color'])\n"
                   "new_nodetree.links.new(prev_pnode.outputs['Next Alpha'], pnode.inputs['Prev Alpha'])\n";
        else if (prevSection->m_type == ISection::Type::CLR)
            out << "new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], pnode.inputs['Prev Color'])\n"
                   "new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], pnode.inputs['Prev Alpha'])\n";
    }

    /* Row Break in gridder */
    out << "gridder.row_break(2)\n";
}
示例#13
0
 void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
 {
     if (particle1)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1);
         ent->name = name + "_part1";
     }
     if (particle2)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2);
         ent->name = name + "_part2";
     }
     if (particle3)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3);
         ent->name = name + "_part3";
     }
     if (particle4)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4);
         ent->name = name + "_part4";
     }
     if (particle5)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5);
         ent->name = name + "_part5";
     }
     if (particle6)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6);
         ent->name = name + "_part6";
     }
     if (particle7)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7);
         ent->name = name + "_part7";
     }
     if (elsc)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc);
         ent->name = name + "_elsc";
     }
     if (model1)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1);
         ent->name = name + "_model1";
     }
     if (model2)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2);
         ent->name = name + "_model2";
     }
     if (skin)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(skin);
         ent->name = name + "_skin";
     }
     if (rig)
     {
         PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(rig);
         ent->name = name + "_rig";
     }
     patternedInfo.nameIDs(pakRouter, name + "_patterned");
     actorParameters1.nameIDs(pakRouter, name + "_actp1");
     actorParameters2.nameIDs(pakRouter, name + "_actp2");
     animationParameters.nameANCS(pakRouter, name + "_animp");
 }