Adding support for adding block types with particular behaviour
authorlbessard
Thu, 23 Aug 2007 09:39:18 +0200
changeset 78 049f2e7090a2
parent 77 346a43f179a5
child 79 b22f661cbcfb
Adding support for adding block types with particular behaviour
PLCGenerator.py
plcopen/structures.py
--- a/PLCGenerator.py	Thu Aug 23 09:26:02 2007 +0200
+++ b/PLCGenerator.py	Thu Aug 23 09:39:18 2007 +0200
@@ -53,6 +53,111 @@
                 compute += "\n"
     return compute
 
+
+def GeneratePouProgram(pou_name):
+    if not pouComputed.get(pou_name, True):
+        pouComputed[pou_name] = True
+        global currentProject, currentProgram
+        pou = currentProject.getPou(pou_name)
+        pou_type = pou.getPouType().getValue()
+        if pou_type in pouTypeNames:
+            pou_program = PouProgram(pou.getName(), pouTypeNames[pou_type])
+        else:
+            raise ValueError, "Undefined pou type"
+        pou_program.GenerateInterface(pou.getInterface())
+        pou_program.GenerateProgram(pou)
+        currentProgram += pou_program.GenerateSTProgram()
+
+def GenerateConfiguration(configuration):
+    config = "\nCONFIGURATION %s\n"%configuration.getName()
+    for varlist in configuration.getGlobalVars():
+        config += "  VAR_GLOBAL"
+        if varlist.getRetain():
+            config += " RETAIN"
+        if varlist.getConstant():
+            config += " CONSTANT"
+        config += "\n"
+        for var in varlist.getVariable():
+            var_type = var.getType().getValue()
+            config += "    %s "%var.getName()
+            address = var.getAddress()
+            if address:
+                config += "AT %s "%address
+            config += ": %s"%var_type
+            initial = var.getInitialValue()
+            if initial:
+                value = str(initial.getValue())
+                value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value)
+                if var_type == "STRING":
+                    config += " := '%s'"%value
+                elif var_type == "WSTRING":
+                    config += " := \"%s\""%value
+                else:
+                    config += " := %s"%value
+            config += ";\n"
+        config += "  END_VAR\n"
+    for resource in configuration.getResource():
+        config += GenerateResource(resource)
+    config += "END_CONFIGURATION\n"
+    return config
+    
+def GenerateResource(resource):
+    resrce = "\n  RESOURCE %s ON BEREMIZ\n"%resource.getName()
+    for varlist in resource.getGlobalVars():
+        resrce += "    VAR_GLOBAL"
+        if varlist.getRetain():
+            resrce += " RETAIN"
+        if varlist.getConstant():
+            resrce += " CONSTANT"
+        resrce += "\n"
+        for var in varlist.getVariable():
+            var_type = var.getType().getValue()
+            resrce += "      %s "%var.getName()
+            address = var.getAddress()
+            if address:
+                resrce += "AT %s "%address
+            resrce += ": %s"%var.getType().getValue()
+            initial = var.getInitialValue()
+            if initial:
+                value = str(initial.getValue())
+                value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value)
+                if var_type == "STRING":
+                    resrce += " := '%s'"%value
+                elif var_type == "WSTRING":
+                    resrce += " := \"%s\""%value
+                else:
+                    resrce += " := %s"%value
+            resrce += ";\n"
+        resrce += "    END_VAR\n"
+    tasks = resource.getTask()
+    for task in tasks:
+        resrce += "    TASK %s("%task.getName()
+        args = []
+        single = task.getSingle()
+        if single:
+            args.append("SINGLE := %s"%single)
+        interval = task.getInterval()
+        if interval:
+            text = "t#"
+            if interval.hour != 0:
+                text += "%dh"%interval.hour
+            if interval.minute != 0:
+                text += "%dm"%interval.minute
+            if interval.second != 0:
+                text += "%ds"%interval.second
+            if interval.microsecond != 0:
+                text += "%dms"%(interval.microsecond / 1000)
+            args.append("INTERVAL := %s"%text)
+        args.append("PRIORITY := %s"%str(task.priority.getValue()))
+        resrce += ",".join(args) + ");\n"
+    for task in tasks:
+        for instance in task.getPouInstance():
+            resrce += "    PROGRAM %s WITH %s : %s;\n"%(instance.getName(), task.getName(), instance.getType())
+    for instance in resource.getPouInstance():
+        resrce += "    PROGRAM %s : %s;\n"%(instance.getName(), instance.getType())
+    resrce += "  END_RESOURCE\n"
+    return resrce
+
 """
 Module implementing methods for generating PLC programs in ST or IL
 """
