-
Notifications
You must be signed in to change notification settings - Fork 129
Getting Started
π§π§ WIP π§π§. If you encountered any problems, feel free to open an issue/a discussion!
The best way to get started is probably going for the examples, especially the Stable Diffusion example. However, if you want a step-by-step guidance, this is the right place to go!
carefree-drawboard
π¨ requires the following to get started:
- Python 3.8+
- Node.js 12.22.0+
pip install carefree-drawboard
npm install --global yarn
Create a folder (e.g., my_fancy_app
) wherever you like, get into it, and run
cfdraw init
When you run this command for the first time, we will use
yarn
to install the JavaScript dependencies for you, which may be quite slow!
This command will write two files to your folder (my_fancy_app
). After which you can run the app in development mode:
cfdraw run
And you should see your app running at http://localhost:5123. Now you can play with the generated app.py
file and see warm reload (yeah, not hot enough because we rely on the reload
provided by uvicorn
π€£).
Notice that the generated template implements a Gaussian Blur plugin, which requires an image to pop up. You can upload an image either by dropping on directly to the drawboard π¨, or by clicking the
Plus
button at the top right corner and selectUpload Image
.
20230415-131404.mp4
In this section we'll break down the codes in app.py
to show you what's going on under the hood.
class Plugin(IHttpFieldsPlugin):
...
This line shows that we are utilizing the IHttpFieldsPlugin
binding to define our plugin. An IHttpFieldsPlugin
is a convenient interface that allows you to create a plugin with multiple input fields (e.g., text inputs, number inputs) in a declarative way.
See PythonHttpFieldsPlugin for more details.
Every IHttpFieldsPlugin
only needs to define two stuffs:
- The
settings
property, which is used for defining Styles. - The
process
method, which is used to define logics (algorithms).
Let's see the settings
property first:
@property
def settings(self) -> IPluginSettings:
return IPluginSettings(
w=300,
h=180,
nodeConstraint=NodeConstraints.IMAGE,
pivot=PivotType.RT,
follow=True,
pluginInfo=IHttpFieldsPluginInfo(
definitions=dict(
size=INumberField(
default=3,
min=1,
max=10,
step=1,
isInt=True,
label="Size",
)
),
),
)
-
w
,h
: the width and height of the expanded panel.
If we need to specify the button's wh, we can use
iconW
andiconH
.
-
nodeConstraint
: control whether this plugin will be displayed. By specifyingNodeConstraints.IMAGE
, it means that this plugin will only occur when anImageNode
is selected.
See
Node
andPlugin Positioning
for more details.
-
pivot
,follow
: positioning settings of this plugin.
See
Pivot
andPlugin Positioning
for more details.
-
pluginInfo
: specify some behaviors of the expanded panel.
See
IHttpFieldsPluginInfo
for more details.
Apart from these, the easiest and (maybe) also the most important thing we need to do is assigning a nice-looking icon to our plugin. We can achieve this by specifying an src
argument to the returned IPluginSettings
instance:
@property
def settings(self) -> IPluginSettings:
return IPluginSettings(
src="...",
w=300,
h=180,
...
Here, the src
should be a url of the desired image. If you don't have one in hand, you may try use this one.
After saving the modifications, you should be able to see the icon of your plugin changes, cool!
You can play with other fields in
IPluginSettings
to see what will happen!
def process(self, data: IPluginRequest) -> Image.Image:
image = self.load_image(data.nodeData.src)
return image.filter(ImageFilter.GaussianBlur(data.extraData["size"]))
- The incoming argument,
data
, contains all necessary information from the drawboard π¨. There are two common properties that you may need:-
nodeData
, it is anINodeData
instance.- If no nodes are selected, this field will be empty.
- If multiple nodes are selected, this field will be empty and please use
nodeDataList
instead.
-
nodeDataList
, it is a list ofINodeData
instance.- If no nodes are selected, this field will be empty.
- Please use this field if multiple nodes are selected.
- If only one node is selected, this field will be empty and please use
nodeData
instead.
-
extraData
, it is adict
that aligns to thedefinitions
field defined in theIHttpFieldsPluginInfo
.
-
- The
load_image
is a build-in method that can load aPIL.Image
for further processing.
We will add more build-in methods in the future based on your needs!
- The
process
method can directly return anstr
, or aPIL.Image
, or alist
of them. This is because someMiddleware
incarefree-drawboard
π¨ will convert them to the data structure we actually need.
See Middleware for more details.