+ # Cache USBCode Assignment
+ def cacheAssignment( self, operator, scanCode, result ):
+ self.assignmentCache.append( [ operator, scanCode, result ] )
+
+ # Assign cached USBCode Assignments
+ def replayCachedAssignments( self ):
+ # Iterate over each item in the assignment cache
+ for item in self.assignmentCache:
+ # Check operator, and choose the specified assignment action
+ # Append Case
+ if item[0] == ":+":
+ self.appendScanCode( item[1], item[2] )
+
+ # Remove Case
+ elif item[0] == ":-":
+ self.removeScanCode( item[1], item[2] )
+
+ # Replace Case
+ elif item[0] == ":":
+ self.replaceScanCode( item[1], item[2] )
+
+ # Clear assignment cache
+ self.assignmentCache = []
+
+ # Generate/Correlate Layers
+ def generate( self ):
+ self.generateIndices()
+ self.sortIndexLists()
+ self.generateTriggerLists()
+
+ # Generates Index of Results and Triggers
+ def generateIndices( self ):
+ # Iterate over every trigger result, and add to the resultsIndex and triggersIndex
+ for layer in range( 0, len( self.macros ) ):
+ for trigger in self.macros[ layer ].keys():
+ # Each trigger has a list of results
+ for result in self.macros[ layer ][ trigger ]:
+ # Only add, with an index, if result hasn't been added yet
+ if not result in self.resultsIndex:
+ self.resultsIndex[ result ] = len( self.resultsIndex )
+
+ # Then add a trigger for each result, if trigger hasn't been added yet
+ triggerItem = tuple( [ trigger, self.resultsIndex[ result ] ] )
+ if not triggerItem in self.triggersIndex:
+ self.triggersIndex[ triggerItem ] = len( self.triggersIndex )
+
+ # Sort Index Lists using the indices rather than triggers/results
+ def sortIndexLists( self ):
+ self.resultsIndexSorted = [ None ] * len( self.resultsIndex )
+ # Iterate over the resultsIndex and sort by index
+ for result in self.resultsIndex.keys():
+ self.resultsIndexSorted[ self.resultsIndex[ result ] ] = result
+
+ self.triggersIndexSorted = [ None ] * len( self.triggersIndex )
+ # Iterate over the triggersIndex and sort by index
+ for trigger in self.triggersIndex.keys():
+ self.triggersIndexSorted[ self.triggersIndex[ trigger ] ] = trigger
+
+ # Generates Trigger Lists per layer using index lists
+ def generateTriggerLists( self ):
+ for layer in range( 0, len( self.macros ) ):
+ # Set max scancode to 0xFF (255)
+ # But keep track of the actual max scancode and reduce the list size
+ self.triggerList.append( [ [] ] * 0xFF )
+ self.maxScanCode.append( 0x00 )
+
+ # Iterate through trigger macros to locate necessary ScanCodes and corresponding triggerIndex
+ for trigger in self.macros[ layer ].keys():
+ for variant in range( 0, len( self.macros[ layer ][ trigger ] ) ):
+ # Identify result index
+ resultIndex = self.resultsIndex[ self.macros[ layer ][ trigger ][ variant ] ]
+
+ # Identify trigger index
+ triggerIndex = self.triggersIndex[ tuple( [ trigger, resultIndex ] ) ]
+
+ # Iterate over the trigger to locate the ScanCodes
+ for sequence in trigger:
+ for combo in sequence:
+ # Append triggerIndex for each found scanCode of the Trigger List
+ # Do not re-add if triggerIndex is already in the Trigger List
+ if not triggerIndex in self.triggerList[ layer ][ combo ]:
+ # Append is working strangely with list pre-initialization
+ # Doing a 0 check replacement instead -HaaTa
+ if len( self.triggerList[ layer ][ combo ] ) == 0:
+ self.triggerList[ layer ][ combo ] = [ triggerIndex ]
+ else:
+ self.triggerList[ layer ][ combo ].append( triggerIndex )
+
+ # Look for max Scan Code
+ if combo > self.maxScanCode[ layer ]:
+ self.maxScanCode[ layer ] = combo
+
+ # Shrink triggerList to actual max size
+ self.triggerList[ layer ] = self.triggerList[ layer ][ : self.maxScanCode[ layer ] + 1 ]
+
+ # Calculate first scan code for layer, useful for uC implementations trying to save RAM
+ firstScanCode = 0
+ for triggerList in range( 0, len( self.triggerList[ layer ] ) ):
+ firstScanCode = triggerList
+
+ # Break if triggerList has items
+ if len( self.triggerList[ layer ][ triggerList ] ) > 0:
+ break;
+ self.firstScanCode.append( firstScanCode )
+
+ # Determine overall maxScanCode
+ self.overallMaxScanCode = 0x00
+ for maxVal in self.maxScanCode:
+ if maxVal > self.overallMaxScanCode:
+ self.overallMaxScanCode = maxVal
+
+
+class Variables:
+ # Container for variables
+ # Stores three sets of variables, the overall combined set, per layer, and per file
+ def __init__( self ):
+ # Dictionaries of variables
+ self.baseLayout = dict()
+ self.fileVariables = dict()
+ self.layerVariables = [ dict() ]
+ self.overallVariables = dict()
+ self.defines = dict()
+
+ self.currentFile = ""
+ self.currentLayer = 0
+ self.baseLayoutEnabled = True
+
+ def baseLayoutFinished( self ):
+ self.baseLayoutEnabled = False
+
+ def setCurrentFile( self, name ):
+ # Store using filename and current layer
+ self.currentFile = name
+ self.fileVariables[ name ] = dict()
+
+ # If still processing BaseLayout
+ if self.baseLayoutEnabled:
+ if '*LayerFiles' in self.baseLayout.keys():
+ self.baseLayout['*LayerFiles'] += [ name ]
+ else:
+ self.baseLayout['*LayerFiles'] = [ name ]
+ # Set for the current layer
+ else:
+ if '*LayerFiles' in self.layerVariables[ self.currentLayer ].keys():
+ self.layerVariables[ self.currentLayer ]['*LayerFiles'] += [ name ]
+ else:
+ self.layerVariables[ self.currentLayer ]['*LayerFiles'] = [ name ]
+
+ def incrementLayer( self ):
+ # Store using layer index
+ self.currentLayer += 1
+ self.layerVariables.append( dict() )
+
+ def assignVariable( self, key, value ):
+ # Overall set of variables
+ self.overallVariables[ key ] = value
+
+ # The Name variable is a special accumulation case
+ if key == 'Name':
+ # BaseLayout still being processed
+ if self.baseLayoutEnabled:
+ if '*NameStack' in self.baseLayout.keys():
+ self.baseLayout['*NameStack'] += [ value ]
+ else:
+ self.baseLayout['*NameStack'] = [ value ]
+ # Layers
+ else:
+ if '*NameStack' in self.layerVariables[ self.currentLayer ].keys():
+ self.layerVariables[ self.currentLayer ]['*NameStack'] += [ value ]
+ else:
+ self.layerVariables[ self.currentLayer ]['*NameStack'] = [ value ]
+
+ # If still processing BaseLayout
+ if self.baseLayoutEnabled:
+ self.baseLayout[ key ] = value
+ # Set for the current layer
+ else:
+ self.layerVariables[ self.currentLayer ][ key ] = value
+
+ # File context variables
+ self.fileVariables[ self.currentFile ][ key ] = value
+