KiCad scripting plugin architecture, footprint wizards first
This commit is contained in:
parent
f114e800a4
commit
edee5dc1ce
|
@ -231,14 +231,15 @@ set(PCBNEW_COMMON_SRCS
|
|||
# Scripting sources
|
||||
##
|
||||
|
||||
if (KICAD_SCRIPTING)
|
||||
|
||||
set(PCBNEW_SCRIPTING_PYTHON_HELPERS
|
||||
set(PCBNEW_SCRIPTING_PYTHON_HELPERS
|
||||
../scripting/wx_python_helpers.cpp
|
||||
../scripting/python_scripting.cpp
|
||||
scripting/pcbnew_scripting_helpers.cpp
|
||||
scripting/pcbnew_footprint_wizards.cpp
|
||||
)
|
||||
|
||||
if (KICAD_SCRIPTING)
|
||||
|
||||
set(PCBNEW_SCRIPTING_SRCS
|
||||
pcbnew_wrap.cxx
|
||||
${PCBNEW_SCRIPTING_PYTHON_HELPERS}
|
||||
|
@ -279,6 +280,7 @@ if (KICAD_SCRIPTING)
|
|||
DEPENDS scripting/board.i
|
||||
DEPENDS scripting/board_item.i
|
||||
DEPENDS scripting/module.i
|
||||
DEPENDS scripting/plugins.i
|
||||
DEPENDS scripting/units.i
|
||||
DEPENDS ../scripting/dlist.i
|
||||
DEPENDS ../scripting/kicad.i
|
||||
|
|
|
@ -133,5 +133,7 @@
|
|||
|
||||
%include "board.i"
|
||||
%include "module.i"
|
||||
%include "plugins.i"
|
||||
%include "units.i"
|
||||
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/**
|
||||
* @file pcbnew_footprint_wizards.cpp
|
||||
* @brief Class PCBNEW_FOOTPRINT_WIZARDS
|
||||
*/
|
||||
|
||||
#include "pcbnew_footprint_wizards.h"
|
||||
#include <stdio.h>
|
||||
|
||||
FOOTPRINT_WIZARD::FOOTPRINT_WIZARD(PyObject *aWizard)
|
||||
{
|
||||
this->py_wizard = aWizard;
|
||||
Py_XINCREF(aWizard);
|
||||
}
|
||||
|
||||
FOOTPRINT_WIZARD::~FOOTPRINT_WIZARD()
|
||||
{
|
||||
Py_XDECREF(this->py_wizard);
|
||||
}
|
||||
|
||||
PyObject* FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aArglist)
|
||||
{
|
||||
PyObject *pFunc;
|
||||
|
||||
/* pFunc is a new reference to the desired method */
|
||||
pFunc = PyObject_GetAttrString(this->py_wizard, aMethod);
|
||||
|
||||
if (pFunc && PyCallable_Check(pFunc))
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
result = PyObject_CallObject(pFunc, aArglist);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyObject *t, *v, *b;
|
||||
PyErr_Fetch(&t, &v, &b);
|
||||
printf ("calling %s()\n",aMethod);
|
||||
printf ("Exception: %s\n",PyString_AsString(PyObject_Str(v)));
|
||||
printf (" : %s\n",PyString_AsString(PyObject_Str(b)));
|
||||
}
|
||||
|
||||
|
||||
if (result)
|
||||
{
|
||||
Py_XDECREF(pFunc);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("method not found, or not callable: %s\n",aMethod);
|
||||
}
|
||||
|
||||
if (pFunc) Py_XDECREF(pFunc);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxString FOOTPRINT_WIZARD::CallRetStrMethod(const char* aMethod, PyObject *aArglist)
|
||||
{
|
||||
wxString ret;
|
||||
PyObject *result = CallMethod(aMethod,aArglist);
|
||||
if (result)
|
||||
{
|
||||
const char *str_res = PyString_AsString(result);
|
||||
ret = wxString::FromUTF8(str_res);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("method not found, or not callable: %s\n",aMethod);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
wxString FOOTPRINT_WIZARD::GetName()
|
||||
{
|
||||
return CallRetStrMethod("GetName");
|
||||
}
|
||||
|
||||
wxString FOOTPRINT_WIZARD::GetImage()
|
||||
{
|
||||
return CallRetStrMethod("GetImage");
|
||||
}
|
||||
|
||||
wxString FOOTPRINT_WIZARD::GetDescription()
|
||||
{
|
||||
return CallRetStrMethod("GetDescription");
|
||||
}
|
||||
|
||||
int FOOTPRINT_WIZARD::GetNumParameterPages()
|
||||
{
|
||||
int ret;
|
||||
PyObject *result;
|
||||
|
||||
/* Time to call the callback */
|
||||
result = CallMethod("GetNumParameterPages",NULL);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (!PyInt_Check(result)) return -1;
|
||||
ret = PyInt_AsLong(result);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxString FOOTPRINT_WIZARD::GetParameterPageName(int aPage)
|
||||
{
|
||||
wxString ret;
|
||||
PyObject *arglist;
|
||||
PyObject *result;
|
||||
|
||||
/* Time to call the callback */
|
||||
arglist = Py_BuildValue("(i)", aPage);
|
||||
result = CallMethod("GetParameterPageName",arglist);
|
||||
Py_DECREF(arglist);
|
||||
|
||||
if (result)
|
||||
{
|
||||
const char *str_res = PyString_AsString(result);
|
||||
ret = wxString::FromUTF8(str_res);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxArrayString FOOTPRINT_WIZARD::GetParameterNames(int aPage)
|
||||
{
|
||||
wxArrayString a;
|
||||
return a;
|
||||
}
|
||||
|
||||
wxArrayString FOOTPRINT_WIZARD::GetParameterValues(int aPage)
|
||||
{
|
||||
wxArrayString a;
|
||||
return a;
|
||||
}
|
||||
|
||||
wxString FOOTPRINT_WIZARD::SetParameterValues(int aPage,wxArrayString& aValues)
|
||||
{
|
||||
wxString ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE FOOTPRINT_WIZARD::*GetModule()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::vector<FOOTPRINT_WIZARD*> FOOTPRINT_WIZARDS::m_FootprintWizards;
|
||||
|
||||
void FOOTPRINT_WIZARDS::register_wizard(PyObject* wizard)
|
||||
{
|
||||
FOOTPRINT_WIZARD *fw;
|
||||
|
||||
fw = new FOOTPRINT_WIZARD(wizard);
|
||||
m_FootprintWizards.push_back(fw);
|
||||
|
||||
printf("Registered python footprint wizard '%s'\n",
|
||||
(const char*)fw->GetName().mb_str());
|
||||
|
||||
int pages = fw->GetNumParameterPages();
|
||||
printf(" %d pages\n",pages);
|
||||
|
||||
for (int n=0; n<pages; n++)
|
||||
{
|
||||
printf(" page %d->'%s'\n",n,
|
||||
(const char*)fw->GetParameterPageName(n).mb_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file pcbnew_footprint_wizards.h
|
||||
* @brief Class PCBNEW_FOOTPRINT_WIZARDS
|
||||
*/
|
||||
|
||||
#ifndef PCBNEW_FOOTPRINT_WIZARDS_H
|
||||
#define PCBNEW_FOOTPRINT_WIZARDS_H
|
||||
#include <Python.h>
|
||||
#include <vector>
|
||||
#include <wxPcbStruct.h>
|
||||
|
||||
class FOOTPRINT_WIZARD
|
||||
{
|
||||
|
||||
PyObject *py_wizard;
|
||||
PyObject *CallMethod(const char *aMethod, PyObject *aArglist=NULL);
|
||||
wxString CallRetStrMethod(const char *aMethod, PyObject *aArglist=NULL);
|
||||
public:
|
||||
FOOTPRINT_WIZARD(PyObject *wizard);
|
||||
~FOOTPRINT_WIZARD();
|
||||
wxString GetName();
|
||||
wxString GetImage();
|
||||
wxString GetDescription();
|
||||
int GetNumParameterPages();
|
||||
wxString GetParameterPageName(int aPage);
|
||||
wxArrayString GetParameterNames(int aPage);
|
||||
wxArrayString GetParameterValues(int aPage);
|
||||
wxString SetParameterValues(int aPage,wxArrayString& aValues);
|
||||
MODULE *GetModule();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FOOTPRINT_WIZARDS
|
||||
{
|
||||
private:
|
||||
static std::vector<FOOTPRINT_WIZARD*> m_FootprintWizards;
|
||||
|
||||
public:
|
||||
static void register_wizard(PyObject *wizard);
|
||||
|
||||
};
|
||||
|
||||
#endif /* PCBNEW_FOOTPRINT_WIZARDS_H */
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
%{
|
||||
#include <scripting/pcbnew_footprint_wizards.h>
|
||||
%}
|
||||
|
||||
class FOOTPRINT_WIZARDS
|
||||
{
|
||||
public:
|
||||
static void register_wizard(PyObject *wizard);
|
||||
|
||||
};
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from pcbnew import *
|
||||
|
||||
class FPCFootprintWizard(FootprintWizardPlugin):
|
||||
def __init__(self):
|
||||
FootprintWizardPlugin.__init__(self)
|
||||
self.name = "FPC"
|
||||
self.description = "FPC Footprint Wizard"
|
||||
self.parameters = {
|
||||
"Pads":
|
||||
{"n":40,"pitch":0.5,"width":0.25,"height":1.6},
|
||||
"Shield":
|
||||
{"shield_to_pad":1.6,"from_top":1.3,"width":1.5,"height":2}
|
||||
}
|
||||
|
||||
def smdRectPad(self,module,size,pos,name):
|
||||
pad = D_PAD(module)
|
||||
pad.SetSize(size)
|
||||
pad.SetShape(PAD_RECT)
|
||||
pad.SetAttribute(PAD_SMD)
|
||||
pad.SetLayerMask(PAD_SMD_DEFAULT_LAYERS)
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPadName(name)
|
||||
return pad
|
||||
|
||||
def BuildFootprint(self):
|
||||
|
||||
pads = self.parameters["Pads"]["n"]
|
||||
pad_width = self.parameters["Pads"]["width"]
|
||||
pad_height = self.parameters["Pads"]["height"]
|
||||
pad_pitch = self.parameters["Pads"]["pitch"]
|
||||
shl_width = self.parameters["Shield"]["width"]
|
||||
shl_height = self.parameters["Shield"]["height"]
|
||||
shl_to_pad = self.parameters["Shield"]["shield_to_pad"]
|
||||
shl_from_top = self.parameters["Shield"]["from_top"]
|
||||
|
||||
size_pad = wxSizeMM(pad_width,pad_height)
|
||||
size_shld = wxSizeMM(shl_width,shl_height)
|
||||
|
||||
|
||||
# create a new module, it's parent is our previously created pcb
|
||||
module = MODULE(None)
|
||||
module.SetReference("FPC"+str(pads)) # give it a reference name
|
||||
module.m_Reference.SetPos0(wxPointMM(-1,-1))
|
||||
|
||||
# create a pad array and add it to the module
|
||||
|
||||
for n in range (0,pads):
|
||||
pad = self.smdRectPad(module,size_pad,wxPointMM(pad_pitch*n,0),str(n+1))
|
||||
module.Add(pad)
|
||||
|
||||
|
||||
pad_s0 = self.smdRectPad(module,
|
||||
size_shld,
|
||||
wxPointMM(-shl_to_pad,shl_from_top),
|
||||
"0")
|
||||
pad_s1 = self.smdRectPad(module,
|
||||
size_shld,
|
||||
wxPointMM((pads-1)*pad_pitch+shl_to_pad,shl_from_top),
|
||||
"0")
|
||||
|
||||
module.Add(pad_s0)
|
||||
module.Add(pad_s1)
|
||||
|
||||
e = EDGE_MODULE(module)
|
||||
e.SetStart0(wxPointMM(-1,0))
|
||||
e.SetEnd0(wxPointMM(0,0))
|
||||
e.SetWidth(FromMM(0.2))
|
||||
e.SetLayer(EDGE_LAYER)
|
||||
e.SetShape(S_SEGMENT)
|
||||
module.Add(e)
|
||||
|
||||
# save the PCB to disk
|
||||
module.SetLibRef("FPC"+str(pads))
|
||||
|
||||
self.module = module
|
||||
|
||||
# create our footprint wizard
|
||||
fpc_wizard = FPCFootprintWizard()
|
||||
|
||||
# register it into pcbnew
|
||||
fpc_wizard.register()
|
|
@ -110,3 +110,4 @@
|
|||
/* std template mappings */
|
||||
%template(intVector) std::vector<int>;
|
||||
|
||||
%include "kicadplugins.i"
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo <miguelangel@nbee.es>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
%pythoncode
|
||||
{
|
||||
|
||||
|
||||
# KiCadPlugin base class will register any plugin into the right place
|
||||
class KiCadPlugin:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def register(self):
|
||||
if isinstance(self,FilePlugin):
|
||||
pass # register to file plugins in C++
|
||||
if isinstance(self,FootprintWizardPlugin):
|
||||
FOOTPRINT_WIZARDS.register_wizard(self)
|
||||
return
|
||||
|
||||
if isinstance(self,ActionPlugin):
|
||||
pass # register to action plugins in C++
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
# This will be the file io scripting based plugins class
|
||||
class FilePlugin(KiCadPlugin):
|
||||
def __init__(self):
|
||||
KiCadPlugin.__init__(self)
|
||||
|
||||
|
||||
# Scriping footprint wizards
|
||||
class FootprintWizardPlugin(KiCadPlugin):
|
||||
def __init__(self):
|
||||
KiCadPlugin.__init__(self)
|
||||
self.defaults()
|
||||
|
||||
def defaults(self):
|
||||
self.module = None
|
||||
self.parameters = {}
|
||||
self.name = "Undefined Footprint Wizard plugin"
|
||||
self.description = ""
|
||||
self.image = ""
|
||||
|
||||
def GetName(self):
|
||||
return self.name
|
||||
|
||||
def GetImage(self):
|
||||
return self.image
|
||||
|
||||
def GetDescription(self):
|
||||
return self.description
|
||||
|
||||
|
||||
def GetNumParameterPages(self):
|
||||
return len(self.parameters)
|
||||
|
||||
def GetParameterPageName(self,page_n):
|
||||
return self.parameters.keys()[page_n]
|
||||
|
||||
def GetParameterNames(self,page_n):
|
||||
name = self.GetParameterPageName(page_n)
|
||||
return self.parameters[name].keys()
|
||||
|
||||
def GetParameterValues(self,page_n):
|
||||
name = self.GetParameterPageName(page_n)
|
||||
return self.parameters[name].keys()
|
||||
|
||||
def GetParameterValues(self,page_n):
|
||||
name = self.GetParameterPageName(page_n)
|
||||
return self.parameters[name].values()
|
||||
|
||||
|
||||
def SetParameterValues(self,page_n,values):
|
||||
name = self.GetParameterPageName(pagen_n)
|
||||
keys = self.parameters[name].values()
|
||||
n=0
|
||||
for key in keys:
|
||||
self.parameters[name][key] = values[n]
|
||||
n+=1
|
||||
|
||||
def GetModule(self):
|
||||
self.BuildFootprint()
|
||||
return self.module
|
||||
|
||||
def BuildFootprint(self):
|
||||
return
|
||||
|
||||
def Show(self):
|
||||
print "Footprint Wizard Name: ",self.GetName()
|
||||
print "Footprint Wizard Description: ",self.GetDescription()
|
||||
n_pages = self.GetNumParameterPages()
|
||||
print " setup pages: ",n_pages
|
||||
for page in range(0,n_pages):
|
||||
name = self.GetParameterPageName(page)
|
||||
values = self.GetParameterValues(page)
|
||||
names = self.GetParameterNames(page)
|
||||
print "page %d) %s"%(page,name)
|
||||
for n in range (0,len(values)):
|
||||
print "\t%s\t:\t%s"%(names[n],values[n])
|
||||
|
||||
class ActionPlugin(KiCadPlugin):
|
||||
def __init__(self):
|
||||
KiCadPlugin.__init__(self)
|
||||
|
||||
|
||||
def LoadPlugins():
|
||||
import os
|
||||
import sys
|
||||
|
||||
plugins_dir = os.environ['HOME']+'/.kicad_plugins/'
|
||||
|
||||
sys.path.append(plugins_dir)
|
||||
|
||||
for module in os.listdir(plugins_dir):
|
||||
if os.path.isdir(plugins_dir+module):
|
||||
__import__(module, locals(), globals())
|
||||
|
||||
if module == '__init__.py' or module[-3:] != '.py':
|
||||
continue
|
||||
__import__(module[:-3], locals(), globals())
|
||||
|
||||
|
||||
}
|
|
@ -90,15 +90,6 @@ void pcbnewInitPythonScripting()
|
|||
swigAddModules();
|
||||
swigSwitchPythonBuiltin();
|
||||
|
||||
#if 0
|
||||
/* print the list of modules available from python */
|
||||
while(PyImport_Inittab[i].name)
|
||||
{
|
||||
printf("name[%d]=>%s\n",i,PyImport_Inittab[i].name);
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
/* setup the scripting path, we may need to add the installation path
|
||||
|
@ -106,7 +97,9 @@ void pcbnewInitPythonScripting()
|
|||
|
||||
PyRun_SimpleString("import sys\n"
|
||||
"sys.path.append(\".\")\n"
|
||||
"import pcbnew\n");
|
||||
"import pcbnew\n"
|
||||
"pcbnew.LoadPlugins()"
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue