Skip to content

Instantly share code, notes, and snippets.

@fwilleke80
Last active November 6, 2018 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fwilleke80/3030563798ce405067710b7ed2f2b785 to your computer and use it in GitHub Desktop.
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.
#!/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