Note: Please don't quote this whole post if you reply to it. Thanks.
Edit: Just when I thought I had everything figured out... I tested some things out and realize you still need the initial square as a "mask", so the anomalies created by the edges don't "leak out" too far.
It seems a counterclockwise square works just fine.
So after a bunch of Google searching and trial and error I FINALLY came up with a Blender (Franken) script that will export the coordinates of a plane to a .binary file that can be read by S4S.
This is in no way a replacement for a batch fix, but instead its here for content creators or people with a limited CC (unless the batch fix will also include auto model cutout creation?)
This would probably be better placed in the Tutorial forum but I don't have permission to post there.
(If there's anyone that is much better at coding sees anything that could be cleaned up in the code I would be most grateful for any modifications.)
1. Export an LOD.blend from S4S, or open the LOD.blend you are working on.
2. Enable Blender debug so you can see the numbers given to the vertices.
import bpy
bpy.app.debug = True
Diagram:
1a. Change window into text editor
1b. Create new text file. You can rename it if you want.
1c. Paste the script.
1d. Run script
2. Alternatively you can paste or write the script in the console. Making the bottom window a console is the same step as 1a. except you select "Python Console".
3. In Edit Mode, check Indices. Now the window will display the number on each selected vertex.
(Number color can be changed at User Preferences...--> Themes --> 3d View --> Face Angle Text)
(As you can see, the window model actually already has a plane with vertices in the correct order, so that could actually be used as your base for the cutout instead of creating a new shape. You can skip to step 7 to export your edited plane.)
3.You will now need to create a circle since a plane doesn't number the vertices in order.
In Object Mode, Align the window to Front Ortho (Numpad 1, Numpad5), and create a circle (Shift+A) with the desired amount of vertices, selecting "Align to view" from the left panel.
4. In Edit Mode you will need to select Indices again to see the edges.
(As you can see the numbers go counter clockwise and are in order.)
5. You can do further tweaking of the circle by dissolving vertices. The order will not be affected.
6. Rearrange the vertices as desired.
7. You will now need to follow step 2 again to paste and run this script.
(Take note that you can also copy and paste this script, creating your own .txt file, then open it in the Text Editor window so you won't need to reference this page for the script.)
It will create a ModelCutout.binary file in the same place your LOD.blend file is located.
You will need to create 2 plane meshes:
1. Initial square bounds
2. The shape of the window within those bounds.
(You only need to export a square window once. While I think all you need is the initial four edges, you can always import it twice into S4S just in case.)
Both scripts are exactly the same except for the name of the file.
ModelCutoutShape.binary
import bpy
from bpy import context
import struct
import os,sys
import bmesh
ob = bpy.context.object
me = ob.data
if ob.mode == 'EDIT':
bpy.ops.object.editmode_toggle()
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
current_obj = bpy.context.active_object
verts_local = [v.co for v in current_obj.data.vertices.values()]
verts_world = [current_obj.matrix_world * v_local for v_local in verts_local]
# write to file
f2 = open(bpy.path.abspath("//ModelCutoutShape.binary"), "wb")
#X,Z,Y
for v in me.vertices:
vertex = me.vertices
v = v.co
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
#Selects Vertex 0
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.mesh.select_all(action = 'DESELECT')
bpy.ops.object.mode_set(mode = 'OBJECT')
obj.data.vertices[0].select = True
bpy.ops.object.mode_set(mode = 'EDIT')
# Get a BMesh representation
bm = bmesh.from_edit_mesh(me)
bm.faces.active = None
#X,Z,Y - Vertex 0
for v in bm.verts:
if v.select:
v = v.co
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
# Opens and writes header to top of file
f2 = open(bpy.path.abspath("//ModelCutoutShape.binary"), "wb")
#Header - Type and Version
f2.write(b'\x17\x6A\x57\x07\x01\x00\x00\x00')
#Header - Number of edges
f2.write(struct.pack('<i', len(me.vertices)))
f2.close()
ModelCutoutSquareBoundary.binary
import bpy
from bpy import context
import struct
import os,sys
import bmesh
ob = bpy.context.object
me = ob.data
if ob.mode == 'EDIT':
bpy.ops.object.editmode_toggle()
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
current_obj = bpy.context.active_object
verts_local = [v.co for v in current_obj.data.vertices.values()]
verts_world = [current_obj.matrix_world * v_local for v_local in verts_local]
# write to file
f2 = open(bpy.path.abspath("//ModelCutoutSquareBoundary.binary"), "wb")
#X,Z,Y
for v in me.vertices:
vertex = me.vertices
v = v.co
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
#Selects Vertex 0
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.mesh.select_all(action = 'DESELECT')
bpy.ops.object.mode_set(mode = 'OBJECT')
obj.data.vertices[0].select = True
bpy.ops.object.mode_set(mode = 'EDIT')
# Get a BMesh representation
bm = bmesh.from_edit_mesh(me)
bm.faces.active = None
#X,Z,Y - Vertex 0
for v in bm.verts:
if v.select:
v = v.co
f2.write(struct.pack('<'+'fff', v[0], v[2], 0.0))
# Opens and writes header to top of file
f2 = open(bpy.path.abspath("//ModelCutoutSquareBoundary.binary"), "wb")
#Header - Type and Version
f2.write(b'\x17\x6A\x57\x07\x01\x00\x00\x00')
#Header - Number of edges
f2.write(struct.pack('<i', len(me.vertices)))
f2.close()
8. In S4S Edit Edges, Clear, and Save.
9. Right click the first Model Cutout and Import the ModelCutoutSquareBoundary.binary and then ModelCutoutShape.binary
10. Save and test in game.