1 module creator.io.inpexport; 2 import creator.atlas; 3 import creator.ext; 4 import inochi2d; 5 6 private { 7 vec2 mapUVCoord(vec2 value, vec2 min, vec2 max) { 8 vec2 range = max - min; 9 vec2 tmp = (value - min); 10 vec2 off = vec2(tmp.x / range.x, tmp.y / range.y); 11 12 vec2 clamped = vec2( 13 clamp(off.x, 0, 1), 14 clamp(off.y, 0, 1), 15 ); 16 return clamped; 17 } 18 } 19 20 void incExportINP(Puppet origin, Atlas[] atlasses, string file) { 21 Puppet editable = inLoadINPPuppet(inWriteINPPuppetMemory(origin)); 22 23 // Apply all atlasses 24 foreach(Part part; editable.getAllParts()) { 25 foreach(Atlas atlas; atlasses) { 26 27 // Look for our part in the atlas 28 if (part.uuid in atlas.mappings) { 29 30 // This will remap the UV coordinates of the part 31 // To 0..1 range if need be. 32 vec2[] uvs = part.getMesh().uvs.dup; 33 vec4 uvArea = vec4(1, 1, 0, 0); 34 foreach(vec2 uv; uvs) { 35 if (uv.x < uvArea.x) uvArea.x = uv.x; 36 if (uv.y < uvArea.y) uvArea.y = uv.y; 37 if (uv.x > uvArea.z) uvArea.z = uv.x; 38 if (uv.y > uvArea.w) uvArea.w = uv.y; 39 } 40 vec2 minUV = uvArea.xy; 41 vec2 maxUV = uvArea.zw; 42 foreach(ref uv; uvs) uv = uv.mapUVCoord(minUV, maxUV); 43 44 // Now we need to scale those UV coordinates to fit within the mapping 45 float atlasSize = cast(float)atlas.textures[0].width; 46 rect mapping = atlas.mappings[part.uuid]; 47 foreach(ref uv; uvs) { 48 uv.x = (mapping.x+(uv.x*mapping.width))/atlasSize; 49 uv.y = (mapping.y+(uv.y*mapping.height))/atlasSize; 50 } 51 52 // Apply our UVs 53 part.getMesh().uvs = uvs; 54 55 // Finally apply our atlas textures to the part 56 foreach(i; 0..TextureUsage.COUNT) { 57 part.textures[i] = atlas.textures[i]; 58 } 59 60 break; 61 } 62 } 63 } 64 65 // Flatten all parameter groups 66 Parameter[] params; 67 foreach(i, ref param; editable.parameters) { 68 import std.array : insertInPlace; 69 if (auto group = cast(ExParameterGroup)param) params ~= group.children; 70 else params ~= param; 71 } 72 editable.parameters = params; 73 74 // Remove cameras 75 foreach(ref camera; editable.findNodesType!ExCamera(editable.root)) { 76 camera.parent = null; 77 } 78 79 editable.populateTextureSlots(); 80 inWriteINPPuppet(editable, file); 81 }