@@ -120,7 +225,11 @@
                     if connections and len(connections) == 1:
                         expression = self.ComputeFBDExpression(body, connections[0])
                         self.Program += "  %s := %s;\n"%(var, expression)
-                if isinstance(instance, plcopen.connector):
+                elif isinstance(instance, plcopen.block):
+                    type = instance.getTypeName()
+                    block_infos = GetBlockType(type)
+                    block_infos["generate"](self, instance, body, None)
+                elif isinstance(instance, plcopen.connector):
                     connector = instance.getName()
                     if self.ComputedConnectors.get(connector, None):
                         continue 
@@ -161,36 +270,9 @@
         if isinstance(instance, (plcopen.inVariable, plcopen.inOutVariable)):
             return instance.getExpression()
         elif isinstance(instance, plcopen.block):
-            name = instance.getInstanceName()
             type = instance.getTypeName()
             block_infos = GetBlockType(type)
-            if block_infos["type"] == "function":
-                GeneratePouProgram(type)
-                vars = []
-                for variable in instance.inputVariables.getVariable():
-                    connections = variable.connectionPointIn.getConnections()
-                    if connections and len(connections) == 1:
-                        value = self.ComputeFBDExpression(body, connections[0])
-                        vars.append(self.ExtractModifier(variable, value))
-                variable = instance.outputVariables.getVariable()[0]
-                return self.ExtractModifier(variable, "%s(%s)"%(type, ", ".join(vars)))
-            elif block_infos["type"] == "functionBlock":
-                if not self.ComputedBlocks.get(name, False):
-                    vars = []
-                    for variable in instance.inputVariables.getVariable():
-                        connections = variable.connectionPointIn.getConnections()
-                        if connections and len(connections) == 1:
-                            parameter = variable.getFormalParameter()
-                            value = self.ComputeFBDExpression(body, connections[0])
-                            vars.append(self.ExtractModifier(variable, "%s := %s"%(parameter, value)))
-                    self.Program += "  %s(%s);\n"%(name, ", ".join(vars))
-                    self.ComputedBlocks[name] = True
-                connectionPoint = link.getPosition()[-1]
-                for variable in instance.outputVariables.getVariable():
-                    blockPointx, blockPointy = variable.connectionPointOut.getRelPosition()
-                    if instance.getX() + blockPointx == connectionPoint.getX() and instance.getY() + blockPointy == connectionPoint.getY():
-                        return self.ExtractModifier(variable, "%s.%s"%(name, variable.getFormalParameter()))
-                raise ValueError, "No output variable found"
+            return block_infos["generate"](self, instance, body, link)
         elif isinstance(instance, plcopen.continuation):
             name = instance.getName()
             computed_value = self.ComputedConnectors.get(name, None)
@@ -557,109 +639,8 @@
         program += "END_%s\n\n"%self.Type
         return program
 
