forked from bartvdbraak/blender
Made it so blender has an active render layer for Uv and Vertex color mesh layers.
This means changing the active UV/VCol layers wont change what renders. needed to adjust the minor version so old files will copy the active layer to the render-uv/vcol layer. boxpack2d.py - redoen in C now, dont need python version.
This commit is contained in:
parent
0b0f0b0ffb
commit
c24aa10561
@ -1,498 +0,0 @@
|
|||||||
'''
|
|
||||||
# 2D Box packing function used by archimap
|
|
||||||
# packs any list of 2d boxes into a square and returns a list of packed boxes.
|
|
||||||
# Example of usage.
|
|
||||||
import boxpack2d
|
|
||||||
|
|
||||||
# Build boxe list.
|
|
||||||
# the unique ID is not used.
|
|
||||||
# just the width and height.
|
|
||||||
boxes2Pack = []
|
|
||||||
anyUniqueID = 0; w = 2.2; h = 3.8
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 1; w = 4.1; h = 1.2
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 2; w = 5.2; h = 9.2
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 3; w = 8.3; h = 7.3
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 4; w = 1.1; h = 5.1
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 5; w = 2.9; h = 8.1
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
anyUniqueID = 6; w = 4.2; h = 6.2
|
|
||||||
boxes2Pack.append([anyUniqueID, w,h])
|
|
||||||
# packedLs is a list of [(anyUniqueID, left, bottom, width, height)...]
|
|
||||||
packWidth, packHeight, packedLs = boxpack2d.boxPackIter(boxes2Pack)
|
|
||||||
'''
|
|
||||||
|
|
||||||
from Blender import NMesh, Window, Object, Scene
|
|
||||||
'''
|
|
||||||
def debug_(x,y,z):
|
|
||||||
ob = Object.New("Empty")
|
|
||||||
ob.loc= x,y,z
|
|
||||||
Scene.GetCurrent().link(ob)
|
|
||||||
'''
|
|
||||||
|
|
||||||
# a box packing vert
|
|
||||||
class vt:
|
|
||||||
def __init__(self, x,y):
|
|
||||||
self.x, self.y = x, y
|
|
||||||
|
|
||||||
self.free = 15
|
|
||||||
|
|
||||||
# Set flags so cant test bottom left of 0/0
|
|
||||||
#~ BLF = 1; TRF = 2; TLF = 4; BRF = 8
|
|
||||||
|
|
||||||
#self.users = [] # A list of boxes.
|
|
||||||
# Rather then users, store Quadrents
|
|
||||||
self.blb = self.tlb = self.brb = self.trb = None
|
|
||||||
|
|
||||||
|
|
||||||
# A hack to remember the box() that last intersectec this vert
|
|
||||||
self.intersectCache = ([], [], [], [])
|
|
||||||
|
|
||||||
class vertList:
|
|
||||||
def __init__(self, verts=[]):
|
|
||||||
self.verts = verts
|
|
||||||
|
|
||||||
def sortCorner(self,w,h):
|
|
||||||
'''
|
|
||||||
Sorts closest first. - uses the box w/h as a bias,
|
|
||||||
this makes it so its less likely to have lots of poking out bits
|
|
||||||
that use too much
|
|
||||||
Lambada based sort
|
|
||||||
'''
|
|
||||||
# self.verts.sort(lambda A, B: cmp(max(A.x+w, A.y+h) , max(B.x+w, B.y+h))) # Reverse area sort
|
|
||||||
try: self.verts.sort(key = lambda b: max(b.x+w, b.y+h) ) # Reverse area sort
|
|
||||||
except: self.verts.sort(lambda A, B: cmp(max(A.x+w, A.y+h) , max(B.x+w, B.y+h))) # Reverse area sort
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class box:
|
|
||||||
def __init__(self, width, height, id=None):
|
|
||||||
|
|
||||||
self.id= id
|
|
||||||
|
|
||||||
self.area = width * height # real area
|
|
||||||
self.farea = width + height # fake area
|
|
||||||
#self.farea = float(min(width, height)) / float(max(width, height)) # fake area
|
|
||||||
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
|
|
||||||
# Append 4 new verts
|
|
||||||
# (BL,TR,TL,BR) / 0,1,2,3
|
|
||||||
self.v=v= [vt(0,0), vt(width,height), vt(0,height), vt(width,0)]
|
|
||||||
|
|
||||||
# Set the interior quadrents as used.
|
|
||||||
v[0].free &= ~TRF
|
|
||||||
v[1].free &= ~BLF
|
|
||||||
v[2].free &= ~BRF
|
|
||||||
v[3].free &= ~TLF
|
|
||||||
|
|
||||||
#for v in self.v:
|
|
||||||
# v.users.append(self)
|
|
||||||
v[0].trb = self
|
|
||||||
v[1].blb = self
|
|
||||||
v[2].brb = self
|
|
||||||
v[3].tlb = self
|
|
||||||
|
|
||||||
|
|
||||||
def updateV34(self):
|
|
||||||
'''
|
|
||||||
Updates verts 3 & 4 from 1 and 2
|
|
||||||
since 3 and 4 are only there foill need is resizing/ rotating of patterns on the fly while I painr new box placement
|
|
||||||
but may be merged later with other verts
|
|
||||||
'''
|
|
||||||
self.v[TL].x = self.v[BL].x
|
|
||||||
self.v[TL].y = self.v[TR].y
|
|
||||||
|
|
||||||
self.v[BR].x = self.v[TR].x
|
|
||||||
self.v[BR].y = self.v[BL].y
|
|
||||||
|
|
||||||
|
|
||||||
def setLeft(self, lft):
|
|
||||||
self.v[TR].x = lft + self.v[TR].x - self.v[BL].x
|
|
||||||
self.v[BL].x = lft
|
|
||||||
# update othere verts
|
|
||||||
self.updateV34()
|
|
||||||
|
|
||||||
def setRight(self, rgt):
|
|
||||||
self.v[BL].x = rgt - (self.v[TR].x - self.v[BL].x)
|
|
||||||
self.v[TR].x = rgt
|
|
||||||
self.updateV34()
|
|
||||||
|
|
||||||
def setBottom(self, btm):
|
|
||||||
self.v[TR].y = btm + self.v[TR].y - self.v[BL].y
|
|
||||||
self.v[BL].y = btm
|
|
||||||
self.updateV34()
|
|
||||||
|
|
||||||
def setTop(self, tp):
|
|
||||||
self.v[BL].y = tp - (self.v[TR].y - self.v[BL].y)
|
|
||||||
self.v[TR].y = tp
|
|
||||||
self.updateV34()
|
|
||||||
|
|
||||||
def getLeft(self):
|
|
||||||
return self.v[BL].x
|
|
||||||
|
|
||||||
def getRight(self):
|
|
||||||
return self.v[TR].x
|
|
||||||
|
|
||||||
def getBottom(self):
|
|
||||||
return self.v[BL].y
|
|
||||||
|
|
||||||
def getTop(self):
|
|
||||||
return self.v[TR].y
|
|
||||||
|
|
||||||
def overlapAll(self, boxLs, intersectCache): # Flag index lets us know which quadere
|
|
||||||
''' Returns none, meaning it didnt overlap any new boxes '''
|
|
||||||
v= self.v
|
|
||||||
if v[BL].x < 0:
|
|
||||||
return True
|
|
||||||
elif v[BL].y < 0:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
bIdx = len(intersectCache)
|
|
||||||
while bIdx:
|
|
||||||
bIdx-=1
|
|
||||||
b = intersectCache[bIdx]
|
|
||||||
if not ( v[TR].y <= b.v[BL].y or\
|
|
||||||
v[BL].y >= b.v[TR].y or\
|
|
||||||
v[BL].x >= b.v[TR].x or\
|
|
||||||
v[TR].x <= b.v[BL].x ):
|
|
||||||
|
|
||||||
return True # Intersection with existing box
|
|
||||||
#return 0 # Must keep looking
|
|
||||||
|
|
||||||
for b in boxLs.boxes:
|
|
||||||
if not (v[TR].y <= b.v[BL].y or\
|
|
||||||
v[BL].y >= b.v[TR].y or\
|
|
||||||
v[BL].x >= b.v[TR].x or\
|
|
||||||
v[TR].x <= b.v[BL].x ):
|
|
||||||
|
|
||||||
return b # Intersection with new box.
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place(self, vert, quad):
|
|
||||||
'''
|
|
||||||
Place the box on the free quadrent of the vert
|
|
||||||
'''
|
|
||||||
if quad == BLF:
|
|
||||||
self.setRight(vert.x)
|
|
||||||
self.setTop(vert.y)
|
|
||||||
|
|
||||||
elif quad == TRF:
|
|
||||||
self.setLeft(vert.x)
|
|
||||||
self.setBottom(vert.y)
|
|
||||||
|
|
||||||
elif quad == TLF:
|
|
||||||
self.setRight(vert.x)
|
|
||||||
self.setBottom(vert.y)
|
|
||||||
|
|
||||||
elif quad == BRF:
|
|
||||||
self.setLeft(vert.x)
|
|
||||||
self.setTop(vert.y)
|
|
||||||
|
|
||||||
# Trys to lock a box onto another box's verts
|
|
||||||
# cleans up double verts after
|
|
||||||
def tryVert(self, boxes, baseVert):
|
|
||||||
for flagIndex, freeQuad in enumerate(quadFlagLs):
|
|
||||||
#print 'Testing ', self.width
|
|
||||||
if baseVert.free & freeQuad:
|
|
||||||
|
|
||||||
self.place(baseVert, freeQuad)
|
|
||||||
overlapBox = self.overlapAll(boxes, baseVert.intersectCache[flagIndex])
|
|
||||||
if overlapBox is False: # There is no overlap
|
|
||||||
baseVert.free &= ~freeQuad # Removes quad
|
|
||||||
# Appends all verts but the one that matches. this removes the need for remove doubles
|
|
||||||
for vIdx in (0,1,2,3): # (BL,TR,TL,BR) / 0,1,2,3
|
|
||||||
self_v= self.v[vIdx] # shortcut
|
|
||||||
if not (self_v.x == baseVert.x and self_v.y == baseVert.y):
|
|
||||||
boxList.packedVerts.verts.append(self_v)
|
|
||||||
else:
|
|
||||||
baseVert.free &= self_v.free # make sure the that any unfree areas are wiped.
|
|
||||||
|
|
||||||
# Inherit used boxes from old verts
|
|
||||||
if self_v.blb: baseVert.blb = self_v.blb
|
|
||||||
if self_v.brb: baseVert.brb = self_v.brb #print 'inherit2'
|
|
||||||
if self_v.tlb: baseVert.tlb = self_v.tlb #print 'inherit3'
|
|
||||||
if self_v.trb: baseVert.trb = self_v.trb #print 'inherit4'
|
|
||||||
self.v[vIdx] = baseVert
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Logical checking for used verts by compares box sized and works out verts that may be free.
|
|
||||||
# Verticle
|
|
||||||
|
|
||||||
if baseVert.tlb and baseVert.trb and\
|
|
||||||
(self == baseVert.tlb or self == baseVert.trb):
|
|
||||||
if baseVert.tlb.height > baseVert.trb.height:
|
|
||||||
baseVert.trb.v[TL].free &= ~(TLF|BLF)
|
|
||||||
elif baseVert.tlb.height < baseVert.trb.height:
|
|
||||||
baseVert.tlb.v[TR].free &= ~(TRF|BRF)
|
|
||||||
else: # same
|
|
||||||
baseVert.tlb.v[TR].free &= ~BLF
|
|
||||||
baseVert.trb.v[TL].free &= ~BRF
|
|
||||||
|
|
||||||
|
|
||||||
elif baseVert.blb and baseVert.brb and\
|
|
||||||
(self == baseVert.blb or self == baseVert.brb):
|
|
||||||
if baseVert.blb.height > baseVert.brb.height:
|
|
||||||
baseVert.brb.v[BL].free &= ~(TLF|BLF)
|
|
||||||
elif baseVert.blb.height < baseVert.brb.height:
|
|
||||||
baseVert.blb.v[BR].free &= ~(TRF|BRF)
|
|
||||||
else: # same
|
|
||||||
baseVert.blb.v[BR].free &= ~TRF
|
|
||||||
baseVert.brb.v[BL].free &= ~TLF
|
|
||||||
|
|
||||||
# Horizontal
|
|
||||||
if baseVert.tlb and baseVert.blb and\
|
|
||||||
(self == baseVert.tlb or self == baseVert.blb):
|
|
||||||
if baseVert.tlb.width > baseVert.blb.width:
|
|
||||||
baseVert.blb.v[TL].free &= ~(TLF|TRF)
|
|
||||||
elif baseVert.tlb.width < baseVert.blb.width:
|
|
||||||
baseVert.tlb.v[BL].free &= ~(BLF|BRF)
|
|
||||||
else: # same
|
|
||||||
baseVert.blb.v[TL].free &= ~TRF
|
|
||||||
baseVert.tlb.v[BL].free &= ~BRF
|
|
||||||
|
|
||||||
|
|
||||||
elif baseVert.trb and baseVert.brb and\
|
|
||||||
(self == baseVert.trb or self == baseVert.brb):
|
|
||||||
if baseVert.trb.width > baseVert.brb.width:
|
|
||||||
baseVert.brb.v[TR].free &= ~(TRF|TRF)
|
|
||||||
elif baseVert.trb.width < baseVert.brb.width:
|
|
||||||
baseVert.trb.v[BR].free &= ~(BLF|BRF)
|
|
||||||
else: # same
|
|
||||||
baseVert.brb.v[TR].free &= ~TLF
|
|
||||||
baseVert.trb.v[BR].free &= ~BLF
|
|
||||||
# END LOGICAL VREE SIZE REMOVAL
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 1 # Working
|
|
||||||
|
|
||||||
# We have a box that intersects that quadrent.
|
|
||||||
elif overlapBox is not False and overlapBox is not True: # True is used for a box thats alredt in the freq list or out of bounds error.
|
|
||||||
# There was an overlap, add this box to the verts list
|
|
||||||
#quadFlagLs = (BLF,BRF,TLF,TRF)
|
|
||||||
baseVert.intersectCache[flagIndex].append(overlapBox)
|
|
||||||
|
|
||||||
# Limit the cache size
|
|
||||||
if len(baseVert.intersectCache[flagIndex]) > 8:
|
|
||||||
del baseVert.intersectCache[flagIndex][0]
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
class boxList:
|
|
||||||
#Global vert pool, stores used lists
|
|
||||||
packedVerts = vertList() # will be vertList()
|
|
||||||
|
|
||||||
def __init__(self, boxes):
|
|
||||||
self.boxes = boxes
|
|
||||||
|
|
||||||
# keep a running update of the width and height so we know the area
|
|
||||||
# initialize with first box, fixes but where we whwere only packing 1 box
|
|
||||||
# At the moment we only start with 1 box so the code below will loop over 1. but thats ok.
|
|
||||||
width = height = 0.0
|
|
||||||
if boxes:
|
|
||||||
for b in boxes:
|
|
||||||
if width < b.width: width= b.width
|
|
||||||
if height < b.height: height= b.height
|
|
||||||
self.width= width
|
|
||||||
self.height= height
|
|
||||||
|
|
||||||
# boxArea is the total area of all boxes in the list,
|
|
||||||
# can be used with packArea() to determine waistage.
|
|
||||||
self.boxArea = 0 # incremented with addBox()
|
|
||||||
|
|
||||||
|
|
||||||
# Just like MyBoxLs.boxes.append(), but sets bounds
|
|
||||||
def addBoxPack(self, box):
|
|
||||||
'''Adds the box to the boxlist and resized the main bounds and adds area. '''
|
|
||||||
self.width = max(self.width, box.getRight())
|
|
||||||
self.height = max(self.height, box.getTop())
|
|
||||||
|
|
||||||
self.boxArea += box.area
|
|
||||||
|
|
||||||
# iterate through these
|
|
||||||
#~ quadFlagLs = (1,8,4,2)
|
|
||||||
#~ # Flags for vert idx used quads
|
|
||||||
#~ BLF = 1; TRF = 2; TLF = 4; BRF = 8
|
|
||||||
#~ quadFlagLs = (BLF,BRF,TLF,TRF)
|
|
||||||
|
|
||||||
# Look through all the free vert quads and see if there are some we can remove
|
|
||||||
#
|
|
||||||
|
|
||||||
for v in box.v:
|
|
||||||
|
|
||||||
# Is my bottom being used.
|
|
||||||
|
|
||||||
if v.free & BLF and v.free & BRF: # BLF and BRF
|
|
||||||
for b in self.boxes:
|
|
||||||
if b.v[TR].y == v.y:
|
|
||||||
if b.v[TR].x > v.x:
|
|
||||||
if b.v[BL].x < v.x:
|
|
||||||
v.free &= ~(BLF|BRF) # Removes quad
|
|
||||||
|
|
||||||
# Is my left being used.
|
|
||||||
if v.free & BLF and v.free & TLF:
|
|
||||||
for b in self.boxes:
|
|
||||||
if b.v[TR].x == v.x:
|
|
||||||
if b.v[TR].y > v.y:
|
|
||||||
if b.v[BL].y < v.y:
|
|
||||||
v.free &= ~(BLF|TLF) # Removes quad
|
|
||||||
|
|
||||||
if v.free & TRF and v.free & TLF:
|
|
||||||
# Is my top being used.
|
|
||||||
for b in self.boxes:
|
|
||||||
if b.v[BL].y == v.y:
|
|
||||||
if b.v[TR].x > v.x:
|
|
||||||
if b.v[BL].x < v.x:
|
|
||||||
v.free &= ~(TLF|TRF) # Removes quad
|
|
||||||
|
|
||||||
|
|
||||||
# Is my right being used.
|
|
||||||
if v.free & TRF and v.free & BRF:
|
|
||||||
for b in self.boxes:
|
|
||||||
if b.v[BL].x == v.x:
|
|
||||||
if b.v[TR].y > v.y:
|
|
||||||
if b.v[BL].y < v.y:
|
|
||||||
v.free &= ~(BRF|TRF) # Removes quad
|
|
||||||
|
|
||||||
|
|
||||||
self.boxes.append(box)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Just like MyBoxLs.boxes.append(), but sets bounds
|
|
||||||
def addBox(self, box):
|
|
||||||
self.boxes.append(box)
|
|
||||||
self.boxArea += box.area
|
|
||||||
|
|
||||||
# The area of the backing bounds.
|
|
||||||
def packedArea(self):
|
|
||||||
return self.width * self.height
|
|
||||||
|
|
||||||
# Sort boxes by area
|
|
||||||
def sortArea(self):
|
|
||||||
try: self.boxes.sort(key=lambda b: b.area )
|
|
||||||
except: self.boxes.sort(lambda A, B: cmp(A.area, B.area) )
|
|
||||||
|
|
||||||
|
|
||||||
# BLENDER only
|
|
||||||
def draw(self):
|
|
||||||
m = NMesh.GetRaw()
|
|
||||||
|
|
||||||
|
|
||||||
for b in self.boxes:
|
|
||||||
z = min(b.width, b.height ) / max(b.width, b.height )
|
|
||||||
#z = b.farea
|
|
||||||
#z=0
|
|
||||||
f = NMesh.Face()
|
|
||||||
m.verts.append(NMesh.Vert(b.getLeft(), b.getBottom(), z))
|
|
||||||
f.v.append(m.verts[-1])
|
|
||||||
m.verts.append(NMesh.Vert(b.getRight(), b.getBottom(), z))
|
|
||||||
f.v.append(m.verts[-1])
|
|
||||||
m.verts.append(NMesh.Vert(b.getRight(), b.getTop(), z))
|
|
||||||
f.v.append(m.verts[-1])
|
|
||||||
m.verts.append(NMesh.Vert(b.getLeft(), b.getTop(), z))
|
|
||||||
f.v.append(m.verts[-1])
|
|
||||||
m.faces.append(f)
|
|
||||||
NMesh.PutRaw(m, 's')
|
|
||||||
Window.Redraw(1)
|
|
||||||
|
|
||||||
def pack(self):
|
|
||||||
self.sortArea()
|
|
||||||
|
|
||||||
if not self.boxes:
|
|
||||||
return
|
|
||||||
|
|
||||||
packedboxes = boxList([self.boxes[-1]])
|
|
||||||
|
|
||||||
# Remove verts we KNOW cant be added to
|
|
||||||
|
|
||||||
unpackedboxes = self.boxes[:-1]
|
|
||||||
|
|
||||||
# Start with this box, the biggest box
|
|
||||||
boxList.packedVerts.verts.extend(packedboxes.boxes[0].v)
|
|
||||||
|
|
||||||
while unpackedboxes: # != [] - while the list of unpacked boxes is not empty.
|
|
||||||
|
|
||||||
freeBoxIdx = len(unpackedboxes)
|
|
||||||
while freeBoxIdx:
|
|
||||||
freeBoxIdx-=1
|
|
||||||
freeBoxContext= unpackedboxes[freeBoxIdx]
|
|
||||||
# Sort the verts with this boxes dimensions as a bias, so less poky out bits are made.
|
|
||||||
boxList.packedVerts.sortCorner(freeBoxContext.width, freeBoxContext.height)
|
|
||||||
|
|
||||||
vertIdx = 0
|
|
||||||
|
|
||||||
for baseVert in boxList.packedVerts.verts:
|
|
||||||
if baseVert.free: # != 0
|
|
||||||
# This will lock the box if its possibel
|
|
||||||
if freeBoxContext.tryVert(packedboxes, baseVert):
|
|
||||||
packedboxes.addBoxPack( unpackedboxes.pop(freeBoxIdx) ) # same as freeBoxContext. but may as well pop at the same time.
|
|
||||||
freeBoxIdx = -1
|
|
||||||
break
|
|
||||||
|
|
||||||
freeBoxIdx +=1
|
|
||||||
|
|
||||||
boxList.packedVerts.verts = [] # Free the list, so it dosent use ram between runs.
|
|
||||||
|
|
||||||
self.width = packedboxes.width
|
|
||||||
self.height = packedboxes.height
|
|
||||||
#
|
|
||||||
def list(self):
|
|
||||||
''' Once packed, return a list of all boxes as a list of tuples - (X/Y/WIDTH/HEIGHT) '''
|
|
||||||
return [(b.id, b.getLeft(), b.getBottom(), b.width, b.height ) for b in self.boxes]
|
|
||||||
|
|
||||||
|
|
||||||
''' Define all globals here '''
|
|
||||||
# vert IDX's, make references easier to understand.
|
|
||||||
BL = 0; TR = 1; TL = 2; BR = 3
|
|
||||||
|
|
||||||
# iterate through these
|
|
||||||
# Flags for vert idx used quads
|
|
||||||
BLF = 1; TRF = 2; TLF = 4; BRF = 8
|
|
||||||
quadFlagLs = (BLF,BRF,TLF,TRF)
|
|
||||||
|
|
||||||
|
|
||||||
# Packs a list w/h's into box types and places then #Iter times
|
|
||||||
def boxPackIter(boxLs, iter=1, draw=0):
|
|
||||||
iterIdx = 0
|
|
||||||
bestArea = None
|
|
||||||
# Iterate over packing the boxes to get the best FIT!
|
|
||||||
while iterIdx < iter:
|
|
||||||
myBoxLs = boxList([])
|
|
||||||
for b in boxLs:
|
|
||||||
myBoxLs.addBox( box(b[1], b[2], b[0]) ) # w/h/id
|
|
||||||
|
|
||||||
myBoxLs.pack()
|
|
||||||
# myBoxLs.draw() # Draw as we go?
|
|
||||||
|
|
||||||
newArea = myBoxLs.packedArea()
|
|
||||||
|
|
||||||
#print 'pack test %s of %s, area:%.2f' % (iterIdx, iter, newArea)
|
|
||||||
|
|
||||||
# First time?
|
|
||||||
if bestArea == None:
|
|
||||||
bestArea = newArea
|
|
||||||
bestBoxLs = myBoxLs
|
|
||||||
elif newArea < bestArea:
|
|
||||||
bestArea = newArea
|
|
||||||
bestBoxLs = myBoxLs
|
|
||||||
iterIdx+=1
|
|
||||||
|
|
||||||
|
|
||||||
if draw:
|
|
||||||
bestBoxLs.draw()
|
|
||||||
|
|
||||||
#print 'best area: %.4f, %.2f%% efficient' % (bestArea, (float(bestBoxLs.boxArea) / (bestArea+0.000001))*100)
|
|
||||||
|
|
||||||
return bestBoxLs.width, bestBoxLs.height, bestBoxLs.list()
|
|
@ -44,7 +44,7 @@ struct ListBase;
|
|||||||
struct MemFile;
|
struct MemFile;
|
||||||
|
|
||||||
#define BLENDER_VERSION 243
|
#define BLENDER_VERSION 243
|
||||||
#define BLENDER_SUBVERSION 1
|
#define BLENDER_SUBVERSION 2
|
||||||
|
|
||||||
#define BLENDER_MINVERSION 240
|
#define BLENDER_MINVERSION 240
|
||||||
#define BLENDER_MINSUBVERSION 0
|
#define BLENDER_MINSUBVERSION 0
|
||||||
|
@ -184,6 +184,7 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type,
|
|||||||
int CustomData_get_layer_index(const struct CustomData *data, int type);
|
int CustomData_get_layer_index(const struct CustomData *data, int type);
|
||||||
int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name);
|
int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name);
|
||||||
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
|
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
|
||||||
|
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
|
||||||
|
|
||||||
/* copies the data from source to the data element at index in the first
|
/* copies the data from source to the data element at index in the first
|
||||||
* layer of type
|
* layer of type
|
||||||
@ -204,6 +205,7 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi
|
|||||||
|
|
||||||
/* sets the nth layer of type as active */
|
/* sets the nth layer of type as active */
|
||||||
void CustomData_set_layer_active(struct CustomData *data, int type, int n);
|
void CustomData_set_layer_active(struct CustomData *data, int type, int n);
|
||||||
|
void CustomData_set_layer_render(struct CustomData *data, int type, int n);
|
||||||
|
|
||||||
/* adds flag to the layer flags */
|
/* adds flag to the layer flags */
|
||||||
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag);
|
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag);
|
||||||
|
@ -410,7 +410,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
|
|||||||
{
|
{
|
||||||
const LayerTypeInfo *typeInfo;
|
const LayerTypeInfo *typeInfo;
|
||||||
CustomDataLayer *layer, *newlayer;
|
CustomDataLayer *layer, *newlayer;
|
||||||
int i, type, number = 0, lasttype = -1, lastactive = 0;
|
int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0;
|
||||||
|
|
||||||
for(i = 0; i < source->totlayer; ++i) {
|
for(i = 0; i < source->totlayer; ++i) {
|
||||||
layer = &source->layers[i];
|
layer = &source->layers[i];
|
||||||
@ -421,6 +421,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
|
|||||||
if (type != lasttype) {
|
if (type != lasttype) {
|
||||||
number = 0;
|
number = 0;
|
||||||
lastactive = layer->active;
|
lastactive = layer->active;
|
||||||
|
lastrender = layer->active_rnd;
|
||||||
lasttype = type;
|
lasttype = type;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -437,8 +438,10 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
|
|||||||
newlayer = customData_add_layer__internal(dest, type, alloctype,
|
newlayer = customData_add_layer__internal(dest, type, alloctype,
|
||||||
layer->data, totelem, layer->name);
|
layer->data, totelem, layer->name);
|
||||||
|
|
||||||
if(newlayer)
|
if(newlayer) {
|
||||||
newlayer->active = lastactive;
|
newlayer->active = lastactive;
|
||||||
|
newlayer->active_rnd = lastrender;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,6 +529,17 @@ int CustomData_get_active_layer_index(const CustomData *data, int type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CustomData_get_render_layer_index(const CustomData *data, int type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i < data->totlayer; ++i)
|
||||||
|
if(data->layers[i].type == type)
|
||||||
|
return i + data->layers[i].active_rnd;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void CustomData_set_layer_active(CustomData *data, int type, int n)
|
void CustomData_set_layer_active(CustomData *data, int type, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -535,6 +549,16 @@ void CustomData_set_layer_active(CustomData *data, int type, int n)
|
|||||||
data->layers[i].active = n;
|
data->layers[i].active = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CustomData_set_layer_render(CustomData *data, int type, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i < data->totlayer; ++i)
|
||||||
|
if(data->layers[i].type == type)
|
||||||
|
data->layers[i].active_rnd = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag)
|
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -617,11 +641,14 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||||||
else
|
else
|
||||||
data->layers[index].name[0] = '\0';
|
data->layers[index].name[0] = '\0';
|
||||||
|
|
||||||
if(index > 0 && data->layers[index-1].type == type)
|
if(index > 0 && data->layers[index-1].type == type) {
|
||||||
data->layers[index].active = data->layers[index-1].active;
|
data->layers[index].active = data->layers[index-1].active;
|
||||||
else
|
data->layers[index].active_rnd = data->layers[index-1].active_rnd;
|
||||||
|
} else {
|
||||||
data->layers[index].active = 0;
|
data->layers[index].active = 0;
|
||||||
|
data->layers[index].active_rnd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
customData_update_offsets(data);
|
customData_update_offsets(data);
|
||||||
|
|
||||||
return &data->layers[index];
|
return &data->layers[index];
|
||||||
@ -679,8 +706,10 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
|
|||||||
i = CustomData_get_layer_index(data, type);
|
i = CustomData_get_layer_index(data, type);
|
||||||
|
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
for (; i < data->totlayer && data->layers[i].type == type; i++)
|
for (; i < data->totlayer && data->layers[i].type == type; i++) {
|
||||||
data->layers[i].active--;
|
data->layers[i].active--;
|
||||||
|
data->layers[i].active_rnd--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->totlayer <= data->maxlayer-CUSTOMDATA_GROW)
|
if (data->totlayer <= data->maxlayer-CUSTOMDATA_GROW)
|
||||||
|
@ -4316,6 +4316,18 @@ static void customdata_version_242(Mesh *me)
|
|||||||
mesh_update_customdata_pointers(me);
|
mesh_update_customdata_pointers(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*only copy render texface layer from active*/
|
||||||
|
static void customdata_version_243(Mesh *me)
|
||||||
|
{
|
||||||
|
CustomDataLayer *layer;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
for (a=0; a < me->fdata.totlayer; a++) {
|
||||||
|
layer= &me->fdata.layers[a];
|
||||||
|
layer->active_rnd = layer->active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* struct NodeImageAnim moved to ImageUser, and we make it default available */
|
/* struct NodeImageAnim moved to ImageUser, and we make it default available */
|
||||||
static void do_version_ntree_242_2(bNodeTree *ntree)
|
static void do_version_ntree_242_2(bNodeTree *ntree)
|
||||||
{
|
{
|
||||||
@ -6416,6 +6428,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* render layer added, this is not the active layer */
|
||||||
|
if(main->versionfile <= 243 || main->subversionfile < 2) {
|
||||||
|
Mesh *me;
|
||||||
|
for(me=main->mesh.first; me; me=me->id.next)
|
||||||
|
customdata_version_243(me);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||||
|
@ -406,6 +406,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
|
|||||||
#define B_SETTFACE 2079
|
#define B_SETTFACE 2079
|
||||||
#define B_SETMCOL 2080
|
#define B_SETMCOL 2080
|
||||||
#define B_JOINTRIA 2081
|
#define B_JOINTRIA 2081
|
||||||
|
#define B_SETTFACE_RND 2082
|
||||||
|
#define B_SETMCOL_RND 2083
|
||||||
|
|
||||||
/* *********************** */
|
/* *********************** */
|
||||||
#define B_VGROUPBUTS 2100
|
#define B_VGROUPBUTS 2100
|
||||||
|
@ -38,6 +38,8 @@ typedef struct CustomDataLayer {
|
|||||||
int offset; /* in editmode, offset of layer in block */
|
int offset; /* in editmode, offset of layer in block */
|
||||||
int flag; /* general purpose flag */
|
int flag; /* general purpose flag */
|
||||||
int active; /* number of the active layer of this type */
|
int active; /* number of the active layer of this type */
|
||||||
|
int active_rnd; /* number of the layer to render*/
|
||||||
|
char pad[4];
|
||||||
char name[32]; /* layer name */
|
char name[32]; /* layer name */
|
||||||
void *data; /* layer data */
|
void *data; /* layer data */
|
||||||
} CustomDataLayer;
|
} CustomDataLayer;
|
||||||
|
@ -1757,7 +1757,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak
|
|||||||
|
|
||||||
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
|
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
|
||||||
mtface= &((MTFace*)layer->data)[edp->f];
|
mtface= &((MTFace*)layer->data)[edp->f];
|
||||||
n= vlakren_customdata_layer_num(mtfn++, layer->active);
|
n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
|
||||||
mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
|
mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
|
||||||
|
|
||||||
*mtf= *mtface;
|
*mtf= *mtface;
|
||||||
@ -1769,7 +1769,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak
|
|||||||
}
|
}
|
||||||
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
|
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
|
||||||
mcol= &((MCol*)layer->data)[edp->f*4];
|
mcol= &((MCol*)layer->data)[edp->f*4];
|
||||||
n= vlakren_customdata_layer_num(mcn++, layer->active);
|
n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
|
||||||
mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
|
mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
|
||||||
|
|
||||||
mc[0]= mcol[edp->i1];
|
mc[0]= mcol[edp->i1];
|
||||||
@ -1996,13 +1996,13 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
|
|||||||
name= layer->name;
|
name= layer->name;
|
||||||
|
|
||||||
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
|
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
|
||||||
n= vlakren_customdata_layer_num(mtfn++, layer->active);
|
n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
|
||||||
mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
|
mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
|
||||||
mtface= (MTFace*)layer->data;
|
mtface= (MTFace*)layer->data;
|
||||||
*mtf= mtface[a];
|
*mtf= mtface[a];
|
||||||
}
|
}
|
||||||
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
|
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
|
||||||
n= vlakren_customdata_layer_num(mcn++, layer->active);
|
n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
|
||||||
mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
|
mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
|
||||||
mcol= (MCol*)layer->data;
|
mcol= (MCol*)layer->data;
|
||||||
memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
|
memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
|
||||||
|
@ -172,7 +172,7 @@
|
|||||||
|
|
||||||
static float editbutweight= 1.0;
|
static float editbutweight= 1.0;
|
||||||
float editbutvweight= 1;
|
float editbutvweight= 1;
|
||||||
static int actmcol= 0, acttface= 0;
|
static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0;
|
||||||
|
|
||||||
extern ListBase editNurb;
|
extern ListBase editNurb;
|
||||||
|
|
||||||
@ -691,10 +691,10 @@ static void delete_customdata_layer(void *data1, void *data2)
|
|||||||
Mesh *me= (Mesh*)data1;
|
Mesh *me= (Mesh*)data1;
|
||||||
CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
|
CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
|
||||||
CustomDataLayer *layer= (CustomDataLayer*)data2;
|
CustomDataLayer *layer= (CustomDataLayer*)data2;
|
||||||
void *actlayerdata, *layerdata=layer->data;
|
void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
|
||||||
int type= layer->type;
|
int type= layer->type;
|
||||||
int index= CustomData_get_layer_index(data, type);
|
int index= CustomData_get_layer_index(data, type);
|
||||||
int i, actindex;
|
int i, actindex, rndindex;
|
||||||
|
|
||||||
/*ok, deleting a non-active layer needs to preserve the active layer indices.
|
/*ok, deleting a non-active layer needs to preserve the active layer indices.
|
||||||
to do this, we store a pointer to the .data member of both layer and the active layer,
|
to do this, we store a pointer to the .data member of both layer and the active layer,
|
||||||
@ -704,6 +704,7 @@ static void delete_customdata_layer(void *data1, void *data2)
|
|||||||
this is necassary because the deletion functions only support deleting the active
|
this is necassary because the deletion functions only support deleting the active
|
||||||
layer. */
|
layer. */
|
||||||
actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
|
actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
|
||||||
|
rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
|
||||||
CustomData_set_layer_active(data, type, layer - &data->layers[index]);
|
CustomData_set_layer_active(data, type, layer - &data->layers[index]);
|
||||||
|
|
||||||
/* Multires is handled seperately because the display data is separate
|
/* Multires is handled seperately because the display data is separate
|
||||||
@ -741,6 +742,21 @@ static void delete_customdata_layer(void *data1, void *data2)
|
|||||||
CustomData_set_layer_active(data, type, actindex);
|
CustomData_set_layer_active(data, type, actindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rndlayerdata != layerdata) {
|
||||||
|
/*find index. . .*/
|
||||||
|
rndindex = CustomData_get_layer_index(data, type);
|
||||||
|
for (i=rndindex; i<data->totlayer; i++) {
|
||||||
|
if (data->layers[i].data == rndlayerdata) {
|
||||||
|
rndindex = i - rndindex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*set index. . .*/
|
||||||
|
CustomData_set_layer_render(data, type, rndindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||||
|
|
||||||
if(type == CD_MTFACE)
|
if(type == CD_MTFACE)
|
||||||
@ -753,7 +769,12 @@ static void delete_customdata_layer(void *data1, void *data2)
|
|||||||
allqueue(REDRAWBUTSEDIT, 0);
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int customdata_buttons(uiBlock *block, Mesh *me, CustomData *data, int type, int *activep, int setevt, int newevt, char *label, char *shortlabel, char *browsetip, char *newtip, char *deltip, int x, int y)
|
static int customdata_buttons(
|
||||||
|
uiBlock *block, Mesh *me, CustomData *data,
|
||||||
|
int type, int *activep, int *renderp,
|
||||||
|
int setevt, int setevt_rnd, int newevt,
|
||||||
|
char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
|
||||||
|
char *newtip, char *deltip, int x, int y)
|
||||||
{
|
{
|
||||||
CustomDataLayer *layer;
|
CustomDataLayer *layer;
|
||||||
uiBut *but;
|
uiBut *but;
|
||||||
@ -777,9 +798,11 @@ static int customdata_buttons(uiBlock *block, Mesh *me, CustomData *data, int ty
|
|||||||
|
|
||||||
if(layer->type == type) {
|
if(layer->type == type) {
|
||||||
*activep= layer->active + 1;
|
*activep= layer->active + 1;
|
||||||
|
*renderp= layer->active_rnd + 1;
|
||||||
|
|
||||||
uiDefButI(block, ROW, setevt, "", x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
|
uiDefButI(block, ROW, setevt, "A", x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
|
||||||
but=uiDefBut(block, TEX, setevt, "", x+25,y,170,19, layer->name, 0.0, 31.0, 0, 0, label);
|
uiDefButI(block, ROW, setevt_rnd, "R", x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
|
||||||
|
but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
|
||||||
uiButSetFunc(but, verify_customdata_name_func, data, layer);
|
uiButSetFunc(but, verify_customdata_name_func, data, layer);
|
||||||
but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
|
but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
|
||||||
uiButSetFunc(but, delete_customdata_layer, me, layer);
|
uiButSetFunc(but, delete_customdata_layer, me, layer);
|
||||||
@ -848,14 +871,14 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me)
|
|||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
|
||||||
fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
|
fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
|
||||||
yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface,
|
yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
|
||||||
B_SETTFACE, B_NEWTFACE, "UV Texture", "UV Texture:",
|
B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
|
||||||
"Set active UV texture", "Creates a new UV texture layer",
|
"Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
|
||||||
"Removes the current UV texture layer", 190, 130);
|
"Removes the current UV texture layer", 190, 130);
|
||||||
|
|
||||||
yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol,
|
yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
|
||||||
B_SETMCOL, B_NEWMCOL, "Vertex Color", "Vertex Color:",
|
B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
|
||||||
"Sets active vertex color layer", "Creates a new vertex color layer",
|
"Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
|
||||||
"Removes the current vertex color layer", 190, yco-5);
|
"Removes the current vertex color layer", 190, yco-5);
|
||||||
|
|
||||||
if(yco < 0)
|
if(yco < 0)
|
||||||
@ -4147,6 +4170,15 @@ void do_meshbuts(unsigned short event)
|
|||||||
allqueue(REDRAWBUTSEDIT, 0);
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case B_SETMCOL_RND:
|
||||||
|
if (G.obedit || me) {
|
||||||
|
CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
|
||||||
|
CustomData_set_layer_render(fdata, CD_MCOL, actmcol_rnd-1);
|
||||||
|
|
||||||
|
BIF_undo_push("Set Render Vertex Color");
|
||||||
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case B_NEWTFACE:
|
case B_NEWTFACE:
|
||||||
if(me)
|
if(me)
|
||||||
@ -4197,7 +4229,15 @@ void do_meshbuts(unsigned short event)
|
|||||||
allqueue(REDRAWIMAGE, 0);
|
allqueue(REDRAWIMAGE, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case B_SETTFACE_RND:
|
||||||
|
if (G.obedit || me) {
|
||||||
|
CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
|
||||||
|
CustomData_set_layer_render(fdata, CD_MTFACE, acttface_rnd-1);
|
||||||
|
BIF_undo_push("Set Render UV Texture");
|
||||||
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case B_FLIPNORM:
|
case B_FLIPNORM:
|
||||||
if(G.obedit) {
|
if(G.obedit) {
|
||||||
flip_editnormals();
|
flip_editnormals();
|
||||||
|
Loading…
Reference in New Issue
Block a user