pretty simple just allows for the easy removal of junk before you want to save runtimes or publish your game etc.
you should make a new save before running this script as it WILL remove any documentation and it will delete all textblocks with out game-engine-users aka anything not linked up or active to a controller block, or filter2d logic block.
import bpy
import os
import re
def process_text_block(text_block):
comment_pattern = r'#[^\n]*'
docstring_pattern = r'""".*?"""|\'\'\'.*?\'\'\''
print_pattern = r'print\(.*?\)'
new_lines = []
for line in text_block.lines:
line.body = re.sub(comment_pattern, '', line.body)
line.body = re.sub(docstring_pattern, '', line.body, flags=re.DOTALL)
line.body = re.sub(print_pattern, 'pass', line.body)
line.body = line.body.replace("pass)","pass")
line.body = line.body.replace("pass(","pass")
line.body = line.body.replace("pass,","pass")
new_lines.append(line.body)
text_block.clear()
text_block.write("\n".join(new_lines))
os.system("cls")
GameUsers = set()
AllBpyTextNames = set(T.name for T in bpy.data.texts)
for Scene in bpy.data.scenes:
for obj in Scene.objects:
if obj.game:
for sensor in obj.game.sensors:
if sensor.active:
for controller in sensor.controllers:
if controller.active and controller.type == 'PYTHON' and controller.text:
TxtContains = list(controller.text.lines)
for Line in TxtContains:
if "import" in Line.body or "from" in Line.body:
if Line.body.split()[1]+'.py' in AllBpyTextNames:
GameUsers.add(Line.body.split()[1]+'.py')
GameUsers.add(controller.text.name)
for actuator in controller.actuators:
if actuator.active and actuator.type == "FILTER_2D" and actuator.glsl_shader:
GameUsers.add(actuator.glsl_shader.name)
ScriptsName = bpy.context.space_data.text.name
for text in bpy.data.texts:
if text.name not in GameUsers and text.name != ScriptsName:
bpy.data.texts.remove(bpy.data.texts[text.name], do_unlink=True)
for text in bpy.data.texts:
if '.glsl' not in text.name and text.name != ScriptsName:
process_text_block(text)
#for 2.78a+
#Find Game-Users, delete files that are non Game-Users and modify files to remove
#documentation and print statements.
#▼ this is a workable method,
import bpy
import os
import re
os.system("cls")
GameUsers = []
AllBpyTextNames = [];
for T in bpy.data.texts:
AllBpyTextNames.append(T.name)
print(AllBpyTextNames)
# Iterate over all objects in the current scene
for Scene in bpy.data.scenes:
for obj in Scene.objects:
# Check if the object has a game engine logic
if obj.game:
# Iterate over all sensors in the object's game engine logic
for sensor in obj.game.sensors:
# Check if the sensor is active
if sensor.active:
# Iterate over all controllers linked to the active sensor
for controller in sensor.controllers:
SkipCheck = False;
# Check if the controller is active
if controller.active:
# If the controller is a Python controller and has a text block assigned
if controller.type == 'PYTHON' and controller.text:
SkipCheck = True;
TxtContains = list(controller.text.lines);
for Line in TxtContains:
if "import" in Line.body or "from" in Line.body:
if Line.body.split()[1]+'.py' in AllBpyTextNames: #to avoid adding stuff like "bge.py" or "math.py"
GameUsers.append(Line.body.split()[1]+'.py')#I think I did this right.
for CA in controller.actuators:
#print(CA.name in Line.body)
if CA.name in Line.body:
SkipCheck = False;
print([controller.text.name, controller])
GameUsers.append(controller.text.name)
#and make it check if its a python-controller that is linked to a actuator
#then if it doesn't contain the actuator in the text it will skip this check:
if SkipCheck == True:
# Iterate over all actuators linked to the active controller
for actuator in controller.actuators:
# Check if the actuator is active
if actuator.active:
# If the actuator is of type "FILTER_2D" and has a GLSL shader
if actuator.type == "FILTER_2D" and actuator.glsl_shader:
print([actuator.glsl_shader.name, actuator])
GameUsers.append(actuator.glsl_shader.name)
print("GameUsers",GameUsers)
TextNames = []
TextGamesUsers = {}
texts = bpy.data.texts
for text in texts:
TextNames.append(text.name)
print("TextNames",TextNames)
for I in GameUsers:
print('i',I,GameUsers.count(I))
TextGamesUsers[I] = GameUsers.count(I)
for text in texts:
if text.name not in TextGamesUsers:
TextGamesUsers[text.name] = 0;
os.system("cls")
ScriptsName = bpy.context.space_data.text.name;
print("Self Name :: ScriptsName",ScriptsName)
for NamedGameUsers in TextGamesUsers:
if TextGamesUsers[NamedGameUsers] == 0:
if not (NamedGameUsers == ScriptsName):
#We need to be *very* careful here:
bpy.data.texts.remove(bpy.data.texts[NamedGameUsers],do_unlink=True)
print(NamedGameUsers)
#Everything else needs to be processed like so:
#Removes documentation and print statements.
# Define the function to process a file
def process_text_block(text_block):
# Regular expression patterns for comments, docstrings and print statements
comment_pattern = r'#[^\n]*'
docstring_pattern = r'""".*?"""|\'\'\'.*?\'\'\''
print_pattern = r'print\(.*?\)'
new_lines = []
for line in text_block.lines:
# Remove comments and docstrings
line.body = re.sub(comment_pattern, '', line.body)
line.body = re.sub(docstring_pattern, '', line.body, flags=re.DOTALL)
# Replace print statements with pass
line.body = re.sub(print_pattern, 'pass', line.body) #<- this doesn't always work sometimes leaving a ')' behind after a pass statement where a print statement originally was.
line.body = line.body.replace("pass)","pass");
line.body = line.body.replace("pass(","pass");
line.body = line.body.replace("pass,","pass");
new_lines.append(line.body)
# Replace the text block's lines with the new lines
text_block.clear()
text_block.write("\n".join(new_lines))
# Process all the remaining text blocks
for text in bpy.data.texts:
if '.glsl' not in text.name and text.name != ScriptsName:
print(text.name)
# Process the text block
process_text_block(text)
a non optimized version of the original ^ in case it has problems.
1 Like