-def GeneratePouProgram(pou_name):
-    if not pouComputed.get(pou_name, True):
-        pouComputed[pou_name] = True
-        global currentProject, currentProgram
-        pou = currentProject.getPou(pou_name)
-        pou_type = pou.getPouType().getValue()
-        if pou_type in pouTypeNames:
-            pou_program = PouProgram(pou.getName(), pouTypeNames[pou_type])
-        else:
-            raise ValueError, "Undefined pou type"
-        pou_program.GenerateInterface(pou.getInterface())
-        pou_program.GenerateProgram(pou)
-        currentProgram += pou_program.GenerateSTProgram()
-
-def GenerateConfiguration(configuration):
-    config = "\nCONFIGURATION %s\n"%configuration.getName()
-    for varlist in configuration.getGlobalVars():
-        config += "  VAR_GLOBAL"
-        if varlist.getRetain():
-            config += " RETAIN"
-        if varlist.getConstant():
-            config += " CONSTANT"
-        config += "\n"
-        for var in varlist.getVariable():
-            var_type = var.getType().getValue()
-            config += "    %s "%var.getName()
-            address = var.getAddress()
-            if address:
-                config += "AT %s "%address
-            config += ": %s"%var_type
-            initial = var.getInitialValue()
-            if initial:
-                value = str(initial.getValue())
-                value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value)
-                if var_type == "STRING":
-                    config += " := '%s'"%value
-                elif var_type == "WSTRING":
-                    config += " := \"%s\""%value
-                else:
-                    config += " := %s"%value
-            config += ";\n"
-        config += "  END_VAR\n"
-    for resource in configuration.getResource():
-        config += GenerateResource(resource)
-    config += "END_CONFIGURATION\n"
-    return config
-    
-def GenerateResource(resource):
-    resrce = "\n  RESOURCE %s ON BEREMIZ\n"%resource.getName()
-    for varlist in resource.getGlobalVars():
-        resrce += "    VAR_GLOBAL"
-        if varlist.getRetain():
-            resrce += " RETAIN"
-        if varlist.getConstant():
-            resrce += " CONSTANT"
-        resrce += "\n"
-        for var in varlist.getVariable():
-            var_type = var.getType().getValue()
-            resrce += "      %s "%var.getName()
-            address = var.getAddress()
-            if address:
-                resrce += "AT %s "%address
-            resrce += ": %s"%var.getType().getValue()
-            initial = var.getInitialValue()
-            if initial:
-                value = str(initial.getValue())
-                value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value)
-                if var_type == "STRING":
-                    resrce += " := '%s'"%value
-                elif var_type == "WSTRING":
-                    resrce += " := \"%s\""%value
-                else:
-                    resrce += " := %s"%value
-            resrce += ";\n"
-        resrce += "    END_VAR\n"
-    tasks = resource.getTask()
-    for task in tasks:
-        resrce += "    TASK %s("%task.getName()
-        args = []
-        single = task.getSingle()
-        if single:
-            args.append("SINGLE := %s"%single)
-        interval = task.getInterval()
-        if interval:
-            text = "t#"
-            if interval.hour != 0:
-                text += "%dh"%interval.hour
-            if interval.minute != 0:
-                text += "%dm"%interval.minute
-            if interval.second != 0:
-                text += "%ds"%interval.second
-            if interval.microsecond != 0:
-                text += "%dms"%(interval.microsecond / 1000)
-            args.append("INTERVAL := %s"%text)
-        args.append("PRIORITY := %s"%str(task.priority.getValue()))
-        resrce += ",".join(args) + ");\n"
-    for task in tasks:
-        for instance in task.getPouInstance():
-            resrce += "    PROGRAM %s WITH %s : %s;\n"%(instance.getName(), task.getName(), instance.getType())
-    for instance in resource.getPouInstance():
-        resrce += "    PROGRAM %s : %s;\n"%(instance.getName(), instance.getType())
-    resrce += "  END_RESOURCE\n"
-    return resrce
+    def GeneratePouProgram(self, pou_name):
+        GeneratePouProgram(pou_name)
 
 def GenerateCurrentProgram(project):
     global currentProject, currentProgram
--- a/plcopen/structures.py	Thu Aug 23 09:26:02 2007 +0200
+++ b/plcopen/structures.py	Thu Aug 23 09:39:18 2007 +0200
@@ -27,6 +27,40 @@
 
 LANGUAGES = ["IL","ST","FBD","LD","SFC"]
 
+def generate_block(generator, block, body, link):
+    name = block.getInstanceName()
+    type = block.getTypeName()
+    block_infos = GetBlockType(type)
+    if block_infos["type"] == "function" and link:
+        generator.GeneratePouProgram(type)
+        vars = []
+        for variable in block.inputVariables.getVariable():
+            connections = variable.connectionPointIn.getConnections()
+            if connections and len(connections) == 1:
+                value = generator.ComputeFBDExpression(body, connections[0])
+                vars.append(generator.ExtractModifier(variable, value))
+        variable = block.outputVariables.getVariable()[0]
+        return generator.ExtractModifier(variable, "%s(%s)"%(type, ", ".join(vars)))
+    elif block_infos["type"] == "functionBlock":
+        if not generator.ComputedBlocks.get(name, False):
+            vars = []
+            for variable in block.inputVariables.getVariable():
+                connections = variable.connectionPointIn.getConnections()
+                if connections and len(connections) == 1:
+                    parameter = variable.getFormalParameter()
+                    value = generator.ComputeFBDExpression(body, connections[0])
+                    vars.append("%s := %s"%(parameter, generator.ExtractModifier(variable, value)))
+            generator.Program += "  %s(%s);\n"%(name, ", ".join(vars))
+            generator.ComputedBlocks[name] = True
+        if link:
+            connectionPoint = link.getPosition()[-1]
+        else:
+            connectionPoint = None
+        for variable in block.outputVariables.getVariable():
+            blockPointx, blockPointy = variable.connectionPointOut.getRelPosition()
+            if not connectionPoint or block.getX() + blockPointx == connectionPoint.getX() and block.getY() + blockPointy == connectionPoint.getY():
+                return generator.ExtractModifier(variable, "%s.%s"%(name, variable.getFormalParameter()))
+        raise ValueError, "No output variable found"
 
 #-------------------------------------------------------------------------------
 #                        Function Block Types definitions
