Last active
November 6, 2018 08:59
-
-
Save fwilleke80/3030563798ce405067710b7ed2f2b785 to your computer and use it in GitHub Desktop.
Put this script into "Cinema 4D Rx/plugins" and run it from the command line to find free resource IDs for a plugin in a certain module. Call with "-h" command line option to get help.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# | |
# Example calls: | |
# | |
# python getc4dresid.py --module lbwss --plugin osurfacespread | |
# Get some free resource IDs from plugin "Osurfacespread" in module "lbwss" | |
# | |
# python getc4dresid.py --module cinea4dsdk --plugin oatom --limit 1 | |
# Get the next free resource ID from plugin "Oatom" in module "cinema4dsdk" | |
# | |
import os | |
import optparse | |
import logging | |
# Script info | |
SCRIPTTITLE = 'Get next free resource ID of C4D plugin' | |
SCRIPTVERSION = '0.3' | |
SCRIPTCOPYRIGHT = '2018 by Frank Willeke' | |
# Logging | |
LOGLEVEL = logging.INFO | |
LOGFILE = 'getc4dresid.log' | |
LOGFORMAT = '%(levelname)s: %(message)s' | |
LOGFILEFORMAT = '%(asctime)s: %(levelname)s: %(message)s' | |
log = logging.getLogger('log') | |
# Parse header file and return a list of all contained IDs | |
def ParseHeaderFile(filename): | |
foundIds = [] | |
with open(filename, "r") as headerFile: | |
for line in headerFile: | |
line = line.strip() | |
beginPos = line.find('=') + 1 | |
resId = line[beginPos:] | |
resId = ''.join(c for c in resId.strip() if c.isdigit()) | |
if resId: | |
foundIds.append(int(resId)) | |
return foundIds | |
# Analyze list of resource IDs and return the distilled information | |
def AnalyzeIds(resourceIds, threshold): | |
if resourceIds is None or len(resourceIds) < 1: | |
raise AttributeError('List resourceIds did not contain any resource IDs') | |
idSmallest = min(resourceIds) | |
idsOverThreshold = [x for x in resourceIds if x > threshold] | |
idSmallestOverThreshold = min(idsOverThreshold) | |
idLargest = max(resourceIds) | |
idFreeRange = idLargest + 1 | |
idFreeIntermediates = [i for i in range(idSmallestOverThreshold, idLargest) if i not in resourceIds] | |
return (idSmallest, idSmallestOverThreshold, idLargest, idFreeIntermediates, idFreeRange) | |
# Set up command line argument options for main script | |
def ParseArgs(parser): | |
parser.add_option("-m", "--module", type="string", dest="modulename", default=None, metavar="MODULENAME", help="Name of module (e.g. 'lbwss' or 'cinema4dsdk')") | |
parser.add_option("-p", "--plugin", type="string", dest="pluginname", default=None, metavar="PLUGINNAME", help="Resource symbol name of plugin in this module (e.g. 'osurfacespread', 'xroadshader' or 'oatom')") | |
parser.add_option("-t", "--threshold", type="int", dest="threshold", default=10000, metavar="THRESHOLD", help="Only list IDs as free if > THRESHOLD (default=20000)") | |
parser.add_option("-l", "--limit", type="int", dest="limit", default=10, metavar="LIMIT", help="Only list LIMIT free ids (default=10)") | |
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="More output") | |
options, args = parser.parse_args() | |
return options, args | |
# Set log preferences | |
def SetupLogging(): | |
log.setLevel(LOGLEVEL) | |
logHandler = logging.StreamHandler() | |
logHandler.setLevel(LOGLEVEL) | |
logFormat = logging.Formatter(LOGFORMAT) | |
logHandler.setFormatter(logFormat) | |
log.addHandler(logHandler) | |
logFileHandler = logging.FileHandler(LOGFILE) | |
logFileHandler.setLevel(LOGLEVEL) | |
logFormat = logging.Formatter(LOGFILEFORMAT) | |
logFileHandler.setFormatter(logFormat) | |
log.addHandler(logFileHandler) | |
# Main function | |
def main(): | |
# Setup logger and modules | |
SetupLogging() | |
# Setup args, then parse | |
parser = optparse.OptionParser() | |
options, args = ParseArgs(parser) | |
optModulename = options.modulename.lower() | |
optPluginname = options.pluginname.lower() | |
optThreshold = options.threshold | |
optLimit = options.limit | |
optVerbose = options.verbose | |
log.debug("options: " + str(options)) | |
scriptTitle = SCRIPTTITLE + ' ' + SCRIPTVERSION | |
# Title | |
if optVerbose: | |
print('+-------------------------------------------------------') | |
print('| ' + scriptTitle) | |
print('|') | |
print('| ' + SCRIPTCOPYRIGHT) | |
print('+-------------------------------------------------------') | |
print('') | |
else: | |
print(scriptTitle) | |
print('-' * len(scriptTitle)) | |
print('') | |
# Check if all required options are set | |
if not optModulename : | |
log.error("No module name specified! Try the name of a subfolder in Cinema's plugin folder!") | |
return | |
if not optPluginname: | |
log.error("No plugin name specified! Try the resource name of a plugin in this module!") | |
return | |
# Find module directory | |
currentDir = os.getcwd() | |
moduleDir = os.path.join(currentDir, optModulename) | |
log.debug('Module path: ' + moduleDir) | |
if not os.path.exists(moduleDir): | |
log.error('Module folder "' + moduleDir + '" not found!') | |
# Find plugin resource | |
pluginResourceHeaderFile = os.path.join(moduleDir, "res", "description", optPluginname + '.h') | |
log.debug('Plugin resource header: ' + pluginResourceHeaderFile) | |
if not os.path.exists(pluginResourceHeaderFile): | |
log.error('Plugin resource header file "' + pluginResourceHeaderFile + '" not found!') | |
# Get all resource Ids from header file | |
resourceIds = ParseHeaderFile(pluginResourceHeaderFile) | |
# Analyze list of resource IDs, get some info | |
(smallestId, idSmallestOverThreshold, largestId, freeIntermediateIds, freeUpRangeId) = AnalyzeIds(resourceIds, optThreshold) | |
# Avoid errors | |
if freeIntermediateIds is None or len(freeIntermediateIds) == 0: | |
freeIntermediateIds = None | |
# Print results | |
if options.verbose: | |
log.info('Analyzed header file ' + str(pluginResourceHeaderFile)) | |
log.info('Found ' + str(len(resourceIds)) + ' IDs') | |
log.info('===========================') | |
log.info('Smallest: ' + str(smallestId)) | |
log.info('Smallest > ' + str(optThreshold) + ': ' + str(idSmallestOverThreshold)) | |
log.info('Largest: ' + str(largestId)) | |
print('') | |
log.info('First ID of free range: ' + str(freeUpRangeId)) | |
log.info('Free intermediate IDs: ' + str(freeIntermediateIds[:optLimit])) | |
print('') | |
if freeIntermediateIds is not None: | |
log.info('You can choose any of the free intermediate IDs (e.g. ' + str(freeIntermediateIds[0]) + ')') | |
log.info('If you likke your IDs less fragmented, or if you need lots of IDs, I suggest you use ' + str(freeUpRangeId)) | |
else: | |
log.info('You can choose any ID, starting with ' + str(freeUpRangeId)) | |
else: | |
if freeIntermediateIds is not None: | |
if optLimit == 1: | |
log.info('Next free ID: ' + str(freeIntermediateIds[0])) | |
else: | |
log.info('Free intermediate IDs: ' + str(freeIntermediateIds[:optLimit])) | |
log.info('Free range starts with: ' + str(freeUpRangeId)) | |
# Kick off the shit... | |
if __name__=='__main__': | |
try: | |
print '' | |
main() | |
print '' | |
except KeyboardInterrupt: | |
log.error('Cancelled') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment