[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EEGBY6RM6QKCM5YAASQWPC":3,"skill-same:01M6EEGBY6RM6QKCM5YAASQWPC":47},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M6EEGBY6RM6QKCM5YAASQWPC","blender-grease-pencil",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fblender-grease-pencil\u002FSKILL.md",[],[18,19],"blender","blender grease pencil","2026-11-10 10:12:30",false,"# Blender Grease Pencil\n\n## Overview\n\nCreate 2D drawings and animations in Blender's 3D space using the Grease Pencil system and Python. Build strokes from point data, manage layers and frames, apply GP-specific modifiers, and animate 2D content — all scriptable from the terminal.\n\n## Instructions\n\n### 1. Create a Grease Pencil object\n\n```python\nimport bpy\n\n# Create a new Grease Pencil data block and object\ngp_data = bpy.data.grease_pencils.new(\"MyDrawing\")\ngp_obj = bpy.data.objects.new(\"MyDrawing\", gp_data)\nbpy.context.collection.objects.link(gp_obj)\n\n# Or use the operator\nbpy.ops.object.gpencil_add(type='EMPTY')  # EMPTY, STROKE, MONKEY, SCENE, COLLECTION\ngp_obj = bpy.context.active_object\n```\n\nTypes for `gpencil_add`: `EMPTY` (blank), `STROKE` (single stroke), `MONKEY` (Suzanne in 2D), `SCENE` (draw over scene), `COLLECTION` (from collection).\n\n### 2. Add layers and frames\n\n```python\nimport bpy\n\ngp_data = bpy.context.active_object.data\n\n# Create a layer\nlayer = gp_data.layers.new(\"Outlines\", set_active=True)\nlayer.info = \"Outlines\"\nlayer.blend_mode = 'REGULAR'  # REGULAR, OVERLAY, ADD, SUBTRACT, MULTIPLY\nlayer.opacity = 1.0\nlayer.use_lights = False\n\n# Create a keyframe on the layer at a specific frame\nframe = layer.frames.new(frame_number=1)\n\n# Additional layers for organization\ncolor_layer = gp_data.layers.new(\"Colors\", set_active=False)\ncolor_frame = color_layer.frames.new(frame_number=1)\n```\n\n### 3. Draw strokes programmatically\n\n```python\nimport bpy\n\ngp_obj = bpy.context.active_object\ngp_data = gp_obj.data\nlayer = gp_data.layers.active\nframe = layer.frames[0]  # or layer.active_frame\n\n# Create a stroke\nstroke = frame.strokes.new()\nstroke.display_mode = '3DSPACE'  # 3DSPACE, 2DSPACE, 2DIMAGE, SCREEN\nstroke.line_width = 10\n\n# Add points to the stroke\nnum_points = 5\nstroke.points.add(num_points)\n\ncoords = [(0, 0, 0), (1, 0.5, 0), (2, 1, 0), (3, 0.5, 0), (4, 0, 0)]\nfor i, (x, y, z) in enumerate(coords):\n    stroke.points[i].co = (x, y, z)\n    stroke.points[i].pressure = 1.0      # pen pressure (0.0 - 1.0)\n    stroke.points[i].strength = 1.0      # color strength (0.0 - 1.0)\n\n# Assign material index to stroke\nstroke.material_index = 0\n```\n\n### 4. Create GP materials\n\n```python\nimport bpy\n\ngp_obj = bpy.context.active_object\n\n# Solid fill material\nmat_solid = bpy.data.materials.new(\"GP_Solid\")\nbpy.data.materials.create_gpencil_data(mat_solid)\nmat_solid.grease_pencil.color = (0.1, 0.1, 0.1, 1.0)       # stroke color\nmat_solid.grease_pencil.fill_color = (0.8, 0.2, 0.2, 1.0)  # fill color\nmat_solid.grease_pencil.show_fill = True\nmat_solid.grease_pencil.show_stroke = True\ngp_obj.data.materials.append(mat_solid)\n\n# Line-only material\nmat_line = bpy.data.materials.new(\"GP_Line\")\nbpy.data.materials.create_gpencil_data(mat_line)\nmat_line.grease_pencil.color = (0.0, 0.0, 0.0, 1.0)\nmat_line.grease_pencil.show_fill = False\nmat_line.grease_pencil.show_stroke = True\ngp_obj.data.materials.append(mat_line)\n```\n\n### 5. Apply Grease Pencil modifiers\n\n```python\nimport bpy\n\ngp_obj = bpy.context.active_object\n\n# Thickness modifier\nthick = gp_obj.grease_pencil_modifiers.new(\"Thickness\", 'GP_THICK')\nthick.thickness_factor = 1.5\n\n# Smooth modifier\nsmooth = gp_obj.grease_pencil_modifiers.new(\"Smooth\", 'GP_SMOOTH')\nsmooth.factor = 0.5\nsmooth.step = 3\n\n# Tint modifier (color shift)\ntint = gp_obj.grease_pencil_modifiers.new(\"Tint\", 'GP_TINT')\ntint.color = (0.2, 0.5, 1.0)\ntint.factor = 0.3\n\n# Noise modifier (hand-drawn look)\nnoise = gp_obj.grease_pencil_modifiers.new(\"Noise\", 'GP_NOISE')\nnoise.factor = 0.5\n\n# Subdivide modifier (smoother curves)\nsubdiv = gp_obj.grease_pencil_modifiers.new(\"Subdivide\", 'GP_SUBDIV')\nsubdiv.level = 2\n\n# Build modifier (animated reveal)\nbuild = gp_obj.grease_pencil_modifiers.new(\"Build\", 'GP_BUILD')\nbuild.mode = 'SEQUENTIAL'  # SEQUENTIAL, CONCURRENT, ADDITIVE\nbuild.start_frame = 1\nbuild.length = 50\n\n# Array modifier (repeat strokes)\narray = gp_obj.grease_pencil_modifiers.new(\"Array\", 'GP_ARRAY')\narray.count = 5\narray.offset = (1.0, 0.0, 0.0)\n```\n\n### 6. Animate Grease Pencil frame by frame\n\n```python\nimport bpy\nimport math\n\ngp_obj = bpy.context.active_object\ngp_data = gp_obj.data\nlayer = gp_data.layers.active\n\ntotal_frames = 24\n\nfor f in range(total_frames):\n    frame = layer.frames.new(frame_number=f + 1)\n\n    stroke = frame.strokes.new()\n    stroke.display_mode = '3DSPACE'\n    stroke.line_width = 8\n\n    # Animate a circle that grows\n    num_points = 32\n    stroke.points.add(num_points)\n    radius = 0.5 + (f \u002F total_frames) * 2.0\n\n    for i in range(num_points):\n        angle = (2 * math.pi * i) \u002F num_points\n        x = radius * math.cos(angle)\n        y = radius * math.sin(angle)\n        stroke.points[i].co = (x, y, 0)\n        stroke.points[i].pressure = 1.0\n        stroke.points[i].strength = 1.0\n\n# Set playback range\nbpy.context.scene.frame_start = 1\nbpy.context.scene.frame_end = total_frames\n```\n\n### 7. Configure drawing guides\n\n```python\nimport bpy\n\n# Guides are properties on the scene's tool settings\nts = bpy.context.scene.tool_settings\ngp_settings = ts.gpencil_sculpt\n\n# Access guide settings (when in Draw mode)\nguide = ts.gpencil_stroke_placement_view3d\n\n# Guide types are set via the tool settings\n# Circular — concentric rings from reference point\n# Radial — rays extending from reference point\n# Parallel — constrained parallel lines\n# Grid — horizontal\u002Fvertical grid lines\n# Isometric — isometric angle constraints\n\n# Note: Guides are interactive Draw mode features.\n# For programmatic geometry, compute constrained points directly:\nimport math\n\ndef snap_to_grid(point, spacing=1.0):\n    return tuple(round(c \u002F spacing) * spacing for c in point)\n\ndef snap_to_radial(point, center=(0, 0, 0), num_rays=8):\n    dx, dy = point[0] - center[0], point[1] - center[1]\n    angle = math.atan2(dy, dx)\n    snap_angle = round(angle \u002F (2 * math.pi \u002F num_rays)) * (2 * math.pi \u002F num_rays)\n    dist = math.sqrt(dx**2 + dy**2)\n    return (center[0] + dist * math.cos(snap_angle),\n            center[1] + dist * math.sin(snap_angle),\n            point[2])\n```\n\n## Examples\n\n### Example 1: Procedural comic panel with text\n\n**User request:** \"Create a simple comic panel layout with borders and speech bubble\"\n\n```python\nimport bpy\nimport math\n\ndef clear_scene():\n    bpy.ops.object.select_all(action='SELECT')\n    bpy.ops.object.delete()\n\nclear_scene()\n\n# Create GP object\ngp_data = bpy.data.grease_pencils.new(\"ComicPanel\")\ngp_obj = bpy.data.objects.new(\"ComicPanel\", gp_data)\nbpy.context.collection.objects.link(gp_obj)\n\n# Materials\nmat_black = bpy.data.materials.new(\"GP_Black\")\nbpy.data.materials.create_gpencil_data(mat_black)\nmat_black.grease_pencil.color = (0, 0, 0, 1)\nmat_black.grease_pencil.show_fill = False\ngp_obj.data.materials.append(mat_black)\n\nmat_bubble = bpy.data.materials.new(\"GP_Bubble\")\nbpy.data.materials.create_gpencil_data(mat_bubble)\nmat_bubble.grease_pencil.color = (0, 0, 0, 1)\nmat_bubble.grease_pencil.fill_color = (1, 1, 1, 1)\nmat_bubble.grease_pencil.show_fill = True\ngp_obj.data.materials.append(mat_bubble)\n\n# Panel border layer\nborder_layer = gp_data.layers.new(\"Borders\")\nborder_frame = border_layer.frames.new(frame_number=1)\n\ndef draw_rect(frame, x, y, w, h, mat_idx=0, width=12):\n    stroke = frame.strokes.new()\n    stroke.display_mode = '3DSPACE'\n    stroke.line_width = width\n    stroke.material_index = mat_idx\n    stroke.points.add(5)\n    corners = [(x, y, 0), (x+w, y, 0), (x+w, y+h, 0), (x, y+h, 0), (x, y, 0)]\n    for i, co in enumerate(corners):\n        stroke.points[i].co = co\n        stroke.points[i].pressure = 1.0\n        stroke.points[i].strength = 1.0\n\n# Outer border\ndraw_rect(border_frame, 0, 0, 6, 4)\n# Inner panels (2 panels side by side)\ndraw_rect(border_frame, 0.2, 0.2, 2.7, 3.6)\ndraw_rect(border_frame, 3.1, 0.2, 2.7, 3.6)\n\n# Speech bubble layer\nbubble_layer = gp_data.layers.new(\"Bubbles\")\nbubble_frame = bubble_layer.frames.new(frame_number=1)\n\nstroke = bubble_frame.strokes.new()\nstroke.display_mode = '3DSPACE'\nstroke.line_width = 6\nstroke.material_index = 1\nnum_pts = 24\nstroke.points.add(num_pts)\ncx, cy, rx, ry = 4.5, 3.0, 0.8, 0.4\nfor i in range(num_pts):\n    angle = (2 * math.pi * i) \u002F num_pts\n    stroke.points[i].co = (cx + rx * math.cos(angle), cy + ry * math.sin(angle), 0)\n    stroke.points[i].pressure = 1.0\n    stroke.points[i].strength = 1.0\n\nbpy.ops.wm.save_as_mainfile(filepath=\"\u002Ftmp\u002Fcomic_panel.blend\")\n```\n\n### Example 2: Animated handwriting effect\n\n**User request:** \"Create an animation that draws text stroke by stroke like handwriting\"\n\n```python\nimport bpy\n\ndef clear_scene():\n    bpy.ops.object.select_all(action='SELECT')\n    bpy.ops.object.delete()\n\nclear_scene()\n\nbpy.ops.object.gpencil_add(type='EMPTY')\ngp_obj = bpy.context.active_object\ngp_data = gp_obj.data\n\n# Material\nmat = bpy.data.materials.new(\"GP_Ink\")\nbpy.data.materials.create_gpencil_data(mat)\nmat.grease_pencil.color = (0.05, 0.05, 0.15, 1)\ngp_data.materials.append(mat)\n\nlayer = gp_data.layers.active\nframe = layer.frames.new(frame_number=1) if not layer.frames else layer.frames[0]\n\n# Define letter paths as point sequences (simplified \"HI\")\nletters = {\n    'H': [(0,0,0),(0,2,0),(0,1,0),(1,1,0),(1,2,0),(1,0,0)],\n    'I': [(2.5,2,0),(2.5,0,0)],\n}\n\nfor letter, points in letters.items():\n    stroke = frame.strokes.new()\n    stroke.display_mode = '3DSPACE'\n    stroke.line_width = 10\n    stroke.material_index = 0\n    stroke.points.add(len(points))\n    for i, co in enumerate(points):\n        stroke.points[i].co = co\n        stroke.points[i].pressure = 1.0\n        stroke.points[i].strength = 1.0\n\n# Add Build modifier for animated reveal\nbuild = gp_obj.grease_pencil_modifiers.new(\"Build\", 'GP_BUILD')\nbuild.mode = 'SEQUENTIAL'\nbuild.start_frame = 1\nbuild.length = 60\n\nbpy.context.scene.frame_start = 1\nbpy.context.scene.frame_end = 60\n\nbpy.ops.wm.save_as_mainfile(filepath=\"\u002Ftmp\u002Fhandwriting.blend\")\n```\n\n## Guidelines\n\n- Use `bpy.data.grease_pencils.new()` for data-level creation. Use `bpy.ops.object.gpencil_add()` for quick object creation with defaults.\n- Always create at least one material and assign it before rendering — GP objects without materials render invisible.\n- Stroke `display_mode` controls coordinate space: `3DSPACE` for world-space strokes, `2DSPACE` for screen-relative. Use `3DSPACE` for most scripted workflows.\n- The `pressure` property on points controls line thickness variation. Set to 1.0 for uniform width, vary between 0.0-1.0 for pen-like tapering.\n- GP modifiers use `grease_pencil_modifiers` (not `modifiers`). Type constants are prefixed with `GP_` (e.g., `GP_THICK`, `GP_SMOOTH`).\n- For frame-by-frame animation, create separate `layer.frames.new(frame_number=N)` entries. Each frame holds independent strokes.\n- The Build modifier is the easiest way to animate stroke reveal without per-frame scripting.\n- Grease Pencil objects support the same transform operations as mesh objects (location, rotation, scale, parenting, constraints).\n- For complex 2D art, organize content across multiple layers (outlines, fills, colors, effects) just like in traditional digital art software.\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Fblender-grease-pencil",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill blender-grease-pencil",{"tool":39,"command":40},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill blender-grease-pencil",{"tool":42,"command":43},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill blender-grease-pencil","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fblender-grease-pencil\u002FSKILL.md",true,[],[48,62,72,81,87,94],{"skillNo":49,"name":50,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":51,"categories":52,"keywords":58,"publishedAt":20},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[53],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[59,60,61],"model","model hierarchy","model hierarchy skill",{"skillNo":63,"name":64,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":68,"publishedAt":20},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[67],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},[69,70,71],"MCP","zoom","zoom mcp",{"skillNo":73,"name":74,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":20},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[78,79,80,70],"sdk","zoom apps sdk","apps",{"skillNo":82,"name":83,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":20},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[83],{"skillNo":88,"name":89,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":93,"publishedAt":20},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[92],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},[89],{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":20},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[96]]