@@ -42,6 +76,7 @@
     - "inputs" : List of the block inputs
     - "outputs" : List of the block outputs
     - "comment" : Comment that will be displayed in the block popup
+    - "generate" : Method that generator will call for generating ST block code
 Inputs and outputs are a tuple of characteristics that are in order:
     - The name
     - The data type
@@ -52,110 +87,104 @@
                [{"name" : "SR", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], 
                     "outputs" : [("Q1","BOOL","none")],
-                    "comment" : "SR bistable\nThe SR bistable is a latch where the Set dominates."},
+                    "comment" : "SR bistable\nThe SR bistable is a latch where the Set dominates.",
+                    "generate" : generate_block},
                 {"name" : "RS", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], 
                     "outputs" : [("Q1","BOOL","none")],
-                    "comment" : "RS bistable\nThe RS bistable is a latch where the Reset dominates."},
+                    "comment" : "RS bistable\nThe RS bistable is a latch where the Reset dominates.",
+                    "generate" : generate_block},
                 {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], 
                     "outputs" : [("BUSY","BOOL","none")],
-                    "comment" : "Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."},
+                    "comment" : "Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources.",
+                    "generate" : generate_block},
                 {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CLK","BOOL","none")], 
                     "outputs" : [("Q","BOOL","none")],
-                    "comment" : "Rising edge detector\nThe output produces a single pulse when a rising edge is detected."},
+                    "comment" : "Rising edge detector\nThe output produces a single pulse when a rising edge is detected.",
+                    "generate" : generate_block},
                 {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CLK","BOOL","none")], 
                     "outputs" : [("Q","BOOL","none")],
-                    "comment" : "Falling edge detector\nThe output produces a single pulse when a falling edge is detected."},
+                    "comment" : "Falling edge detector\nThe output produces a single pulse when a falling edge is detected.",
+                    "generate" : generate_block},
                 {"name" : "CTU", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], 
                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
-                    "comment" : "Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."},
+                    "comment" : "Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value.",
+                    "generate" : generate_block},
                 {"name" : "CTD", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], 
                     "outputs" : [("Q","BOOL","none"),("CV","INT","none")],
-                    "comment" : "Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."},
+                    "comment" : "Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value.",
+                    "generate" : generate_block},
                 {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], 
                     "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")],
-                    "comment" : "Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input ans down on the other."},
+                    "comment" : "Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input ans down on the other.",
+                    "generate" : generate_block},
                 {"name" : "TP", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
-                    "comment" : "Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."},
+                    "comment" : "Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration.",
+                    "generate" : generate_block},
                 {"name" : "TOF", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
-                    "comment" : "On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true."},
+                    "comment" : "On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true.",
+                    "generate" : generate_block},
                 {"name" : "TON", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], 
                     "outputs" : [("Q","BOOL","none"),("ET","TIME","none")],
-                    "comment" : "Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."},
+                    "comment" : "Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false.",
+                    "generate" : generate_block},
                 {"name" : "RTC", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("EN","BOOL","none"),("PDT","DATE_AND_TIME","none")], 
                     "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")],
-                    "comment" : "Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on."},
+                    "comment" : "Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on.",
+                    "generate" : generate_block},
                 {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], 
                     "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")],
-                    "comment" : "Integral\nThe integral function block integrates the value of input XIN over time."},
+                    "comment" : "Integral\nThe integral function block integrates the value of input XIN over time.",
+                    "generate" : generate_block},
                 {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], 
                     "outputs" : [("XOUT","REAL","none")],
