Skip to content

Instantly share code, notes, and snippets.

View semagnum's full-sized avatar
🎯
Focusing

Spencer Magnusson semagnum

🎯
Focusing
View GitHub Profile
@semagnum
semagnum / viewport_shortcuts.py
Created January 13, 2024 17:27
Blender add-on containing shortcuts for Cycles render settings in the viewport.
# Viewport Shortcuts, Blender add-on that contains shortcuts of viewport render settings.
# Copyright (C) 2024 Spencer Magnusson
#
# 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 3 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
@semagnum
semagnum / align_transform_to_selected_face.py
Created September 22, 2023 19:13
Blender operator that aligns transform to selected face
import bpy
class SimpleOperator(bpy.types.Operator):
bl_idname = "mesh.align_transform_to_selected_face"
bl_label = "Align Rotation to Selected Face"
@classmethod
def poll(cls, context):
return context.active_object is not None and any(p.select for p in context.active_object.data.polygons)
@semagnum
semagnum / get_fitted_rect.py
Created March 14, 2023 12:17
Given a 3D point cloud flattened to its normal, get the fitted rectangle
import bpy
import math
from mathutils import Matrix, Vector
from mathutils.geometry import box_fit_2d
def get_box(vertices, normal):
"""Given a set of vertices and normals (both mapped to world space),
:param vertices: list of vertices mapped to world space
@semagnum
semagnum / face_raycast.py
Created March 7, 2023 21:08
Blender operator to shoot a ray into the scene and draw a 3D cube on the closest face
import bpy
from bpy_extras import view3d_utils
import gpu
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
def draw(shade, bat):
shade.bind()
shade.uniform_float("color", (1, 0, 0, 0.25))
bat.draw(shade)
@semagnum
semagnum / mesh_copy.py
Created January 25, 2023 21:58
Extracts mesh data to be used for mesh.from_pydata()
import bpy
from mathutils import Vector
# prereq: go into your object's edit mode
context = bpy.context
mesh = context.edit_object.data
verts = [v.co for v in mesh.vertices]
edges = [[v for v in e.vertices] for e in mesh.edges]
@semagnum
semagnum / Flowmap generator.py
Created December 30, 2022 19:16
From painted vertex color attributes, create an RGB flowmap that shows the "flow" of colors
import bpy
import bmesh
from mathutils import Vector
obj = bpy.context.active_object
me = obj.data
# cannot access color attributes within bmesh,
# so we will create a dict of indices to access the linked edges in object mode
bpy.ops.object.mode_set(mode='EDIT')
@semagnum
semagnum / build.py
Last active April 9, 2023 12:07
Zips a Blender add-on, using the version as part of the filename
import ast
import os
import zipfile
allowed_file_extensions = {'.py', '.md', 'LICENSE'}
exclude_folders = {'doc', 'venv', '.git', '.idea'}
def zipdir(path, ziph: zipfile.ZipFile, zip_subdir_name):
for root, dirs, files in os.walk(path):
@semagnum
semagnum / instance_generators.py
Created January 20, 2022 15:18
Utility functions to iterate over collections and related instanced collections
def coll_iter(curr_coll):
"""
Iterate through hierarchy of collections
:param curr_coll: current collection
:return: generator of collections
"""
yield curr_coll
for child in curr_coll.children:
yield from coll_iter(child)
@semagnum
semagnum / bpy_text_wrap.py
Created November 12, 2021 20:29
text wrap for Blender UI panels (credit to Graswald3d in his G Scatter addon)
import blf
import bpy
def wrap_text(text: str, context):
return_text = []
row_text = ''
width = context.region.width
system = context.preferences.system
ui_scale = system.ui_scale
@semagnum
semagnum / view_frustrum_cull.py
Created November 4, 2021 02:35
Culls objects whose bounding boxes are not intersecting or within camera frustrum
from mathutils.geometry import normal
from mathutils import Vector
from bpy import context
def camera_as_planes(scene, obj):
"""
Return planes in world-space which represent the camera view bounds.
"""
camera = obj.data