-                    "comment" : "Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."},
+                    "comment" : "Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN.",
+                    "generate" : generate_block},
                 {"name" : "PID", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("AUTO","BOOL","none"),("PV","REAL","none"),("SP","REAL","none"),("X0","REAL","none"),("KP","REAL","none"),("TR","REAL","none"),("TD","REAL","none"),("CYCLE","TIME","none")], 
                     "outputs" : [("XOUT","REAL","none")],
-                    "comment" : "PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."},
+                    "comment" : "PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control.",
+                    "generate" : generate_block},
                 {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none"),("HOLDBACK","BOOL","none"),("ERROR","REAL","none"),("PV","REAL","none")], 
                     "outputs" : [("RAMP","BOOL","none"),("XOUT","REAL","none")],
-                    "comment" : "Ramp\nThe RAMP function block is modelled on example given in the standard but with the addition of a 'Holdback' feature."},
+                    "comment" : "Ramp\nThe RAMP function block is modelled on example given in the standard but with the addition of a 'Holdback' feature.",
+                    "generate" : generate_block},
                 {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], 
                     "outputs" : [("Q","BOOL","none")],
-                    "comment" : "Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."},
+                    "comment" : "Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2.",
+                    "generate" : generate_block},
                 {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, 
                     "inputs" : [("PV1","REAL","none"),("PV2","REAL","none"),("RATIO","REAL","none"),("TIMON","TIME","none"),("TIMOFF","TIME","none"),("TOLERANCE","BOOL","none"),("RESET","BOOL","none"),("CYCLE","TIME","none")], 
                     "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")],
-                    "comment" : "Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2."}
+                    "comment" : "Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2.",
+                    "generate" : generate_block}
                 ]},
-            {"name" : "SVGUI function blocks", "list":
-                [{"name" : "Container", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("X","FLOAT","none"),("SetX","BOOL","none"),("Y","FLOAT","none"),("SetY","BOOL","none"),("Angle","FLOAT","none"),("SetAngle","BOOL","none")], 
-                    "outputs" : [("X","FLOAT","none"),("X Changed","BOOL","none"),("Y","FLOAT","none"),("Y Changed","BOOL","none"),("Angle","FLOAT","none"),("Angle Changed","BOOL","none")],
-                    "comment" : "SVGUI Container"},
-                {"name" : "Button", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("Show","BOOL","none"),("Toggle","BOOL","none")], 
-                    "outputs" : [("Visible","BOOL","none"),("State","BOOL","none")],
-                    "comment" : "SVGUI Button"},
-                {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("Text","STRING","none"),("Set Text","BOOL","none")], 
-                    "outputs" : [("Text","STRING","none"),("Text Changed","BOOL","none")],
-                    "comment" : "SVGUI Text Control"},
-                {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("Position","UINT","none"),("Set Position","BOOL","none")], 
-                    "outputs" : [("Position","UINT","none"),("Position Changed","BOOL","none")],
-                    "comment" : "SVGUI ScrollBar"},
-                {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("Selected","UINT","none"),("Set Selected","BOOL","none")], 
-                    "outputs" : [("Selected","UINT","none"),("Selected Changed","BOOL","none")],
-                    "comment" : "SVGUI Notebook"},
-                {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, 
-                    "inputs" : [("Angle","FLOAT","none"),("Set Angle","BOOL","none")], 
-                    "outputs" : [("Angle","FLOAT","none"),("Angle changed","BOOL","none")],
-                    "comment" : "SVGUI Rotating Control"},
-               ]}
              ]
+             
+PluginTypes = []
 
 """
 Function that returns the block definition associated to the block type given
 """
 
 def GetBlockType(type, inputs = None):
-    for category in BlockTypes:
+    for category in BlockTypes + PluginTypes:
         for blocktype in category["list"]:
             if inputs:
                 block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]])
@@ -166,6 +195,12 @@
                 return blocktype
     return None
 
+"""
+Function that add a new plugin to the plugin list
+"""
+
+def AddPlugin(blocklist):
+    PluginTypes.append(blocklist)
 
 #-------------------------------------------------------------------------------
 #                           Data Types definitions
@@ -455,6 +490,7 @@
                 Function_decl_list = []
             if Current_section:
                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
+                Function_decl["generate"] = generate_block
                 baseinputnumber = int(Function_decl.get("baseinputnumber",1))
                 Function_decl["baseinputnumber"] = baseinputnumber
                 for param, value in Function_decl.iteritems():