From efd88ba4a0b24de5e451ae1fac28a624fd3b2f7c Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Thu, 23 Aug 2018 13:12:43 +0400 Subject: [PATCH 001/129] fix bugs: now works in a blender 2.79b --- molecular/__init__.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index b72cae9..c4d5c77 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,8 +19,8 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil)", - "version": (1, 0, 1), - "blender": (2, 6, 8), + "version": (1, 0, 3), + "blender": (2, 7, 9), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), "warning": "", # used for warning icon and text in addons panel @@ -329,7 +329,7 @@ def draw(self, context): subbox = box.box() subbox.enabled = psys.settings.mol_links_active - subbox.label(text = "Initial Linking (at bird):") + subbox.label(text = "Initial Linking (at birth):") row = subbox.row() row.prop(psys.settings,"mol_link_length",text = "search length") row.prop(psys.settings,"mol_link_rellength",text = "Relative") @@ -666,7 +666,8 @@ def execute(self, context): context.scene.objects.link(object2) mod = object2.modifiers.new("tri_for_uv","TRIANGULATE") - mod.use_beauty = False + mod.ngon_method = 'BEAUTY' + mod.quad_method = 'BEAUTY' newmesh = object2.to_mesh(bpy.context.scene,True,"RENDER",True,False) object2.data = newmesh context.scene.update() @@ -684,21 +685,21 @@ def execute(self, context): parloc = (par.location * object2.matrix_world) - object2.location point = object2.closest_point_on_mesh(parloc) #print('closest:',par.location,point[0],point[2]) - vindex1 = object2.data.polygons[point[2]].vertices[0] - vindex2 = object2.data.polygons[point[2]].vertices[1] - vindex3 = object2.data.polygons[point[2]].vertices[2] + vindex1 = object2.data.polygons[point[3]].vertices[0] + vindex2 = object2.data.polygons[point[3]].vertices[1] + vindex3 = object2.data.polygons[point[3]].vertices[2] v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() - uvindex1 = object2.data.polygons[point[2]].loop_start + 0 - uvindex2 = object2.data.polygons[point[2]].loop_start + 1 - uvindex3 = object2.data.polygons[point[2]].loop_start + 2 + uvindex1 = object2.data.polygons[point[3]].loop_start + 0 + uvindex2 = object2.data.polygons[point[3]].loop_start + 1 + uvindex3 = object2.data.polygons[point[3]].loop_start + 2 uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() #print(vertices1.co,vertices2.co,vertices3.co) #print(uv1,uv2,uv3) - p = object2.matrix_world * point[0] + p = object2.matrix_world * point[1] v1 = Vector(v1) v2 = Vector(v2) v3 = Vector(v3) From 9ed2f976d3128939affb1f2500c1e88fd861b35a Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 25 Aug 2018 12:15:18 +0400 Subject: [PATCH 002/129] UI fix --- molecular/__init__.py | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index c4d5c77..d83eb08 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -56,8 +56,8 @@ def define_props(): parset.mol_selfcollision_active = bpy.props.BoolProperty(name = "mol_selfcollision_active", description = "Activate self collsion between particles in the system",default = False) parset.mol_othercollision_active = bpy.props.BoolProperty(name = "mol_othercollision_active", description = "Activate collision with particles from others systems",default = False) - parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1) - parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1) + parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') + parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') item = [] for i in range(1,12): item.append((str(i),"Collision Group " + str(i),"collide only with group " + str(i) )) @@ -65,28 +65,28 @@ def define_props(): parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) - parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005) + parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 3, default = 1) - parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 3, default = 0) + parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 6, default = 0, subtype='FACTOR') parset.mol_link_max = bpy.props.IntProperty(name = "mol_link_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1) - parset.mol_link_stiffrand = bpy.props.FloatProperty(name = "mol_link_stiffrand", description = "Random variation for stiffness",min = 0 ,max = 1 ,default = 0) + parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_stiffrand = bpy.props.FloatProperty(name = "mol_link_stiffrand", description = "Random variation for stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') parset.mol_link_stiffexp = bpy.props.IntProperty(name = "mol_link_stiffexp", description = "Give a exponent force to the spring links", default = 1, min = 1 , max = 10) - parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1) - parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0) + parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) - parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0) + parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_link_samevalue = bpy.props.BoolProperty(name = "mol_link_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - parset.mol_link_estiff = bpy.props.FloatProperty(name = "mol_link_estiff", description = "Expension stiffness of links between particles",min = 0,max = 1, default = 1) - parset.mol_link_estiffrand = bpy.props.FloatProperty(name = "mol_link_estiffrand", description = "Random variation for expansion stiffness",min = 0 ,max = 1 ,default = 0) + parset.mol_link_estiff = bpy.props.FloatProperty(name = "mol_link_estiff", description = "Expension stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_estiffrand = bpy.props.FloatProperty(name = "mol_link_estiffrand", description = "Random variation for expansion stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') parset.mol_link_estiffexp = bpy.props.IntProperty(name = "mol_link_estiffexp", description = "Give a exponent force to the expension spring links", default = 1, min = 1 , max = 10) - parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1) - parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0) + parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) - parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0) + parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') item = [] @@ -94,27 +94,27 @@ def define_props(): item.append((str(i),"Relink Group " + str(i),"Relink only with group " + str(i) )) parset.mol_relink_group = bpy.props.EnumProperty(items = item, description = "Choose a group that new link are possible") parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0) - parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0) + parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 3, default = 1) - parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, precision = 3, default = 0) + parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_relink_max = bpy.props.IntProperty(name = "mol_relink_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1) - parset.mol_relink_stiffrand = bpy.props.FloatProperty(name = "mol_relink_stiffrand", description = "Random variation for stiffness",min = 0, max = 1 ,default = 0) + parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_stiffrand = bpy.props.FloatProperty(name = "mol_relink_stiffrand", description = "Random variation for stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') parset.mol_relink_stiffexp = bpy.props.IntProperty(name = "mol_relink_stiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_damp = bpy.props.FloatProperty(name = "mol_relink_damp", description = "Damping effect on spring links",min = 0, max = 1, default = 1) - parset.mol_relink_damprand = bpy.props.FloatProperty(name = "mol_relink_damprand", description = "Random variation on damping",min = 0 , max = 1, default = 0) - parset.mol_relink_broken = bpy.props.FloatProperty(name = "mol_relink_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) - parset.mol_relink_brokenrand = bpy.props.FloatProperty(name = "mol_relink_brokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0) + parset.mol_relink_damp = bpy.props.FloatProperty(name = "mol_relink_damp", description = "Damping effect on spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_damprand = bpy.props.FloatProperty(name = "mol_relink_damprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_broken = bpy.props.FloatProperty(name = "mol_relink_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_relink_brokenrand = bpy.props.FloatProperty(name = "mol_relink_brokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_relink_samevalue = bpy.props.BoolProperty(name = "mol_relink_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - parset.mol_relink_estiff = bpy.props.FloatProperty(name = "mol_relink_estiff", description = "Stiffness of links expension between particles",min = 0,max = 1, default = 1) - parset.mol_relink_estiffrand = bpy.props.FloatProperty(name = "mol_relink_estiffrand", description = "Random variation for expension stiffness",min = 0, max = 1 ,default = 0) + parset.mol_relink_estiff = bpy.props.FloatProperty(name = "mol_relink_estiff", description = "Stiffness of links expension between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_estiffrand = bpy.props.FloatProperty(name = "mol_relink_estiffrand", description = "Random variation for expension stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') parset.mol_relink_estiffexp = bpy.props.IntProperty(name = "mol_relink_estiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_edamp = bpy.props.FloatProperty(name = "mol_relink_edamp", description = "Damping effect on expension spring links",min = 0, max = 1, default = 1) - parset.mol_relink_edamprand = bpy.props.FloatProperty(name = "mol_relink_deamprand", description = "Random variation on damping",min = 0 , max = 0, default = 0) - parset.mol_relink_ebroken = bpy.props.FloatProperty(name = "mol_relink_ebroken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) - parset.mol_relink_ebrokenrand = bpy.props.FloatProperty(name = "mol_relink_ebrokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0) + parset.mol_relink_edamp = bpy.props.FloatProperty(name = "mol_relink_edamp", description = "Damping effect on expension spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_edamprand = bpy.props.FloatProperty(name = "mol_relink_deamprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_ebroken = bpy.props.FloatProperty(name = "mol_relink_ebroken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_relink_ebrokenrand = bpy.props.FloatProperty(name = "mol_relink_ebrokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_var1 = bpy.props.IntProperty(name = "mol_var1", description = "Current number of particles to calculate substep",min = 1, default = 1000) parset.mol_var2 = bpy.props.IntProperty(name = "mol_var2", description = "Current substep",min = 1, default = 4) From 465c62ffe6a436b33c045cc91b78fbc08d1f23ea Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 25 Aug 2018 12:22:20 +0400 Subject: [PATCH 003/129] Hide Molecular Panel --- molecular/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index d83eb08..5a3a284 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -267,7 +267,11 @@ class MolecularPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "particle" - + + @classmethod + def poll(cls, context): + return context.object.particle_systems.active + def draw_header(self, context): layout = self.layout obj = context.object From dde2ca43eabdab5a95d5599e6d80a2e094c897b8 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 22:50:55 +0400 Subject: [PATCH 004/129] remove old realesee --- release/molecular_20130106.zip | Bin 6028 -> 0 bytes release/molecular_20130203.zip | Bin 8851 -> 0 bytes release/molecular_latest.zip | Bin 8851 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 release/molecular_20130106.zip delete mode 100644 release/molecular_20130203.zip delete mode 100644 release/molecular_latest.zip diff --git a/release/molecular_20130106.zip b/release/molecular_20130106.zip deleted file mode 100644 index 4f44db3d8ef5fc115b2498fc13454f0264104a46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6028 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 C8=>3) diff --git a/release/molecular_latest.zip b/release/molecular_latest.zip deleted file mode 100644 index 6778cad104bd5ee8abd9f8f64e1a0a28e26aaed4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8851 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 C8=>3) From a73088527f0ccc1d08a45011063b7bf236a22858 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 22:53:40 +0400 Subject: [PATCH 005/129] remove old Molecular Core (with Python) --- molecular/molcore.py | 512 ------------------------------------------- 1 file changed, 512 deletions(-) delete mode 100644 molecular/molcore.py diff --git a/molecular/molcore.py b/molecular/molcore.py deleted file mode 100644 index 35f0728..0000000 --- a/molecular/molcore.py +++ /dev/null @@ -1,512 +0,0 @@ -from math import floor -from sys import getsizeof -from time import clock -from random import random - -def init(importdata): - global fps - global substep - global psys - global kdtree - global parlist - - fps = importdata[0][0] - substep = importdata[0][1] - psys = [] - for i in importdata[1:]: - psys.append(ParSys(i)) - parnum = 0 - for i in psys: - parnum += i.parnum - parlist = [] - for i in psys: - for ii in i.particle: - parlist.append(ii) - timer = clock() - kdtree = KDTree() - kdtree.create_nodes(len(parlist)) - kdtree.create_tree(parlist,"root") - print(" KDtree generation take:",round(clock()-timer,5),"sec") - """ - point = (0,0,0) - r = 2 - timer = clock() - rquery = kdtree.rnn_query(point,r) - print(" RNN query number find:",len(rquery)) - print(" KDtree RNN query take:",round(clock()-timer,5),"sec") - timer = clock() - bquery = kdtree.brute_query(point,r) - print(" Brute query number find:",len(bquery)) - print(" Brute query take:",round(clock()-timer,5),"sec") - if len(rquery) != len(bquery): - print("> DONT MATCH!!!") - else: - print(" Match!") - """ - for i in psys: - for ii in i.particle: - create_link(ii) - - #for i in kdtree.nodes: - #ppar = i.particle.id - #print(parlist[ppar].id) - return parnum - - -def simulate(importdata): - global kdtree - global parlist - - update_ParSys(importdata) - #print(len(parlist)) - kdtree.create_tree(parlist,"root") - for parsys in psys: - for par in parsys.particle: - collide(par) - solve_link(par) - #print(par.state) - exportdata = [] - parloc = [] - parvel = [] - parloctmp = [] - parveltmp = [] - for parsys in psys: - for par in parsys.particle: - parloctmp += par.loc - parveltmp += par.vel - parloc.append(parloctmp) - parvel.append(parveltmp) - parloctmp = [] - parveltmp = [] - exportdata = [parloc,parvel] - return exportdata - - - -def collide(par): - global kdtree - - neighbours = kdtree.rnn_query(par.loc,par.size * 2) - - for ii in neighbours: - i = ii[0].particle - if i not in par.collided_with: - if i.sys != par.sys : - if i.sys.othercollision_active == False or par.sys.othercollision_active == False: - return - #print(par.sys.collision_group) - if i.sys.collision_group != par.sys.collision_group: - return - if i.sys == par.sys and par.sys.selfcollision_active == False: - return - - stiff = (fps * (substep +1)) - target = (par.size + i.size) * 0.99 - sqtarget = target**2 - - if par.state <= 1 and i.state <= 1 and i not in par.link_with and par not in i.link_with: - lenghtx = par.loc[0] - i.loc[0] - lenghty = par.loc[1] - i.loc[1] - lenghtz = par.loc[2] - i.loc[2] - sqlenght = ii[1] - if sqlenght != 0 and sqlenght < sqtarget: - lenght = sqlenght**0.5 - factor = (lenght - target) / lenght - ratio1 = (i.mass/(par.mass + i.mass)) - ratio2 = (par.mass/(par.mass + i.mass)) - - par.vel[0] -= (lenghtx * factor * ratio1) * stiff - par.vel[1] -= (lenghty * factor * ratio1) * stiff - par.vel[2] -= (lenghtz * factor * ratio1) * stiff - i.vel[0] += (lenghtx * factor * ratio2) * stiff - i.vel[1] += (lenghty * factor * ratio2) * stiff - i.vel[2] += (lenghtz * factor * ratio2) * stiff - - - - col_normal1 = [(i.loc[0] - par.loc[0]) / lenght,(i.loc[1] - par.loc[1]) / lenght,(i.loc[2] - par.loc[2]) / lenght] - #print("i.vel:",i.vel) - #print("Normal",col_normal1) - #print("Normal_length",(col_normal1[0]**2 + col_normal1[1]**2 + col_normal1[2]**2)**0.5) - col_normal2 = [col_normal1[0] * -1,col_normal1[1] * -1,col_normal1[2] * -1] - - factor1 = dot_product(par.vel,col_normal1) - ypar_vel = [factor1 * col_normal1[0],factor1 * col_normal1[1],factor1 * col_normal1[2]] - xpar_vel = [par.vel[0] - ypar_vel[0],par.vel[1] - ypar_vel[1],par.vel[2] - ypar_vel[2]] - - factor2 = dot_product(i.vel,col_normal2) - yi_vel = [factor2 * col_normal2[0],factor2 * col_normal2[1],factor2* col_normal2[2]] - xi_vel = [i.vel[0] - yi_vel[0],i.vel[1] - yi_vel[1],i.vel[2] - yi_vel[2]] - - #print("yi_vel:",yi_vel) - #print("xi_vel:",xi_vel) - - """ - Ua = factor1 - #print("Ua:",Ua) - Ub = -factor2 - #print("Ub:",Ub) - Cr = 1 - Ma = par.mass - Mb = i.mass - Va = (Cr*Mb*(Ub-Ua)+Ma*Ua+Mb*Ub)/(Ma+Mb) - Vb = (Cr*Ma*(Ua-Ub)+Ma*Ua+Mb*Ub)/(Ma+Mb) - #print("Va:",Va) - #print("Vb:",Vb) - - #print("factor:",-(factor * ratio1) * stiff) - mula = 1 - #print("mula:",mula) - mulb = 1 - #print("mulb:",mulb) - ypar_vel[0] = col_normal1[0] * Va * mula - ypar_vel[1] = col_normal1[1] * Va * mula - ypar_vel[2] = col_normal1[2] * Va * mula - yi_vel[0] = col_normal1[0] * Vb * mulb - yi_vel[1] = col_normal1[1] * Vb * mulb - yi_vel[2] = col_normal1[2] * Vb * mulb - #print("yi_vel after:",yi_vel) - #print("xi_vel after:",xi_vel) - """ - friction = 1 - ((par.sys.friction + i.sys.friction ) / 2) - xpar_vel[0] *= friction - xpar_vel[1] *= friction - xpar_vel[2] *= friction - xi_vel[0] *= friction - xi_vel[1] *= friction - xi_vel[2] *= friction - - #print("par_vel befor:",par.vel) - #print("i_vel befor:",i.vel) - par.vel = [ypar_vel[0] + xpar_vel[0],ypar_vel[1] + xpar_vel[1],ypar_vel[2] + xpar_vel[2]] - i.vel = [yi_vel[0] + xi_vel[0],yi_vel[1] + xi_vel[1],yi_vel[2] + xi_vel[2]] - #print("par_vel after:",par.vel) - #print("i_vel after:",i.vel) - - """ - if abs(Va) < abs(((factor * ratio1) * stiff)): - par.vel[0] -= ((lenghtx * factor * ratio1) * stiff) - par.vel[1] -= ((lenghty * factor * ratio1) * stiff) - par.vel[2] -= ((lenghtz * factor * ratio1) * stiff) - if abs(Vb) < abs(((factor * ratio2) * stiff)): - i.vel[0] += ((lenghtx * factor * ratio2) * stiff) - i.vel[1] += ((lenghty * factor * ratio2) * stiff) - i.vel[2] += ((lenghtz * factor * ratio2) * stiff) - """ - - i.collided_with.append(par) - if (par.sys.relink_chance + par.sys.relink_chance / 2) > 0: - create_link(par,[i,lenght**2]) - - - -def solve_link(par): - broken_links = [] - for link in par.links: - - stiff = link.stiffness * (fps * (substep +1)) - damping = link.damping - timestep = 1/(fps * (substep +1)) - exp = link.exponent - par1 = link.start - par2 = link.end - Loc1 = par1.loc - Loc2 = par2.loc - V1 = link.start.vel - V2 = link.end.vel - LengthX = Loc2[0] - Loc1[0] - LengthY = Loc2[1] - Loc1[1] - LengthZ = Loc2[2] - Loc1[2] - Length = (LengthX**2 + LengthY**2 + LengthZ**2)**(0.5) - if link.lenght != Length: - Vx = V2[0] - V1[0] - Vy = V2[1] - V1[1] - Vz = V2[2] - V1[2] - V = (Vx * LengthX + Vy * LengthY+Vz * LengthZ) / Length - ForceSpring = ((Length - link.lenght)**(exp)) * stiff - ForceDamper = damping * V - ForceX = (ForceSpring + ForceDamper) * LengthX / Length - ForceY = (ForceSpring + ForceDamper) * LengthY / Length - ForceZ = (ForceSpring + ForceDamper) * LengthZ / Length - Force1 = [ForceX,ForceY,ForceZ] - Force2 = [-ForceX,-ForceY,-ForceZ] - ratio1 = (par2.mass/(par1.mass + par2.mass)) - ratio2 = (par1.mass/(par1.mass + par2.mass)) - par1.vel[0] += Force1[0] * ratio1 - par1.vel[1] += Force1[1] * ratio1 - par1.vel[2] += Force1[2] * ratio1 - par2.vel[0] += Force2[0] * ratio2 - par2.vel[1] += Force2[1] * ratio2 - par2.vel[2] += Force2[2] * ratio2 - if Length > (link.lenght * (1 + link.broken)) or Length < (link.lenght * (1 - link.broken)): - #print("broke!!!!!") - broken_links.append(link) - if par2 in par1.link_with: - par1.link_with.remove(par2) - if par1 in par2.link_with: - par2.link_with.remove(par1) - - par.links = list(set(par.links) - set(broken_links)) - - - - - -def update_ParSys(data): - global psys - global substep - global parlist - i = 0 - ii = 0 - #print(data[1][2]) - parlist = [] - for parsys in psys: - for par in parsys.particle: - par.loc = data[i][0][(ii * 3):(ii * 3 + 3)] - par.vel = data[i][1][(ii * 3):(ii * 3 + 3)] - if par.state == 0 and data[i][2][ii] == 0: - par.state = data[i][2][ii] + 1 - create_link(par) - parlist.append(par) - elif par.state == 1 and data[i][2][ii] == 0: - par.state = 1 - parlist.append(par) - else: - par.state = data[i][2][ii] - par.collided_with = [] - #print("state:",par.state) - ii += 1 - ii = 0 - i += 1 - -def create_link(par,parothers = None): - global kdtree - if par.sys.links_active == 0: - return - if parothers == None: - neighbours = kdtree.rnn_query(par.loc,par.sys.link_length) - else: - neighbours = [parothers] - - for ii in neighbours: - if parothers == None: - i = ii[0].particle - else: - i = ii[0] - if par != i: - if par not in i.link_with and i.state <= 1 and par.state <= 1: - link = links() - link.lenght = ii[1]**0.5 - link.start = par - link.end = i - if parothers == None: - stiffrandom = (par.sys.link_stiffrand + i.sys.link_stiffrand) / 2 * 2 - link.stiffness = ((par.sys.link_stiff + i.sys.link_stiff)/2) * (((random() * stiffrandom) - (stiffrandom / 2)) + 1) - link.exponent = abs((par.sys.link_stiffexp + i.sys.link_stiffexp) / 2) - damprandom = ((par.sys.link_damprand + i.sys.link_damprand) / 2) * 2 - link.damping = ((par.sys.link_damp + i.sys.link_damp) / 2) * (((random() * damprandom) - (damprandom / 2)) + 1) - brokrandom = ((par.sys.link_brokenrand + i.sys.link_brokenrand) / 2) * 2 - link.broken = ((par.sys.link_broken + i.sys.link_broken) / 2) * (((random() * brokrandom) - (brokrandom / 2)) + 1) - par.links.append(link) - par.link_with.append(i) - i.link_with.append(par) - del link - if parothers != None and par.sys.relink_group == i.sys.relink_group: - relinkrandom = random() - chancerdom = (par.sys.relink_chancerand + i.sys.relink_chancerand) / 2 * 2 - if relinkrandom <= ((par.sys.relink_chance + i.sys.relink_chance) / 2) * (((random() * chancerdom) - (chancerdom / 2)) + 1): - stiffrandom = (par.sys.relink_stiffrand + i.sys.relink_stiffrand) / 2 * 2 - link.stiffness = ((par.sys.relink_stiff + i.sys.relink_stiff)/2) * (((random() * stiffrandom) - (stiffrandom / 2)) + 1) - link.exponent = abs((par.sys.relink_stiffexp + i.sys.relink_stiffexp) / 2) - damprandom = ((par.sys.relink_damprand + i.sys.relink_damprand) / 2) * 2 - link.damping = ((par.sys.relink_damp + i.sys.relink_damp) / 2) * (((random() * damprandom) - (damprandom / 2)) + 1) - brokrandom = ((par.sys.relink_brokenrand + i.sys.relink_brokenrand) / 2) * 2 - link.broken = ((par.sys.relink_broken + i.sys.relink_broken) / 2) * (((random() * brokrandom) - (brokrandom / 2)) + 1) - par.links.append(link) - par.link_with.append(i) - i.link_with.append(par) - del link - - - #print("num link",len(par.links)) - - -class links: - def __init__(self): - self.lenght = "lenght of the link" - self.start = "first particle starting from" - self.end = "second particle ending with" - self.stiffness = "stiffness of the link" - self.exponent = "exponent of the stiffness" - self.damping = "damping of the link" - self.broken = "max stretch factor to link broken" - -class ParSys: - def __init__(self,data): - global hashgrid - - self.parnum = data[0] - self.particle = [0] * self.parnum - self.sqsize_list = [] - self.selfcollision_active = data[6][0] - self.othercollision_active = data[6][1] - self.collision_group = data[6][2] - self.links_active = data[6][3] - self.link_length = data[6][4] - self.link_stiff = data[6][5] - self.link_stiffrand = data[6][6] - self.link_stiffexp = data[6][7] - self.friction = data[6][8] - self.link_damp = data[6][9] - self.link_damprand = data[6][10] - self.link_broken = data[6][11] - self.link_brokenrand = data[6][12] - self.relink_group = data[6][13] - self.relink_chance = data[6][14] - self.relink_chancerand = data[6][15] - self.relink_stiff = data[6][16] - self.relink_stiffexp = data[6][17] - self.relink_stiffrand = data[6][18] - self.relink_damp = data[6][19] - self.relink_damprand = data[6][20] - self.relink_broken = data[6][21] - self.relink_brokenrand = data[6][22] - - for i in range(self.parnum): - self.particle[i] = Particle() - self.particle[i].id = i - self.particle[i].loc = data[1][(i * 3):(i * 3 + 3)] - self.particle[i].vel = data[2][(i * 3):(i * 3 + 3)] - self.particle[i].size = data[3][i] - self.particle[i].sqsize = sq_number(self.particle[i].size) - if self.particle[i].sqsize not in self.sqsize_list: - self.sqsize_list.append(self.particle[i].sqsize) - self.particle[i].mass = data[4][i] - self.particle[i].state = data[5][i] - self.particle[i].sys = self - #print(self.particle[i].size,self.particle[i].sqsize) - - -class Particle(ParSys): - def __init__(self): - self.id = 0 - self.loc = [0,0,0] - self.vel = [0,0,0] - self.size = "is size" - self.sqsize = "near square number for hashing" - self.mass = "is mass" - self.state = "is alive state" - self.sys = "is parent system" - self.collided_with = [] - self.links = [] - self.link_with = [] - -class KDTree: - root_node = "node on top" - nodes = [] - result = [] - index = 0 - def create_nodes(self,parnum): - if self.nodes == []: - for i in range(parnum): - node = Nodes() - self.nodes.append(node) - self.index = 0 - def create_tree(self,parlist,name,depth = 0): - if not parlist: - return None - - k = len(parlist[0].loc) - axis = depth % k - parlist.sort(key= lambda p: p.loc[axis]) - median = int(len(parlist) / 2) - if depth == 0: - self.index = 0 - node = self.nodes[self.index] - node.name = name - if parlist and depth == 0: - self.root_node = node - self.index += 1 - node.particle = parlist[median] - node.left_child = self.create_tree(parlist[:median],"left" + str(depth+1),depth + 1) - node.right_child = self.create_tree(parlist[median + 1:],"right" + str(depth+1),depth + 1) - return node - - def rnn_query(self,point,dist): - self.result = [] - if self.root_node == None: - return [] - else: - sqdist = dist**2 - #print(" distance to reach:",dist) - k = len(self.root_node.particle.loc) - self.rnn_search(self.root_node,point,dist,sqdist,k) - - return self.result - - def rnn_search(self,node,point,dist,sqdist,k,depth = 0): - - if node == None: - return None - - axis = depth % k - #print(" " + node.name + "(" + str(node.particle.id) + ")" + " viewed at " + str(square_dist(point,node.particle.loc,k)**0.5)) - - if (point[axis] - node.particle.loc[axis])**2 <= sqdist: - realdist = square_dist(point,node.particle.loc,k) - if realdist <= sqdist: - #print(" " + node.name + "(" + str(node.particle.id) + ")" + " added") - self.result.append((node,realdist)) - self.rnn_search(node.left_child,point,dist,sqdist,k,depth + 1) - self.rnn_search(node.right_child,point,dist,sqdist,k,depth + 1) - - else: - if point[axis] <= node.particle.loc[axis]: - self.rnn_search(node.left_child,point,dist,sqdist,k,depth + 1) - if point[axis] >= node.particle.loc[axis]: - self.rnn_search(node.right_child,point,dist,sqdist,k,depth + 1) - - - def brute_query(self,point,dist): - self.result = [] - k = len(point) - dist = dist**2 - for i in self.nodes: - #print(" " + i.name + "(" + str(i.particle.id) + ")" + " viewed at " + str(square_dist(point,i.particle.loc,k)**0.5)) - if square_dist(i.particle.loc,point,k) <= dist: - #print(" " + i.name + "(" + str(i.particle.id) + ")" + " added") - self.result.append(i) - return self.result - - - -class Nodes: - def __init__(self): - name = "node name" - loc = [0,0,0] - particle = "particle" - self.left_child = None - self.right_child = None - - -def sq_number(val): - nearsq = 8 - while val > nearsq or val < nearsq / 2: - if val > nearsq: - nearsq = nearsq * 2 - elif val < nearsq / 2: - nearsq = nearsq / 2 - return nearsq - -def square_dist(point1,point2,k): - sq_dist = 0 - for i in range(k): - sq_dist += (point1[i] - point2[i])**2 - return sq_dist - -def cross_product(u,v): - cross = [(u[1] * v[2] - u[2] * v[1]),(u[2] * v[0] - u[0] * v[2]),(u[0] * v[1] - u[1] * v[0])] - return cross -def dot_product(u,v): - dot = (u[0] * v[0]) + (u[1] * v[1]) + (u[2] * v[2]) - return dot From 978fe5509765b1a4fbd96c7de91488086925e8ae Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 22:54:57 +0400 Subject: [PATCH 006/129] move sources dir in root folder --- {molecular/sources => sources}/cmolcore.pyx | 0 {molecular/sources => sources}/setup.bat | 0 {molecular/sources => sources}/setup.py | 0 {molecular/sources => sources}/setup64.bat | 0 {molecular/sources => sources}/setup64.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {molecular/sources => sources}/cmolcore.pyx (100%) rename {molecular/sources => sources}/setup.bat (100%) rename {molecular/sources => sources}/setup.py (100%) rename {molecular/sources => sources}/setup64.bat (100%) rename {molecular/sources => sources}/setup64.py (100%) diff --git a/molecular/sources/cmolcore.pyx b/sources/cmolcore.pyx similarity index 100% rename from molecular/sources/cmolcore.pyx rename to sources/cmolcore.pyx diff --git a/molecular/sources/setup.bat b/sources/setup.bat similarity index 100% rename from molecular/sources/setup.bat rename to sources/setup.bat diff --git a/molecular/sources/setup.py b/sources/setup.py similarity index 100% rename from molecular/sources/setup.py rename to sources/setup.py diff --git a/molecular/sources/setup64.bat b/sources/setup64.bat similarity index 100% rename from molecular/sources/setup64.bat rename to sources/setup64.bat diff --git a/molecular/sources/setup64.py b/sources/setup64.py similarity index 100% rename from molecular/sources/setup64.py rename to sources/setup64.py From 5f49168c8f8989df703108476ba48f343a78c9bc Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 22:56:44 +0400 Subject: [PATCH 007/129] remove binary files --- molecular/cmolcore.pyd | Bin 60416 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 molecular/cmolcore.pyd diff --git a/molecular/cmolcore.pyd b/molecular/cmolcore.pyd deleted file mode 100644 index f7f3773448ac2af7836cb4f24d01806cc1299a58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60416 zcmeFa3w#vS-9A2>Y#>0$21qn&kX09n8gX-jgd`Big@{2T1f(UHL=sFSgqUm;6cN}& zS;x?{#Yz<`6m6~5R$FQ@&=?F5!5gC0LvM8K+>?hS%b>bR08qS^SkDg@nD?B=k}g ztK=gC`SB-CQ6}XICafmqp$J|C`71Ih9pORp2xps=*Z|qF=bDsF6fDT!ct_-AS_pN1wlJrL1Foy(HX5x+6G9*MXzYU$&B+ zJ-)K4bP>E$JOmlXa16zkdXF&C`zPq? zD{Gc6gemAl_)_Tm_g)%afo@uVrgU zDK3Z2raEkP*9u#_y26&`{L<>Mo&9^#M>HR7JWChJ(xjpgSFSD2Joe$w?3*U%^h1PnB(d$Ad0eu`fLvW`&V_)C7P9W<=V_4 z$U%j^{iw}7<1w&4_y-_bE`o%)?#HPR#Obg!-Hf`ux3xIVR}wosOt?PP^mCtwO1l*H zAjm31R?F7&k?7Sw4nkW|YdA$=?Uc`Dwz)re1mzz$ozdak71!CSu{nt%wUrJ5ej*(?9A(3?VC6eEauyim}4`>sERGduxAL+Q4%qDjmy$F4GEnw0}WD zhP|CFH^_0v`>$3Q%iNP~#wonJ%-r+dLC=lDd-lHRIn-^ryTkHCN9UpLL*3h8W?!cy z4VR?hCqWt^Nh3~3+Prt=nDh|GIkUIZi{7ww^F59;ot>uiXB$5j^?D;^^+M}TSNHr* zu$(2yd*16YZ|Jt&)BVihos#E$Z)neZo%4-&>FiOuheE;b8Ro+~d$Pm3XM`W#**WK` zxwBm_JH4jmQSGeuFZ{3h;L3}^pu$4TC?n3$K zLAA+dMpJP;z4MDPpY5()mdj|L9t}p8;wq;g3sj>=Vwid=it>_S&WtD0ZbQe<+?Eow10vmb}hW;MUi zh2Y-$8zl1!)g3|@XO{`BI0X@B=cGm}xu?XIfXm}VO3?R6DN%?`%~Mc_nr9Xz=7r-F zuI5GH6rtut;S{CjMdK8$=EdR^tLDYw6sP7{ak8qk8|>%43tD`)dP7-lj;uCER+}TM z&5_mS$ZB(BwK=ldoc`6GjcPsT!JIw0wrpwKHPBIWjI+Z8A^+pHaD5Gr!uz&tt=X{sN##+aW2NNJSW>Xu?)05k~Fdm z49;2^%SWrBPPfU0$%v(S59ruz;%vU6SkE@5dNc3rm$?$DW?!qNxfmDDtc_IC(tI}( zQu-}KSa%$t6Nok#*?mRZOg^+;L%wn9DCavS*C^rb<^z`Ix!^E_6sRYMkS=NC5F=Mj z6{R^a2dc4|H`CUl=y}pIpE}|)1cf779YiAxYVH7cK4(iXK=VOIgI+lUjFtD`Y!ok| z!Lx_ZX_WCaLq<$@6r&s|5`eb>He+9`1d`lSj;4WF3#gVS z9+{#LO}Ti_0=A?R+QRb@Iy(e*90J>lz_uZt)Pd&%-!o7Urv<`Sz%z zX1GQ*A83p+?BNX)qpRzfb652ItI;On5V%p0lQY9uw1-#K0&~Xjc(6B~(|ln0VAuZ8 zoNx@V`!jOFZ>ebRSXQRaj!?~OoQla?n=!nJgkuH}W`J;_n(K@p*>rVzO0&-~&UtHu z;$Wd8)WMh)4Py-N2jRJI^i>hwGeqR4Q2wV~-R?24i#JSf)KSnq8oI}F7U(>h z3E>mK%L#P~ypX1*J^)7bH1)a!b%xzli1BJh3Qlod(-P>Zu4#6865WxoR4Z%hR0pX= z3FIV*DzM`e=PF2nVWZU$249E>zG-IM0x==bKMfYF zjZvE)VRdXfN6NH{zN-*p`JJ{V=ycJY zwpBPecbb~_-g>DT(vsUTWap8P&}rzIp@-EqLM<}8t~9Gf;jSyg)uIU3l@V%Dl$);lEsAqp8K-7jT~n=|OVHQ1&7Cu64u;cKl>ON|+QrV}V=j2Q#XL)0 zFYpVVc79=UBs;$dam+)otw6JgXdU?#XZqpA;DeOr#Z9(VxGWCMMX!rV%iztJSI@trs%5iet@8Nx@u&vEha|*QWpw#0j?ul1rh3uC|5z0IwRUu5UtKYI3ko0jdAKMtENLsCmgYan)Owsu zmS#)`6mjgvL+4e<(bKU=GgS3-9MbfXp0?^X()ev%=2nED;>?RMQK{%y zEs$YRMsjhi2<75f5zED~BAAO~MKl-3if}HD74e)KD+2mzT0q7ErpYYQ5gP}SPzy9D zc7ait(b~|9Mj%AOK~9$@u!&<>Hq@~}j(FEQEtt)?YdEvQg=-N0PjTh*zAep_&wH{= zS3d8zvR(O6IOV$Xqj4&5<;UVw=*s6^ZjmeBD&?R@gUNvz1Or>x4s8j137pzu{@g3a z+h2Yka-6D(A)3{>t47>;p}+Zb+Epe;s88v{2or7>(l05Be3;4H7}%+!a4x8xW(>j?foM`GZ&s z=(tc#UBRi)=a|=ayWc$K^QG@u8Pj6!%t&jDROgwUp(ad4o6i9!Y%WI>F_J+tOVbX{ zIp1}R#gHfhc?Wa`Ss|ksbI&d$eKB`Zqb{#SWYD03zYBBKrWxShY)AcSObVqa#>fhJ zA#)1ah@HI*ii*c!!@*lJ-krsQE*d6|Lb$Sv)w^0TN22KkF4xL@FWj&QzBJCe z5Mv98yTVrC|7;2yMq`6XamBlYaXnl-+bmqbHtWG$1>^t0vWN}yaad8xLp%n2&Si9VTF($ zW`vW9v@2&;39d{lhi`6`nz`3*;2jP}D$~j{H?P&udZ3%{)Do3QbcK;b7RDlYC1zxp zrgBCpTWBFXP^QMao#4Q5P^Qi@BeE0F-Dko^(Kx5!%#or@oyL`meuD+lY-23ieJM&1 z_HOEM%-{?TZpvJ|ySR<(M`-V#s9BWN)TO3UOw5B{`sl%yMw7FnIQ^qrk6?W$6E&Mf zjhHlrptz=v#wRk+{v1QyU*3%w&JBt;oRYXM^uFiZRVd8XUyU6gJ2f@dpoH&HjSLiL zs1e@kPDa{L0yicDl}K}c_Onw};x8ycSKzH@iHhZ~hH;hMqjDo|-EP4a%w zU!@fo>09A{HO+kvwUU$Q-XP=LoWv$kK#`iscypG;912kaw7-wkwT+x?(_}rnyIf?9>9a2Qw($$Cn53 zG2J#TuDio<+~9XLb?EQc{QbQSMZ({I5ULF0^AEQQ$Z+nvL7kfmvhTyW=3b@#1J2#} z!HJx^>Zg9r9kQs^eKWwm?mgPyy(?UMusE^TaT;Q;fU_cJy0UVFda0Qsp_dC@0!5$6 zTXgsHKfx%xn|CjwPwdH$?+H8dx3B87wN&Tncx;+}b+)A?5*KPd8!SeA6A~Ew3w(`O zgDgT^&r|1eRll&gg-(CG54ST3003{r{tIY(?%rA=9-7q?r6D?)#BynQd;FZhn%F1>BcG zxSlXK3I%cap*Wknh4c{ua`sHKcW2uV??n~a?y)Gpx3ojWxc5O#{cAh?H?5BBo&^yQU5NTN zI!oOah27bOeYDJWzlh9%llX$GG3tVuQ9aX&yR(bC_XZ`hUNF7Bd!Lqmij)m zQusy3y|4Ic7)ou*U6`|gIRKHpOVYEv&;IG9C}jn$1k3qnGiZXO`W5-qSQHN zR}t4xTt(qnb8r-fW-?y$GfNuWbW>no$8s1i54na*ip?~kK zL7&?{Q_I>b zP`!#$uuy=zRB0Z&zj-JUI(yJJorAWen`=dP_6pq)hPlv1EAEmzd#RRnXD`#Kgt?|8 zQ}njzxD|IIQhj^dLr463+cBg+ncg-nP;a}2%VyoH_`j5*PoKMHmB{1&T5t1PJj3X9 z9C}{fzI;p18v%Crbzs!&vSyE4Pi7; zyJA_JO}ViEDB{p2<1pJl4&^AnrU^xNuj2o`9{p}((wa@82=V{7j7)1V{-8GTzdk;# zK|})M|61HMxO8De)Bo1E;V2aec6SmO^|*ORl*<46#m(s;`S!Tc$Er2B@r7*szt=jl zb@r^m^cZ>kUz2+~+Jz)LIk`DHS-|eT35>ejkBL(Ge?PfPLGtZ#f1hKN7<0rJ&il^%X*X!F3;KJRBrYpu!OVeI7X=va-j#`=@V}`Mg_e-Wk zOH~W1(q~jzn&0KlldR)d&5{eEDcgTB8aJPJV9JV-FB^v8xkNjc@$8*t&<;5pw08xd z^^P}ahWXQYM;dv<^*rdFB1{w|bx(1HK%FAYVAIgiH9IKf5AomjTPWS_eQJD)B6+sr zKiz5DH~MQJY1mD$W`k~%Kb^O(Uw)V_oo)#)H)8bi4<3-;n|GF;C+hZ|ZdBSo!{4@^ zJH)bK-(`goSJ!4P@}UhBz!vLnh16iPQ*WGYJc|WHjs$9Mlo^D%B>Y{hAjo8I4?=N2 zh;ue?q;MAZiCCD<2oq1qlMzWaW%&>YY73nn?ltowV|uuy1zj9AV_Md(##y~8LQPrY z9AxrfUZrG&HDO?BJU~hs{djuG~rRuyCEV@p1-i*iRX_Dm(u`~4y7oIoc z3A$zNJcx`(t2XaY)-GjW+b6;72-hC(nZ#XK#);vRbxbF@p56H-*RweTx&ZuGvDH)> z;anN6temRi@m0Jt4^Qwf*95kRjCi#+LckN%>=Y~!$Ew-bA}Y65LOHpw)V13y_GBXM z6Lq4-W9}5nEluTTqQ(G2C*sd!oabJqBs|q&b6%zZg<6D z-MpUDplqIkChE#VNMNr(p5QEs-5ddTr01I(!w%(#dxyBNt0hJOgjt`p$K7)T_u1Ar zvGwz&sK!Y7I1BD>o_I!J<1NM>QNg@OYiec;!gKcs0y<+#PdBH|Gv;|0kk#%Nu&Mz5(|Kj8?fqk7u}g zw2s&I!f1hNJ^4Vj%0RX1F-}(9vU;HUSr#m3sM4}}pl*#8mbHpNwTeKs>Vaxl*4o#y zZuj$*Kl!2O?y)X#hLNS)8N5x~~yp0cq_86PxK<4-yb*Y;{RBXUNqvn2kD;IbW@tZ-5aDMF~*x#PUGNTWgam4n^t1CWY`-@8 zGi`Y9n0q#>6r=xPdM|*nd!zFrjQRnG?prW7TF(7Na7o-I!NFWir$VE!t%;Kmj_KS|i3}qo%2#ze9>z`NcMr)pEhOUxhUBw! zOaLqShh!W=GU{YPl4Ciii!|DIn~@g7ghjnGQZWu?3lmO~Gt#q!3C}WSq<_as0B59& zS_92V4P*L^@ri%cjrj!l|06-!{)!%y_3(NibN3I*fW!2OgEAn?iGva>{z177D`*Hx zD}vHGASnGtbkEDW9e)b0Qw_>djU)6C9s3O|%_R)BQ`Xc)H%VdFDyhR{`>iThPt#>V4SHThcI9YgRa z!qObd2NM6c?vw0z^6*`w^<8XBlyjs(;O-x-A=+={^Jd zO{`Kx>nb`nkROa2B;L-a$O&YMK7mX*`MGBx)^C}6g2jLCsSFWzO%Y>LikN$*_{}}B z(&_4VJAc;;x?Nw!YH8r;?ZQJZ+GcZ=TzC?%smP~ZyD{)KT~Ch$Fi*zC+VifAi+i7S zg=bvc`hH{D=q5~{Zv5W0HAxK!m2=MSBfVSi_E(q@} zvoRyMLao6)KUauO=BB@W@Ckz%3r6aIn||x_dStB!cW<9J!g))0$jWTIsi@Y4bCqnS zCU2z37^gNy6AiFJB|@1KJ+3lfX}Dh~yWPKkPWN((s4&o?O>di`WsQi$0uC4dQZn+f zHboQCvV5YW&W%tt%l29Qqh$l}-XiB(HMdF2UaeN8U@z|!=Pg)HNtZllBKpL73g_Ca z6Y@&XsX^6BHBUz>BYpR)vTZVhFrdG_t-m@wNEP3`zq&Z6 z3|K2Xv!Bi3jd(>_HO2EXT%s9z_Fkbi4E+hZwl+3e_Y`8{0r7|I?gA<(Y;nvTZLrUw zp8^<7F2v?>c?(N-Lqu<@EyVVZ+|wGPjmhv63>r&wQ_$-B=_RKhvGIK(u{PXv2tF{w zI8eau!uF7VEXGiqXO~eao;5hpuub?cI~4z=@xRPa^fS5Xz%9-7|H8v8^qZ#DnCfg} zImNaDJfpK&n$Jd-XRR>2w%pw8Thto(rM12f$v);ovR^y{=F7mm{U2CTYOjRJ8t=w_sdd{wXU-y>+jA2(0QzH#fPo7u-;&ZZ#~;Wg*KjN&wqI+MWDkJF zNybq+rDvEw@C6@+ox}VpqojWZzzzU|OyhJ)58u=82RufuROVM3C2b6Vt(A-!I;H1E ze_#>0E@l38MoF^*V3Q@|6*{HoVt*ixT&2ukY?Krp0Q(qE%b-k!PU(5eA2=X^YJ*}Y zfbGketTBpyR1z7eXQKpe(#brk1XdZqO)RF9$ws4?MUvOQ37Jo4|7L zd6Ff?I|gvB1dbWN2m!c0+5Rs*G(Fd%;|B1a4#>xwR}y_6_?JffO_qcqEUY(l<8?v{ zaR#C%MiQQ;1F}RPTA?WMJmQQq&rw33Y`;(kB;l(%;Y8vLBTuI!oU8+q@KK%cGUAL9 z&pncGmJUe5CY`XHID^3Jz$^TpY`@k>S0Hr@Q-&YCR|;tj&^r|*&i*9h1<7uLbe#8W zQR=fsI#Q(HWttA^(;HiwZ^OH3o@Mw?f3JftD6Br30OMg(crH%vOaG3B8grEI1np5{ z_?AZVft6QwHQAz(%Rkq88$ZMZgm0^JL)PZ?a&{8lvQbdskMaGUI&AcYn* zy3hj*l#hD8f*h!aA0I(I{JemFJ%U2kbMpnL=jBRioR#}g&kIcG6{w@BHVPH9*MpXI zUtneildM1;EPXA{_)}|aD?%^kX6T+gzwO!Qi{S>lvLlqnq0VJdilu23p#_ETPm#Ky z2&Y`Uy|wOZ44UmMtYv{2ScU!;#^SDGXJ&{Gd;jpQ8@w-5v^ZjWaZB7#?)St#Y;_p7 zjknYdP2Xq9JEqP|QRi^;K!H2|No~9J-5iZ)C#WItU9p;%poW8^B)!m9?65d*ic%bd zC{|;rb5BLfIyZ=sJx?u&PM;BN$#dWm`@k@M7B@x+B?hhD6EzMyw!@04Zi%h9Cl8AV zws}1{JeA;Xt9dL65gWX@glk!I8U>hHpw7t^f<1~C{lz};Z`dxx?r`AvWQvae6L?Ra z8Ko7f4d$M_a9maO!v;##Y$t@c5Zk>^T<1jL+c@)j=0|BfInhX$^vsXOE_arl6N_|J&-~b)9CLT284_V$ z16kjutU2M`mEi&^1mqS_M0aJxVNwVFuMTi0DMez+ zSfP7_ET{$r(Hi?i0SaCXp_N zO;P&1?zg)49`5Yf2a_UMg5*A#q$jGn|9*HcKDRVKR-K8~k)r08F)j}(maB1O^dfF(DdiI4uzsa8PJt{#`dy+-*_lthv8=Qz6akn zp%$E0@dU$*uTTG{16P&vIDpwO^xB} zkiqH(1lR=~ zj^3f*5Hy)q3eoySGMY^pgk^tFf$LmcJ8)fv>mp&3Wk}VqaUI^-jqhJ|-)UO~9Yj_x zq8t!diqLiNO147Cefaa9{Jz~(PbX;M+^eH{cJV5@=jv$iz`<9?zQM+~IEt-fAMzGQ z%dTc|EV~$##XdQ7SsFgvtehp=)#8rg zmXuh8j2No0hQYC^-qtcZN{k>aO|pZ^fke=L9;4{>oriiz&Nm-FYTW0Il-%Ay@~lmR zd@(jI1ffgeg61^bPWxwwz1K4WWZ?5LmZr-GWONZO8UVu|%wR$4Xt9wGt&|%)Idi73S3H)CgA< zv#Nw}nNqkaKjDyH09M)R*b8_u$JSPtusB^H_hT1`BGP0L1%5?9RIwks$MxYhGbTOm zw|1b{#2d?sgP+_KP1O)1rLP#Hj2+o{{}y$l{sJ)e+beFD3<36vS4i0^glzn%i%|aL zzUhQo3KdJ!>98~^E)+#*Zx#)3AFW_%{)`=u)bvT-o437*2f0$;kG6{&O`)jgMbK%w z6yhElp21Pl-ihb-+Xo@f^E@IM1SNnqg7z1g$+uNiIUQpTneu$*Y*Wm`UEcdJ33KXL1CS=}hJ^Ig-f> znY@z8QB0o2V7B(z#HfXVMQOtP zj5!phPyc9X4u@c#FEE`I!Eb3A0%hTlg4MgYykWfMzWV4_hyi?ikrwHFeiS7(R8Qe% zt2F1}zE82Z1ACmhGJN6f{k8s{9c6Lu6xU-uX z@#@kO@9gG&^FTYhkGpSVjpDJyy_u*nKyRq>5imEAHb!8H9rMKk&kow8h@S4)o zW2CX{F0$`Kc1GAnusFi;Mj)1L8ixyta6tHU%}lf}m=m3zc)1H5tYf~bN_>q2s2GvN zvc8K$ocN$%S65C1vjTp=1fQroG+hYREBb6 zjC8$QJdV5XepHwdZ*IJs7T6|e-^%yvyzW=#N6$4#&Cf`?d-X1h8me`@hD% zBw#agiCcnRQ~&##(0z~Sn$Hu`^ld_+S`!l8bl)uqp=?62L7EUJYJHoKoVXcHD1jA< zCiH1WF!h6m`)#A$F7uRMjuI1+A z-ZzqN4L38cLlY9OM~mLk3UYLsvPp_gQ`|Gh0^VH5RUgG9&aUYZuBB1(HRUgO zJFK_|{o3b4&$+fbHL!O2D{>Xp9b`a%>%MFzK9I&;7mJ14i(R+@nn;Wb{!CoR1V0Ca zIZuURS(j)R)1@j_h-p&^&uR?cj>C$5w(AqG8SBR-)wuN#Rp4Gje=c6)iVkfD2m zF`6^*gd5+S{S@DvJ;se;A+BS5uiyskGpgr)@60u9PPb_Le8vnQoC(59)fL#~4YIlN zovw88(p)lV&(hwQ+9ra?mCkL zdk$Ya6#cCQF46j1+&E&)>vpe}<3oqzeD_5hkAVk_O?(~O*BC3l!BfoTs@{R`WA+3A zzVfDG_M+{l#40%M92etTDaCw(;@TG~zM_RMaUd*;5f)M7ML6&=Bg4YMu-Gi30;{Fs zyKK1atiny$JXZw1GS2|W4G;j0@ay#qfVed@<%*yIfaRiP1!@Tb0AzDy0HlckNJ0Rd zDFPr?^t%jz^PnLD0N+m==>JaX|K4{c;s0Oh{`iLdL{9H0aI=_5@nB)6iaboBi#k3a}q2F^Cxc_QDS>=*Ah? z@6{ukYkR}~#-L$;DG2lQurHEfpDM!s5`_KfBJ5*~u>Tdd6q$|%jQMEs9N3tKJh(-V z_}jqqABgxARwyF=d{!95k8t8L;lykyAL8s4bTp^t#QyQVjXiFF>izu}A>w`8FZFo; zG5Pw%JGZE^X9(w*)H^@C8FO*;4ADX6hwL!fHuavN-&DNY9l;8Pof3lxiuPEBFhARn ztn=c)7CPw;q2FfvXOm9OK2gFx8#e3qc>sKJ>s}KvF^Ab4q%5dV2NmWU%p<;66*7WU z>+j-dp~7D`=_*7UD(oaCR2UJYEU2&yDr_*AOB23NFZ`CB{7FPD?H9UB&ZIGTSK}T}OoZg=!6cIY z3^SO07o4Io`gIJCUlP~{{{FNH6>hyxSK$uuwc$yY;$BQlsBn9bvNV5AGni+dstN=A zIXXzy{%XVvHMVWk)%XROof}vg2*WE(r~-x zS`jYCy65iIbuy2^3u$UVBQP2iD!eU6yWb#;((#P|lk{?gz+a(-Z4`>%qELbFgP zzUhsdrEn1*xFg-%e-%`8!uJO$F=(V*&(2@B-Wg)-HLRySU^_YMJ<1X6TdXIC%wPUo zx85D#k=9#BOelJLka9$)4(nAI+`GmGw%$q4TmsC`&kRz#hym?>rU3Uda^&pZplk9G z20y9EE@DEHV;m3zSVZ*5(BvM2dsq-nf_iN`duiQk3-4!*hS#*GoG0hC1wmx&8}o9A zJ$kpU>m)_Cnl{N zq?|VF#pQ@mU~nHjH?V~2a6V>BzwFy@Ui+E(MGmAVVP-k(?Yv7j)I;EtW`2~IP~yQL zWwo(mgAz`IJ1vM3C*8mYes3l{Nag{r!+4 zbf`0=IELAQ)S-l!@WZ>DF$Azj+c2p^lEHoEsp>FbKDZ`G-Tr!{2|XVAiEhpLh92vQ z2|eZoDXT3)>T#XHy>QI;>5C6IX9!?Fe;qP~4sZWh*I^&{q%Zap6FPJSDXVR`)ZteK z_ha~)U!Zy3|Ex`v1*z9xhisvP)sQ0H&>_OmVM36y@LTSpgZg``Zh@~ypP~)};^|q= z1Wv*ixk8V5h9nPwPx>O4nDE8sAZ4{#q#kD)-1(=fN5B4QQjmK6eSyudSQB3VBi)*# z3>{Vx6FNi%DXT3?>M+;f{%PDP`l6o>zu_$9B>Ye)blAU6*I^C#q#t$=6FS@)q^!0P zQiq=y+(*tjMI8pjQ*@BJ{e4j+^awX3c^5MrsmI4Hx*qRv))T-cZ6l=~`$#G7LM}K} zJ^J~=8Kho+9g2kxxrP)ah7NW^haUtft8J9jVUWRn!MLQLrJ%OGX7ohE(p zgu(rT*i-aHKOHiH)a&nu3ZaADkRsa9AIH4SUw|2z5cOWCv>PVr1%gsNU1{+G2xB(Ijam{k2dt?)Zu)C`|Kb( z1dY7u92)e-LV34xfFq@+eHyGTl7@@yE z9VQ2<*I$PfLWg5bx(=rsI=n$l=nx&GtTy1(;SUD)A)a5n#ILXGwy#kFDP zL4ULw+&b^nS7Wjv$lYL-{5q$o)a>t%4Z0$Yx9S!( z8H$t>6M^*&C)EM$(uUh!Dl*aF-j4;SQ&Oa#Kkg1vufG}_bv1ssQdeUMSfxMiAtuzg zE=X~0SpA?Hbq4q8r>cfu`!EHm*j-FA)=pyu#^xAb(&u*Q5!YWVr%HQplx zFrdF859x}`F+_P3tkNG-i3xu^9Hh85EWcBc(+zGn7W_|1k$&wXCrG{iYCNK=vF>Kw zqGuRt+(b;M!H*~fvPv7Cz)+1MgZq+GRm0C8kMb_zB>eH1uE=hD#Y~O>POwUUJWfm~ zvMNY%ZFsOpMQ%5^9e9ZJ{rTgJAobz~M%%N^XWKm+wn7XQ@A=E0Gj-)8;LhF*%smTp zS$y-OD<=ghzHpF0G*h5yT{)Qo&B+!gjb)6;%&TfG zt7@1itwdmP{jdUoSy7CdYme(vv@(&f%7nAayVK7H){h}Tw0;Sk^38pe-!UBnVoZ0<#v|GLjd0v`)|8$7r_ zFA;m8zMl_ytwNFR2baOcn&_K*Kjftg-_2^*i*MRM_#;U93oj_7@Ylsd_*zUNDSS9? zyWG{BQ8w8GO<&>l8VzI3(2Vt*tZzR~sPB~k^$7}D-`(R--#3^zvA*3j*5^#{tq@vB zy;yus?cJ5rx1${S%`LH$&D530D=oNehqTnfB zcwYGuZ;>ww#e3Y?$)b2n=sen&Gnv37zarYcT2IPa4-?}T#kON_o8ozq$%mQ57C}Xl zY$x_-Vs?@|!X)XoV{@xUvH?lgq4sFhw>_Oiw-eaieg%Qa1a6Q(1%W99DkZR-KsJG5 z39KV9l|YUJwh)*`AV~t-2;>krM*`0g$R!XZfg=R+2>4)6$ni0Od;;%DAUq7fbOMJY z5J!N0yyrOy*a=)pV7mlz3CtkyumlPXfL|sED}h}EiU=f2pqs#z1kRPfQ3A6FjF5mb2*7Lt?8i_`Gy#T+=Y5j^ z;t9+la99GF1m+TWUIIk~t|G8Q0u==25%{eHmJ#>?fqNuyCxIUla7kbjf%ycMNnk61 z5(45&mAl)YA+UhJTuJc;fvXARN#GcPQUWOwIBo#vNg!e{D9T8|FC9QzD}izXCJFFE z*W0fla18%}qJY3c0&hy7gg^y>7bH+epppRF09cv`EF$oT1U3-3mcYFdc!WR|fjcD7 zL7*Df-W4d|6{fCZsun3XQ;V4@L+UH0*yO#lkctXNY6(-hNO7m+_FASUAeF|{Ql{dO zDrBmTsWXu(W9oXQ@ImZ$2UGP(8S^ho^QGt>JQ?gGD$r0wA0eB#omjPwdCpQVF{vb-b2?$I&NOH4kaQWeNHQryP0I4<5|sQmyxVzawMBL`yN@q)d8>>z|c#bu2Xu_NpvZb?4u;(SV?4{ zo@fb(F9nOPEK~xsbUx3ApQGH}?N<{JecRs%9BMB!fc+A<)&QOY(B8mgwo&tMC6R%8 z?vX&FPUdk*V1)rJBe1)jpFoy<=CzXI4g;7gfgc+{o@BX?z%}>S zlq`QBkV6)eq}XZz$Bqkyw;RBl1a`M~5y&OW3zA~50sKV*FB-rjlI0+QJhI#?DGnLH z9TIrU0G3OZ_X*^arAktKU;tN1;4=frmn@;|GpCa!RZ@f*fK39!3}BRGIh{ZOSwbYm z83ypdXF~lk25^MH?)Hlah%w|vNpZ0Ov`Zk_03MYrQwWGrW}~E-Y5=MPrW?Rb61c(u zs%07cDQ7tj&65-h3}Cth78<|=$+DDy7^%ieit7y^S^_s3K&WJK5)fnAho1`dn+@P^ z5>O3bKY`utcM}k!-BXg{=LYaQ3EXc0_eqxD5)k9zos!~F1GrfNe>8yWBny8{TaK7N zkQ6%&pg;m$1~5^wyi7ohspm_IzZyV{1P&U2S+e|#fEaZ@`b4PjF@V2I;C%yliNNmm zFA0coxkFNXZ2-TQ0DqxHQv5=)SO|!byG2rrFn|>j;1}#A#bU{F9sx17|4>qlHGoSc zz@Ime6ls!WA^|b_kCPPX25_1LrWin&WVwuhm>+!nu~2`e0lX!F*#>Zc!0z@^0%8WS zQ&N;0z+)1))&TC8EDZ$29AllNXf%LZByh6<)JT@w35Z$9d`aOlfEg0_kpZMjmU{_^ zc}l#bxX%Dim%tVS7$jMKPe9CMKKV$f|F{9XErCB9z{>=7w|5d)!2aWDNwM1i9+$wg z2Czx8yhcFGhJGX|dJJHt1l}}&C6dKUK+Km)B*nW1aG3-?GJr`E_|gC_kYx2#8tPA0$Ph0c@7QL<4A* zEI9-gQm|VkMVa%c6Y9T3 zfU{Z8zX%*^|Azs*Dgmzn?3OH_5#W^9vsF@jZU9>(;4^@qNS0xo(Q;nwSuH7s8$g`| zMj1eSz^#*Xg1a35dG63!4 zhJxW9GF-`g_v&3=A>sGMHmo7=rkQIA5!yN2hBXVM#gBHhv03(O`?Z7;K_kt(Y{e zm}ekIO9_5vjVn8>k9FV{PQgd0^pDj0V&1@#Pjkoe_^vP;R&uz|(iIlZH63aZmVm3@ zodd;@QappvwQ>CpfASk@TkOck4^*Fk`}YR-UJTC=0dq%DN)yEN#XN%Qx1@Y)DUTVY zaGu0c_`5EYWj{;Fg?3xgzO|Gtqm(R^;){u;@$qD~@x0*L?*oq~Qmd4v7AslXgw-1J zH?vYW0xQWjv&f~fJHFMX+-@js`bXFUdNd1bL{pE3D?r)e-v*=0rJ4SKT~PaYSKz zl(5PM+H(+o+$)Da@P0mQ5hrUZ|zV8`y1)$rUi-P$rSA0S;hS#nr_2L4Ydn2cS zjzO!C--GqV?4bDKNflQN;nXM!2C*aPSav4-T1ZTsU^A9S@T2v{((b{54Xjtbk077t z=O$P*(9bLh5z)2`^YRy*8Ygc))@!h5a7k&e*VWS-!~=Bj$GwEl;nH&%s7N3TfeXAb zODoXwb;5hg2XqF#vVKKb--Y&pWDWF45TC-1DMa~QVf+9f?IyqZ*A+HTOLv9wTh+`# zFA$HD`%Bnj3!f=yre_Cb_4hAmH2-FtizO=22W_qZQ$UqYz@A0+L_>B<^Ft_^Z4@0@ zQLOmcm_W)lAH?rM1$YMP%%V9JN6uy&g~3oaoTG^v!;xfL8$9B+RpMzLsnjUvJ0@3D z^8v(4k?28Y#dd`We#qcGSMQ7(W7)fsx34$5;Z0GD=Rw*+AC~wPv@KOAoo}kYi?ucH zC})-xX?$b%Yb0Ae)4syvgP^0`t8lUGna@C{vSk@KQ8vx3eJh!taBlt+%J8fWP*88I ze2#)VfBgnOUj$yo^BIWyOc`2@Ki}9QXwus18(XNIi?wrscFxt#723H(J6CDvGVMH1 zJKw3D*K6li?YvPtZ_v&UXy;Ahyr@GS1to@K|EkOx|u1?P3SbUrm zm@N*SYLV+zJb)^8y@;QvnCJd8*qui)np&FLK!$44oX5?L7l9<40|$8A4Xhs}s$f>Z zs)EtEtE5w_)_FYJu^)`~mKr#$Mou-ewK{=wn(4ku)Dy+>`xFgU%U!v)vr#3_W88es zvucHHjN({_)7gsSc5sM7`)aNi8X^nzl%gR)WidyhvM`pt^Z4MdFy_+mD~~vjCOD4|LqS$(ZiATdmUVpKpr(?T(|~5CM(<$iVB^i| z@D5yU-^Ju!OVg9c+)hePDvskfA*Z8QXJ^FfF9}+lPUKsjm>rJa)KP~yzldtNO;JD$ zHsm&~L$31+tEK6fxCpm2ZN&xRpEKz@Q2;y{3q*16_!>=~MaqI3#;f=h9?U(ImNlZl zpYZ?CQO?eAaL2XaaC^Wasp}8GlU8`r22aL2cO`VTN|{HYm;4>NWkx~JC zS9Ob^_@7^0K4|qm^iaMF_B|Pbs#d?lEYlaLAr>{nx^G7f9t-%eAN7f-rURBIJ_O4P z+Nvn6VxC>qsYJ{e-M3_I;ok)TwLBM#29p*u6_YQP)dRyXo z^QHqZBY%H%3?g|^t8c$RTJRP5Y_ltdxftL)&Rr27b+Ug!`-@daH|>G{zw|k57-%fM z==((4YeF+_`~WrCJ5ketnfQ$MuGsmVi3jmP#?F=;lN#MjLfGnhL!hV0#^d zWcgiTOjA|wddesIClu)h>b?rrQ%5T%%#n_oQT4@(TGdcCkbGnSa_w>RK_Uc>!0%9E zRx5t7cfUG691-_dy_5?iF}kPuS9hX6-TXGnM$pD4ev0so26v?E7#tl9N5`UT?L_dH zIaNjh6wLh){%`JZbvmZAeQCwIxHrb;$}zhiNA_k4=@O#ip*BR*D}Mx;u44fDR?rSd z`@DDP_7ws#(jdxUm@u(pey7e~41P66H^BkN*=k67cjE}}Wx74X(|a6aTu-ah!of{v z2+O5{4V7wzsRiM#8DeM{jfWdL4Zo)j8t?1i-6G`Q?>(rEHyj0W>oFLFIu__diHHXw zD{86|7a(gqqLtSbM!UjZiu)=2$C7uWKOu-{8z-|-r7<-1Ezfa}I|PyI{i!ZolUBqt z?spK@-XAkI_~#qDLK`QWw6jAyuhP!Tw6je+$7|%cD8C~yLOJ%&I#f? z$Mp}i1ozC#g#8LfBH;fv!{^(}(Tm=!LZCxrv4M!^|Ni}FEWm*B|KpuMG5TfGOY+*E zMo;qtyhlJIMhk){a1*fOz_7$5|A0LJECiinU+f`Z5x|D@p?d^aj33=&z{UWJ>O;2` z*d@S5^ue|P%LaBvA8ZG(9{|I8q5Q*R{|;bfepoiJYk~F3Vp1xA)%jt$z?K8U6wxS; zx6ZfvVFkdNfnm~M(Cq?t2e7`f=-I)}&%hVuRbSO{CeFX-k#4xEH~lKo_m2Iljze;w zKdbff#wFKO)?1e@vM#J^9M@oNY^bc5q|92n)N%RJipoh!QF*J<*7AFuhYu0E~>6Y1t6)cbttnc8yagI zN@?km^6J{sQd~GH8yvV;ShIBDVx_*k_S#CtQN5&6SthUjlvuCz3x4o_li!mCYO1ff zcHzR(hSG`~lP*piUr|#77u8o@TixKOtS?4B2p|Syd6_tTFg`{=$)rf{g)isrhRjI74P?*GDY3bO8(o$=ErK7RFwz9%nyR`P= zu?^OE$MU*L>)7#0c6-AGN_njn^)S>e|J8>*Ky*7QTFYpWf~*oyIED^P_&2)P$7 zT~Y^S7`fIPD(f4nm)2S#1X|gWr4@}emDX`%$0tJgan_2Zl?_nKVO>)0SXgDPZ>;rW zQj}{Nt7{z9wKSoADVjD7ztX(&V~W29ah~0BBdDeFR5IzsJ^mN zSYFA-T@H7iOi{k^=Z$-X}hlnEk1*>Sm&a-)IQ9sJyzSvA%NBP;>`# ztLq(&PVM5_r8m}E>l!K> zE0)4*Xz=9@+NrL7sblHFr8T{Vs~FF5;Y2*wK-q@so1nR*rOf~RJ9P_0YekrDnx&Xl zgqzNaFq_w6ytV@8-R+SvJ|A}_C{rWDogq1q){vQz;Zr*!Io_n;$i@+8_4z);S;>jC z=Q_;=w}lqm9`b`o8eNONbQFeEK#1-t@B2WT$FS;^CBa(E%E z%=$Lr*b5rG;UNBK_pLbg0b?Cf@2Qayw}(!RjJnM{H8R>67E;t188vlJWW>}iIBYi^ zW&`O_9Ph9`EPgBbk^4<0&am6ew}&=|gboeeEu1Cj_)AUi+kC!5AcKF(igdD&y&9D) zFB5bRjK$9=;wF*)H|Rolhv!qWl6Z9A|6<` zvXJcqizV;J;C&UmyHCXXWME!9^e9dC`CdK|Z`VLx`lANCpMsY+&p~8vHHC(m268J3 z<>m(St`wi|xf9jhF_4>eyTN-^s?WzCI166);DB|LKOQl3;RK&=S>%cMYa$2Mu826O z0{=C+cw8_#D1Tk(U84iB3;u_|-&yYSy~j==kiYXIJ3>O=j0#kM&>#HQ*ZX{b;Ksbb z{H-COTV@91kH^i-TTh`s=y}f-$#n8xze691y8Me4zO7_*u!14xo;d=2GOb(iqa&&-Jzt;*z8>`Vi z09tPHqb)?gfJ@3sncc|aFAK8o%yowS;5Kvq?VNnTK0dRs`oGxW-#>@=qiYlw`y68(N;TwbL0vZ0+A8aS3`g0vM!#B*4aC7)(@ zYY}wF5sb3pT3Mxm{!pY9jzjx#lz@K&`BCpY#9AJ_KuJr*b%`WKb}-$kH;;tpeLk_) zAld@v9dkJAK*s-Le}m`D;`UZ0DaxcU!~h9HX#2KLuyp`RI3Db;~Q1qUD$3 zHl$R?SjvC@{$H}dGAn&5|Bhd1Qew|FDG&6)>=&7oTwweAVDo_00Xy0UTLtV+U=io^ zmbU>v0{RHBK!4ltg3f*%ZXCyPMBq`u**GTQn1!PZM?DVyt--k!$2~Y6!0`xFBa!`9Jx5kaMa;gi(?}W{%ys1KaL|f-or8I ze3KH5BLT-G9K|>)aNK}nEslF|JdERM9NjpM;V_RgDRDULIHut!#!-c1C64tt9>DPj z9M9nRJB~r|Cgn67HXKPfrr{{YaUG6jIM(9Wfa4Jy9XR&mID+FC4&?&KhhsdBX*h~; z)Zkc!;~pHp!?6R$b2#3>aSTT|d~C%r8Al0@S{y5JY{2m_jvYAo_h0|~-}cXoN^T{V zpDJ_etFd}pUNgILA=g%Lf0u`qvU-15`NlN8(otC6;K-}5Uy6;QBSMg#DVC}V%4;iX zDyL#NC010wbm3IFl!Mk3!tTAgyap>T{zZ-tEvziRVF0Y$WiGC1KtXfMYZ@z+znHbP zBb4iajCjpmN5pCpXG>T(tf^UATe%EtZBHqsmG$+t*kjuivS?9FV?&jq{4_)^X6*`D zQVzm}it=Je-O?MCS3|CEz>1jC9fGCf3T#FS!HSV#S&RL)K)H%I2O?%U}a4yX%qc0 zz0C0#cBgUKtu()W>5|zFEUjKUwYFk5oCF>{uNW(+iZTo79IW$~US4@4dQzlvs~0*- z;h#$#l^QQ**E%k!R6RAjKh<5p5k93kHFzGN+^wbZmMyHTW9-f3`X<(am7i-l`Ah4u z=E?O7$#=!Vg^l%GxW(#)L{PyM*IdW2_){+;6;htmkgLk;Yx9;V$__nEx6P@oFRyMW zzXr?6&lA6)yrz_)T3m$?sDKOybQBLD99Sck8H)07FZ)k`k4ooysPRIc+a$G;DercbvUBl1;J{R^CuqqZwbR2TdWC{7a|S z)iLsx>uC`Wx9TY&&Kjnc)?N$ccv9BsX(}d=ANNIObJeyKa{OFJMJc~SYG&n<(wSO& z{JoZ*rM2LvnHJqsX%1ZKs7z9nUA-7|l-j)vOg`bFHE`e6n-;QQ9cK9zvr8LlwT3;M zX%TXzIjCAWw>OP483BrN-T+MZ%-DW8Y(a{0NiTM3LvcO&ya~O?tm=hTIe1inhhd76 z-issfWnGg7V0vBqkW*Y=zOZsy`NGAe1$eZAs3z7}S0kJA%SNgQBv{We(lTyFhZZfL zQ(L`|%|Ex2Cq*gfgVAAn8=dKg>rz}E5Z8N~Iel_3<+xMZ+aoDTb)Q@*Q40|EJ#*y~ z6D8GL3WY?Qo$cVmnjCfzd@|I+oYMUAnubb<(uhF*nLsYbIH3W`eFCA$bp#zQ=cFfb zT$VTM^1Q<2B=Iy0Y|-F3nPW-A4GZh>U`OYR2VbB=&^aVkCTM~ke5{7}&>p=hN)c%P zdth$9+)=f(Hd#Jxgn$0~_wTa+pZy(aKk+_~e_!qYE%|@b0%v4@T^EPr73@thV@LA; zrY!%h`+va#QF2XnkUh#i);`JpbNkEoBldsT7bi9(-kZ23ac|^o!Gz(lgRm zrMIO2Ed7`1(8s+hE7(yf#3ob>Zaznt{fNzoZu8Fyv8km1Xy&Ac&lP3D}eTeE(X zWu2l}vGxEn+?2Q>aZ}<$iH|03OMD~o{lt$GeTnBMtxMXFv^VLkqz{vhCk;uCO+GvM z#^h&`-N~OMf0-PXa#qTsl+`JBrrecsZ_4W_e^2qIe3259dQoaaYIEwQ)Q3~IrtV1H zmwF)e&D3{OKTB06tekM$guIC}Cx)d>OY@|~r+d=BOy4spEaRSxEg1=!8JWMzd@l3L z%$Te(S%q0kvYc6e$a*&Go2=!Ne>Ay$@@td7nQWVqI_0t{E2rGeT@-dj;hOT@_D!(f zutZzp_{2$x(-UhFe+DaVO?)OXI%!f;b&@lwC8;CnUrAplB_&^$d{gp<0hT$n$$Sy{Yk?!&d*qwac{<}8AX{Z zGk=`<+sv0T-^m=Cb${0OtXHx|OulsTt&=~W96u#v%A6@TPgy_ZMaq?pXJ$BEYOl1f zv~Rb6WWNCN97y~J>}gF(PjV!^mozllmRz3v- zspn7l!Gvcgd@*78#BmcZn^-aN{)uO#rKVkxc4yj-wD;4>(_7QGr2i%Tt@M$TW=`sw z^wy-WCr!$@F5|(BF`08RugSbE^GBH*Gat!3lzB$h`mD#Y_GX1mo;bN-^81s|ni4-{ z=9IE2H%-|z<=H9kPEm>!1yes|g#8M8wf$H2u*8vx6B4H+7ABS?HYW~FIur4?An8VU zeq^#b@uw4?ocQ9z4C@8H^!Q1y zPC7PeRp#2vi?VLYYRSr+ym#`E$wQ_f+7zV>&wOxt#(uz_m^dSGVd9F!pC&$-_(I|_ z#Qd2_*-2L>RVCe-bYIfer0yh7k~uj(IX$^Jd0Db6`2qMXEG0T6EoEWKwv-oB9I3aY zUOi#Sgd5X-l=f`eztWWStn?-6KThA2{!scK(|4sGPXAZ>On7qTq`N1*0*QuXshByPM%yidF|xR$)Qum zP8mNXf6AIEznHRZ$|qA4^w^YtyuHTWiq`v>{V98w-Df{7F)s1K#EFUX5*rgAPdp2r zz7mnQCuw+cGUBcl?dA{3XQia4%t~38ax}%4az<)K>cZ3&soPRdpK#%X+zE^Szjm$v zr>iOqe{g1y28NUkTqDzsWYszMoO{l>=iGCy;74NVAkdmRYCs026p~!BpI-EXd+zFSj%Kfrg_R1u+T5VDR73R)^ zY%<*(H_xpC72T&F)=TtSJ*2Pb87AI*U~WO}tG!D>{L6j5Mp*7d+fXfPM1yDnUW!}s zDLjg2g5J+sQ`U>5oK%x`vY2MketMaP*z@fwyUFgh$LuUt$o8;fY#|psop0j5@IQeO zN_;3ziu2-cQRGyB|9t5Q;m5x|-we0&X66hut)YuMCuQuZc5> z<~cKDu9z8KyjSP7c&9!1PwLHo<9r?!qkZUO;7TfBTY>xW1kSZetbo;SVd5vxlC5MK zO`-X8gx;j#_G9+Dfaw|ghW!F7W&2q>qx^B6#kcb*9xmdFTRQbp6~D|8FpL7QkNJqM0CK_hGn zm=I+0F2EQb)C?tpEfr=-EQPIMds!Vj&c0(q><4y{jk8dGH=oO6_=CWdWS+uT@Mj>q zTwcKU@Blx+-{B4XC~xIGe1H%05k3a>xdXaKw0KB7A~5ui1o5=U5Lse_$QMOot2iKP zL<7|C6VWcZ#gMol#-XS9oERtB$#xDqP2e@(IH#QfXTcUR9%xsAH;4eXV-c zSwQ?}byZC&>~c2&RGD_0$;ECd^r_wMLATyL>bAP=Zl~Mh#_BkYHP^0A(wRC>7wav$ z0z9Tx*XtJj6?BYVJ*=l$rpuf% zXAJlJ-db-x_#!Bz1Lm<%hETK=r{OG|gY&_k>TnZo#-D+Y{|Y`e$69E`TgpnXR$B#D zrFGcqw Date: Sun, 26 Aug 2018 23:01:38 +0400 Subject: [PATCH 008/129] edit setup bat --- sources/setup.bat | 2 +- sources/setup64.bat | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sources/setup.bat b/sources/setup.bat index 9444896..134808b 100644 --- a/sources/setup.bat +++ b/sources/setup.bat @@ -1 +1 @@ -python setup.py build_ext --inplace \ No newline at end of file +"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup.py build_ext --inplace \ No newline at end of file diff --git a/sources/setup64.bat b/sources/setup64.bat index 0cb9fce..8499930 100644 --- a/sources/setup64.bat +++ b/sources/setup64.bat @@ -1,3 +1 @@ -D:\Python33_x64\python.exe" setup64.py build_ext --inplace - -"C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\mt.exe" -inputresource:D:\stuff\blender-2.66a-windows64\python33.dll;#2 -outputresource:D:\sandbox\blender_db\new_substep_molecular\cmolcore.pyd;#2 +"C:\Program Project\Python 3.5.4 64 bit\python.exe" setup64.py build_ext --inplace \ No newline at end of file From 811e4f3433b7a0213a10b2d6e12a832c7a232467 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 23:03:30 +0400 Subject: [PATCH 009/129] rename 'setup' files to 'setup32' --- sources/setup.bat | 1 - sources/setup32.bat | 1 + sources/{setup.py => setup32.py} | 0 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 sources/setup.bat create mode 100644 sources/setup32.bat rename sources/{setup.py => setup32.py} (100%) diff --git a/sources/setup.bat b/sources/setup.bat deleted file mode 100644 index 134808b..0000000 --- a/sources/setup.bat +++ /dev/null @@ -1 +0,0 @@ -"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup.py build_ext --inplace \ No newline at end of file diff --git a/sources/setup32.bat b/sources/setup32.bat new file mode 100644 index 0000000..c5bb9f7 --- /dev/null +++ b/sources/setup32.bat @@ -0,0 +1 @@ +"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup32.py build_ext --inplace \ No newline at end of file diff --git a/sources/setup.py b/sources/setup32.py similarity index 100% rename from sources/setup.py rename to sources/setup32.py From 1a643ec1ebd805ea87bb0d7fd0dcf53faf369ed1 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 23:04:49 +0400 Subject: [PATCH 010/129] remove ToDo.txt file --- ToDo.txt | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 ToDo.txt diff --git a/ToDo.txt b/ToDo.txt deleted file mode 100644 index bb13b83..0000000 --- a/ToDo.txt +++ /dev/null @@ -1,31 +0,0 @@ -[x] fix zero devision can happen in somes normal cases -[x] Separate compression / expansion stiffness -[x] Link tension ( bigger or smaller than when is created ) -[x] Max links per particles option -[x] Bake when finish option -[x] start render when finish option -[x] Free the memory when finish or stopped -[x] Max velocity info to give some keys on how much substeps needed -[x] Multithread kdtree searching -[x] Multithread kdtree creation -[x] Link search distance relative to particles size option -[x] Time scale instead of FPS -[x] Fix UI bug when object without pSystem are selected. -[x] Print: new links at this frames , total links from beginning and links broken -[x] Fix bug when mass by density is not check -[x] Fix more than 24hours estimating time issue -[ ] Support links length on randomly sized particles. -[x] Fix memory crash issues. -[x] Add collision "damping". -[ ] Make broken links with particles penetrating don't explode. - -[wip] ***Deeper profiling before doing in the list below*** -[ ] detect INF value in location and velocity -[ ] Try to see if I can send info of particles by memory adress to gain speed (like Mohamed does for it's mesher addon) -[wip] Optimisation in the code ( kdtree search and creation take most of the time when profiling ) -[ ] clean and comments the code -[x] Multithread particles collisions and links solving -[ ] Optimize my own quicksort to stop when median is find -[ ] make particles not born or dead don't be calculated in kdtree -[ ] optimize links searching by puting dead links at the end of array and calloc them when iteration finish -[ ] Make link exponent work more propertly From c2ca48b970fb75184dfe1f556cf096677369292f Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 23:07:37 +0400 Subject: [PATCH 011/129] edit README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 13cfce9..d55fa15 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Blender-Molecular-Script ======================== -This is my molecular python script for blender.Inspired from the 2d simulator Really (1998) and Lagoa Multiphysic in Softimage. +This is my molecular python script for blender. Inspired from the 2d simulator Really (1998) and Lagoa Multiphysic in Softimage. To download the latest version go on my blog: @@ -27,5 +27,3 @@ To activate the plugins: Visit my blog about this script for donation, comments or more detail : http://pyroevil.com - -You can find older version in the release folder. From ac87b8ed9af89c23fac534538e5e01ec14d10713 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 26 Aug 2018 23:45:05 +0400 Subject: [PATCH 012/129] 1.0.4 --- molecular/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 5a3a284..70a106b 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -18,8 +18,8 @@ bl_info = { "name": "Molecular script", - "author": "Jean-Francois Gallant(PyroEvil)", - "version": (1, 0, 3), + "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", + "version": (1, 0, 4), "blender": (2, 7, 9), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), From fc010267fe0e857cef6017ddca7a3e48c1bbcfdb Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 2 Sep 2018 20:32:58 +0400 Subject: [PATCH 013/129] precision=6 for all parameters --- molecular/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 70a106b..db9431c 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -67,7 +67,7 @@ def define_props(): parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) - parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 3, default = 1) + parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 6, default = 0, subtype='FACTOR') parset.mol_link_max = bpy.props.IntProperty(name = "mol_link_max", description = "Maximum of links per particles",min = 0,default = 16) parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') @@ -75,7 +75,7 @@ def define_props(): parset.mol_link_stiffexp = bpy.props.IntProperty(name = "mol_link_stiffexp", description = "Give a exponent force to the spring links", default = 1, min = 1 , max = 10) parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) + parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_link_samevalue = bpy.props.BoolProperty(name = "mol_link_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) @@ -85,7 +85,7 @@ def define_props(): parset.mol_link_estiffexp = bpy.props.IntProperty(name = "mol_link_estiffexp", description = "Give a exponent force to the expension spring links", default = 1, min = 1 , max = 10) parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 3) + parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') @@ -93,9 +93,9 @@ def define_props(): for i in range(1,12): item.append((str(i),"Relink Group " + str(i),"Relink only with group " + str(i) )) parset.mol_relink_group = bpy.props.EnumProperty(items = item, description = "Choose a group that new link are possible") - parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0) + parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0, precision=6) parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') - parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 3, default = 1) + parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, default = 0, precision=6, subtype='FACTOR') parset.mol_relink_max = bpy.props.IntProperty(name = "mol_relink_max", description = "Maximum of links per particles",min = 0,default = 16) parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') From d935b0c11ea762b684f0c62c744953a89b1a6565 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 2 Sep 2018 23:59:28 +0400 Subject: [PATCH 014/129] deleted global variables --- molecular/__init__.py | 168 ++++++++++++++++-------------------------- 1 file changed, 63 insertions(+), 105 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index db9431c..7086387 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -42,7 +42,6 @@ import pstats, cProfile import multiprocessing -mol_simrun = False def define_props(): @@ -128,10 +127,21 @@ def define_props(): bpy.types.Scene.mol_render = bpy.props.BoolProperty(name = "mol_render", description = "Start rendering animation when simulation is finish. WARNING: It's freeze blender until render is finish.",default = False) bpy.types.Scene.mol_cpu = bpy.props.IntProperty(name = "mol_cpu", description = "Numbers of cpu's included for process the simulation", default = multiprocessing.cpu_count(),min = 1,max =multiprocessing.cpu_count()) + bpy.types.Scene.mol_exportdata = [] + bpy.types.Scene.mol_minsize = bpy.props.FloatProperty() + bpy.types.Scene.mol_simrun = bpy.props.BoolProperty(default=False) + bpy.types.Scene.mol_timeremain = bpy.props.StringProperty() + bpy.types.Scene.mol_old_endframe = bpy.props.IntProperty() + bpy.types.Scene.mol_newlink = bpy.props.IntProperty() + bpy.types.Scene.mol_deadlink = bpy.props.IntProperty() + bpy.types.Scene.mol_totallink = bpy.props.IntProperty() + bpy.types.Scene.mol_totaldeadlink = bpy.props.IntProperty() + bpy.types.Scene.mol_objuvbake = bpy.props.StringProperty() + bpy.types.Scene.mol_psysuvbake = bpy.props.StringProperty() + bpy.types.Scene.mol_stime = bpy.props.FloatProperty() + + def pack_data(initiate): - global mol_exportdata - global mol_minsize - global mol_simrun psyslen = 0 parnum = 0 scene = bpy.context.scene @@ -176,8 +186,8 @@ def pack_data(initiate): psys.point_cache.frame_step = psys.point_cache.frame_step psyslen += 1 psys.particles.foreach_get('size',par_size) - if mol_minsize > min(par_size): - mol_minsize = min(par_size) + if bpy.context.scene.mol_minsize > min(par_size): + bpy.context.scene.mol_minsize = min(par_size) if psys.settings.mol_link_samevalue: psys.settings.mol_link_estiff = psys.settings.mol_link_stiff @@ -247,6 +257,7 @@ def pack_data(initiate): params[43] = psys.settings.mol_relink_ebrokenrand params[44] = psys.settings.mol_link_friction + mol_exportdata = bpy.context.scene.mol_exportdata if initiate: mol_exportdata[0][2] = psyslen mol_exportdata[0][3] = parnum @@ -281,10 +292,6 @@ def draw_header(self, context): row.prop(psys.settings,"mol_active", text = "") def draw(self, context): - global mol_simrun - global mol_timeremain - global mol_objuvbake - global mol_psysuvbake layout = self.layout scn = bpy.context.scene @@ -460,21 +467,21 @@ def draw(self, context): row.prop(scn,"mol_bake",text = "Bake all at ending") row.prop(scn,"mol_render",text = "Render at ending") row = layout.row() - if mol_simrun == False and psys.point_cache.is_baked == False: + if scn.mol_simrun == False and psys.point_cache.is_baked == False: row.enabled = True row.operator("object.mol_simulate",icon = 'RADIO',text = "Start Molecular Simulation") row = layout.row() row.enabled = False row.operator("ptcache.free_bake_all", text="Free All Bakes") - if psys.point_cache.is_baked == True and mol_simrun == False: + if psys.point_cache.is_baked == True and scn.mol_simrun == False: row.enabled = False row.operator("object.mol_simulate",icon = 'RADIO',text = "Simulation baked") row = layout.row() row.enabled = True row.operator("ptcache.free_bake_all", text="Free All Bakes") - if mol_simrun == True: + if scn.mol_simrun == True: row.enabled = False - row.operator("object.mol_simulate",icon = 'RADIO',text = "Process: " + mol_timeremain + " left") + row.operator("object.mol_simulate",icon = 'RADIO',text = "Process: " + scn.mol_timeremain + " left") row = layout.row() row.enabled = False row.operator("ptcache.free_bake_all", text="Free All Bakes") @@ -499,8 +506,6 @@ def draw(self, context): row.operator("object.mol_set_global_uv",icon = 'GROUP_UVS',text = "Set Global UV") row = subbox.row() if obj.data.uv_layers.active != None: - mol_objuvbake = context.object - mol_psysuvbake = context.object.particle_systems.active row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV (current: " + str(obj.data.uv_textures.active.name) + ")" ) else: row.active = False @@ -555,34 +560,19 @@ class MolSimulate(bpy.types.Operator): def execute(self, context): - global mol_substep - global mol_old_endframe - global mol_exportdata - global mol_report - global mol_minsize - global mol_newlink - global mol_deadlink - global mol_totallink - global mol_totaldeadlink - global mol_simrun - global mol_timeremain - - mol_simrun = True - mol_timeremain = "...Simulating..." - - mol_minsize = 1000000000 - - mol_newlink = 0 - mol_deadlink = 0 - mol_totallink = 0 - mol_totaldeadlink = 0 - print("Molecular Sim start--------------------------------------------------") mol_stime = clock() scene = bpy.context.scene + scene.mol_simrun = True + scene.mol_minsize = 1000000000.0 + scene.mol_newlink = 0 + scene.mol_deadlink = 0 + scene.mol_totallink = 0 + scene.mol_totaldeadlink = 0 + scene.mol_timeremain = "...Simulating..." object = bpy.context.object scene.frame_set(frame = scene.frame_start) - mol_old_endframe = scene.frame_end + scene.mol_old_endframe = scene.frame_end mol_substep = scene.mol_substep scene.render.frame_map_old = 1 scene.render.frame_map_new = mol_substep + 1 @@ -593,8 +583,9 @@ def execute(self, context): else: fps = scene.render.fps cpu = scene.mol_cpu - mol_exportdata = [] - mol_exportdata = [[fps,mol_substep,0,0,cpu]] + mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata.clear() + mol_exportdata.append([fps,mol_substep,0,0,cpu]) mol_stime = clock() pack_data(True) #print("sys number",mol_exportdata[0][2]) @@ -616,17 +607,6 @@ class MolSetGlobalUV(bpy.types.Operator): def execute(self, context): - global mol_substep - global mol_old_endframe - global mol_exportdata - global mol_report - global mol_minsize - global mol_newlink - global mol_deadlink - global mol_totallink - global mol_totaldeadlink - global mol_simrun - global mol_timeremain scene = bpy.context.scene object = bpy.context.object psys = object.particle_systems.active @@ -644,23 +624,14 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): - global mol_substep - global mol_old_endframe - global mol_exportdata - global mol_report - global mol_minsize - global mol_newlink - global mol_deadlink - global mol_totallink - global mol_totaldeadlink - global mol_simrun - global mol_timeremain - global mol_objuvbake - global mol_psysuvbake - scene = context.scene - object = mol_objuvbake - + scene.mol_objuvbake = context.object.name + scene.mol_psysuvbake = context.object.particle_systems.active.name + object = bpy.data.objects[scene.mol_objuvbake] + + if not object.data.uv_layers.active: + return {'FINISHED'} + print(' start bake uv from:',object.name) #object2 = object.copy() @@ -683,7 +654,7 @@ def execute(self, context): mod.use_beauty = False bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name) """ - psys = mol_psysuvbake + psys = context.object.particle_systems[scene.mol_psysuvbake] #print('-------------start------------') for par in psys.particles: parloc = (par.location * object2.matrix_world) - object2.location @@ -732,21 +703,6 @@ class MolSimulateModal(bpy.types.Operator): _timer = None def modal(self, context, event): - global mol_substep - global mol_old_endframe - global mol_exportdata - global mol_stime - global mol_importdata - global mol_minsize - global mol_newlink - global mol_deadlink - global mol_totallink - global mol_totaldeadlink - global mol_timeremain - global mol_simrun - global mol_objuvbake - global mol_psysuvbake - #mol_stime = clock() scene = bpy.context.scene frame_end = scene.frame_end @@ -760,14 +716,14 @@ def modal(self, context, event): fake_context["point_cache"] = psys.point_cache bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 - scene.frame_end = mol_old_endframe + scene.frame_end = scene.mol_old_endframe for obj in bpy.data.objects: for psys in obj.particle_systems: for psys in obj.particle_systems: if psys.settings.mol_bakeuv == True: - mol_objuvbake = obj - mol_psysuvbake = psys + scene.mol_objuvbake = obj.name + mol_psysuvbake = psys.name bpy.context.scene.update() scene.frame_set(frame = psys.settings.frame_start) bpy.context.scene.update() @@ -779,14 +735,15 @@ def modal(self, context, event): scene.frame_set(frame = scene.frame_start) cmolcore.memfree() - mol_simrun = False + scene.mol_simrun = False print("--------------------------------------------------Molecular Sim end") return self.cancel(context) if event.type == 'TIMER': if frame_current == scene.frame_start: - mol_stime = clock() - mol_exportdata = [] + scene.mol_stime = clock() + mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata.clear() #stimex = clock() pack_data(False) #print("packdata time",clock() - stimex,"sec") @@ -801,27 +758,28 @@ def modal(self, context, event): psys.particles.foreach_set('velocity',mol_importdata[1][i]) i += 1 #print("inject new velocity time",clock() - stimex,"sec") + mol_substep = scene.mol_substep framesubstep = frame_current/(mol_substep+1) if framesubstep == int(framesubstep): etime = clock() print(" frame " + str(framesubstep + 1) + ":") - print(" links created:",mol_newlink) - if mol_totallink != 0: - print(" links broked :",mol_deadlink) - print(" total links:",mol_totallink - mol_totaldeadlink ,"/",mol_totallink," (",round((((mol_totallink - mol_totaldeadlink) / mol_totallink) * 100),2),"%)") - print(" Molecular Script: " + str(round(etime - mol_stime,3)) + " sec") - remain = (((etime - mol_stime) * (mol_old_endframe - framesubstep - 1))) + print(" links created:", scene.mol_newlink) + if scene.mol_totallink != 0: + print(" links broked :", scene.mol_deadlink) + print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100),2),"%)") + print(" Molecular Script: " + str(round(etime - scene.mol_stime,3)) + " sec") + remain = (((etime - scene.mol_stime) * (scene.mol_old_endframe - framesubstep - 1))) days = int(strftime('%d',gmtime(remain))) - 1 - mol_timeremain = strftime(str(days) + ' days %H hours %M mins %S secs', gmtime(remain)) - print(" Remaining estimated:",mol_timeremain) - mol_newlink = 0 - mol_deadlink = 0 - mol_stime = clock() + scene.mol_timeremain = strftime(str(days) + ' days %H hours %M mins %S secs', gmtime(remain)) + print(" Remaining estimated:", scene.mol_timeremain) + scene.mol_newlink = 0 + scene.mol_deadlink = 0 + scene.mol_stime = clock() stime2 = clock() - mol_newlink += mol_importdata[2] - mol_deadlink += mol_importdata[3] - mol_totallink = mol_importdata[4] - mol_totaldeadlink = mol_importdata[5] + scene.mol_newlink += mol_importdata[2] + scene.mol_deadlink += mol_importdata[3] + scene.mol_totallink = mol_importdata[4] + scene.mol_totaldeadlink = mol_importdata[5] scene.frame_set(frame = frame_current + 1) if framesubstep == int(framesubstep): etime2 = clock() From ec53b13dc76e5fc0afc1e0b3587dc7bb09861b11 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 3 Sep 2018 00:19:56 +0400 Subject: [PATCH 015/129] divided into modules --- molecular/__init__.py | 795 +--------------------------------------- molecular/operators.py | 257 +++++++++++++ molecular/properties.py | 100 +++++ molecular/simulate.py | 133 +++++++ molecular/ui.py | 280 ++++++++++++++ 5 files changed, 786 insertions(+), 779 deletions(-) create mode 100644 molecular/operators.py create mode 100644 molecular/properties.py create mode 100644 molecular/simulate.py create mode 100644 molecular/ui.py diff --git a/molecular/__init__.py b/molecular/__init__.py index 7086387..9cbfb6c 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -27,794 +27,31 @@ "wiki_url": "http://pyroevil.com/molecular-script-docs/", "tracker_url": "http://pyroevil.com/contact/" , "category": "Object"} - -import bpy -try: - from molecular import cmolcore -except: - print("cmolcore not working") -from random import random -from math import pi -from mathutils import Vector -from mathutils.geometry import barycentric_transform as barycentric -import imp -from time import clock,sleep,strftime,gmtime -import pstats, cProfile -import multiprocessing - - -def define_props(): - - parset = bpy.types.ParticleSettings - parset.mol_active = bpy.props.BoolProperty(name = "mol_active", description = "Activate molecular script for this particles system",default = False) - parset.mol_refresh = bpy.props.BoolProperty(name = "mol_refresh", description = "Simple property used to refresh data in the process",default = True) - parset.mol_density_active = bpy.props.BoolProperty(name="mol_density_active", description="Control particle weight by density",default = False) - item = [("-1","custom","put your parameter below"),("1555","sand","1555kg per meter cu"),("1000","water","1000kg per meter cu"),("7800","iron","7800kg per meter cu")] - parset.mol_matter = bpy.props.EnumProperty(items = item, description = "Choose a matter preset for density") - parset.mol_density = bpy.props.FloatProperty(name = "mol_density", description = "Density of the matter kg/cube meter", default = 1000, min = 0.001) - - parset.mol_selfcollision_active = bpy.props.BoolProperty(name = "mol_selfcollision_active", description = "Activate self collsion between particles in the system",default = False) - parset.mol_othercollision_active = bpy.props.BoolProperty(name = "mol_othercollision_active", description = "Activate collision with particles from others systems",default = False) - parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') - parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') - item = [] - for i in range(1,12): - item.append((str(i),"Collision Group " + str(i),"collide only with group " + str(i) )) - parset.mol_collision_group = bpy.props.EnumProperty(items = item, description = "Choose a collision group you want to collide with") - - parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) - parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) - parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') - parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) - parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) - parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 6, default = 0, subtype='FACTOR') - parset.mol_link_max = bpy.props.IntProperty(name = "mol_link_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_stiffrand = bpy.props.FloatProperty(name = "mol_link_stiffrand", description = "Random variation for stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_link_stiffexp = bpy.props.IntProperty(name = "mol_link_stiffexp", description = "Give a exponent force to the spring links", default = 1, min = 1 , max = 10) - parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_link_samevalue = bpy.props.BoolProperty(name = "mol_link_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - - parset.mol_link_estiff = bpy.props.FloatProperty(name = "mol_link_estiff", description = "Expension stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_estiffrand = bpy.props.FloatProperty(name = "mol_link_estiffrand", description = "Random variation for expansion stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_link_estiffexp = bpy.props.IntProperty(name = "mol_link_estiffexp", description = "Give a exponent force to the expension spring links", default = 1, min = 1 , max = 10) - parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - - - item = [] - for i in range(1,12): - item.append((str(i),"Relink Group " + str(i),"Relink only with group " + str(i) )) - parset.mol_relink_group = bpy.props.EnumProperty(items = item, description = "Choose a group that new link are possible") - parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0, precision=6) - parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') - parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) - parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_max = bpy.props.IntProperty(name = "mol_relink_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_stiffrand = bpy.props.FloatProperty(name = "mol_relink_stiffrand", description = "Random variation for stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_stiffexp = bpy.props.IntProperty(name = "mol_relink_stiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_damp = bpy.props.FloatProperty(name = "mol_relink_damp", description = "Damping effect on spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_damprand = bpy.props.FloatProperty(name = "mol_relink_damprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_broken = bpy.props.FloatProperty(name = "mol_relink_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_relink_brokenrand = bpy.props.FloatProperty(name = "mol_relink_brokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_relink_samevalue = bpy.props.BoolProperty(name = "mol_relink_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - - parset.mol_relink_estiff = bpy.props.FloatProperty(name = "mol_relink_estiff", description = "Stiffness of links expension between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_estiffrand = bpy.props.FloatProperty(name = "mol_relink_estiffrand", description = "Random variation for expension stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_estiffexp = bpy.props.IntProperty(name = "mol_relink_estiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_edamp = bpy.props.FloatProperty(name = "mol_relink_edamp", description = "Damping effect on expension spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_edamprand = bpy.props.FloatProperty(name = "mol_relink_deamprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_ebroken = bpy.props.FloatProperty(name = "mol_relink_ebroken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_relink_ebrokenrand = bpy.props.FloatProperty(name = "mol_relink_ebrokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_var1 = bpy.props.IntProperty(name = "mol_var1", description = "Current number of particles to calculate substep",min = 1, default = 1000) - parset.mol_var2 = bpy.props.IntProperty(name = "mol_var2", description = "Current substep",min = 1, default = 4) - parset.mol_var3 = bpy.props.IntProperty(name = "mol_var3", description = "Targeted number of particles you want to increase or decrease from current system to calculate substep you need to achieve similar effect",min = 1, default = 1000) - parset.mol_bakeuv = bpy.props.BoolProperty(name = "mol_bakeuv", description = "Bake uv when finish",default = False) - - bpy.types.Scene.mol_timescale_active = bpy.props.BoolProperty(name = "mol_timescale_active", description = "Activate TimeScaling",default = False) - bpy.types.Scene.timescale = bpy.props.FloatProperty(name = "timescale", description = "SpeedUp or Slow down the simulation with this multiplier", default = 1) - bpy.types.Scene.mol_substep = bpy.props.IntProperty(name = "mol_substep", description = "mol_substep. Higher equal more stable and accurate but more slower",min = 0, max = 900, default = 4) - bpy.types.Scene.mol_bake = bpy.props.BoolProperty(name = "mol_bake", description = "Bake simulation when finish",default = True) - bpy.types.Scene.mol_render = bpy.props.BoolProperty(name = "mol_render", description = "Start rendering animation when simulation is finish. WARNING: It's freeze blender until render is finish.",default = False) - bpy.types.Scene.mol_cpu = bpy.props.IntProperty(name = "mol_cpu", description = "Numbers of cpu's included for process the simulation", default = multiprocessing.cpu_count(),min = 1,max =multiprocessing.cpu_count()) - - bpy.types.Scene.mol_exportdata = [] - bpy.types.Scene.mol_minsize = bpy.props.FloatProperty() - bpy.types.Scene.mol_simrun = bpy.props.BoolProperty(default=False) - bpy.types.Scene.mol_timeremain = bpy.props.StringProperty() - bpy.types.Scene.mol_old_endframe = bpy.props.IntProperty() - bpy.types.Scene.mol_newlink = bpy.props.IntProperty() - bpy.types.Scene.mol_deadlink = bpy.props.IntProperty() - bpy.types.Scene.mol_totallink = bpy.props.IntProperty() - bpy.types.Scene.mol_totaldeadlink = bpy.props.IntProperty() - bpy.types.Scene.mol_objuvbake = bpy.props.StringProperty() - bpy.types.Scene.mol_psysuvbake = bpy.props.StringProperty() - bpy.types.Scene.mol_stime = bpy.props.FloatProperty() - - -def pack_data(initiate): - psyslen = 0 - parnum = 0 - scene = bpy.context.scene - for obj in bpy.data.objects: - for psys in obj.particle_systems: - if psys.settings.mol_matter != "-1": - psys.settings.mol_density = float(psys.settings.mol_matter) - if psys.settings.mol_active == True and len(psys.particles) > 0: - parlen = len(psys.particles) - par_loc = [0,0,0] * parlen - par_vel = [0,0,0] * parlen - par_size = [0] * parlen - par_alive = [] - for par in psys.particles: - parnum += 1 - if par.alive_state == "UNBORN": - par_alive.append(2) - if par.alive_state == "ALIVE": - par_alive.append(0) - if par.alive_state == "DEAD": - par_alive.append(3) - - psys.particles.foreach_get('location',par_loc) - psys.particles.foreach_get('velocity',par_vel) - - if initiate: - par_mass = [] - - if psys.settings.mol_density_active: - for par in psys.particles: - par_mass.append(psys.settings.mol_density * (4/3*pi*((par.size/2)**3))) - else: - for par in psys.particles: - par_mass.append(psys.settings.mass) - """ - if scene.mol_timescale_active == True: - psys.settings.timestep = 1 / (scene.render.fps / scene.timescale) - else: - psys.settings.timestep = 1 / scene.render.fps - """ - #psys.settings.count = psys.settings.count - psys.point_cache.frame_step = psys.point_cache.frame_step - psyslen += 1 - psys.particles.foreach_get('size',par_size) - if bpy.context.scene.mol_minsize > min(par_size): - bpy.context.scene.mol_minsize = min(par_size) - - if psys.settings.mol_link_samevalue: - psys.settings.mol_link_estiff = psys.settings.mol_link_stiff - psys.settings.mol_link_estiffrand = psys.settings.mol_link_stiffrand - psys.settings.mol_link_estiffexp = psys.settings.mol_link_stiffexp - psys.settings.mol_link_edamp = psys.settings.mol_link_damp - psys.settings.mol_link_edamprand = psys.settings.mol_link_damprand - psys.settings.mol_link_ebroken = psys.settings.mol_link_broken - psys.settings.mol_link_ebrokenrand = psys.settings.mol_link_brokenrand - - if psys.settings.mol_relink_samevalue: - psys.settings.mol_relink_estiff = psys.settings.mol_relink_stiff - psys.settings.mol_relink_estiffrand = psys.settings.mol_relink_stiffrand - psys.settings.mol_relink_estiffexp = psys.settings.mol_relink_stiffexp - psys.settings.mol_relink_edamp = psys.settings.mol_relink_damp - psys.settings.mol_relink_edamprand = psys.settings.mol_relink_damprand - psys.settings.mol_relink_ebroken = psys.settings.mol_relink_broken - psys.settings.mol_relink_ebrokenrand = psys.settings.mol_relink_brokenrand - - params = [0] * 45 - params[0] = psys.settings.mol_selfcollision_active - params[1] = psys.settings.mol_othercollision_active - params[2] = psys.settings.mol_collision_group - params[3] = psys.settings.mol_friction - params[4] = psys.settings.mol_collision_damp - params[5] = psys.settings.mol_links_active - if psys.settings.mol_link_rellength == True: - params[6] = psys.settings.particle_size * psys.settings.mol_link_length - else: - params[6] = psys.settings.mol_link_length - params[7] = psys.settings.mol_link_max - params[8] = psys.settings.mol_link_tension - params[9] = psys.settings.mol_link_tensionrand - params[10] = psys.settings.mol_link_stiff - params[11] = psys.settings.mol_link_stiffrand - params[12] = psys.settings.mol_link_stiffexp - params[13] = psys.settings.mol_link_damp - params[14] = psys.settings.mol_link_damprand - params[15] = psys.settings.mol_link_broken - params[16] = psys.settings.mol_link_brokenrand - params[17] = psys.settings.mol_link_estiff - params[18] = psys.settings.mol_link_estiffrand - params[19] = psys.settings.mol_link_estiffexp - params[20] = psys.settings.mol_link_edamp - params[21] = psys.settings.mol_link_edamprand - params[22] = psys.settings.mol_link_ebroken - params[23] = psys.settings.mol_link_ebrokenrand - params[24] = psys.settings.mol_relink_group - params[25] = psys.settings.mol_relink_chance - params[26] = psys.settings.mol_relink_chancerand - params[27] = psys.settings.mol_relink_max - params[28] = psys.settings.mol_relink_tension - params[29] = psys.settings.mol_relink_tensionrand - params[30] = psys.settings.mol_relink_stiff - params[31] = psys.settings.mol_relink_stiffexp - params[32] = psys.settings.mol_relink_stiffrand - params[33] = psys.settings.mol_relink_damp - params[34] = psys.settings.mol_relink_damprand - params[35] = psys.settings.mol_relink_broken - params[36] = psys.settings.mol_relink_brokenrand - params[37] = psys.settings.mol_relink_estiff - params[38] = psys.settings.mol_relink_estiffexp - params[39] = psys.settings.mol_relink_estiffrand - params[40] = psys.settings.mol_relink_edamp - params[41] = psys.settings.mol_relink_edamprand - params[42] = psys.settings.mol_relink_ebroken - params[43] = psys.settings.mol_relink_ebrokenrand - params[44] = psys.settings.mol_link_friction - - mol_exportdata = bpy.context.scene.mol_exportdata - if initiate: - mol_exportdata[0][2] = psyslen - mol_exportdata[0][3] = parnum - #print(par_loc) - mol_exportdata.append((parlen,par_loc,par_vel,par_size,par_mass,par_alive,params)) - pass - else: - #print(par_loc) - mol_exportdata.append((par_loc,par_vel,par_alive)) - pass - - - -class MolecularPanel(bpy.types.Panel): - """Creates a Panel in the Object properties window""" - bl_label = "Molecular script" - bl_idname = "OBJECT_PT_molecular" - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "particle" - - @classmethod - def poll(cls, context): - return context.object.particle_systems.active - - def draw_header(self, context): - layout = self.layout - obj = context.object - psys = obj.particle_systems.active - row = layout.row() - if psys != None: - row.prop(psys.settings,"mol_active", text = "") - - def draw(self, context): - - layout = self.layout - scn = bpy.context.scene - obj = context.object - psys = obj.particle_systems.active - if psys != None: - layout.enabled = psys.settings.mol_active - row = layout.row() - row.label(text = "Density:") - box = layout.box() - box.prop(psys.settings,"mol_density_active", text = "Calculate particles weight by density") - subbox = box.box() - subbox.enabled = psys.settings.mol_density_active - row = subbox.row() - row.prop(psys.settings,"mol_matter",text = "Preset:") - row = subbox.row() - if int(psys.settings.mol_matter) == 0: - row.enabled = True - elif int(psys.settings.mol_matter) >= 1: - row.enabled = False - row.prop(psys.settings, "mol_density", text = "Kg per CubeMeter:") - #subsubbox = subbox.box() - #row = subsubbox.row() - #row.label(text = "Particle info:") - #row = subsubbox.row() - #row.label(icon = "INFO",text = "size: " + str(round(psys.settings.particle_size,5)) + " m") - #row.label(icon = "INFO",text = "volume: " + str(round(psys.settings.particle_size**3,5)) + " m3") - #row = subsubbox.row() - pmass = (psys.settings.particle_size**3) * psys.settings.mol_density - #row.label(icon = "INFO",text = "mass: " + str(round(pmass,5)) + " kg") - row = subbox.row() - row.label(icon = "INFO",text = "Total system approx weight: " + str(round(len(psys.particles) * pmass,4)) + " kg") - row = layout.row() - row.label(text = "Collision:") - box = layout.box() - box.prop(psys.settings,"mol_selfcollision_active", text = "Activate Self Collision") - box.prop(psys.settings,"mol_othercollision_active", text = "Activate Collision with others") - box.prop(psys.settings,"mol_collision_group",text = " Collide only with:") - box.prop(psys.settings,"mol_friction",text = " Friction:") - box.prop(psys.settings,"mol_collision_damp",text = " Damping:") - - row = layout.row() - row.label(text = "Links:") - box = layout.box() - box.prop(psys.settings,"mol_links_active", text = "Activate Particles linking") - - subbox = box.box() - subbox.enabled = psys.settings.mol_links_active - subbox.label(text = "Initial Linking (at birth):") - row = subbox.row() - row.prop(psys.settings,"mol_link_length",text = "search length") - row.prop(psys.settings,"mol_link_rellength",text = "Relative") - row = subbox.row() - row.prop(psys.settings,"mol_link_max",text = "Max links") - row = subbox.row() - row.prop(psys.settings,"mol_link_friction",text = "Link friction") - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_link_tension",text = "Tension") - row.prop(psys.settings,"mol_link_tensionrand",text = "Rand Tension") - row = subbox.row() - row.prop(psys.settings,"mol_link_stiff",text = "Stiff") - row.prop(psys.settings,"mol_link_stiffrand",text = "Rand Stiff") - #row = subbox.row() - #row.prop(psys.settings,"mol_link_stiffexp",text = "Exponent") - #row.label(text = "") - row = subbox.row() - row.prop(psys.settings,"mol_link_damp",text = "Damping") - row.prop(psys.settings,"mol_link_damprand",text = "Rand Damping") - row = subbox.row() - row.prop(psys.settings,"mol_link_broken",text = "broken") - row.prop(psys.settings,"mol_link_brokenrand",text = "Rand Broken") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_link_samevalue", text = "Same values for compression/expansion") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_estiff",text = "E Stiff") - row.prop(psys.settings,"mol_link_estiffrand",text = "Rand E Stiff") - #row = subbox.row() - #row.enabled = not psys.settings.mol_link_samevalue - #row.prop(psys.settings,"mol_link_estiffexp",text = "E Exponent") - #row.label(text = "") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_edamp",text = "E Damping") - row.prop(psys.settings,"mol_link_edamprand",text = "Rand E Damping") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_ebroken",text = "E broken") - row.prop(psys.settings,"mol_link_ebrokenrand",text = "Rand E Broken") - - - subbox = box.box() - subbox.active = psys.settings.mol_links_active - subbox.label(text = "New Linking (at collision):") - row = subbox.row() - row.prop(psys.settings,"mol_relink_group",text = "Only links with:") - row = subbox.row() - row.prop(psys.settings,"mol_relink_chance",text = "% linking") - row.prop(psys.settings,"mol_relink_chancerand",text = "Rand % linking") - row = subbox.row() - row.prop(psys.settings,"mol_relink_max",text = "Max links") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_relink_tension",text = "Tension") - row.prop(psys.settings,"mol_relink_tensionrand",text = "Rand Tension") - row = subbox.row() - row.prop(psys.settings,"mol_relink_stiff",text = "Stiff") - row.prop(psys.settings,"mol_relink_stiffrand",text = "Rand Stiff") - #row = subbox.row() - #row.prop(psys.settings,"mol_relink_stiffexp",text = "Exp") - #row.label(text = "") - row = subbox.row() - row.prop(psys.settings,"mol_relink_damp",text = "Damping") - row.prop(psys.settings,"mol_relink_damprand",text = "Rand Damping") - row = subbox.row() - row.prop(psys.settings,"mol_relink_broken",text = "broken") - row.prop(psys.settings,"mol_relink_brokenrand",text = "Rand broken") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_relink_samevalue", text = "Same values for compression/expansion") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_estiff",text = "E Stiff") - row.prop(psys.settings,"mol_relink_estiffrand",text = "Rand E Stiff") - #row = subbox.row() - #row.enabled = not psys.settings.mol_relink_samevalue - #row.prop(psys.settings,"mol_relink_estiffexp",text = "Exp") - #row.label(text = "") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_edamp",text = "E Damping") - row.prop(psys.settings,"mol_relink_edamprand",text = "Rand E Damping") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_ebroken",text = "E broken") - row.prop(psys.settings,"mol_relink_ebrokenrand",text = "Rand E broken") - - row = layout.row() - row.label(text = "UV's:") - box = layout.box() - row = box.row() - if obj.data.uv_layers.active != None: - row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: " + str(obj.data.uv_textures.active.name) + ")" ) - else: - row.active = False - row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: None)" ) - - row = layout.row() - row.label(text = "") - row = layout.row() - row.label(text = "Simulate") - row = layout.row() - row.prop(scn,"frame_start",text = "Start Frame") - row.prop(scn,"frame_end",text = "End Frame") - #row = layout.row() - #row.prop(scn,"mol_timescale_active",text = "Activate TimeScaling") - #row = layout.row() - #row.enabled = scn.mol_timescale_active - #row.prop(scn,"timescale",text = "TimeScale") - #row.label(text = "") - row = layout.row() - row.prop(scn,"mol_substep",text = "mol_substep") - row.label(text = "") - row = layout.row() - row.label(text = "CPU used:") - row.prop(scn,"mol_cpu",text = "CPU") - row = layout.row() - row.prop(scn,"mol_bake",text = "Bake all at ending") - row.prop(scn,"mol_render",text = "Render at ending") - row = layout.row() - if scn.mol_simrun == False and psys.point_cache.is_baked == False: - row.enabled = True - row.operator("object.mol_simulate",icon = 'RADIO',text = "Start Molecular Simulation") - row = layout.row() - row.enabled = False - row.operator("ptcache.free_bake_all", text="Free All Bakes") - if psys.point_cache.is_baked == True and scn.mol_simrun == False: - row.enabled = False - row.operator("object.mol_simulate",icon = 'RADIO',text = "Simulation baked") - row = layout.row() - row.enabled = True - row.operator("ptcache.free_bake_all", text="Free All Bakes") - if scn.mol_simrun == True: - row.enabled = False - row.operator("object.mol_simulate",icon = 'RADIO',text = "Process: " + scn.mol_timeremain + " left") - row = layout.row() - row.enabled = False - row.operator("ptcache.free_bake_all", text="Free All Bakes") - - box = layout.box() - row = box.row() - box.enabled = True - row.label(text = "Molecular Tools:",icon = 'MODIFIER') - subbox = box.box() - row = subbox.row() - row.label(text = "Particle UV:") - row = subbox.row() - row.alignment = 'CENTER' - row.label(icon = 'INFO',text = "Set current particles position ") - row = subbox.row() - row.alignment = 'CENTER' - row.label(text = "has global or current uv in angular velocity.") - row = subbox.row() - row.alignment = 'CENTER' - row.label(text = " Retrieve it with Cycles particle info node") - row = subbox.row() - row.operator("object.mol_set_global_uv",icon = 'GROUP_UVS',text = "Set Global UV") - row = subbox.row() - if obj.data.uv_layers.active != None: - row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV (current: " + str(obj.data.uv_textures.active.name) + ")" ) - else: - row.active = False - row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV ( no uvs found)") - subbox = box.box() - row = subbox.row() - row.label(text = "SUBSTEPS CALCULATOR:") - row = subbox.row() - row.label(icon = 'INFO',text = "Current systems have: " + str(len(psys.particles)) + " particles") - row = subbox.row() - row.prop(psys.settings,"mol_var1",text = "Current numbers of particles") - row = subbox.row() - row.prop(psys.settings,"mol_var2",text = "Current substep") - row = subbox.row() - row.prop(psys.settings,"mol_var3",text = "Targeted numbers of particles") - diff = (psys.settings.mol_var3 / psys.settings.mol_var1) - factor = (psys.settings.mol_var3**(1/3) / psys.settings.mol_var1**(1/3)) - newsubstep = int(round(factor * psys.settings.mol_var2)) - row = subbox.row() - row.label(icon = 'FORWARD',text = "You must set new substep to: " + str(newsubstep)) - row = subbox.row() - row.label(icon = 'ERROR',text = "Multiply particles size by: " + str(round(1/factor,5))) - row = subbox.row() - row.label(icon = 'ERROR',text = "Multiply others sys particle number by: " + str(round(diff,5))) - - - box = layout.box() - row = box.row() - box.active = False - box.alert = False - row.alignment = 'CENTER' - row.label(text = "THANKS TO ALL DONATORS !") - row = box.row() - row.alignment = 'CENTER' - row.label(text = "If you want donate to support my work") - row = box.row() - row.alignment = 'CENTER' - row.operator("wm.url_open", text=" click here to Donate ", icon='URL').url = "www.pyroevil.com/donate/" - row = box.row() - row.alignment = 'CENTER' - row.label(text = "or visit: ") - row = box.row() - row.alignment = 'CENTER' - row.label(text = "www.pyroevil.com/donate/") - -class MolSimulate(bpy.types.Operator): - """Tooltip""" - bl_idname = "object.mol_simulate" - bl_label = "Mol Simulate" - - - def execute(self, context): - print("Molecular Sim start--------------------------------------------------") - mol_stime = clock() - scene = bpy.context.scene - scene.mol_simrun = True - scene.mol_minsize = 1000000000.0 - scene.mol_newlink = 0 - scene.mol_deadlink = 0 - scene.mol_totallink = 0 - scene.mol_totaldeadlink = 0 - scene.mol_timeremain = "...Simulating..." - object = bpy.context.object - scene.frame_set(frame = scene.frame_start) - scene.mol_old_endframe = scene.frame_end - mol_substep = scene.mol_substep - scene.render.frame_map_old = 1 - scene.render.frame_map_new = mol_substep + 1 - scene.frame_end *= mol_substep + 1 - - if scene.mol_timescale_active == True: - fps = scene.render.fps / scene.timescale - else: - fps = scene.render.fps - cpu = scene.mol_cpu - mol_exportdata = bpy.context.scene.mol_exportdata - mol_exportdata.clear() - mol_exportdata.append([fps,mol_substep,0,0,cpu]) - mol_stime = clock() - pack_data(True) - #print("sys number",mol_exportdata[0][2]) - etime = clock() - print(" " + "PackData take " + str(round(etime - mol_stime,3)) + "sec") - mol_stime = clock() - mol_report = cmolcore.init(mol_exportdata) - etime = clock() - print(" " + "Export time take " + str(round(etime - mol_stime,3)) + "sec") - print(" total numbers of particles: " + str(mol_report)) - print(" start processing:") - bpy.ops.wm.mol_simulate_modal() - return {'FINISHED'} - -class MolSetGlobalUV(bpy.types.Operator): - """Tooltip""" - bl_idname = "object.mol_set_global_uv" - bl_label = "Mol Set UV" - - - def execute(self, context): - scene = bpy.context.scene - object = bpy.context.object - psys = object.particle_systems.active - coord = [0,0,0] * len(psys.particles) - psys.particles.foreach_get("location",coord) - psys.particles.foreach_set("angular_velocity",coord) - - return {'FINISHED'} - - -class MolSetActiveUV(bpy.types.Operator): - """Tooltip""" - bl_idname = "object.mol_set_active_uv" - bl_label = "Mol Set Active UV" - - - def execute(self, context): - scene = context.scene - scene.mol_objuvbake = context.object.name - scene.mol_psysuvbake = context.object.particle_systems.active.name - object = bpy.data.objects[scene.mol_objuvbake] - - if not object.data.uv_layers.active: - return {'FINISHED'} - - print(' start bake uv from:',object.name) - #object2 = object.copy() - - obdata = object.data.copy() - object2 = bpy.data.objects.new(name="mol_uv_temp",object_data = obdata) - object2.matrix_world = object.matrix_world - - context.scene.objects.link(object2) - mod = object2.modifiers.new("tri_for_uv","TRIANGULATE") - mod.ngon_method = 'BEAUTY' - mod.quad_method = 'BEAUTY' - newmesh = object2.to_mesh(bpy.context.scene,True,"RENDER",True,False) - object2.data = newmesh - context.scene.update() - """ - oldmesh = object.data - newmesh = object.data.copy() - object.data = newmesh - mod = object.modifiers.new("tri_for_uv","TRIANGULATE") - mod.use_beauty = False - bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name) - """ - psys = context.object.particle_systems[scene.mol_psysuvbake] - #print('-------------start------------') - for par in psys.particles: - parloc = (par.location * object2.matrix_world) - object2.location - point = object2.closest_point_on_mesh(parloc) - #print('closest:',par.location,point[0],point[2]) - vindex1 = object2.data.polygons[point[3]].vertices[0] - vindex2 = object2.data.polygons[point[3]].vertices[1] - vindex3 = object2.data.polygons[point[3]].vertices[2] - v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() - v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() - v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() - uvindex1 = object2.data.polygons[point[3]].loop_start + 0 - uvindex2 = object2.data.polygons[point[3]].loop_start + 1 - uvindex3 = object2.data.polygons[point[3]].loop_start + 2 - uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() - uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() - uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() - #print(vertices1.co,vertices2.co,vertices3.co) - #print(uv1,uv2,uv3) - p = object2.matrix_world * point[1] - v1 = Vector(v1) - v2 = Vector(v2) - v3 = Vector(v3) - uv1 = Vector(uv1) - uv2 = Vector(uv2) - uv3 = Vector(uv3) - #print(a,b,c,uv1,uv2,uv3,p) - newuv = barycentric(p,v1,v2,v3,uv1,uv2,uv3) - #print('New UVs:',newuv) - parloc = par.location * object2.matrix_world - dist = (Vector((parloc[0] - p[0],parloc[1] - p[1],parloc[2] - p[2]))).length - newuv[2] = dist - newuv = newuv.to_tuple() - par.angular_velocity = newuv - scene.objects.unlink(object2) - bpy.data.objects.remove(object2) - bpy.data.meshes.remove(newmesh) - print(' uv baked on:',psys.settings.name) - - return {'FINISHED'} - -class MolSimulateModal(bpy.types.Operator): - """Operator which runs its self from a timer""" - bl_idname = "wm.mol_simulate_modal" - bl_label = "Simulate Molecular" - _timer = None - - def modal(self, context, event): - #mol_stime = clock() - scene = bpy.context.scene - frame_end = scene.frame_end - frame_current = scene.frame_current - if event.type == 'ESC' or frame_current == frame_end: - if frame_current == frame_end and scene.mol_bake == True: - fake_context = bpy.context.copy() - for obj in bpy.data.objects: - for psys in obj.particle_systems: - if psys.settings.mol_active == True and len(psys.particles) > 0: - fake_context["point_cache"] = psys.point_cache - bpy.ops.ptcache.bake_from_cache(fake_context) - scene.render.frame_map_new = 1 - scene.frame_end = scene.mol_old_endframe - - for obj in bpy.data.objects: - for psys in obj.particle_systems: - for psys in obj.particle_systems: - if psys.settings.mol_bakeuv == True: - scene.mol_objuvbake = obj.name - mol_psysuvbake = psys.name - bpy.context.scene.update() - scene.frame_set(frame = psys.settings.frame_start) - bpy.context.scene.update() - bpy.ops.object.mol_set_active_uv() - - if frame_current == frame_end and scene.mol_render == True: - bpy.ops.render.render(animation=True) - - scene.frame_set(frame = scene.frame_start) - - cmolcore.memfree() - scene.mol_simrun = False - print("--------------------------------------------------Molecular Sim end") - return self.cancel(context) - - if event.type == 'TIMER': - if frame_current == scene.frame_start: - scene.mol_stime = clock() - mol_exportdata = bpy.context.scene.mol_exportdata - mol_exportdata.clear() - #stimex = clock() - pack_data(False) - #print("packdata time",clock() - stimex,"sec") - mol_importdata = cmolcore.simulate(mol_exportdata) - i = 0 - #stimex = clock() - for obj in bpy.data.objects: - for psys in obj.particle_systems: - if psys.settings.mol_active == True and len(psys.particles) > 0: - #print(len(mol_importdata[i][1])) - #print(len(psys.particles)) - psys.particles.foreach_set('velocity',mol_importdata[1][i]) - i += 1 - #print("inject new velocity time",clock() - stimex,"sec") - mol_substep = scene.mol_substep - framesubstep = frame_current/(mol_substep+1) - if framesubstep == int(framesubstep): - etime = clock() - print(" frame " + str(framesubstep + 1) + ":") - print(" links created:", scene.mol_newlink) - if scene.mol_totallink != 0: - print(" links broked :", scene.mol_deadlink) - print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100),2),"%)") - print(" Molecular Script: " + str(round(etime - scene.mol_stime,3)) + " sec") - remain = (((etime - scene.mol_stime) * (scene.mol_old_endframe - framesubstep - 1))) - days = int(strftime('%d',gmtime(remain))) - 1 - scene.mol_timeremain = strftime(str(days) + ' days %H hours %M mins %S secs', gmtime(remain)) - print(" Remaining estimated:", scene.mol_timeremain) - scene.mol_newlink = 0 - scene.mol_deadlink = 0 - scene.mol_stime = clock() - stime2 = clock() - scene.mol_newlink += mol_importdata[2] - scene.mol_deadlink += mol_importdata[3] - scene.mol_totallink = mol_importdata[4] - scene.mol_totaldeadlink = mol_importdata[5] - scene.frame_set(frame = frame_current + 1) - if framesubstep == int(framesubstep): - etime2 = clock() - print(" Blender: " + str(round(etime2 - stime2,3)) + " sec") - stime2 = clock() - return {'PASS_THROUGH'} - - def execute(self, context): - self._timer = context.window_manager.event_timer_add(0.000000001, context.window) - context.window_manager.modal_handler_add(self) - return {'RUNNING_MODAL'} +import bpy - def cancel(self, context): - context.window_manager.event_timer_remove(self._timer) - return {'CANCELLED'} +from . import properties +from . import ui +from . import operators def register(): - define_props() - bpy.utils.register_class(MolSimulateModal) - bpy.utils.register_class(MolSimulate) - bpy.utils.register_class(MolSetGlobalUV) - bpy.utils.register_class(MolSetActiveUV) - bpy.utils.register_class(MolecularPanel) - pass + properties.define_props() + bpy.utils.register_class(operators.MolSimulateModal) + bpy.utils.register_class(operators.MolSimulate) + bpy.utils.register_class(operators.MolSetGlobalUV) + bpy.utils.register_class(operators.MolSetActiveUV) + bpy.utils.register_class(ui.MolecularPanel) def unregister(): - bpy.utils.unregister_class(MolSimulateModal) - bpy.utils.unregister_class(MolSimulate) - bpy.utils.unregister_class(MolSetGlobalUV) - bpy.utils.unregister_class(MolSetActiveUV) - bpy.utils.unregister_class(MolecularPanel) - pass + bpy.utils.unregister_class(operators.MolSimulateModal) + bpy.utils.unregister_class(operators.MolSimulate) + bpy.utils.unregister_class(operators.MolSetGlobalUV) + bpy.utils.unregister_class(operators.MolSetActiveUV) + bpy.utils.unregister_class(ui.MolecularPanel) + - if __name__ == "__main__": register() diff --git a/molecular/operators.py b/molecular/operators.py new file mode 100644 index 0000000..1ed63c8 --- /dev/null +++ b/molecular/operators.py @@ -0,0 +1,257 @@ + +from time import clock, sleep, strftime, gmtime + +import bpy +from mathutils import Vector +from mathutils.geometry import barycentric_transform as barycentric + +from . import simulate + +try: + from . import cmolcore +except: + print("cmolcore not working") + + +class MolSimulate(bpy.types.Operator): + """Tooltip""" + bl_idname = "object.mol_simulate" + bl_label = "Mol Simulate" + + + def execute(self, context): + print("Molecular Sim start--------------------------------------------------") + mol_stime = clock() + scene = bpy.context.scene + scene.mol_simrun = True + scene.mol_minsize = 1000000000.0 + scene.mol_newlink = 0 + scene.mol_deadlink = 0 + scene.mol_totallink = 0 + scene.mol_totaldeadlink = 0 + scene.mol_timeremain = "...Simulating..." + object = bpy.context.object + scene.frame_set(frame = scene.frame_start) + scene.mol_old_endframe = scene.frame_end + mol_substep = scene.mol_substep + scene.render.frame_map_old = 1 + scene.render.frame_map_new = mol_substep + 1 + scene.frame_end *= mol_substep + 1 + + if scene.mol_timescale_active == True: + fps = scene.render.fps / scene.timescale + else: + fps = scene.render.fps + cpu = scene.mol_cpu + mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata.clear() + mol_exportdata.append([fps,mol_substep,0,0,cpu]) + mol_stime = clock() + simulate.pack_data(True) + #print("sys number",mol_exportdata[0][2]) + etime = clock() + print(" " + "PackData take " + str(round(etime - mol_stime,3)) + "sec") + mol_stime = clock() + mol_report = cmolcore.init(mol_exportdata) + etime = clock() + print(" " + "Export time take " + str(round(etime - mol_stime,3)) + "sec") + print(" total numbers of particles: " + str(mol_report)) + print(" start processing:") + bpy.ops.wm.mol_simulate_modal() + return {'FINISHED'} + +class MolSetGlobalUV(bpy.types.Operator): + """Tooltip""" + bl_idname = "object.mol_set_global_uv" + bl_label = "Mol Set UV" + + + def execute(self, context): + scene = bpy.context.scene + object = bpy.context.object + psys = object.particle_systems.active + coord = [0,0,0] * len(psys.particles) + psys.particles.foreach_get("location",coord) + psys.particles.foreach_set("angular_velocity",coord) + + return {'FINISHED'} + + +class MolSetActiveUV(bpy.types.Operator): + """Tooltip""" + bl_idname = "object.mol_set_active_uv" + bl_label = "Mol Set Active UV" + + + def execute(self, context): + scene = context.scene + scene.mol_objuvbake = context.object.name + scene.mol_psysuvbake = context.object.particle_systems.active.name + object = bpy.data.objects[scene.mol_objuvbake] + + if not object.data.uv_layers.active: + return {'FINISHED'} + + print(' start bake uv from:',object.name) + #object2 = object.copy() + + obdata = object.data.copy() + object2 = bpy.data.objects.new(name="mol_uv_temp",object_data = obdata) + object2.matrix_world = object.matrix_world + + context.scene.objects.link(object2) + mod = object2.modifiers.new("tri_for_uv","TRIANGULATE") + mod.ngon_method = 'BEAUTY' + mod.quad_method = 'BEAUTY' + newmesh = object2.to_mesh(bpy.context.scene,True,"RENDER",True,False) + object2.data = newmesh + context.scene.update() + """ + oldmesh = object.data + newmesh = object.data.copy() + object.data = newmesh + mod = object.modifiers.new("tri_for_uv","TRIANGULATE") + mod.use_beauty = False + bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name) + """ + psys = context.object.particle_systems[scene.mol_psysuvbake] + #print('-------------start------------') + for par in psys.particles: + parloc = (par.location * object2.matrix_world) - object2.location + point = object2.closest_point_on_mesh(parloc) + #print('closest:',par.location,point[0],point[2]) + vindex1 = object2.data.polygons[point[3]].vertices[0] + vindex2 = object2.data.polygons[point[3]].vertices[1] + vindex3 = object2.data.polygons[point[3]].vertices[2] + v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() + v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() + v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() + uvindex1 = object2.data.polygons[point[3]].loop_start + 0 + uvindex2 = object2.data.polygons[point[3]].loop_start + 1 + uvindex3 = object2.data.polygons[point[3]].loop_start + 2 + uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() + uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() + uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() + #print(vertices1.co,vertices2.co,vertices3.co) + #print(uv1,uv2,uv3) + p = object2.matrix_world * point[1] + v1 = Vector(v1) + v2 = Vector(v2) + v3 = Vector(v3) + uv1 = Vector(uv1) + uv2 = Vector(uv2) + uv3 = Vector(uv3) + #print(a,b,c,uv1,uv2,uv3,p) + newuv = barycentric(p,v1,v2,v3,uv1,uv2,uv3) + #print('New UVs:',newuv) + parloc = par.location * object2.matrix_world + dist = (Vector((parloc[0] - p[0],parloc[1] - p[1],parloc[2] - p[2]))).length + newuv[2] = dist + newuv = newuv.to_tuple() + par.angular_velocity = newuv + scene.objects.unlink(object2) + bpy.data.objects.remove(object2) + bpy.data.meshes.remove(newmesh) + print(' uv baked on:',psys.settings.name) + + return {'FINISHED'} + +class MolSimulateModal(bpy.types.Operator): + """Operator which runs its self from a timer""" + bl_idname = "wm.mol_simulate_modal" + bl_label = "Simulate Molecular" + _timer = None + + def modal(self, context, event): + #mol_stime = clock() + scene = bpy.context.scene + frame_end = scene.frame_end + frame_current = scene.frame_current + if event.type == 'ESC' or frame_current == frame_end: + if frame_current == frame_end and scene.mol_bake == True: + fake_context = bpy.context.copy() + for obj in bpy.data.objects: + for psys in obj.particle_systems: + if psys.settings.mol_active == True and len(psys.particles) > 0: + fake_context["point_cache"] = psys.point_cache + bpy.ops.ptcache.bake_from_cache(fake_context) + scene.render.frame_map_new = 1 + scene.frame_end = scene.mol_old_endframe + + for obj in bpy.data.objects: + for psys in obj.particle_systems: + for psys in obj.particle_systems: + if psys.settings.mol_bakeuv == True: + scene.mol_objuvbake = obj.name + mol_psysuvbake = psys.name + bpy.context.scene.update() + scene.frame_set(frame = psys.settings.frame_start) + bpy.context.scene.update() + bpy.ops.object.mol_set_active_uv() + + if frame_current == frame_end and scene.mol_render == True: + bpy.ops.render.render(animation=True) + + scene.frame_set(frame = scene.frame_start) + + cmolcore.memfree() + scene.mol_simrun = False + print("--------------------------------------------------Molecular Sim end") + return self.cancel(context) + + if event.type == 'TIMER': + if frame_current == scene.frame_start: + scene.mol_stime = clock() + mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata.clear() + #stimex = clock() + simulate.pack_data(False) + #print("packdata time",clock() - stimex,"sec") + mol_importdata = cmolcore.simulate(mol_exportdata) + i = 0 + #stimex = clock() + for obj in bpy.data.objects: + for psys in obj.particle_systems: + if psys.settings.mol_active == True and len(psys.particles) > 0: + #print(len(mol_importdata[i][1])) + #print(len(psys.particles)) + psys.particles.foreach_set('velocity',mol_importdata[1][i]) + i += 1 + #print("inject new velocity time",clock() - stimex,"sec") + mol_substep = scene.mol_substep + framesubstep = frame_current/(mol_substep+1) + if framesubstep == int(framesubstep): + etime = clock() + print(" frame " + str(framesubstep + 1) + ":") + print(" links created:", scene.mol_newlink) + if scene.mol_totallink != 0: + print(" links broked :", scene.mol_deadlink) + print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100),2),"%)") + print(" Molecular Script: " + str(round(etime - scene.mol_stime,3)) + " sec") + remain = (((etime - scene.mol_stime) * (scene.mol_old_endframe - framesubstep - 1))) + days = int(strftime('%d',gmtime(remain))) - 1 + scene.mol_timeremain = strftime(str(days) + ' days %H hours %M mins %S secs', gmtime(remain)) + print(" Remaining estimated:", scene.mol_timeremain) + scene.mol_newlink = 0 + scene.mol_deadlink = 0 + scene.mol_stime = clock() + stime2 = clock() + scene.mol_newlink += mol_importdata[2] + scene.mol_deadlink += mol_importdata[3] + scene.mol_totallink = mol_importdata[4] + scene.mol_totaldeadlink = mol_importdata[5] + scene.frame_set(frame = frame_current + 1) + if framesubstep == int(framesubstep): + etime2 = clock() + print(" Blender: " + str(round(etime2 - stime2,3)) + " sec") + stime2 = clock() + return {'PASS_THROUGH'} + + def execute(self, context): + self._timer = context.window_manager.event_timer_add(0.000000001, context.window) + context.window_manager.modal_handler_add(self) + return {'RUNNING_MODAL'} + + def cancel(self, context): + context.window_manager.event_timer_remove(self._timer) + return {'CANCELLED'} diff --git a/molecular/properties.py b/molecular/properties.py new file mode 100644 index 0000000..839295d --- /dev/null +++ b/molecular/properties.py @@ -0,0 +1,100 @@ + +import multiprocessing + +import bpy + + +def define_props(): + parset = bpy.types.ParticleSettings + parset.mol_active = bpy.props.BoolProperty(name = "mol_active", description = "Activate molecular script for this particles system",default = False) + parset.mol_refresh = bpy.props.BoolProperty(name = "mol_refresh", description = "Simple property used to refresh data in the process",default = True) + parset.mol_density_active = bpy.props.BoolProperty(name="mol_density_active", description="Control particle weight by density",default = False) + item = [("-1","custom","put your parameter below"),("1555","sand","1555kg per meter cu"),("1000","water","1000kg per meter cu"),("7800","iron","7800kg per meter cu")] + parset.mol_matter = bpy.props.EnumProperty(items = item, description = "Choose a matter preset for density") + parset.mol_density = bpy.props.FloatProperty(name = "mol_density", description = "Density of the matter kg/cube meter", default = 1000, min = 0.001) + + parset.mol_selfcollision_active = bpy.props.BoolProperty(name = "mol_selfcollision_active", description = "Activate self collsion between particles in the system",default = False) + parset.mol_othercollision_active = bpy.props.BoolProperty(name = "mol_othercollision_active", description = "Activate collision with particles from others systems",default = False) + parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') + parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') + item = [] + for i in range(1,12): + item.append((str(i),"Collision Group " + str(i),"collide only with group " + str(i) )) + parset.mol_collision_group = bpy.props.EnumProperty(items = item, description = "Choose a collision group you want to collide with") + + parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) + parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) + parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') + parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) + parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) + parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 6, default = 0, subtype='FACTOR') + parset.mol_link_max = bpy.props.IntProperty(name = "mol_link_max", description = "Maximum of links per particles",min = 0,default = 16) + parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_stiffrand = bpy.props.FloatProperty(name = "mol_link_stiffrand", description = "Random variation for stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') + parset.mol_link_stiffexp = bpy.props.IntProperty(name = "mol_link_stiffexp", description = "Give a exponent force to the spring links", default = 1, min = 1 , max = 10) + parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') + + parset.mol_link_samevalue = bpy.props.BoolProperty(name = "mol_link_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) + + parset.mol_link_estiff = bpy.props.FloatProperty(name = "mol_link_estiff", description = "Expension stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_estiffrand = bpy.props.FloatProperty(name = "mol_link_estiffrand", description = "Random variation for expansion stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') + parset.mol_link_estiffexp = bpy.props.IntProperty(name = "mol_link_estiffexp", description = "Give a exponent force to the expension spring links", default = 1, min = 1 , max = 10) + parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') + + item = [] + for i in range(1,12): + item.append((str(i),"Relink Group " + str(i),"Relink only with group " + str(i) )) + parset.mol_relink_group = bpy.props.EnumProperty(items = item, description = "Choose a group that new link are possible") + parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0, precision=6) + parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') + parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) + parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_max = bpy.props.IntProperty(name = "mol_relink_max", description = "Maximum of links per particles",min = 0,default = 16) + parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_stiffrand = bpy.props.FloatProperty(name = "mol_relink_stiffrand", description = "Random variation for stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_stiffexp = bpy.props.IntProperty(name = "mol_relink_stiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) + parset.mol_relink_damp = bpy.props.FloatProperty(name = "mol_relink_damp", description = "Damping effect on spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_damprand = bpy.props.FloatProperty(name = "mol_relink_damprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_broken = bpy.props.FloatProperty(name = "mol_relink_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_relink_brokenrand = bpy.props.FloatProperty(name = "mol_relink_brokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') + + parset.mol_relink_samevalue = bpy.props.BoolProperty(name = "mol_relink_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) + + parset.mol_relink_estiff = bpy.props.FloatProperty(name = "mol_relink_estiff", description = "Stiffness of links expension between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_estiffrand = bpy.props.FloatProperty(name = "mol_relink_estiffrand", description = "Random variation for expension stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_estiffexp = bpy.props.IntProperty(name = "mol_relink_estiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) + parset.mol_relink_edamp = bpy.props.FloatProperty(name = "mol_relink_edamp", description = "Damping effect on expension spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') + parset.mol_relink_edamprand = bpy.props.FloatProperty(name = "mol_relink_deamprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') + parset.mol_relink_ebroken = bpy.props.FloatProperty(name = "mol_relink_ebroken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) + parset.mol_relink_ebrokenrand = bpy.props.FloatProperty(name = "mol_relink_ebrokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') + + parset.mol_var1 = bpy.props.IntProperty(name = "mol_var1", description = "Current number of particles to calculate substep",min = 1, default = 1000) + parset.mol_var2 = bpy.props.IntProperty(name = "mol_var2", description = "Current substep",min = 1, default = 4) + parset.mol_var3 = bpy.props.IntProperty(name = "mol_var3", description = "Targeted number of particles you want to increase or decrease from current system to calculate substep you need to achieve similar effect",min = 1, default = 1000) + parset.mol_bakeuv = bpy.props.BoolProperty(name = "mol_bakeuv", description = "Bake uv when finish",default = False) + + bpy.types.Scene.mol_timescale_active = bpy.props.BoolProperty(name = "mol_timescale_active", description = "Activate TimeScaling",default = False) + bpy.types.Scene.timescale = bpy.props.FloatProperty(name = "timescale", description = "SpeedUp or Slow down the simulation with this multiplier", default = 1) + bpy.types.Scene.mol_substep = bpy.props.IntProperty(name = "mol_substep", description = "mol_substep. Higher equal more stable and accurate but more slower",min = 0, max = 900, default = 4) + bpy.types.Scene.mol_bake = bpy.props.BoolProperty(name = "mol_bake", description = "Bake simulation when finish",default = True) + bpy.types.Scene.mol_render = bpy.props.BoolProperty(name = "mol_render", description = "Start rendering animation when simulation is finish. WARNING: It's freeze blender until render is finish.",default = False) + bpy.types.Scene.mol_cpu = bpy.props.IntProperty(name = "mol_cpu", description = "Numbers of cpu's included for process the simulation", default = multiprocessing.cpu_count(),min = 1,max =multiprocessing.cpu_count()) + + bpy.types.Scene.mol_exportdata = [] + bpy.types.Scene.mol_minsize = bpy.props.FloatProperty() + bpy.types.Scene.mol_simrun = bpy.props.BoolProperty(default=False) + bpy.types.Scene.mol_timeremain = bpy.props.StringProperty() + bpy.types.Scene.mol_old_endframe = bpy.props.IntProperty() + bpy.types.Scene.mol_newlink = bpy.props.IntProperty() + bpy.types.Scene.mol_deadlink = bpy.props.IntProperty() + bpy.types.Scene.mol_totallink = bpy.props.IntProperty() + bpy.types.Scene.mol_totaldeadlink = bpy.props.IntProperty() + bpy.types.Scene.mol_objuvbake = bpy.props.StringProperty() + bpy.types.Scene.mol_psysuvbake = bpy.props.StringProperty() + bpy.types.Scene.mol_stime = bpy.props.FloatProperty() diff --git a/molecular/simulate.py b/molecular/simulate.py new file mode 100644 index 0000000..180686c --- /dev/null +++ b/molecular/simulate.py @@ -0,0 +1,133 @@ + +from math import pi + +import bpy + + +def pack_data(initiate): + psyslen = 0 + parnum = 0 + scene = bpy.context.scene + for obj in bpy.data.objects: + for psys in obj.particle_systems: + if psys.settings.mol_matter != "-1": + psys.settings.mol_density = float(psys.settings.mol_matter) + if psys.settings.mol_active == True and len(psys.particles) > 0: + parlen = len(psys.particles) + par_loc = [0,0,0] * parlen + par_vel = [0,0,0] * parlen + par_size = [0] * parlen + par_alive = [] + for par in psys.particles: + parnum += 1 + if par.alive_state == "UNBORN": + par_alive.append(2) + if par.alive_state == "ALIVE": + par_alive.append(0) + if par.alive_state == "DEAD": + par_alive.append(3) + + psys.particles.foreach_get('location',par_loc) + psys.particles.foreach_get('velocity',par_vel) + + if initiate: + par_mass = [] + + if psys.settings.mol_density_active: + for par in psys.particles: + par_mass.append(psys.settings.mol_density * (4/3*pi*((par.size/2)**3))) + else: + for par in psys.particles: + par_mass.append(psys.settings.mass) + """ + if scene.mol_timescale_active == True: + psys.settings.timestep = 1 / (scene.render.fps / scene.timescale) + else: + psys.settings.timestep = 1 / scene.render.fps + """ + #psys.settings.count = psys.settings.count + psys.point_cache.frame_step = psys.point_cache.frame_step + psyslen += 1 + psys.particles.foreach_get('size',par_size) + if bpy.context.scene.mol_minsize > min(par_size): + bpy.context.scene.mol_minsize = min(par_size) + + if psys.settings.mol_link_samevalue: + psys.settings.mol_link_estiff = psys.settings.mol_link_stiff + psys.settings.mol_link_estiffrand = psys.settings.mol_link_stiffrand + psys.settings.mol_link_estiffexp = psys.settings.mol_link_stiffexp + psys.settings.mol_link_edamp = psys.settings.mol_link_damp + psys.settings.mol_link_edamprand = psys.settings.mol_link_damprand + psys.settings.mol_link_ebroken = psys.settings.mol_link_broken + psys.settings.mol_link_ebrokenrand = psys.settings.mol_link_brokenrand + + if psys.settings.mol_relink_samevalue: + psys.settings.mol_relink_estiff = psys.settings.mol_relink_stiff + psys.settings.mol_relink_estiffrand = psys.settings.mol_relink_stiffrand + psys.settings.mol_relink_estiffexp = psys.settings.mol_relink_stiffexp + psys.settings.mol_relink_edamp = psys.settings.mol_relink_damp + psys.settings.mol_relink_edamprand = psys.settings.mol_relink_damprand + psys.settings.mol_relink_ebroken = psys.settings.mol_relink_broken + psys.settings.mol_relink_ebrokenrand = psys.settings.mol_relink_brokenrand + + params = [0] * 45 + params[0] = psys.settings.mol_selfcollision_active + params[1] = psys.settings.mol_othercollision_active + params[2] = psys.settings.mol_collision_group + params[3] = psys.settings.mol_friction + params[4] = psys.settings.mol_collision_damp + params[5] = psys.settings.mol_links_active + if psys.settings.mol_link_rellength == True: + params[6] = psys.settings.particle_size * psys.settings.mol_link_length + else: + params[6] = psys.settings.mol_link_length + params[7] = psys.settings.mol_link_max + params[8] = psys.settings.mol_link_tension + params[9] = psys.settings.mol_link_tensionrand + params[10] = psys.settings.mol_link_stiff + params[11] = psys.settings.mol_link_stiffrand + params[12] = psys.settings.mol_link_stiffexp + params[13] = psys.settings.mol_link_damp + params[14] = psys.settings.mol_link_damprand + params[15] = psys.settings.mol_link_broken + params[16] = psys.settings.mol_link_brokenrand + params[17] = psys.settings.mol_link_estiff + params[18] = psys.settings.mol_link_estiffrand + params[19] = psys.settings.mol_link_estiffexp + params[20] = psys.settings.mol_link_edamp + params[21] = psys.settings.mol_link_edamprand + params[22] = psys.settings.mol_link_ebroken + params[23] = psys.settings.mol_link_ebrokenrand + params[24] = psys.settings.mol_relink_group + params[25] = psys.settings.mol_relink_chance + params[26] = psys.settings.mol_relink_chancerand + params[27] = psys.settings.mol_relink_max + params[28] = psys.settings.mol_relink_tension + params[29] = psys.settings.mol_relink_tensionrand + params[30] = psys.settings.mol_relink_stiff + params[31] = psys.settings.mol_relink_stiffexp + params[32] = psys.settings.mol_relink_stiffrand + params[33] = psys.settings.mol_relink_damp + params[34] = psys.settings.mol_relink_damprand + params[35] = psys.settings.mol_relink_broken + params[36] = psys.settings.mol_relink_brokenrand + params[37] = psys.settings.mol_relink_estiff + params[38] = psys.settings.mol_relink_estiffexp + params[39] = psys.settings.mol_relink_estiffrand + params[40] = psys.settings.mol_relink_edamp + params[41] = psys.settings.mol_relink_edamprand + params[42] = psys.settings.mol_relink_ebroken + params[43] = psys.settings.mol_relink_ebrokenrand + params[44] = psys.settings.mol_link_friction + + mol_exportdata = bpy.context.scene.mol_exportdata + if initiate: + mol_exportdata[0][2] = psyslen + mol_exportdata[0][3] = parnum + #print(par_loc) + mol_exportdata.append((parlen,par_loc,par_vel,par_size,par_mass,par_alive,params)) + pass + else: + #print(par_loc) + mol_exportdata.append((par_loc,par_vel,par_alive)) + pass diff --git a/molecular/ui.py b/molecular/ui.py new file mode 100644 index 0000000..062511c --- /dev/null +++ b/molecular/ui.py @@ -0,0 +1,280 @@ + +import bpy + + +class MolecularPanel(bpy.types.Panel): + """Creates a Panel in the Object properties window""" + bl_label = "Molecular script" + bl_idname = "OBJECT_PT_molecular" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "particle" + + @classmethod + def poll(cls, context): + return context.object.particle_systems.active + + def draw_header(self, context): + layout = self.layout + obj = context.object + psys = obj.particle_systems.active + row = layout.row() + if psys != None: + row.prop(psys.settings,"mol_active", text = "") + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys != None: + layout.enabled = psys.settings.mol_active + row = layout.row() + row.label(text = "Density:") + box = layout.box() + box.prop(psys.settings,"mol_density_active", text = "Calculate particles weight by density") + subbox = box.box() + subbox.enabled = psys.settings.mol_density_active + row = subbox.row() + row.prop(psys.settings,"mol_matter",text = "Preset:") + row = subbox.row() + if int(psys.settings.mol_matter) == 0: + row.enabled = True + elif int(psys.settings.mol_matter) >= 1: + row.enabled = False + row.prop(psys.settings, "mol_density", text = "Kg per CubeMeter:") + #subsubbox = subbox.box() + #row = subsubbox.row() + #row.label(text = "Particle info:") + #row = subsubbox.row() + #row.label(icon = "INFO",text = "size: " + str(round(psys.settings.particle_size,5)) + " m") + #row.label(icon = "INFO",text = "volume: " + str(round(psys.settings.particle_size**3,5)) + " m3") + #row = subsubbox.row() + pmass = (psys.settings.particle_size**3) * psys.settings.mol_density + #row.label(icon = "INFO",text = "mass: " + str(round(pmass,5)) + " kg") + row = subbox.row() + row.label(icon = "INFO",text = "Total system approx weight: " + str(round(len(psys.particles) * pmass,4)) + " kg") + row = layout.row() + row.label(text = "Collision:") + box = layout.box() + box.prop(psys.settings,"mol_selfcollision_active", text = "Activate Self Collision") + box.prop(psys.settings,"mol_othercollision_active", text = "Activate Collision with others") + box.prop(psys.settings,"mol_collision_group",text = " Collide only with:") + box.prop(psys.settings,"mol_friction",text = " Friction:") + box.prop(psys.settings,"mol_collision_damp",text = " Damping:") + + row = layout.row() + row.label(text = "Links:") + box = layout.box() + box.prop(psys.settings,"mol_links_active", text = "Activate Particles linking") + + subbox = box.box() + subbox.enabled = psys.settings.mol_links_active + subbox.label(text = "Initial Linking (at birth):") + row = subbox.row() + row.prop(psys.settings,"mol_link_length",text = "search length") + row.prop(psys.settings,"mol_link_rellength",text = "Relative") + row = subbox.row() + row.prop(psys.settings,"mol_link_max",text = "Max links") + row = subbox.row() + row.prop(psys.settings,"mol_link_friction",text = "Link friction") + layout.separator() + row = subbox.row() + row.prop(psys.settings,"mol_link_tension",text = "Tension") + row.prop(psys.settings,"mol_link_tensionrand",text = "Rand Tension") + row = subbox.row() + row.prop(psys.settings,"mol_link_stiff",text = "Stiff") + row.prop(psys.settings,"mol_link_stiffrand",text = "Rand Stiff") + #row = subbox.row() + #row.prop(psys.settings,"mol_link_stiffexp",text = "Exponent") + #row.label(text = "") + row = subbox.row() + row.prop(psys.settings,"mol_link_damp",text = "Damping") + row.prop(psys.settings,"mol_link_damprand",text = "Rand Damping") + row = subbox.row() + row.prop(psys.settings,"mol_link_broken",text = "broken") + row.prop(psys.settings,"mol_link_brokenrand",text = "Rand Broken") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop(psys.settings,"mol_link_samevalue", text = "Same values for compression/expansion") + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings,"mol_link_estiff",text = "E Stiff") + row.prop(psys.settings,"mol_link_estiffrand",text = "Rand E Stiff") + #row = subbox.row() + #row.enabled = not psys.settings.mol_link_samevalue + #row.prop(psys.settings,"mol_link_estiffexp",text = "E Exponent") + #row.label(text = "") + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings,"mol_link_edamp",text = "E Damping") + row.prop(psys.settings,"mol_link_edamprand",text = "Rand E Damping") + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings,"mol_link_ebroken",text = "E broken") + row.prop(psys.settings,"mol_link_ebrokenrand",text = "Rand E Broken") + + subbox = box.box() + subbox.active = psys.settings.mol_links_active + subbox.label(text = "New Linking (at collision):") + row = subbox.row() + row.prop(psys.settings,"mol_relink_group",text = "Only links with:") + row = subbox.row() + row.prop(psys.settings,"mol_relink_chance",text = "% linking") + row.prop(psys.settings,"mol_relink_chancerand",text = "Rand % linking") + row = subbox.row() + row.prop(psys.settings,"mol_relink_max",text = "Max links") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop(psys.settings,"mol_relink_tension",text = "Tension") + row.prop(psys.settings,"mol_relink_tensionrand",text = "Rand Tension") + row = subbox.row() + row.prop(psys.settings,"mol_relink_stiff",text = "Stiff") + row.prop(psys.settings,"mol_relink_stiffrand",text = "Rand Stiff") + #row = subbox.row() + #row.prop(psys.settings,"mol_relink_stiffexp",text = "Exp") + #row.label(text = "") + row = subbox.row() + row.prop(psys.settings,"mol_relink_damp",text = "Damping") + row.prop(psys.settings,"mol_relink_damprand",text = "Rand Damping") + row = subbox.row() + row.prop(psys.settings,"mol_relink_broken",text = "broken") + row.prop(psys.settings,"mol_relink_brokenrand",text = "Rand broken") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop(psys.settings,"mol_relink_samevalue", text = "Same values for compression/expansion") + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings,"mol_relink_estiff",text = "E Stiff") + row.prop(psys.settings,"mol_relink_estiffrand",text = "Rand E Stiff") + #row = subbox.row() + #row.enabled = not psys.settings.mol_relink_samevalue + #row.prop(psys.settings,"mol_relink_estiffexp",text = "Exp") + #row.label(text = "") + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings,"mol_relink_edamp",text = "E Damping") + row.prop(psys.settings,"mol_relink_edamprand",text = "Rand E Damping") + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings,"mol_relink_ebroken",text = "E broken") + row.prop(psys.settings,"mol_relink_ebrokenrand",text = "Rand E broken") + + row = layout.row() + row.label(text = "UV's:") + box = layout.box() + row = box.row() + if obj.data.uv_layers.active != None: + row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: " + str(obj.data.uv_textures.active.name) + ")" ) + else: + row.active = False + row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: None)" ) + + row = layout.row() + row.label(text = "") + row = layout.row() + row.label(text = "Simulate") + row = layout.row() + row.prop(scn,"frame_start",text = "Start Frame") + row.prop(scn,"frame_end",text = "End Frame") + #row = layout.row() + #row.prop(scn,"mol_timescale_active",text = "Activate TimeScaling") + #row = layout.row() + #row.enabled = scn.mol_timescale_active + #row.prop(scn,"timescale",text = "TimeScale") + #row.label(text = "") + row = layout.row() + row.prop(scn,"mol_substep",text = "mol_substep") + row.label(text = "") + row = layout.row() + row.label(text = "CPU used:") + row.prop(scn,"mol_cpu",text = "CPU") + row = layout.row() + row.prop(scn,"mol_bake",text = "Bake all at ending") + row.prop(scn,"mol_render",text = "Render at ending") + row = layout.row() + if scn.mol_simrun == False and psys.point_cache.is_baked == False: + row.enabled = True + row.operator("object.mol_simulate",icon = 'RADIO',text = "Start Molecular Simulation") + row = layout.row() + row.enabled = False + row.operator("ptcache.free_bake_all", text="Free All Bakes") + if psys.point_cache.is_baked == True and scn.mol_simrun == False: + row.enabled = False + row.operator("object.mol_simulate",icon = 'RADIO',text = "Simulation baked") + row = layout.row() + row.enabled = True + row.operator("ptcache.free_bake_all", text="Free All Bakes") + if scn.mol_simrun == True: + row.enabled = False + row.operator("object.mol_simulate",icon = 'RADIO',text = "Process: " + scn.mol_timeremain + " left") + row = layout.row() + row.enabled = False + row.operator("ptcache.free_bake_all", text="Free All Bakes") + + box = layout.box() + row = box.row() + box.enabled = True + row.label(text = "Molecular Tools:",icon = 'MODIFIER') + subbox = box.box() + row = subbox.row() + row.label(text = "Particle UV:") + row = subbox.row() + row.alignment = 'CENTER' + row.label(icon = 'INFO',text = "Set current particles position ") + row = subbox.row() + row.alignment = 'CENTER' + row.label(text = "has global or current uv in angular velocity.") + row = subbox.row() + row.alignment = 'CENTER' + row.label(text = " Retrieve it with Cycles particle info node") + row = subbox.row() + row.operator("object.mol_set_global_uv",icon = 'GROUP_UVS',text = "Set Global UV") + row = subbox.row() + if obj.data.uv_layers.active != None: + row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV (current: " + str(obj.data.uv_textures.active.name) + ")" ) + else: + row.active = False + row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV ( no uvs found)") + subbox = box.box() + row = subbox.row() + row.label(text = "SUBSTEPS CALCULATOR:") + row = subbox.row() + row.label(icon = 'INFO',text = "Current systems have: " + str(len(psys.particles)) + " particles") + row = subbox.row() + row.prop(psys.settings,"mol_var1",text = "Current numbers of particles") + row = subbox.row() + row.prop(psys.settings,"mol_var2",text = "Current substep") + row = subbox.row() + row.prop(psys.settings,"mol_var3",text = "Targeted numbers of particles") + diff = (psys.settings.mol_var3 / psys.settings.mol_var1) + factor = (psys.settings.mol_var3**(1/3) / psys.settings.mol_var1**(1/3)) + newsubstep = int(round(factor * psys.settings.mol_var2)) + row = subbox.row() + row.label(icon = 'FORWARD',text = "You must set new substep to: " + str(newsubstep)) + row = subbox.row() + row.label(icon = 'ERROR',text = "Multiply particles size by: " + str(round(1/factor,5))) + row = subbox.row() + row.label(icon = 'ERROR',text = "Multiply others sys particle number by: " + str(round(diff,5))) + + box = layout.box() + row = box.row() + box.active = False + box.alert = False + row.alignment = 'CENTER' + row.label(text = "THANKS TO ALL DONATORS !") + row = box.row() + row.alignment = 'CENTER' + row.label(text = "If you want donate to support my work") + row = box.row() + row.alignment = 'CENTER' + row.operator("wm.url_open", text=" click here to Donate ", icon='URL').url = "www.pyroevil.com/donate/" + row = box.row() + row.alignment = 'CENTER' + row.label(text = "or visit: ") + row = box.row() + row.alignment = 'CENTER' + row.label(text = "www.pyroevil.com/donate/") From fda459dc72fcf1d15057d397762ecbbb53b0a694 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 3 Sep 2018 07:44:08 +0400 Subject: [PATCH 016/129] addd git ignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd4b95a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +cmolcore.pyd From 30c5fdff2d483c2ff703c62520798f7ad12e4bc1 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 3 Sep 2018 09:27:51 +0400 Subject: [PATCH 017/129] Linking Group and Activate Others Linking Options --- molecular/properties.py | 7 +++ molecular/simulate.py | 6 ++- molecular/ui.py | 2 + sources/cmolcore.pyx | 98 +++++++++++++++++++++++------------------ 4 files changed, 69 insertions(+), 44 deletions(-) diff --git a/molecular/properties.py b/molecular/properties.py index 839295d..1ca97d9 100644 --- a/molecular/properties.py +++ b/molecular/properties.py @@ -23,6 +23,13 @@ def define_props(): parset.mol_collision_group = bpy.props.EnumProperty(items = item, description = "Choose a collision group you want to collide with") parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) + parset.mol_other_link_active = bpy.props.BoolProperty(name = "mol_other_link_active", description = "",default = False) + + item = [] + for i in range(1,12): + item.append((str(i),"Link Group " + str(i),"Link only with group " + str(i) )) + parset.mol_link_group = bpy.props.EnumProperty(items = item, description = "") + parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) diff --git a/molecular/simulate.py b/molecular/simulate.py index 180686c..2a1fb70 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -70,7 +70,7 @@ def pack_data(initiate): psys.settings.mol_relink_ebroken = psys.settings.mol_relink_broken psys.settings.mol_relink_ebrokenrand = psys.settings.mol_relink_brokenrand - params = [0] * 45 + params = [0] * 47 params[0] = psys.settings.mol_selfcollision_active params[1] = psys.settings.mol_othercollision_active params[2] = psys.settings.mol_collision_group @@ -118,7 +118,9 @@ def pack_data(initiate): params[41] = psys.settings.mol_relink_edamprand params[42] = psys.settings.mol_relink_ebroken params[43] = psys.settings.mol_relink_ebrokenrand - params[44] = psys.settings.mol_link_friction + params[44] = psys.settings.mol_link_friction + params[45] = psys.settings.mol_link_group + params[46] = psys.settings.mol_other_link_active mol_exportdata = bpy.context.scene.mol_exportdata if initiate: diff --git a/molecular/ui.py b/molecular/ui.py index 062511c..42edcae 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -67,6 +67,8 @@ def draw(self, context): row.label(text = "Links:") box = layout.box() box.prop(psys.settings,"mol_links_active", text = "Activate Particles linking") + box.prop(psys.settings,"mol_other_link_active", text = "Activate Particles linking with Others") + box.prop(psys.settings,"mol_link_group",text = " Linking only with:") subbox = box.box() subbox.enabled = psys.settings.mol_links_active diff --git a/sources/cmolcore.pyx b/sources/cmolcore.pyx index 0549217..9a2af2d 100644 --- a/sources/cmolcore.pyx +++ b/sources/cmolcore.pyx @@ -131,6 +131,8 @@ cpdef init(importdata): psys[i].relink_ebroken = importdata[i + 1][6][42] psys[i].relink_ebrokenrand = importdata[i + 1][6][43] psys[i].link_friction = importdata[i + 1][6][44] + psys[i].link_group = int(importdata[i + 1][6][45]) + psys[i].other_link_active = importdata[i + 1][6][46] parlist[jj].sys = &psys[i] parlist[jj].collided_with = malloc( 1 * cython.sizeof(int) ) @@ -1155,6 +1157,7 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: cdef float tensionrandom = 0 cdef float chancerdom = 0 cdef Particle *fakepar = NULL + cdef int create_links fakepar = malloc( 1 * cython.sizeof(Particle)) par = &parlist[par_id] #printdb(693) @@ -1200,48 +1203,56 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: link.end = par2.id #printdb(732) link.friction = (par.sys.link_friction + par2.sys.link_friction) / 2 - if parothers_id == -1: - tensionrandom = (par.sys.link_tensionrand + par2.sys.link_tensionrand) / 2 * 2 - srand(1) - tension = ((par.sys.link_tension + par2.sys.link_tension)/2) * ((((rand() / rand_max) * tensionrandom) - (tensionrandom / 2)) + 1) - srand(2) - link.lenght = ((square_dist(par.loc,par2.loc,3))**0.5) * tension - stiffrandom = (par.sys.link_stiffrand + par2.sys.link_stiffrand) / 2 * 2 - link.stiffness = ((par.sys.link_stiff + par2.sys.link_stiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) - srand(3) - link.estiffness = ((par.sys.link_estiff + par2.sys.link_estiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) - srand(4) - link.exponent = abs(int((par.sys.link_stiffexp + par2.sys.link_stiffexp) / 2))#### - link.eexponent = abs(int((par.sys.link_estiffexp + par2.sys.link_estiffexp) / 2))#### - damprandom = ((par.sys.link_damprand + par2.sys.link_damprand) / 2) * 2 - link.damping = ((par.sys.link_damp + par2.sys.link_damp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) - srand(5) - link.edamping = ((par.sys.link_edamp + par2.sys.link_edamp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) - brokrandom = ((par.sys.link_brokenrand + par2.sys.link_brokenrand) / 2) * 2 - srand(6) - link.broken = ((par.sys.link_broken + par2.sys.link_broken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) - srand(7) - link.ebroken = ((par.sys.link_ebroken + par2.sys.link_ebroken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) - #printdb(748) - par.links[par.links_num] = link[0] - par.links_num += 1 - par.links_activnum += 1 - #printdb(752) - par.links = realloc(par.links,(par.links_num + 2) * cython.sizeof(Links) ) - - #printdb(755) - par.link_with[par.link_withnum] = par2.id - par.link_withnum += 1 - #printdb(758) - par.link_with = realloc(par.link_with,(par.link_withnum + 2) * cython.sizeof(int) ) - - par2.link_with[par2.link_withnum] = par.id - par2.link_withnum += 1 - #printdb(763) - par2.link_with = realloc(par2.link_with,(par2.link_withnum + 2) * cython.sizeof(int) ) - newlinks += 1 - #free(link) - #printdb(766) + if parothers_id == -1 and par.sys.link_group == par2.sys.link_group: + if par.sys.id != par2.sys.id: + if par.sys.other_link_active and par2.sys.other_link_active: + create_links = 1 + else: + create_links = 0 + else: + create_links = 1 + if create_links == 1: + tensionrandom = (par.sys.link_tensionrand + par2.sys.link_tensionrand) / 2 * 2 + srand(1) + tension = ((par.sys.link_tension + par2.sys.link_tension)/2) * ((((rand() / rand_max) * tensionrandom) - (tensionrandom / 2)) + 1) + srand(2) + link.lenght = ((square_dist(par.loc,par2.loc,3))**0.5) * tension + stiffrandom = (par.sys.link_stiffrand + par2.sys.link_stiffrand) / 2 * 2 + link.stiffness = ((par.sys.link_stiff + par2.sys.link_stiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) + srand(3) + link.estiffness = ((par.sys.link_estiff + par2.sys.link_estiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) + srand(4) + link.exponent = abs(int((par.sys.link_stiffexp + par2.sys.link_stiffexp) / 2))#### + link.eexponent = abs(int((par.sys.link_estiffexp + par2.sys.link_estiffexp) / 2))#### + damprandom = ((par.sys.link_damprand + par2.sys.link_damprand) / 2) * 2 + link.damping = ((par.sys.link_damp + par2.sys.link_damp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) + srand(5) + link.edamping = ((par.sys.link_edamp + par2.sys.link_edamp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) + brokrandom = ((par.sys.link_brokenrand + par2.sys.link_brokenrand) / 2) * 2 + srand(6) + link.broken = ((par.sys.link_broken + par2.sys.link_broken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) + srand(7) + link.ebroken = ((par.sys.link_ebroken + par2.sys.link_ebroken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) + #printdb(748) + par.links[par.links_num] = link[0] + par.links_num += 1 + par.links_activnum += 1 + #printdb(752) + par.links = realloc(par.links,(par.links_num + 2) * cython.sizeof(Links) ) + + #printdb(755) + par.link_with[par.link_withnum] = par2.id + par.link_withnum += 1 + #printdb(758) + par.link_with = realloc(par.link_with,(par.link_withnum + 2) * cython.sizeof(int) ) + + par2.link_with[par2.link_withnum] = par.id + par2.link_withnum += 1 + #printdb(763) + par2.link_with = realloc(par2.link_with,(par2.link_withnum + 2) * cython.sizeof(int) ) + newlinks += 1 + #free(link) + #printdb(766) if parothers_id != -1 and par.sys.relink_group == par2.sys.relink_group: #printdb(769) @@ -1379,6 +1390,9 @@ cdef struct ParSys: float relink_ebroken float relink_ebrokenrand float link_friction + int link_group + int other_link_active + cdef struct SParticle: int id From e9eca10006a172aecf22e2d3c82508ec45fd1074 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 3 Sep 2018 14:11:38 +0400 Subject: [PATCH 018/129] #9 Groups as an integer value --- molecular/properties.py | 17 +++++------------ sources/cmolcore.pyx | 6 +++--- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/molecular/properties.py b/molecular/properties.py index 1ca97d9..eff5a48 100644 --- a/molecular/properties.py +++ b/molecular/properties.py @@ -17,18 +17,13 @@ def define_props(): parset.mol_othercollision_active = bpy.props.BoolProperty(name = "mol_othercollision_active", description = "Activate collision with particles from others systems",default = False) parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') - item = [] - for i in range(1,12): - item.append((str(i),"Collision Group " + str(i),"collide only with group " + str(i) )) - parset.mol_collision_group = bpy.props.EnumProperty(items = item, description = "Choose a collision group you want to collide with") + + parset.mol_collision_group = bpy.props.IntProperty(default=1, min=1, description = "Choose a collision group you want to collide with") parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) parset.mol_other_link_active = bpy.props.BoolProperty(name = "mol_other_link_active", description = "",default = False) - item = [] - for i in range(1,12): - item.append((str(i),"Link Group " + str(i),"Link only with group " + str(i) )) - parset.mol_link_group = bpy.props.EnumProperty(items = item, description = "") + parset.mol_link_group = bpy.props.IntProperty(default=1, min=1, description = "") parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') @@ -54,10 +49,8 @@ def define_props(): parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - item = [] - for i in range(1,12): - item.append((str(i),"Relink Group " + str(i),"Relink only with group " + str(i) )) - parset.mol_relink_group = bpy.props.EnumProperty(items = item, description = "Choose a group that new link are possible") + parset.mol_relink_group = bpy.props.IntProperty(default=1, min=1, description = "Choose a group that new link are possible") + parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0, precision=6) parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) diff --git a/sources/cmolcore.pyx b/sources/cmolcore.pyx index 9a2af2d..5a66e58 100644 --- a/sources/cmolcore.pyx +++ b/sources/cmolcore.pyx @@ -88,7 +88,7 @@ cpdef init(importdata): parlist[jj].state = importdata[i + 1][5][ii] psys[i].selfcollision_active = importdata[i + 1][6][0] psys[i].othercollision_active = importdata[i + 1][6][1] - psys[i].collision_group = int(importdata[i + 1][6][2]) + psys[i].collision_group = importdata[i + 1][6][2] psys[i].friction = importdata[i + 1][6][3] psys[i].collision_damp = importdata[i + 1][6][4] psys[i].links_active = importdata[i + 1][6][5] @@ -110,7 +110,7 @@ cpdef init(importdata): psys[i].link_edamprand = importdata[i + 1][6][21] psys[i].link_ebroken = importdata[i + 1][6][22] psys[i].link_ebrokenrand = importdata[i + 1][6][23] - psys[i].relink_group = int(importdata[i + 1][6][24]) + psys[i].relink_group = importdata[i + 1][6][24] psys[i].relink_chance = importdata[i + 1][6][25] psys[i].relink_chancerand = importdata[i + 1][6][26] psys[i].relink_max = importdata[i + 1][6][27] @@ -131,7 +131,7 @@ cpdef init(importdata): psys[i].relink_ebroken = importdata[i + 1][6][42] psys[i].relink_ebrokenrand = importdata[i + 1][6][43] psys[i].link_friction = importdata[i + 1][6][44] - psys[i].link_group = int(importdata[i + 1][6][45]) + psys[i].link_group = importdata[i + 1][6][45] psys[i].other_link_active = importdata[i + 1][6][46] parlist[jj].sys = &psys[i] From 9cc2bfcc1aa152682e0fc8fb575eeda644af0894 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Thu, 20 Sep 2018 19:33:23 +0400 Subject: [PATCH 019/129] refactor cmolcore.pyx: PEP8 --- sources/cmolcore.pyx | 1156 +++++++++++++++++++++++++----------------- 1 file changed, 681 insertions(+), 475 deletions(-) diff --git a/sources/cmolcore.pyx b/sources/cmolcore.pyx index 5a66e58..0d1d85b 100644 --- a/sources/cmolcore.pyx +++ b/sources/cmolcore.pyx @@ -2,22 +2,31 @@ #cython: boundscheck=False #cython: cdivision=True -# NOTE: order of slow fonction to be optimize/multithreaded: kdtreesearching , kdtreecreating , linksolving +# NOTE: order of slow fonction to be optimize/multithreaded: +# kdtreesearching, kdtreecreating, linksolving + cimport cython from time import clock -from cython.parallel import parallel , prange , threadid -from libc.stdlib cimport malloc , realloc, free , rand , srand, abs +from cython.parallel import parallel, prange, threadid +from libc.stdlib cimport malloc, realloc, free, rand, srand, abs + cdef extern from *: int INT_MAX float FLT_MAX + cdef extern from "stdlib.h": ctypedef void const_void "const void" - void qsort(void *base, int nmemb, int size,int(*compar)(const_void *, const_void *)) nogil + void qsort( + void *base, + int nmemb, + int size, + int(*compar)(const_void *, const_void *) + )nogil + - cdef float fps = 0 cdef int substep = 0 cdef float deltatime = 0 @@ -34,6 +43,7 @@ cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL print("cmolcore imported with success! v1.01") + cpdef init(importdata): global fps global substep @@ -57,23 +67,21 @@ cpdef init(importdata): totaldeadlinks = 0 fps = float(importdata[0][0]) substep = int(importdata[0][1]) - deltatime = (fps * (substep +1)) + deltatime = (fps * (substep + 1)) psysnum = importdata[0][2] parnum = importdata[0][3] cpunum = importdata[0][4] - deadlinks = malloc( cpunum * cython.sizeof(int) ) - print " Number of cpu's used:",cpunum - psys = malloc( psysnum * cython.sizeof(ParSys) ) - #printdb(40) - parlist = malloc( parnum * cython.sizeof(Particle) ) - #printdb(parnum) - parlistcopy = malloc( parnum * cython.sizeof(SParticle) ) + deadlinks = malloc(cpunum * cython.sizeof(int)) + print(" Number of cpu's used:", cpunum) + psys = malloc(psysnum * cython.sizeof(ParSys)) + parlist = malloc(parnum * cython.sizeof(Particle)) + parlistcopy = malloc(parnum * cython.sizeof(SParticle)) cdef int jj = 0 - #printdb(47) for i in xrange(psysnum): psys[i].id = i - psys[i].parnum = importdata[i+1][0] - psys[i].particles = malloc( psys[i].parnum * cython.sizeof(Particle) ) + psys[i].parnum = importdata[i + 1][0] + psys[i].particles = malloc(psys[i].parnum * \ + cython.sizeof(Particle)) psys[i].particles = &parlist[jj] for ii in xrange(psys[i].parnum): parlist[jj].id = jj @@ -133,91 +141,119 @@ cpdef init(importdata): psys[i].link_friction = importdata[i + 1][6][44] psys[i].link_group = importdata[i + 1][6][45] psys[i].other_link_active = importdata[i + 1][6][46] - + parlist[jj].sys = &psys[i] - parlist[jj].collided_with = malloc( 1 * cython.sizeof(int) ) + parlist[jj].collided_with = malloc(1 * cython.sizeof(int)) parlist[jj].collided_num = 0 - parlist[jj].links = malloc( 1 * cython.sizeof(Links) ) + parlist[jj].links = malloc(1 * cython.sizeof(Links)) parlist[jj].links_num = 0 parlist[jj].links_activnum = 0 - parlist[jj].link_with = malloc( 1 * cython.sizeof(int) ) + parlist[jj].link_with = malloc(1 * cython.sizeof(int)) parlist[jj].link_withnum = 0 parlist[jj].neighboursmax = 10 - parlist[jj].neighbours = malloc( parlist[jj].neighboursmax * cython.sizeof(int) ) + parlist[jj].neighbours = malloc(parlist[jj].neighboursmax * \ + cython.sizeof(int)) parlist[jj].neighboursnum = 0 jj += 1 - + jj = 0 - #printdb(115) - kdtree = malloc( 1 * cython.sizeof(KDTree) ) - #printdb(115) - KDTree_create_nodes(kdtree,parnum) - #printdb(117) + kdtree = malloc(1 * cython.sizeof(KDTree)) + KDTree_create_nodes(kdtree, parnum) + with nogil: - for i in prange(parnum,schedule='dynamic',chunksize=10,num_threads=cpunum): + for i in prange( + parnum, + schedule='dynamic', + chunksize=10, + num_threads=cpunum + ): parlistcopy[i].id = parlist[i].id parlistcopy[i].loc[0] = parlist[i].loc[0] parlistcopy[i].loc[1] = parlist[i].loc[1] parlistcopy[i].loc[2] = parlist[i].loc[2] - - #printdb(119) - KDTree_create_tree(kdtree,parlistcopy,0,parnum - 1,0,-1,0,1) - #printdb(120) + + KDTree_create_tree(kdtree, parlistcopy, 0, parnum - 1, 0, -1, 0, 1) + with nogil: - for i in prange(kdtree.thread_index,schedule='dynamic',chunksize=10,num_threads=cpunum): - KDTree_create_tree(kdtree,parlistcopy,kdtree.thread_start[i],kdtree.thread_end[i],kdtree.thread_name[i],kdtree.thread_parent[i],kdtree.thread_depth[i],0) - #printdb(121) + for i in prange( + kdtree.thread_index, + schedule='dynamic', + chunksize=10, + num_threads=cpunum + ): + KDTree_create_tree( + kdtree, + parlistcopy, + kdtree.thread_start[i], + kdtree.thread_end[i], + kdtree.thread_name[i], + kdtree.thread_parent[i], + kdtree.thread_depth[i], + 0 + ) + with nogil: - for i in prange(parnum,schedule='dynamic',chunksize=10,num_threads=cpunum): + for i in prange( + parnum, + schedule='dynamic', + chunksize=10, + num_threads=cpunum + ): if parlist[i].sys.links_active == 1: - KDTree_rnn_query(kdtree,&parlist[i],parlist[i].loc,parlist[i].sys.link_length) - #printdb(122) + KDTree_rnn_query( + kdtree, + &parlist[i], + parlist[i].loc, + parlist[i].sys.link_length + ) + for i in xrange(parnum): - #printdb(123) - create_link(parlist[i].id,parlist[i].sys.link_max) + create_link(parlist[i].id, parlist[i].sys.link_max) if parlist[i].neighboursnum > 1: - #printdb(124) - #free(parlist[i].neighbours) + # free(parlist[i].neighbours) parlist[i].neighboursnum = 0 - #printdb(125) - #printdb(126) - #testkdtree(3) totallinks += newlinks - print " New links created: ",newlinks + print(" New links created: ", newlinks) return parnum - - -cdef void printdb (int linenumber, text = ""): + + +cdef void printdb(int linenumber, text = ""): cdef int dbactive = 1 if dbactive == 1: print(linenumber) + cdef testkdtree(int verbose = 0): global kdtree global parnum if verbose >= 3: - print("RootNode:",kdtree.root_node[0].index) + print("RootNode:", kdtree.root_node[0].index) for i in xrange(parnum): - print("Parent",kdtree.nodes[i].index,"Particle:",kdtree.nodes[i].particle[0].id) - print(" Left",kdtree.nodes[i].left_child[0].index) - print(" Right",kdtree.nodes[i].right_child[0].index) + print( + "Parent", + kdtree.nodes[i].index, + "Particle:", + kdtree.nodes[i].particle[0].id + ) + print(" Left", kdtree.nodes[i].left_child[0].index) + print(" Right", kdtree.nodes[i].right_child[0].index) - cdef float *a = [0,0,0] + cdef float *a = [0, 0, 0] cdef Particle *b - b = malloc( 1 * cython.sizeof(Particle) ) + b = malloc(1 * cython.sizeof(Particle)) if verbose >= 1: print("start searching") - KDTree_rnn_query(kdtree,b,a,2) + KDTree_rnn_query(kdtree, b, a, 2) output = [] if verbose >= 2: print("Result") for i in xrange(b[0].neighboursnum): - print(" Query Particle:",parlist[b[0].neighbours[i]].id) + print(" Query Particle:", parlist[b[0].neighbours[i]].id) if verbose >= 1: - print("number of particle find:",b[0].neighboursnum) + print("number of particle find:", b[0].neighboursnum) free(b) - - + + cpdef simulate(importdata): global kdtree global parlist @@ -231,8 +267,8 @@ cpdef simulate(importdata): global totallinks global totaldeadlinks global deadlinks - - cdef int i= 0 + + cdef int i = 0 cdef int ii = 0 cdef int profiling = 0 @@ -243,33 +279,32 @@ cpdef simulate(importdata): cdef float maxY = -INT_MAX cdef float maxZ = -INT_MAX cdef float maxSize = -INT_MAX - cdef Pool *parPool = malloc( 1 * cython.sizeof(Pool) ) - parPool.parity = malloc( 2 * cython.sizeof(Parity) ) + cdef Pool *parPool = malloc(1 * cython.sizeof(Pool)) + parPool.parity = malloc(2 * cython.sizeof(Parity)) parPool[0].axis = -1 parPool[0].offset = 0 parPool[0].max = 0 - #cdef float *zeropoint = [0,0,0] + # cdef float *zeropoint = [0,0,0] newlinks = 0 for i in xrange(cpunum): deadlinks[i] = 0 - #printdb(140) if profiling == 1: print("-->start simulate") stime2 = clock() stime = clock() - + update(importdata) - + if profiling == 1: - print("-->update time", clock() - stime,"sec") + print("-->update time", clock() - stime, "sec") stime = clock() - #printdb(145) + for i in xrange(parnum): parlistcopy[i].id = parlist[i].id parlistcopy[i].loc[0] = parlist[i].loc[0] - #if parlist[i].loc[0] >= FLT_MAX or parlist[i].loc[0] <= -FLT_MAX : - #print('ALERT! INF value in X') + # if parlist[i].loc[0] >= FLT_MAX or parlist[i].loc[0] <= -FLT_MAX : + # print('ALERT! INF value in X') if parlist[i].loc[0] < minX: minX = parlist[i].loc[0] if parlist[i].loc[0] > maxX: @@ -291,27 +326,25 @@ cpdef simulate(importdata): maxSize = parlist[i].links[ii].lenght if (parlist[i].size * 2) > maxSize: maxSize = (parlist[i].size * 2) - #''' + if (maxX - minX) >= (maxY - minY) and (maxX - minX) >= (maxZ - minZ): parPool[0].axis = 0 parPool[0].offset = 0 - minX parPool[0].max = maxX + parPool[0].offset - + if (maxY - minY) > (maxX - minX) and (maxY - minY) > (maxZ - minZ): parPool[0].axis = 1 parPool[0].offset = 0 - minY parPool[0].max = maxY + parPool[0].offset - + if (maxZ - minZ) > (maxY - minY) and (maxZ - minZ) > (maxX - minX): parPool[0].axis = 2 parPool[0].offset = 0 - minZ parPool[0].max = maxZ + parPool[0].offset - + if (parPool[0].max / ( cpunum * 10 )) > maxSize: maxSize = (parPool[0].max / ( cpunum * 10 )) - - #printdb(155) - + ''' cdef float Xsize = maxX - minX cdef float Ysize = maxY - minY @@ -319,7 +352,6 @@ cpdef simulate(importdata): cdef float newXsize = Xsize cdef float newYsize = Ysize cdef float newZsize = Zsize - #print(Xsize,Ysize,Zsize) pyaxis = [] for i in xrange(64): if Xsize >= Ysize and Xsize >= Zsize: @@ -336,117 +368,145 @@ cpdef simulate(importdata): Ysize = newYsize Zsize = newZsize pyaxis.append(kdtree.axis[i]) - #print(pyaxis) - ''' - - + ''' + cdef int pair cdef int heaps cdef float scale = 1 / ( maxSize * 2.1 ) - #printdb(160) - #print('minX:',minX,'maxX:',maxX) - #print('minY:',minY,'maxY:',maxY) - #print('minZ:',minZ,'maxZ:',maxZ) - #print('Maxsize:',maxSize) - #print('Max divide by square of CPU numbers:',(parPool[0].max / ( cpunum * 8 ))) - #print('Axe:',parPool[0].axis) - #print('Offset:',parPool[0].offset) - #print('Max:',parPool[0].max) - #print('Scale:',scale) + for pair in xrange(2): - #print("i:",i) - parPool[0].parity[pair].heap = malloc(((parPool[0].max * scale) + 1) * cython.sizeof(Heap) ) + + parPool[0].parity[pair].heap = \ + malloc(((parPool[0].max * scale) + 1) * \ + cython.sizeof(Heap)) + for heaps in range((parPool[0].max * scale) + 1): - #print("1- pair:",pair,"heaps:",heaps,"particles:",0) parPool[0].parity[pair].heap[heaps].parnum = 0 parPool[0].parity[pair].heap[heaps].maxalloc = 50 - parPool[0].parity[pair].heap[heaps].par = malloc( parPool[0].parity[pair].heap[heaps].maxalloc * cython.sizeof(int) ) - #printdb(165) + + parPool[0].parity[pair].heap[heaps].par = \ + malloc(parPool[0].parity[pair].heap[heaps].maxalloc * \ + cython.sizeof(int)) + for i in xrange(parnum): - #printdb(166) - #print('axis:',parPool[0].axis) - #print('position:',parlist[i].loc[parPool[0].axis]) - #print('offset:',parPool[0].offset) - #print('scale:',scale) - #print('non-int pair',(((parlist[i].loc[parPool[0].axis] + parPool[0].offset) * scale) % 2)) - pair = (((parlist[i].loc[parPool[0].axis] + parPool[0].offset) * scale) % 2) - heaps = ((parlist[i].loc[parPool[0].axis] + parPool[0].offset) * scale) - #print("- pair:",pair,"heaps:",heaps,"particles:",parlist[i].id) - #print(parPool[0].parity[pair].heap[heaps].parnum) + pair = ((( + parlist[i].loc[parPool[0].axis] + parPool[0].offset) * scale) % 2 + ) + heaps = (( + parlist[i].loc[parPool[0].axis] + parPool[0].offset) * scale + ) parPool[0].parity[pair].heap[heaps].parnum += 1 - #print(parPool[0].parity[pair].heap[heaps].parnum) - #printdb(167) - if parPool[0].parity[pair].heap[heaps].parnum > parPool[0].parity[pair].heap[heaps].maxalloc: - #printdb(168) - parPool[0].parity[pair].heap[heaps].maxalloc = (parPool[0].parity[pair].heap[heaps].maxalloc * 1.25) - #printdb(169) - parPool[0].parity[pair].heap[heaps].par = realloc( parPool[0].parity[pair].heap[heaps].par,( parPool[0].parity[pair].heap[heaps].maxalloc + 2 ) * cython.sizeof(int) ) - #printdb(170) - parPool[0].parity[pair].heap[heaps].par[(parPool[0].parity[pair].heap[heaps].parnum - 1)] = parlist[i].id - #printdb(171) - #''' - - #printdb(172) + + if parPool[0].parity[pair].heap[heaps].parnum > \ + parPool[0].parity[pair].heap[heaps].maxalloc: + + parPool[0].parity[pair].heap[heaps].maxalloc = \ + (parPool[0].parity[pair].heap[heaps].maxalloc * 1.25) + + parPool[0].parity[pair].heap[heaps].par = \ + realloc( + parPool[0].parity[pair].heap[heaps].par, + (parPool[0].parity[pair].heap[heaps].maxalloc + 2 ) * \ + cython.sizeof(int) + ) + + parPool[0].parity[pair].heap[heaps].par[ + (parPool[0].parity[pair].heap[heaps].parnum - 1)] = parlist[i].id + if profiling == 1: - print("-->copy data time", clock() - stime,"sec") + print("-->copy data time", clock() - stime, "sec") stime = clock() - - #printdb(173) - KDTree_create_tree(kdtree,parlistcopy,0,parnum - 1,0,-1,0,1) - #printdb(180) + + KDTree_create_tree(kdtree, parlistcopy, 0, parnum - 1, 0, -1, 0, 1) + with nogil: - for i in prange(kdtree.thread_index,schedule='dynamic',chunksize=10,num_threads=cpunum): - KDTree_create_tree(kdtree,parlistcopy,kdtree.thread_start[i],kdtree.thread_end[i],kdtree.thread_name[i],kdtree.thread_parent[i],kdtree.thread_depth[i],0) - + for i in prange( + kdtree.thread_index, + schedule='dynamic', + chunksize=10, + num_threads=cpunum + ): + KDTree_create_tree( + kdtree, + parlistcopy, + kdtree.thread_start[i], + kdtree.thread_end[i], + kdtree.thread_name[i], + kdtree.thread_parent[i], + kdtree.thread_depth[i], + 0 + ) + if profiling == 1: print("-->create tree time", clock() - stime,"sec") stime = clock() - + with nogil: - for i in prange(parnum,schedule='dynamic',chunksize=10,num_threads=cpunum): - KDTree_rnn_query(kdtree,&parlist[i],parlist[i].loc,parlist[i].size * 2) - - #printdb(189) + for i in prange( + parnum, + schedule='dynamic', + chunksize=10, + num_threads=cpunum + ): + KDTree_rnn_query( + kdtree, + &parlist[i], + parlist[i].loc, + parlist[i].size * 2 + ) + if profiling == 1: - print("-->neighbours time", clock() - stime,"sec") + print("-->neighbours time", clock() - stime, "sec") stime = clock() - #''' with nogil: - for pair in xrange(2): - for heaps in prange((parPool[0].max * scale) + 1,schedule='dynamic',chunksize=1,num_threads=cpunum): + for heaps in prange( + (parPool[0].max * scale) + 1, + schedule='dynamic', + chunksize=1, + num_threads=cpunum + ): for i in xrange(parPool[0].parity[pair].heap[heaps].parnum): - collide(&parlist[parPool[0].parity[pair].heap[heaps].par[i]]) - solve_link(&parlist[parPool[0].parity[pair].heap[heaps].par[i]]) - if parlist[parPool[0].parity[pair].heap[heaps].par[i]].neighboursnum > 1: - #printdb(192) - #free(parlist[i].neighbours) - parlist[parPool[0].parity[pair].heap[heaps].par[i]].neighboursnum = 0 - ''' + + collide( + &parlist[parPool[0].parity[pair].heap[heaps].par[i]] + ) + + solve_link( + &parlist[parPool[0].parity[pair].heap[heaps].par[i]] + ) + + if parlist[ + parPool[0].parity[pair].heap[heaps].par[i] + ].neighboursnum > 1: + + # free(parlist[i].neighbours) + + parlist[ + parPool[0].parity[pair].heap[heaps].par[i] + ].neighboursnum = 0 + + ''' with nogil: for i in xrange(parnum): - #printdb(190) collide(&parlist[i]) - #printdb(192) solve_link(&parlist[i]) if parlist[i].neighboursnum > 1: - #printdb(192) #free(parlist[i].neighbours) parlist[i].neighboursnum = 0 - #printdb(194) ''' - + if profiling == 1: - print("-->collide/solve link time", clock() - stime,"sec") + print("-->collide/solve link time", clock() - stime, "sec") stime = clock() - + exportdata = [] parloc = [] parvel = [] parloctmp = [] parveltmp = [] - #printdb(196) + for i in xrange(psysnum): for ii in xrange(psys[i].parnum): parloctmp.append(psys[i].particles[ii].loc[0]) @@ -455,22 +515,26 @@ cpdef simulate(importdata): parveltmp.append(psys[i].particles[ii].vel[0]) parveltmp.append(psys[i].particles[ii].vel[1]) parveltmp.append(psys[i].particles[ii].vel[2]) - parloc.append(parloctmp) + parloc.append(parloctmp) parvel.append(parveltmp) parloctmp = [] parveltmp = [] - #printdb(198) - - #print " New links at this frame: ",newlinks - #print " Broken links this frame: ",deadlinks + totallinks += newlinks pydeadlinks = 0 for i in xrange(cpunum): pydeadlinks += deadlinks[i] totaldeadlinks += pydeadlinks - #print " left: ",totallinks - totaldeadlinks," on ",totallinks - exportdata = [parloc,parvel,newlinks,pydeadlinks,totallinks,totaldeadlinks] - #''' + + exportdata = [ + parloc, + parvel, + newlinks, + pydeadlinks, + totallinks, + totaldeadlinks + ] + for pair in xrange(2): for heaps in range((parPool[0].max * scale) + 1): parPool[0].parity[pair].heap[heaps].parnum = 0 @@ -478,12 +542,13 @@ cpdef simulate(importdata): free(parPool[0].parity[pair].heap) free(parPool[0].parity) free(parPool) - #''' + if profiling == 1: - print("-->export time", clock() - stime,"sec") - print("-->all process time", clock() - stime2,"sec") + print("-->export time", clock() - stime, "sec") + print("-->all process time", clock() - stime2, "sec") return exportdata + cpdef memfree(): global kdtree global psysnum @@ -495,7 +560,7 @@ cpdef memfree(): global substep global deadlinks cdef int i = 0 - #printdb(200) + fps = 0 substep = 0 deltatime = 0 @@ -505,11 +570,11 @@ cpdef memfree(): totaldeadlinks = 0 free(deadlinks) deadlinks = NULL - #printdb(205) + for i in xrange(parnum): if parnum >= 1: - #free(parlist[i].sys) - #parlist[i].sys = NULL + # free(parlist[i].sys) + # parlist[i].sys = NULL if parlist[i].neighboursnum >= 1: free(parlist[i].neighbours) parlist[i].neighbours = NULL @@ -531,26 +596,25 @@ cpdef memfree(): free(parlist[i].neighbours) parlist[i].neighbours = NULL parlist[i].neighboursnum = 0 - #printdb(208) - + for i in xrange(psysnum): if psysnum >= 1: - #free(psys[i].particles) + # free(psys[i].particles) psys[i].particles = NULL - #printdb(210) - + if psysnum >= 1: free(psys) psys = NULL - #printdb(215) + if parnum >= 1: free(parlistcopy) parlistcopy = NULL free(parlist) parlist = NULL - #printdb(220) + parnum = 0 psysnum = 0 + if kdtree.numnodes >= 1: for i in xrange(kdtree.numnodes): free(kdtree.nodes[i].particle) @@ -559,6 +623,7 @@ cpdef memfree(): kdtree.nodes[i].left_child = NULL free(kdtree.nodes[i].right_child) kdtree.nodes[i].right_child = NULL + free(kdtree.thread_nodes) kdtree.thread_nodes = NULL free(kdtree.thread_start) @@ -575,11 +640,11 @@ cpdef memfree(): kdtree.nodes = NULL free(kdtree.root_node) kdtree.root_node = NULL + free(kdtree) kdtree = NULL - - + #@cython.cdivision(True) cdef void collide(Particle *par)nogil: global kdtree @@ -601,12 +666,12 @@ cdef void collide(Particle *par)nogil: cdef float ratio2 = 0 cdef float factor1 = 0 cdef float factor2 = 0 - cdef float *col_normal1 = [0,0,0] - cdef float *col_normal2 = [0,0,0] - cdef float *ypar_vel = [0,0,0] - cdef float *xpar_vel = [0,0,0] - cdef float *yi_vel = [0,0,0] - cdef float *xi_vel = [0,0,0] + cdef float *col_normal1 = [0, 0, 0] + cdef float *col_normal2 = [0, 0, 0] + cdef float *ypar_vel = [0, 0, 0] + cdef float *xpar_vel = [0, 0, 0] + cdef float *yi_vel = [0, 0, 0] + cdef float *xi_vel = [0, 0, 0] cdef float friction1 = 0 cdef float friction2 = 0 cdef float damping1 = 0 @@ -623,59 +688,61 @@ cdef void collide(Particle *par)nogil: cdef float force1 = 0 cdef float force2 = 0 cdef float mathtmp = 0 - + if par.state >= 2: return - if par.sys.selfcollision_active == False and par.sys.othercollision_active == False: + if par.sys.selfcollision_active == False \ + and par.sys.othercollision_active == False: return - #printdb(282) - #neighbours = KDTree_rnn_query(kdtree,par.loc,par.size * 2) + + # neighbours = KDTree_rnn_query(kdtree, par.loc, par.size * 2) neighbours = par.neighbours - #printdb(284) - #for i in xrange(kdtree.num_result): + + # for i in xrange(kdtree.num_result): for i in xrange(par.neighboursnum): check = 0 - #printdb(287) if parlist[i].id == -1: check += 1 - #printdb(290) par2 = &parlist[neighbours[i]] - #printdb(292) if par.id == par2.id: check += 10 - #printdb(295) - if arraysearch(par2.id,par.collided_with,par.collided_num) == -1: - #if par2 not in par.collided_with: - #printdb(298) + if arraysearch(par2.id, par.collided_with, par.collided_num) == -1: + # if par2 not in par.collided_with: if par2.sys.id != par.sys.id : - #printdb(300) - if par2.sys.othercollision_active == False or par.sys.othercollision_active == False: - #printdb(302) + if par2.sys.othercollision_active == False or \ + par.sys.othercollision_active == False: check += 100 + if par2.sys.collision_group != par.sys.collision_group: - #printdb(304) check += 1000 - if par2.sys.id == par.sys.id and par.sys.selfcollision_active == False: - #printdb(308) + + if par2.sys.id == par.sys.id and \ + par.sys.selfcollision_active == False: check += 10000 - #printdb(310) + stiff = deltatime target = (par.size + par2.size) * 0.999 sqtarget = target * target - #printdb(314) - if check == 0 and par2.state <= 1 and arraysearch(par2.id,par.link_with,par.link_withnum) == -1 and arraysearch(par.id,par2.link_with,par2.link_withnum) == -1: - #if par.state <= 1 and par2.state <= 1 and par2 not in par.link_with and par not in par2.link_with: - #printdb(317) + + if check == 0 and par2.state <= 1 and \ + arraysearch( + par2.id, par.link_with, par.link_withnum + ) == -1 and \ + arraysearch( + par.id, par2.link_with, par2.link_withnum + ) == -1: + + # if par.state <= 1 and par2.state <= 1 and \ + # par2 not in par.link_with and par not in par2.link_with: lenghtx = par.loc[0] - par2.loc[0] lenghty = par.loc[1] - par2.loc[1] lenghtz = par.loc[2] - par2.loc[2] - sqlenght = square_dist(par.loc,par2.loc,3) - #printdb(322) + sqlenght = square_dist(par.loc, par2.loc, 3) if sqlenght != 0 and sqlenght < sqtarget: - lenght = sqlenght**0.5 + lenght = sqlenght ** 0.5 invlenght = 1 / lenght factor = (lenght - target) * invlenght - ratio1 = (par2.mass/(par.mass + par2.mass)) + ratio1 = (par2.mass / (par.mass + par2.mass)) ratio2 = 1 - ratio1 mathtmp = factor * stiff @@ -687,9 +754,6 @@ cdef void collide(Particle *par)nogil: par2.vel[0] += lenghtx * force2 par2.vel[1] += lenghty * force2 par2.vel[2] += lenghtz * force2 - - - #printdb(336) col_normal1[0] = (par2.loc[0] - par.loc[0]) * invlenght col_normal1[1] = (par2.loc[1] - par.loc[1]) * invlenght @@ -697,26 +761,25 @@ cdef void collide(Particle *par)nogil: col_normal2[0] = col_normal1[0] * -1 col_normal2[1] = col_normal1[1] * -1 col_normal2[2] = col_normal1[2] * -1 - - factor1 = dot_product(par.vel,col_normal1) - + + factor1 = dot_product(par.vel,col_normal1) + ypar_vel[0] = factor1 * col_normal1[0] ypar_vel[1] = factor1 * col_normal1[1] ypar_vel[2] = factor1 * col_normal1[2] xpar_vel[0] = par.vel[0] - ypar_vel[0] xpar_vel[1] = par.vel[1] - ypar_vel[1] xpar_vel[2] = par.vel[2] - ypar_vel[2] - #printdb(352) - - factor2 = dot_product(par2.vel,col_normal2) - + + factor2 = dot_product(par2.vel, col_normal2) + yi_vel[0] = factor2 * col_normal2[0] yi_vel[1] = factor2 * col_normal2[1] yi_vel[2] = factor2 * col_normal2[2] xi_vel[0] = par2.vel[0] - yi_vel[0] xi_vel[1] = par2.vel[1] - yi_vel[1] xi_vel[2] = par2.vel[2] - yi_vel[2] - + ''' Ua = factor1 Ub = -factor2 @@ -726,10 +789,10 @@ cdef void collide(Particle *par)nogil: Va = (Cr*Mb*(Ub-Ua)+Ma*Ua+Mb*Ub)/(Ma+Mb) Vb = (Cr*Ma*(Ua-Ub)+Ma*Ua+Mb*Ub)/(Ma+Mb) - #mula = 1 - #mulb = 1 - #Va = Va * (1 - Cr) - #Vb = Vb * (1 - Cr) + # mula = 1 + # mulb = 1 + # Va = Va * (1 - Cr) + # Vb = Vb * (1 - Cr) ypar_vel[0] = col_normal1[0] * Va ypar_vel[1] = col_normal1[1] * Va ypar_vel[2] = col_normal1[2] * Va @@ -738,41 +801,64 @@ cdef void collide(Particle *par)nogil: yi_vel[2] = col_normal1[2] * Vb ''' - #printdb(381) - friction1 = 1 - (((par.sys.friction + par2.sys.friction) * 0.5) * ratio1) - friction2 = 1 - (((par.sys.friction + par2.sys.friction) * 0.5) * ratio2) - damping1 = 1 - (((par.sys.collision_damp + par2.sys.collision_damp) * 0.5) * ratio1) - damping2 = 1 - (((par.sys.collision_damp + par2.sys.collision_damp) * 0.5) * ratio2) - #xpar_vel[0] *= friction - #xpar_vel[1] *= friction - #xpar_vel[2] *= friction - #xi_vel[0] *= friction - #xi_vel[1] *= friction - #xi_vel[2] *= friction - - par.vel[0] = ((ypar_vel[0] * damping1) + (yi_vel[0] * (1 - damping1))) + ((xpar_vel[0] * friction1) + ( xi_vel[0] * ( 1 - friction1))) - par.vel[1] = ((ypar_vel[1] * damping1) + (yi_vel[1] * (1 - damping1))) + ((xpar_vel[1] * friction1) + ( xi_vel[1] * ( 1 - friction1))) - par.vel[2] = ((ypar_vel[2] * damping1) + (yi_vel[2] * (1 - damping1))) + ((xpar_vel[2] * friction1) + ( xi_vel[2] * ( 1 - friction1))) - par2.vel[0] = ((yi_vel[0] * damping2) + (ypar_vel[0] * (1 - damping2))) + ((xi_vel[0] * friction2) + ( xpar_vel[0] * ( 1 - friction2))) - par2.vel[1] = ((yi_vel[1] * damping2) + (ypar_vel[1] * (1 - damping2))) + ((xi_vel[1] * friction2) + ( xpar_vel[1] * ( 1 - friction2))) - par2.vel[2] = ((yi_vel[2] * damping2) + (ypar_vel[2] * (1 - damping2))) + ((xi_vel[2] * friction2) + ( xpar_vel[2] * ( 1 - friction2))) - #printdb(396) - + friction1 = 1 - ((( + par.sys.friction + par2.sys.friction) * 0.5) * ratio1 + ) + + friction2 = 1 - ((( + par.sys.friction + par2.sys.friction) * 0.5) * ratio2 + ) + + damping1 = 1 - ((( + par.sys.collision_damp + par2.sys.collision_damp + ) * 0.5) * ratio1) + + damping2 = 1 - ((( + par.sys.collision_damp + par2.sys.collision_damp + ) * 0.5) * ratio2) + + # xpar_vel[0] *= friction + # xpar_vel[1] *= friction + # xpar_vel[2] *= friction + # xi_vel[0] *= friction + # xi_vel[1] *= friction + # xi_vel[2] *= friction + + par.vel[0] = ((ypar_vel[0] * damping1) + (yi_vel[0] * \ + (1 - damping1))) + ((xpar_vel[0] * friction1) + \ + ( xi_vel[0] * ( 1 - friction1))) + + par.vel[1] = ((ypar_vel[1] * damping1) + (yi_vel[1] * \ + (1 - damping1))) + ((xpar_vel[1] * friction1) + \ + ( xi_vel[1] * ( 1 - friction1))) + + par.vel[2] = ((ypar_vel[2] * damping1) + (yi_vel[2] * \ + (1 - damping1))) + ((xpar_vel[2] * friction1) + \ + ( xi_vel[2] * ( 1 - friction1))) + + par2.vel[0] = ((yi_vel[0] * damping2) + (ypar_vel[0] * \ + (1 - damping2))) + ((xi_vel[0] * friction2) + \ + ( xpar_vel[0] * ( 1 - friction2))) + + par2.vel[1] = ((yi_vel[1] * damping2) + (ypar_vel[1] * \ + (1 - damping2))) + ((xi_vel[1] * friction2) + \ + ( xpar_vel[1] * ( 1 - friction2))) + + par2.vel[2] = ((yi_vel[2] * damping2) + (ypar_vel[2] * \ + (1 - damping2))) + ((xi_vel[2] * friction2) + \ + ( xpar_vel[2] * ( 1 - friction2))) par2.collided_with[par2.collided_num] = par.id par2.collided_num += 1 - par2.collided_with = realloc(par2.collided_with,(par2.collided_num + 1) * cython.sizeof(int) ) - if ((par.sys.relink_chance + par2.sys.relink_chance) / 2) > 0: - #printdb(405) - create_link(par.id,par.sys.link_max * 2,par2.id) + par2.collided_with = realloc( + par2.collided_with, + (par2.collided_num + 1) * cython.sizeof(int) + ) + + if ((par.sys.relink_chance + par2.sys.relink_chance) / 2) \ + > 0: - #printdb(416) - #printdb(417) - #printdb(418) - #printdb(419) - #free(neighbours) - #free(par2) - #printdb(422) + create_link(par.id,par.sys.link_max * 2, par2.id) cdef void solve_link(Particle *par)nogil: @@ -786,10 +872,10 @@ cdef void solve_link(Particle *par)nogil: cdef float exp = 0 cdef Particle *par1 = NULL cdef Particle *par2 = NULL - cdef float *Loc1 = [0,0,0] - cdef float *Loc2 = [0,0,0] - cdef float *V1 = [0,0,0] - cdef float *V2 = [0,0,0] + cdef float *Loc1 = [0, 0, 0] + cdef float *Loc2 = [0, 0, 0] + cdef float *V1 = [0, 0, 0] + cdef float *V2 = [0, 0, 0] cdef float LengthX = 0 cdef float LengthY = 0 cdef float LengthZ = 0 @@ -803,23 +889,23 @@ cdef void solve_link(Particle *par)nogil: cdef float ForceX = 0 cdef float ForceY = 0 cdef float ForceZ = 0 - cdef float *Force1 = [0,0,0] - cdef float *Force2 = [0,0,0] + cdef float *Force1 = [0, 0, 0] + cdef float *Force2 = [0, 0, 0] cdef float ratio1 = 0 cdef float ratio2 = 0 cdef int parsearch = 0 cdef int par2search = 0 - cdef float *normal1 = [0,0,0] - cdef float *normal2 = [0,0,0] + cdef float *normal1 = [0, 0, 0] + cdef float *normal2 = [0, 0, 0] cdef float factor1 = 0 cdef float factor2 = 0 cdef float friction1 = 0 cdef float friction2 = 0 - cdef float *ypar1_vel = [0,0,0] - cdef float *xpar1_vel = [0,0,0] - cdef float *ypar2_vel = [0,0,0] - cdef float *xpar2_vel = [0,0,0] - #broken_links = [] + cdef float *ypar1_vel = [0, 0, 0] + cdef float *xpar1_vel = [0, 0, 0] + cdef float *ypar2_vel = [0, 0, 0] + cdef float *xpar2_vel = [0, 0, 0] + # broken_links = [] if par.state >= 2: return for i in xrange(par.links_num): @@ -841,7 +927,7 @@ cdef void solve_link(Particle *par)nogil: LengthX = Loc2[0] - Loc1[0] LengthY = Loc2[1] - Loc1[1] LengthZ = Loc2[2] - Loc1[2] - Length = (LengthX**2 + LengthY**2 + LengthZ**2)**(0.5) + Length = (LengthX ** 2 + LengthY ** 2 + LengthZ ** 2) ** (0.5) if par.links[i].lenght != Length and Length != 0: if par.links[i].lenght > Length: stiff = par.links[i].stiffness * deltatime @@ -854,8 +940,8 @@ cdef void solve_link(Particle *par)nogil: Vx = V2[0] - V1[0] Vy = V2[1] - V1[1] Vz = V2[2] - V1[2] - V = (Vx * LengthX + Vy * LengthY+Vz * LengthZ) / Length - ForceSpring = ((Length - par.links[i].lenght)**(exp)) * stiff + V = (Vx * LengthX + Vy * LengthY + Vz * LengthZ) / Length + ForceSpring = ((Length - par.links[i].lenght) ** (exp)) * stiff ForceDamper = damping * V ForceX = (ForceSpring + ForceDamper) * LengthX / Length ForceY = (ForceSpring + ForceDamper) * LengthY / Length @@ -874,26 +960,25 @@ cdef void solve_link(Particle *par)nogil: par2.vel[0] += Force2[0] * ratio2 par2.vel[1] += Force2[1] * ratio2 par2.vel[2] += Force2[2] * ratio2 - + normal1[0] = LengthX / Length normal1[1] = LengthY / Length normal1[2] = LengthZ / Length normal2[0] = normal1[0] * -1 normal2[1] = normal1[1] * -1 normal2[2] = normal1[2] * -1 - - factor1 = dot_product(par1.vel,normal1) - + + factor1 = dot_product(par1.vel, normal1) + ypar1_vel[0] = factor1 * normal1[0] ypar1_vel[1] = factor1 * normal1[1] ypar1_vel[2] = factor1 * normal1[2] xpar1_vel[0] = par1.vel[0] - ypar1_vel[0] xpar1_vel[1] = par1.vel[1] - ypar1_vel[1] xpar1_vel[2] = par1.vel[2] - ypar1_vel[2] - #printdb(352) - - factor2 = dot_product(par2.vel,normal2) - + + factor2 = dot_product(par2.vel, normal2) + ypar2_vel[0] = factor2 * normal2[0] ypar2_vel[1] = factor2 * normal2[1] ypar2_vel[2] = factor2 * normal2[2] @@ -901,42 +986,63 @@ cdef void solve_link(Particle *par)nogil: xpar2_vel[1] = par2.vel[1] - ypar2_vel[1] xpar2_vel[2] = par2.vel[2] - ypar2_vel[2] - - #printdb(381) friction1 = 1 - ((par.links[i].friction) * ratio1) friction2 = 1 - ((par.links[i].friction) * ratio2) - - par1.vel[0] = ypar1_vel[0] + ((xpar1_vel[0] * friction1) + ( xpar2_vel[0] * ( 1 - friction1))) - par1.vel[1] = ypar1_vel[1] + ((xpar1_vel[1] * friction1) + ( xpar2_vel[1] * ( 1 - friction1))) - par1.vel[2] = ypar1_vel[2] + ((xpar1_vel[2] * friction1) + ( xpar2_vel[2] * ( 1 - friction1))) - par2.vel[0] = ypar2_vel[0] + ((xpar2_vel[0] * friction2) + ( xpar1_vel[0] * ( 1 - friction2))) - par2.vel[1] = ypar2_vel[1] + ((xpar2_vel[1] * friction2) + ( xpar1_vel[1] * ( 1 - friction2))) - par2.vel[2] = ypar2_vel[2] + ((xpar2_vel[2] * friction2) + ( xpar1_vel[2] * ( 1 - friction2))) - #printdb(396) - - if Length > (par.links[i].lenght * (1 + par.links[i].ebroken)) or Length < (par.links[i].lenght * (1 - par.links[i].broken)): + par1.vel[0] = ypar1_vel[0] + ((xpar1_vel[0] * friction1) + \ + (xpar2_vel[0] * ( 1 - friction1))) + + par1.vel[1] = ypar1_vel[1] + ((xpar1_vel[1] * friction1) + \ + (xpar2_vel[1] * ( 1 - friction1))) + + par1.vel[2] = ypar1_vel[2] + ((xpar1_vel[2] * friction1) + \ + (xpar2_vel[2] * ( 1 - friction1))) + + par2.vel[0] = ypar2_vel[0] + ((xpar2_vel[0] * friction2) + \ + (xpar1_vel[0] * ( 1 - friction2))) + + par2.vel[1] = ypar2_vel[1] + ((xpar2_vel[1] * friction2) + \ + (xpar1_vel[1] * ( 1 - friction2))) + + par2.vel[2] = ypar2_vel[2] + ((xpar2_vel[2] * friction2) + \ + (xpar1_vel[2] * ( 1 - friction2))) + + if Length > (par.links[i].lenght * (1 + par.links[i].ebroken)) \ + or Length < (par.links[i].lenght * (1 - par.links[i].broken)): + par.links[i].start = -1 par.links_activnum -= 1 deadlinks[threadid()] += 1 - parsearch = arraysearch(par2.id,par.link_with,par.link_withnum) + + parsearch = arraysearch( + par2.id, + par.link_with, + par.link_withnum + ) + if parsearch != -1: par.link_with[parsearch] = -1 - par2search = arraysearch(par.id,par2.link_with,par2.link_withnum) + + par2search = arraysearch( + par.id, + par2.link_with, + par2.link_withnum + ) + if par2search != -1: par2.link_with[par2search] = -1 - #broken_links.append(link) - #if par2 in par1.link_with: - #par1.link_with.remove(par2) - #if par1 in par2.link_with: - #par2.link_with.remove(par1) - - #par.links = list(set(par.links) - set(broken_links)) - - #free(par1) - #free(par2) - - + + # broken_links.append(link) + # if par2 in par1.link_with: + # par1.link_with.remove(par2) + # if par1 in par2.link_with: + # par2.link_with.remove(par1) + + # par.links = list(set(par.links) - set(broken_links)) + # free(par1) + # free(par2) + + cdef void update(data): global parlist global parnum @@ -952,109 +1058,136 @@ cdef void update(data): psys[i].particles[ii].vel[0] = data[i][1][(ii * 3)] psys[i].particles[ii].vel[1] = data[i][1][(ii * 3) + 1] psys[i].particles[ii].vel[2] = data[i][1][(ii * 3) + 2] + if psys[i].particles[ii].state == 0 and data[i][2][ii] == 0: psys[i].particles[ii].state = data[i][2][ii] + 1 - #printdb(546) if psys[i].links_active == 1: - KDTree_rnn_query(kdtree,&psys[i].particles[ii],psys[i].particles[ii].loc,psys[i].particles[ii].sys.link_length) - create_link(psys[i].particles[ii].id,psys[i].link_max) - #free(psys[i].particles[ii].neighbours) + KDTree_rnn_query( + kdtree, + &psys[i].particles[ii], + psys[i].particles[ii].loc, + psys[i].particles[ii].sys.link_length + ) + create_link(psys[i].particles[ii].id, psys[i].link_max) + # free(psys[i].particles[ii].neighbours) psys[i].particles[ii].neighboursnum = 0 - #printdb(548) elif psys[i].particles[ii].state == 1 and data[i][2][ii] == 0: psys[i].particles[ii].state = 1 else: psys[i].particles[ii].state = data[i][2][ii] - psys[i].particles[ii].collided_with = realloc(psys[i].particles[ii].collided_with, 1 * cython.sizeof(int) ) + + psys[i].particles[ii].collided_with = realloc( + psys[i].particles[ii].collided_with, + 1 * cython.sizeof(int) + ) psys[i].particles[ii].collided_num = 0 - #printdb(558) - + cdef void KDTree_create_nodes(KDTree *kdtree,int parnum):#nogil: cdef int i = 0 i = 2 - #print("create nodes parnum:",parnum) while i < parnum: i = i * 2 - #print("i:",i) kdtree.numnodes = i - #print("numnodes:",kdtree.numnodes) - kdtree.nodes = malloc( (kdtree.numnodes + 1) * cython.sizeof(Node) ) - kdtree.root_node = malloc( 1 * cython.sizeof(Node) ) + kdtree.nodes = malloc((kdtree.numnodes + 1) * cython.sizeof(Node)) + kdtree.root_node = malloc(1 * cython.sizeof(Node)) + for i in xrange(kdtree.numnodes): kdtree.nodes[i].index = i kdtree.nodes[i].name = -1 kdtree.nodes[i].parent = -1 - kdtree.nodes[i].particle = malloc( 1 * cython.sizeof(SParticle) ) - kdtree.nodes[i].left_child = malloc( 1 * cython.sizeof(Node) ) - kdtree.nodes[i].right_child = malloc( 1 * cython.sizeof(Node) ) + + kdtree.nodes[i].particle = malloc( + 1 * cython.sizeof(SParticle) + ) + + kdtree.nodes[i].left_child = malloc(1 * cython.sizeof(Node)) + kdtree.nodes[i].right_child = malloc(1 * cython.sizeof(Node)) kdtree.nodes[i].left_child[0].index = -1 kdtree.nodes[i].right_child[0].index = -1 + kdtree.nodes[kdtree.numnodes].index = -1 kdtree.nodes[kdtree.numnodes].name = -1 kdtree.nodes[kdtree.numnodes].parent = -1 - kdtree.nodes[kdtree.numnodes].particle = malloc( 1 * cython.sizeof(SParticle) ) - kdtree.nodes[kdtree.numnodes].left_child = malloc( 1 * cython.sizeof(Node) ) - kdtree.nodes[kdtree.numnodes].right_child = malloc( 1 * cython.sizeof(Node) ) + + kdtree.nodes[kdtree.numnodes].particle = malloc( + 1 * cython.sizeof(SParticle) + ) + + kdtree.nodes[kdtree.numnodes].left_child = malloc( + 1 * cython.sizeof(Node) + ) + + kdtree.nodes[kdtree.numnodes].right_child = malloc( + 1 * cython.sizeof(Node) + ) + kdtree.nodes[kdtree.numnodes].left_child[0].index = -1 kdtree.nodes[kdtree.numnodes].right_child[0].index = -1 - kdtree.thread_nodes = malloc( 128 * cython.sizeof(int) ) - kdtree.thread_start = malloc( 128 * cython.sizeof(int) ) - kdtree.thread_end = malloc( 128 * cython.sizeof(int) ) - kdtree.thread_name = malloc( 128 * cython.sizeof(int) ) - kdtree.thread_parent = malloc( 128 * cython.sizeof(int) ) - kdtree.thread_depth = malloc( 128 * cython.sizeof(int) ) - #kdtree.axis = malloc( 64 * cython.sizeof(int) ) + kdtree.thread_nodes = malloc(128 * cython.sizeof(int)) + kdtree.thread_start = malloc(128 * cython.sizeof(int)) + kdtree.thread_end = malloc(128 * cython.sizeof(int)) + kdtree.thread_name = malloc(128 * cython.sizeof(int)) + kdtree.thread_parent = malloc(128 * cython.sizeof(int)) + kdtree.thread_depth = malloc(128 * cython.sizeof(int)) + # kdtree.axis = malloc( 64 * cython.sizeof(int) ) + for i in xrange(64): kdtree.axis[i] = i % 3 + return -cdef Node KDTree_create_tree(KDTree *kdtree,SParticle *kdparlist,int start,int end,int name,int parent,int depth,int initiate)nogil: +cdef Node KDTree_create_tree( + KDTree *kdtree, + SParticle *kdparlist, + int start, + int end, + int name, + int parent, + int depth, + int initiate + )nogil: + global parnum cdef int index = 0 cdef int len = (end - start) + 1 - #print("len:",len) if len <= 0: - #print("num nodes len 0",kdtree.numnodes) return kdtree.nodes[kdtree.numnodes] cdef int axis cdef int k = 3 axis = kdtree.axis[depth] - #depth % k - #printdb(590) - quick_sort(kdparlist + start,len,axis) + # depth % k + quick_sort(kdparlist + start, len, axis) ''' if axis == 0: - qsort(kdparlist + start,len,sizeof(SParticle),compare_x) + qsort(kdparlist + start, len, sizeof(SParticle), compare_x) elif axis == 1: - qsort(kdparlist + start,len,sizeof(SParticle),compare_y) + qsort(kdparlist + start, len, sizeof(SParticle), compare_y) elif axis == 2: - qsort(kdparlist + start,len,sizeof(SParticle),compare_z) + qsort(kdparlist + start, len, sizeof(SParticle), compare_z) ''' cdef int median = (start + end) / 2 - #printdb(598) + if depth == 0: - kdtree.thread_index = 0 - index = 0 + kdtree.thread_index = 0 + index = 0 else: index = (parent * 2) + name + if index > kdtree.numnodes: return kdtree.nodes[kdtree.numnodes] - #printdb(605) + kdtree.nodes[index].name = name kdtree.nodes[index].parent = parent - #printdb(607) + if len >= 1 and depth == 0: kdtree.root_node[0] = kdtree.nodes[0] - #printdb(610) - #print("index",index) - #print("num nodes",kdtree.numnodes) - #print("median",median) + kdtree.nodes[index].particle[0] = kdparlist[median] - #printdb(612) + if parnum > 127: if depth == 4 and initiate == 1: kdtree.thread_nodes[kdtree.thread_index] = index @@ -1063,86 +1196,155 @@ cdef Node KDTree_create_tree(KDTree *kdtree,SParticle *kdparlist,int start,int e kdtree.thread_name[kdtree.thread_index] = name kdtree.thread_parent[kdtree.thread_index] = parent kdtree.thread_depth[kdtree.thread_index] = depth - #print(kdtree.nodes[index].index) kdtree.thread_index += 1 return kdtree.nodes[index] - kdtree.nodes[index].left_child[0] = KDTree_create_tree(kdtree,kdparlist,start,median - 1,1,index,depth + 1,initiate) - #printdb(614) - kdtree.nodes[index].right_child[0] = KDTree_create_tree(kdtree,kdparlist,median + 1,end,2,index,depth + 1,initiate) - #printdb(616) + + kdtree.nodes[index].left_child[0] = KDTree_create_tree( + kdtree, + kdparlist, + start, + median - 1, + 1, + index, + depth + 1, + initiate + ) + kdtree.nodes[index].right_child[0] = KDTree_create_tree( + kdtree, + kdparlist, + median + 1, + end, + 2, + index, + depth + 1, + initiate + ) + return kdtree.nodes[index] -cdef int KDTree_rnn_query(KDTree *kdtree,Particle *par,float point[3],float dist)nogil: +cdef int KDTree_rnn_query( + KDTree *kdtree, + Particle *par, + float point[3], + float dist + )nogil: + global parlist cdef float sqdist = 0 cdef int k = 0 cdef int i = 0 par.neighboursnum = 0 - #printdb(639) - #free(par.neighbours) - #printdb(641) - #printdb(643) + # free(par.neighbours) par.neighbours[0] = -1 - #printdb(645) + if kdtree.root_node[0].index != kdtree.nodes[0].index: par.neighbours[0] = -1 par.neighboursnum = 0 return -1 else: sqdist = dist * dist - KDTree_rnn_search(kdtree,&par[0],kdtree.root_node[0],point,dist,sqdist,3,0) + KDTree_rnn_search( + kdtree, &par[0], + kdtree.root_node[0], + point, + dist, + sqdist, + 3, + 0 + ) #@cython.cdivision(True) -cdef void KDTree_rnn_search(KDTree *kdtree,Particle *par,Node node,float point[3],float dist,float sqdist,int k,int depth)nogil: +cdef void KDTree_rnn_search( + KDTree *kdtree, + Particle *par, + Node node, + float point[3], + float dist, + float sqdist, + int k, + int depth + )nogil: + cdef int axis = 0 cdef float realsqdist = 0 - #printdb(642) + if node.index == -1: return - + cdef SParticle tparticle = node.particle[0] - + axis = kdtree.axis[depth] - #depth % k - #printdb(649) + if (fabs(point[axis] - tparticle.loc[axis])) <= dist: - realsqdist = square_dist(point,tparticle.loc,3) - #printdb(652) + realsqdist = square_dist(point, tparticle.loc, 3) + if realsqdist <= sqdist: - #printdb(654) + par.neighbours[par.neighboursnum] = node.particle[0].id par.neighboursnum += 1 if (par.neighboursnum) >= par.neighboursmax: par.neighboursmax = par.neighboursmax * 2 - par.neighbours = realloc(par.neighbours,(par.neighboursmax) * cython.sizeof(int) ) - #printdb(658) - - #printdb(660) - KDTree_rnn_search(kdtree,&par[0],node.left_child[0],point,dist,sqdist,3,depth + 1) - #printdb(662) - KDTree_rnn_search(kdtree,&par[0],node.right_child[0],point,dist,sqdist,3,depth + 1) - #printdb(664) + par.neighbours = realloc( + par.neighbours, + (par.neighboursmax) * cython.sizeof(int) + ) + + KDTree_rnn_search( + kdtree, + &par[0], + node.left_child[0], + point, + dist, + sqdist, + 3, + depth + 1 + ) + + KDTree_rnn_search( + kdtree, + &par[0], + node.right_child[0], + point, + dist, + sqdist, + 3, + depth + 1 + ) + else: if point[axis] <= tparticle.loc[axis]: - #printdb(667) - KDTree_rnn_search(kdtree,&par[0],node.left_child[0],point,dist,sqdist,3,depth + 1) + KDTree_rnn_search( + kdtree, + &par[0], + node.left_child[0], + point, + dist, + sqdist, + 3, + depth + 1 + ) + if point[axis] >= tparticle.loc[axis]: - #printdb(670) - KDTree_rnn_search(kdtree,&par[0],node.right_child[0],point,dist,sqdist,3,depth + 1) - #printdb(672) - - -cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: - #printdb(676) + KDTree_rnn_search( + kdtree, + &par[0], + node.right_child[0], + point, + dist, + sqdist, + 3, + depth + 1 + ) + + +cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: global kdtree global parlist global parnum global newlinks - #printdb(680) - cdef Links *link = malloc( 1 * cython.sizeof(Links)) - #printdb(682) + cdef Links *link = malloc(1 * cython.sizeof(Links)) cdef int *neighbours = NULL cdef int ii = 0 cdef int neighboursnum = 0 @@ -1158,33 +1360,27 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: cdef float chancerdom = 0 cdef Particle *fakepar = NULL cdef int create_links - fakepar = malloc( 1 * cython.sizeof(Particle)) + fakepar = malloc(1 * cython.sizeof(Particle)) par = &parlist[par_id] - #printdb(693) + if par.state >= 2: return if par.links_activnum >= max_link: return if par.sys.links_active == 0: - #printdb(699) return - #printdb(705) + if parothers_id == -1: - #printdb(707) - #KDTree_rnn_query(kdtree,&fakepar[0],par.loc,par.sys.link_length) - #neighbours = fakepar[0].neighbours + # KDTree_rnn_query(kdtree, &fakepar[0], par.loc, par.sys.link_length) + # neighbours = fakepar[0].neighbours neighbours = par.neighbours neighboursnum = par.neighboursnum - #printdb(709) else: - #printdb(711) - neighbours = malloc( 1 * cython.sizeof(int)) + neighbours = malloc(1 * cython.sizeof(int)) neighbours[0] = parothers_id neighboursnum = 1 - - #printdb(714) + for ii in xrange(neighboursnum): - #printdb(720) if parothers_id == -1: par2 = &parlist[neighbours[ii]] tension = (par.sys.link_tension + par2.sys.link_tension) / 2 @@ -1192,17 +1388,20 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: par2 = &parlist[neighbours[0]] tension = (par.sys.link_tension + par2.sys.link_tension) / 2 if par.id != par2.id: - #printdb(723) - #arraysearch(par2.id,par.link_with,par.link_withnum) - #printdb(725) - if arraysearch(par.id,par2.link_with,par2.link_withnum) == -1 and par2.state <= 1 and par.state <= 1: - #if par not in par2.link_with and par2.state <= 1 and par.state <= 1: - #printdb(728) - #printdb(729) + # arraysearch(par2.id, par.link_with, par.link_withnum) + + if arraysearch(par.id,par2.link_with,par2.link_withnum) == -1 and \ + par2.state <= 1 and par.state <= 1: + + #if par not in par2.link_with and par2.state <= 1 \ + # and par.state <= 1: + link.start = par.id link.end = par2.id - #printdb(732) - link.friction = (par.sys.link_friction + par2.sys.link_friction) / 2 + + link.friction = ( + par.sys.link_friction + par2.sys.link_friction) / 2 + if parothers_id == -1 and par.sys.link_group == par2.sys.link_group: if par.sys.id != par2.sys.id: if par.sys.other_link_active and par2.sys.other_link_active: @@ -1211,6 +1410,7 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: create_links = 0 else: create_links = 1 + if create_links == 1: tensionrandom = (par.sys.link_tensionrand + par2.sys.link_tensionrand) / 2 * 2 srand(1) @@ -1222,8 +1422,8 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: srand(3) link.estiffness = ((par.sys.link_estiff + par2.sys.link_estiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) srand(4) - link.exponent = abs(int((par.sys.link_stiffexp + par2.sys.link_stiffexp) / 2))#### - link.eexponent = abs(int((par.sys.link_estiffexp + par2.sys.link_estiffexp) / 2))#### + link.exponent = abs(int((par.sys.link_stiffexp + par2.sys.link_stiffexp) / 2)) + link.eexponent = abs(int((par.sys.link_estiffexp + par2.sys.link_estiffexp) / 2)) damprandom = ((par.sys.link_damprand + par2.sys.link_damprand) / 2) * 2 link.damping = ((par.sys.link_damp + par2.sys.link_damp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) srand(5) @@ -1233,33 +1433,29 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: link.broken = ((par.sys.link_broken + par2.sys.link_broken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) srand(7) link.ebroken = ((par.sys.link_ebroken + par2.sys.link_ebroken) / 2) * ((((rand() / rand_max) * brokrandom) - (brokrandom / 2)) + 1) - #printdb(748) par.links[par.links_num] = link[0] par.links_num += 1 par.links_activnum += 1 - #printdb(752) - par.links = realloc(par.links,(par.links_num + 2) * cython.sizeof(Links) ) - - #printdb(755) + par.links = realloc(par.links,(par.links_num + 2) * cython.sizeof(Links)) + par.link_with[par.link_withnum] = par2.id par.link_withnum += 1 - #printdb(758) - par.link_with = realloc(par.link_with,(par.link_withnum + 2) * cython.sizeof(int) ) - + + par.link_with = realloc(par.link_with,(par.link_withnum + 2) * cython.sizeof(int)) + par2.link_with[par2.link_withnum] = par.id par2.link_withnum += 1 - #printdb(763) - par2.link_with = realloc(par2.link_with,(par2.link_withnum + 2) * cython.sizeof(int) ) + + par2.link_with = realloc(par2.link_with,(par2.link_withnum + 2) * cython.sizeof(int)) newlinks += 1 - #free(link) - #printdb(766) - + # free(link) + if parothers_id != -1 and par.sys.relink_group == par2.sys.relink_group: - #printdb(769) srand(8) relinkrandom = (rand() / rand_max) chancerdom = (par.sys.relink_chancerand + par2.sys.relink_chancerand) / 2 * 2 srand(9) + if relinkrandom <= ((par.sys.relink_chance + par2.sys.relink_chance) / 2) * ((((rand() / rand_max) * chancerdom) - (chancerdom / 2)) + 1): tensionrandom = (par.sys.relink_tensionrand + par2.sys.relink_tensionrand) / 2 * 2 srand(10) @@ -1271,8 +1467,8 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: srand(12) link.estiffness = ((par.sys.relink_estiff + par2.sys.relink_estiff)/2) * ((((rand() / rand_max) * stiffrandom) - (stiffrandom / 2)) + 1) srand(13) - link.exponent = abs(int((par.sys.relink_stiffexp + par2.sys.relink_stiffexp) / 2))#### - link.eexponent = abs(int((par.sys.relink_estiffexp + par2.sys.relink_estiffexp) / 2))#### + link.exponent = abs(int((par.sys.relink_stiffexp + par2.sys.relink_stiffexp) / 2)) + link.eexponent = abs(int((par.sys.relink_estiffexp + par2.sys.relink_estiffexp) / 2)) damprandom = ((par.sys.relink_damprand + par2.sys.relink_damprand) / 2) * 2 link.damping = ((par.sys.relink_damp + par2.sys.relink_damp) / 2) * ((((rand() / rand_max) * damprandom) - (damprandom / 2)) + 1) srand(14) @@ -1284,21 +1480,22 @@ cdef void create_link(int par_id, int max_link, int parothers_id = -1)nogil: par.links[par.links_num] = link[0] par.links_num += 1 par.links_activnum += 1 - par.links = realloc(par.links,(par.links_num + 1) * cython.sizeof(Links) ) + par.links = realloc(par.links,(par.links_num + 1) * cython.sizeof(Links)) par.link_with[par.link_withnum] = par2.id par.link_withnum += 1 - par.link_with = realloc(par.link_with,(par.link_withnum + 1) * cython.sizeof(int) ) + par.link_with = realloc(par.link_with,(par.link_withnum + 1) * cython.sizeof(int)) par2.link_with[par2.link_withnum] = par.id par2.link_withnum += 1 - par2.link_with = realloc(par2.link_with,(par2.link_withnum + 1) * cython.sizeof(int) ) + par2.link_with = realloc(par2.link_with,(par2.link_withnum + 1) * cython.sizeof(int)) newlinks += 1 - #free(link) - #free(neighbours) - #free(fakepar) - #free(link) - #free(par) - #free(par2) - + # free(link) + # free(neighbours) + # free(fakepar) + # free(link) + # free(par) + # free(par2) + + cdef struct Links: float lenght int start @@ -1312,13 +1509,12 @@ cdef struct Links: float edamping float ebroken float friction - - - + + cdef struct KDTree: int numnodes - #int num_result - #int *result + # int num_result + # int *result Node *root_node Node *nodes char axis[64] @@ -1339,7 +1535,7 @@ cdef struct Node: SParticle *particle Node *left_child Node *right_child - + cdef struct ParSys: int id @@ -1397,7 +1593,8 @@ cdef struct ParSys: cdef struct SParticle: int id float loc[3] - + + cdef struct Particle: int id float loc[3] @@ -1417,15 +1614,18 @@ cdef struct Particle: int neighboursnum int neighboursmax + cdef struct Pool: char axis float offset float max Parity *parity - + + cdef struct Parity: Heap *heap - + + cdef struct Heap: int *par int parnum @@ -1439,7 +1639,8 @@ cdef int compare_x (const void *u, const void *v)nogil: if w > 0: return 1 return 0 - + + cdef int compare_y (const void *u, const void *v)nogil: cdef float w = (u).loc[1] - (v).loc[1] if w < 0: @@ -1447,8 +1648,8 @@ cdef int compare_y (const void *u, const void *v)nogil: if w > 0: return 1 return 0 - - + + cdef int compare_z (const void *u, const void *v)nogil: cdef float w = (u).loc[2] - (v).loc[2] if w < 0: @@ -1456,7 +1657,8 @@ cdef int compare_z (const void *u, const void *v)nogil: if w > 0: return 1 return 0 - + + cdef int compare_id (const void *u, const void *v)nogil: cdef float w = (u).id - (v).id if w < 0: @@ -1465,23 +1667,23 @@ cdef int compare_id (const void *u, const void *v)nogil: return 1 return 0 - -cdef int arraysearch(int element,int *array,int len)nogil: + +cdef int arraysearch(int element, int *array, int len)nogil: cdef int i = 0 - #printdb(939) for i in xrange(len): if element == array[i]: return i - #printdb(943) return -1 - + + cdef float fabs(float value)nogil: if value >= 0: return value if value < 0: return -value - -cdef float sq_number(float val):# nogil: + + +cdef float sq_number(float val): cdef float nearsq = 8 while val > nearsq or val < nearsq / 2: if val > nearsq: @@ -1489,22 +1691,23 @@ cdef float sq_number(float val):# nogil: elif val < nearsq / 2: nearsq = nearsq / 2 return nearsq - -#@cython.cdivision(True) -cdef float square_dist(float point1[3],float point2[3],int k)nogil: + + +#@cython.cdivision(True) +cdef float square_dist(float point1[3], float point2[3], int k)nogil: cdef float sq_dist = 0 for i in xrange(k): sq_dist += (point1[i] - point2[i]) * (point1[i] - point2[i]) return sq_dist - + cdef float dot_product(float u[3],float v[3])nogil: cdef float dot = 0 dot = (u[0] * v[0]) + (u[1] * v[1]) + (u[2] * v[2]) return dot -cdef void quick_sort (SParticle *a, int n, int axis)nogil: +cdef void quick_sort(SParticle *a, int n, int axis)nogil: if (n < 2): return cdef SParticle t @@ -1518,14 +1721,17 @@ cdef void quick_sort (SParticle *a, int n, int axis)nogil: if r[0].loc[axis] > p: r -= 1 - continue #// we need to check the condition (l <= r) every time we change the value of l or r - + # // we need to check the condition (l <= r) every time + # we change the value of l or r + continue + t = l[0] l[0] = r[0] - #l[0], r[0] = r[0], l[0] # suggested by stephan to remove temp variable t but slower + # suggested by stephan to remove temp variable t but slower + # l[0], r[0] = r[0], l[0] l += 1 r[0] = t r -= 1 - - quick_sort(a, r - a + 1,axis) - quick_sort(l, a + n - l,axis) + + quick_sort(a, r - a + 1, axis) + quick_sort(l, a + n - l, axis) From 450c8cabdf289f79a6e1b3a17f0353329723132d Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Tue, 2 Oct 2018 21:32:17 +0400 Subject: [PATCH 020/129] clear export data --- molecular/operators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/molecular/operators.py b/molecular/operators.py index 1ed63c8..bb0cb0e 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -196,6 +196,8 @@ def modal(self, context, event): cmolcore.memfree() scene.mol_simrun = False + mol_exportdata = scene.mol_exportdata + mol_exportdata.clear() print("--------------------------------------------------Molecular Sim end") return self.cancel(context) From 8b5674a1471c882b61252de31d0ef6916c9c69d2 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 00:07:07 +0400 Subject: [PATCH 021/129] move descriptions text in module --- molecular/descriptions.py | 79 ++++++++ molecular/properties.py | 401 ++++++++++++++++++++++++++++++-------- 2 files changed, 401 insertions(+), 79 deletions(-) create mode 100644 molecular/descriptions.py diff --git a/molecular/descriptions.py b/molecular/descriptions.py new file mode 100644 index 0000000..32450a2 --- /dev/null +++ b/molecular/descriptions.py @@ -0,0 +1,79 @@ + +# Matter descriptions +MATTER_CUSTOM = 'put your parameter below' +MATTER_SAND = '1555kg per meter cu' +MATTER_WATER = '1000kg per meter cu' +MATTER_IRON = '7800kg per meter cu' + +# Properties descriptions +ACTIVE = 'Activate molecular script for this particles system' +REFRESH = 'Simple property used to refresh data in the process' + +DENSITY_ACTIVE = 'Control particle weight by density' +MATTER = 'Choose a matter preset for density' +DENSITY = 'Density of the matter kg/cube meter' + +SELF_COLLISION_ACTIVE = 'Activate self collsion between particles in the system' +OTHER_COLLISION_ACTIVE = 'Activate collision with particles from others systems' +FRICTION = 'Friction between particles at collision 0 = no friction , 1 = full friction' +COLLISION_DAMPING = 'Damping between particles at collision 0 = bouncy , 1 = no collision' +COLLISION_GROUP = 'Choose a collision group you want to collide with' + +LINKS_ACTIVE = 'Activate links between particles of this system' +LINK_OTHER_ACTIVE = '' +LINK_GROUP = '' +LINK_RELATIVE_LENGTH = 'Activate search distance relative to particles radius' +LINK_FRICTION = 'Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction' +LINK_LENGTH = 'Searching range to make a link between particles' +LINK_TENSION = 'Make link bigger or smaller than it\'s created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)' +LINK_TENSION_RANDOM = 'Tension random' +LINK_MAX = 'Maximum of links per particles' +LINK_STIFFNESS = 'Stiffness of links between particles' +LINK_STIFFNESS_RANDOM = 'Random variation for stiffness' +LINK_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +LINK_DAMPING = 'Damping effect on spring links' +LINK_DAMPING_RANDOM = 'Random variation on damping' +LINK_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +LINK_BROKEN_RANDOM = 'Give a random variation to the stretch limit' +LINK_SAME_VALUE = 'When active , expansion and compression of the spring have same value' +LINK_EXPENSION_STIFFNESS = 'Expension stiffness of links between particles' +LINK_EXPENSION_STIFFNESS_RANDOM = 'Random variation for expansion stiffness' +LINK_EXPENSION_STIFFNESS_EXPONENT = 'Give a exponent force to the expension spring links' +LINK_EXPENSION_DAMPING = 'Damping effect on expension spring links' +LINK_EXPENSION_DAMPING_RANDOM = 'Random variation on expension damping' +LINK_EXPENSION_BROKEN = 'How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +LINK_EXPENSION_BROKEN_RANDOM = 'Give a random variation to the expension stretch limit' + +RELINK_GROUP = 'Choose a group that new link are possible' +RELINK_CHANCE = 'Chance of a new link are created on collision. 0 = off , 100 = 100% of chance' +RELINK_CHANCE_RANDOM = 'Give a random variation to the chance of new link' +RELINK_TENSION = 'Make link bigger or smaller than it\'s created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)' +RELINK_TENSION_RANDOM = 'Tension random' +RELINK_MAX = 'Maximum of links per particles' +RELINK_STIFFNESS = 'Stiffness of links between particles' +RELINK_STIFFNESS_RANDOM = 'Random variation for stiffness' +RELINK_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +RELINK_DAMPING = 'Damping effect on spring links' +RELINK_DAMPING_RANDOM = 'Random variation on damping' +RELINK_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +RELINK_BROKEN_RANDOM = 'Give a random variation to the stretch limit' +RELINK_SAME_VALUE = 'When active , expansion and compression of the spring have same value' +RELINK_EXPENSION_STIFFNESS = 'Stiffness of links expension between particles' +RELINK_EXPENSION_STIFFNESS_RANDOM = 'Random variation for expension stiffness' +RELINK_EXPENSION_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +RELINK_EXPENSION_DAMPING = 'Damping effect on expension spring links' +RELINK_EXPENSION_DAMPING_RANDOM = 'Random variation on damping' +RELINK_EXPENSION_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +RELINK_EXPENSION_BROKEN_RANDOM = 'Give a random variation to the stretch limit' + +VAR_1 = 'Current number of particles to calculate substep' +VAR_2 = 'Current substep' +VAR_3 = 'Targeted number of particles you want to increase or decrease from current system to calculate substep you need to achieve similar effect' +BAKE_UV = 'Bake uv when finish' + +TIME_SCALE_ACTIVE = 'Activate TimeScaling' +TIME_SCALE = 'SpeedUp or Slow down the simulation with this multiplier' +SUBSTEP = 'mol_substep. Higher equal more stable and accurate but more slower' +BAKE = 'Bake simulation when finish' +RENDER = 'Start rendering animation when simulation is finish. WARNING: It\'s freeze blender until render is finish.' +CPU = 'Numbers of cpu\'s included for process the simulation' diff --git a/molecular/properties.py b/molecular/properties.py index eff5a48..c8aff09 100644 --- a/molecular/properties.py +++ b/molecular/properties.py @@ -3,88 +3,331 @@ import bpy +from . import descriptions + def define_props(): parset = bpy.types.ParticleSettings - parset.mol_active = bpy.props.BoolProperty(name = "mol_active", description = "Activate molecular script for this particles system",default = False) - parset.mol_refresh = bpy.props.BoolProperty(name = "mol_refresh", description = "Simple property used to refresh data in the process",default = True) - parset.mol_density_active = bpy.props.BoolProperty(name="mol_density_active", description="Control particle weight by density",default = False) - item = [("-1","custom","put your parameter below"),("1555","sand","1555kg per meter cu"),("1000","water","1000kg per meter cu"),("7800","iron","7800kg per meter cu")] - parset.mol_matter = bpy.props.EnumProperty(items = item, description = "Choose a matter preset for density") - parset.mol_density = bpy.props.FloatProperty(name = "mol_density", description = "Density of the matter kg/cube meter", default = 1000, min = 0.001) - - parset.mol_selfcollision_active = bpy.props.BoolProperty(name = "mol_selfcollision_active", description = "Activate self collsion between particles in the system",default = False) - parset.mol_othercollision_active = bpy.props.BoolProperty(name = "mol_othercollision_active", description = "Activate collision with particles from others systems",default = False) - parset.mol_friction = bpy.props.FloatProperty(name = "mol_friction", description = "Friction between particles at collision 0 = no friction , 1 = full friction",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') - parset.mol_collision_damp = bpy.props.FloatProperty(name = "mol_collision_damp", description = "Damping between particles at collision 0 = bouncy , 1 = no collision",default = 0.005 , min = 0 , max = 1, precision=6, subtype='FACTOR') - - parset.mol_collision_group = bpy.props.IntProperty(default=1, min=1, description = "Choose a collision group you want to collide with") - - parset.mol_links_active = bpy.props.BoolProperty(name = "mol_links_active", description = "Activate links between particles of this system",default = False) - parset.mol_other_link_active = bpy.props.BoolProperty(name = "mol_other_link_active", description = "",default = False) - - parset.mol_link_group = bpy.props.IntProperty(default=1, min=1, description = "") - - parset.mol_link_rellength = bpy.props.BoolProperty(name = "mol_link_rellength", description = "Activate search distance relative to particles radius",default = True) - parset.mol_link_friction = bpy.props.FloatProperty(name = "mol_link_friction", description = "Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction",min = 0,max = 1, default = 0.005, precision=6, subtype='FACTOR') - parset.mol_link_length = bpy.props.FloatProperty(name = "mol_link_length", description = "Searching range to make a link between particles",min = 0, precision = 6, default = 1) - parset.mol_link_tension = bpy.props.FloatProperty(name = "mol_link_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) - parset.mol_link_tensionrand = bpy.props.FloatProperty(name = "mol_link_tensionrand", description = "Tension random",min = 0,max = 1, precision = 6, default = 0, subtype='FACTOR') - parset.mol_link_max = bpy.props.IntProperty(name = "mol_link_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_link_stiff = bpy.props.FloatProperty(name = "mol_link_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_stiffrand = bpy.props.FloatProperty(name = "mol_link_stiffrand", description = "Random variation for stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_link_stiffexp = bpy.props.IntProperty(name = "mol_link_stiffexp", description = "Give a exponent force to the spring links", default = 1, min = 1 , max = 10) - parset.mol_link_damp = bpy.props.FloatProperty(name = "mol_link_damp", description = "Damping effect on spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_damprand = bpy.props.FloatProperty(name = "mol_link_damprand", description = "Random variation on damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_broken = bpy.props.FloatProperty(name = "mol_link_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_link_brokenrand = bpy.props.FloatProperty(name = "mol_link_brokenrand", description = "Give a random variation to the stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_link_samevalue = bpy.props.BoolProperty(name = "mol_link_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - - parset.mol_link_estiff = bpy.props.FloatProperty(name = "mol_link_estiff", description = "Expension stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_estiffrand = bpy.props.FloatProperty(name = "mol_link_estiffrand", description = "Random variation for expansion stiffness",min = 0 ,max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_link_estiffexp = bpy.props.IntProperty(name = "mol_link_estiffexp", description = "Give a exponent force to the expension spring links", default = 1, min = 1 , max = 10) - parset.mol_link_edamp = bpy.props.FloatProperty(name = "mol_link_edamp", description = "Damping effect on expension spring links",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_link_edamprand = bpy.props.FloatProperty(name = "mol_link_edamprand", description = "Random variation on expension damping",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_link_ebroken = bpy.props.FloatProperty(name = "mol_link_ebroken", description = "How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_link_ebrokenrand = bpy.props.FloatProperty(name = "mol_link_ebrokenrand", description = "Give a random variation to the expension stretch limit",min = 0 ,max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_relink_group = bpy.props.IntProperty(default=1, min=1, description = "Choose a group that new link are possible") - - parset.mol_relink_chance = bpy.props.FloatProperty(name = "mol_relink_chance", description = "Chance of a new link are created on collision. 0 = off , 100 = 100% of chance",min = 0, max = 100, default = 0, precision=6) - parset.mol_relink_chancerand = bpy.props.FloatProperty(name = "mol_relink_chancerand", description = "Give a random variation to the chance of new link", default = 0, min=0, max=1, precision=6, subtype='FACTOR') - parset.mol_relink_tension = bpy.props.FloatProperty(name = "mol_relink_tension", description = "Make link bigger or smaller than it's created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)",min = 0, precision = 6, default = 1) - parset.mol_relink_tensionrand = bpy.props.FloatProperty(name = "mol_relink_tensionrand", description = "Tension random",min = 0,max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_max = bpy.props.IntProperty(name = "mol_relink_max", description = "Maximum of links per particles",min = 0,default = 16) - parset.mol_relink_stiff = bpy.props.FloatProperty(name = "mol_relink_stiff", description = "Stiffness of links between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_stiffrand = bpy.props.FloatProperty(name = "mol_relink_stiffrand", description = "Random variation for stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_stiffexp = bpy.props.IntProperty(name = "mol_relink_stiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_damp = bpy.props.FloatProperty(name = "mol_relink_damp", description = "Damping effect on spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_damprand = bpy.props.FloatProperty(name = "mol_relink_damprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_broken = bpy.props.FloatProperty(name = "mol_relink_broken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_relink_brokenrand = bpy.props.FloatProperty(name = "mol_relink_brokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_relink_samevalue = bpy.props.BoolProperty(name = "mol_relink_samevalue", description = "When active , expansion and compression of the spring have same value",default = True) - - parset.mol_relink_estiff = bpy.props.FloatProperty(name = "mol_relink_estiff", description = "Stiffness of links expension between particles",min = 0,max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_estiffrand = bpy.props.FloatProperty(name = "mol_relink_estiffrand", description = "Random variation for expension stiffness",min = 0, max = 1 ,default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_estiffexp = bpy.props.IntProperty(name = "mol_relink_estiffexp", description = "Give a exponent force to the spring links",min = 1, max = 10, default = 1) - parset.mol_relink_edamp = bpy.props.FloatProperty(name = "mol_relink_edamp", description = "Damping effect on expension spring links",min = 0, max = 1, default = 1, precision=6, subtype='FACTOR') - parset.mol_relink_edamprand = bpy.props.FloatProperty(name = "mol_relink_deamprand", description = "Random variation on damping",min = 0 , max = 1, default = 0, precision=6, subtype='FACTOR') - parset.mol_relink_ebroken = bpy.props.FloatProperty(name = "mol_relink_ebroken", description = "How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...",min = 0, default = 0.5, precision = 6) - parset.mol_relink_ebrokenrand = bpy.props.FloatProperty(name = "mol_relink_ebrokenrand", description = "Give a random variation to the stretch limit",min = 0, max = 1, default = 0, precision=6, subtype='FACTOR') - - parset.mol_var1 = bpy.props.IntProperty(name = "mol_var1", description = "Current number of particles to calculate substep",min = 1, default = 1000) - parset.mol_var2 = bpy.props.IntProperty(name = "mol_var2", description = "Current substep",min = 1, default = 4) - parset.mol_var3 = bpy.props.IntProperty(name = "mol_var3", description = "Targeted number of particles you want to increase or decrease from current system to calculate substep you need to achieve similar effect",min = 1, default = 1000) - parset.mol_bakeuv = bpy.props.BoolProperty(name = "mol_bakeuv", description = "Bake uv when finish",default = False) - - bpy.types.Scene.mol_timescale_active = bpy.props.BoolProperty(name = "mol_timescale_active", description = "Activate TimeScaling",default = False) - bpy.types.Scene.timescale = bpy.props.FloatProperty(name = "timescale", description = "SpeedUp or Slow down the simulation with this multiplier", default = 1) - bpy.types.Scene.mol_substep = bpy.props.IntProperty(name = "mol_substep", description = "mol_substep. Higher equal more stable and accurate but more slower",min = 0, max = 900, default = 4) - bpy.types.Scene.mol_bake = bpy.props.BoolProperty(name = "mol_bake", description = "Bake simulation when finish",default = True) - bpy.types.Scene.mol_render = bpy.props.BoolProperty(name = "mol_render", description = "Start rendering animation when simulation is finish. WARNING: It's freeze blender until render is finish.",default = False) - bpy.types.Scene.mol_cpu = bpy.props.IntProperty(name = "mol_cpu", description = "Numbers of cpu's included for process the simulation", default = multiprocessing.cpu_count(),min = 1,max =multiprocessing.cpu_count()) + + parset.mol_active = bpy.props.BoolProperty( + name="mol_active", description=descriptions.ACTIVE, default=False + ) + parset.mol_refresh = bpy.props.BoolProperty( + name="mol_refresh", description=descriptions.REFRESH, default=True + ) + parset.mol_density_active = bpy.props.BoolProperty( + name="mol_density_active", description=descriptions.DENSITY_ACTIVE, + default=False + ) + + matter_items = [ + ("-1", "custom", descriptions.MATTER_CUSTOM), + ("1555", "sand", descriptions.MATTER_SAND), + ("1000", "water", descriptions.MATTER_WATER), + ("7800", "iron", descriptions.MATTER_IRON) + ] + + parset.mol_matter = bpy.props.EnumProperty( + items=matter_items, description=descriptions.MATTER + ) + parset.mol_density = bpy.props.FloatProperty( + name="mol_density", description=descriptions.DENSITY, + default=1000, min=0.001 + ) + + parset.mol_selfcollision_active = bpy.props.BoolProperty( + name="mol_selfcollision_active", + description=descriptions.SELF_COLLISION_ACTIVE, + default=False + ) + parset.mol_othercollision_active = bpy.props.BoolProperty( + name="mol_othercollision_active", + description=descriptions.OTHER_COLLISION_ACTIVE, + default=False + ) + parset.mol_friction = bpy.props.FloatProperty( + name="mol_friction", description=descriptions.FRICTION, + default=0.005, min=0, max=1, precision=6, subtype='FACTOR' + ) + parset.mol_collision_damp = bpy.props.FloatProperty( + name="mol_collision_damp", description=descriptions.COLLISION_DAMPING, + default=0.005, min=0, max=1, precision=6, subtype='FACTOR' + ) + + parset.mol_collision_group = bpy.props.IntProperty( + default=1, min=1, description=descriptions.COLLISION_GROUP + ) + + parset.mol_links_active = bpy.props.BoolProperty( + name="mol_links_active", description=descriptions.LINKS_ACTIVE, + default=False + ) + parset.mol_other_link_active = bpy.props.BoolProperty( + name="mol_other_link_active", + description=descriptions.LINK_OTHER_ACTIVE, default=False + ) + + parset.mol_link_group = bpy.props.IntProperty( + default=1, min=1, description=descriptions.LINK_GROUP + ) + + parset.mol_link_rellength = bpy.props.BoolProperty( + name="mol_link_rellength", + description=descriptions.LINK_RELATIVE_LENGTH, + default=True + ) + parset.mol_link_friction = bpy.props.FloatProperty( + name="mol_link_friction", description=descriptions.LINK_FRICTION, + min=0, max=1, default=0.005, precision=6, subtype='FACTOR' + ) + parset.mol_link_length = bpy.props.FloatProperty( + name="mol_link_length", description=descriptions.LINK_LENGTH, + min=0, precision=6, default=1 + ) + parset.mol_link_tension = bpy.props.FloatProperty( + name="mol_link_tension", description=descriptions.LINK_TENSION, + min=0, precision=6, default=1 + ) + parset.mol_link_tensionrand = bpy.props.FloatProperty( + name="mol_link_tensionrand", + description=descriptions.LINK_TENSION_RANDOM, + min=0, max=1, precision=6, default=0, subtype='FACTOR' + ) + parset.mol_link_max = bpy.props.IntProperty( + name="mol_link_max", description=descriptions.LINK_MAX, + min=0, default=16 + ) + parset.mol_link_stiff = bpy.props.FloatProperty( + name="mol_link_stiff", description=descriptions.LINK_STIFFNESS, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_link_stiffrand = bpy.props.FloatProperty( + name="mol_link_stiffrand", + description = descriptions.LINK_STIFFNESS_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_link_stiffexp = bpy.props.IntProperty( + name="mol_link_stiffexp", + description=descriptions.LINK_STIFFNESS_EXPONENT, + default=1, min=1, max=10 + ) + parset.mol_link_damp = bpy.props.FloatProperty( + name="mol_link_damp", description=descriptions.LINK_DAMPING, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_link_damprand = bpy.props.FloatProperty( + name="mol_link_damprand", description=descriptions.LINK_DAMPING_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_link_broken = bpy.props.FloatProperty( + name="mol_link_broken", description=descriptions.LINK_BROKEN, + min=0, default=0.5, precision=6 + ) + parset.mol_link_brokenrand = bpy.props.FloatProperty( + name="mol_link_brokenrand", + description=descriptions.LINK_BROKEN_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + + parset.mol_link_samevalue = bpy.props.BoolProperty( + name="mol_link_samevalue", description=descriptions.LINK_SAME_VALUE, + default=True + ) + + parset.mol_link_estiff = bpy.props.FloatProperty( + name="mol_link_estiff", + description=descriptions.LINK_EXPENSION_STIFFNESS, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_link_estiffrand = bpy.props.FloatProperty( + name="mol_link_estiffrand", + description=descriptions.LINK_EXPENSION_STIFFNESS_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_link_estiffexp = bpy.props.IntProperty( + name="mol_link_estiffexp", + description=descriptions.LINK_EXPENSION_STIFFNESS_EXPONENT, + default=1, min=1, max=10 + ) + parset.mol_link_edamp = bpy.props.FloatProperty( + name="mol_link_edamp", description=descriptions.LINK_EXPENSION_DAMPING, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_link_edamprand = bpy.props.FloatProperty( + name="mol_link_edamprand", + description=descriptions.LINK_EXPENSION_DAMPING_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_link_ebroken = bpy.props.FloatProperty( + name="mol_link_ebroken", + description=descriptions.LINK_EXPENSION_BROKEN, + min=0, default=0.5, precision=6 + ) + parset.mol_link_ebrokenrand = bpy.props.FloatProperty( + name="mol_link_ebrokenrand", + description=descriptions.LINK_EXPENSION_BROKEN_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + + parset.mol_relink_group = bpy.props.IntProperty( + default=1, min=1, description=descriptions.RELINK_GROUP + ) + + parset.mol_relink_chance = bpy.props.FloatProperty( + name="mol_relink_chance", + description=descriptions.RELINK_CHANCE, + min=0, max=100, default=0, precision=6 + ) + parset.mol_relink_chancerand = bpy.props.FloatProperty( + name="mol_relink_chancerand", + description=descriptions.RELINK_CHANCE_RANDOM, + default=0, min=0, max=1, precision=6, subtype='FACTOR' + ) + parset.mol_relink_tension = bpy.props.FloatProperty( + name="mol_relink_tension", + description=descriptions.RELINK_TENSION, + min=0, precision=6, default=1 + ) + parset.mol_relink_tensionrand = bpy.props.FloatProperty( + name="mol_relink_tensionrand", + description=descriptions.RELINK_TENSION_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_relink_max = bpy.props.IntProperty( + name="mol_relink_max", + description=descriptions.RELINK_MAX, + min=0, default=16 + ) + parset.mol_relink_stiff = bpy.props.FloatProperty( + name="mol_relink_stiff", + description=descriptions.RELINK_STIFFNESS, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_relink_stiffrand = bpy.props.FloatProperty( + name="mol_relink_stiffrand", + description=descriptions.RELINK_STIFFNESS_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_relink_stiffexp = bpy.props.IntProperty( + name="mol_relink_stiffexp", + description=descriptions.RELINK_STIFFNESS_EXPONENT, + min=1, max=10, default=1 + ) + parset.mol_relink_damp = bpy.props.FloatProperty( + name="mol_relink_damp", + description=descriptions.RELINK_DAMPING, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_relink_damprand = bpy.props.FloatProperty( + name="mol_relink_damprand", + description=descriptions.RELINK_DAMPING_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_relink_broken = bpy.props.FloatProperty( + name="mol_relink_broken", + description=descriptions.RELINK_BROKEN, + min=0, default=0.5, precision=6 + ) + parset.mol_relink_brokenrand = bpy.props.FloatProperty( + name="mol_relink_brokenrand", + description=descriptions.RELINK_BROKEN_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + + parset.mol_relink_samevalue = bpy.props.BoolProperty( + name="mol_relink_samevalue", + description=descriptions.RELINK_SAME_VALUE, + default=True + ) + + parset.mol_relink_estiff = bpy.props.FloatProperty( + name="mol_relink_estiff", + description=descriptions.RELINK_EXPENSION_STIFFNESS, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_relink_estiffrand = bpy.props.FloatProperty( + name="mol_relink_estiffrand", + description=descriptions.RELINK_EXPENSION_STIFFNESS_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_relink_estiffexp = bpy.props.IntProperty( + name="mol_relink_estiffexp", + description=descriptions.RELINK_EXPENSION_STIFFNESS_EXPONENT, + min=1, max=10, default=1 + ) + parset.mol_relink_edamp = bpy.props.FloatProperty( + name="mol_relink_edamp", + description=descriptions.RELINK_EXPENSION_DAMPING, + min=0, max=1, default=1, precision=6, subtype='FACTOR' + ) + parset.mol_relink_edamprand = bpy.props.FloatProperty( + name="mol_relink_deamprand", + description=descriptions.RELINK_EXPENSION_DAMPING_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + parset.mol_relink_ebroken = bpy.props.FloatProperty( + name="mol_relink_ebroken", + description=descriptions.RELINK_EXPENSION_BROKEN, + min=0, default=0.5, precision=6 + ) + parset.mol_relink_ebrokenrand = bpy.props.FloatProperty( + name="mol_relink_ebrokenrand", + description=descriptions.RELINK_EXPENSION_BROKEN_RANDOM, + min=0, max=1, default=0, precision=6, subtype='FACTOR' + ) + + parset.mol_var1 = bpy.props.IntProperty( + name="mol_var1", + description=descriptions.VAR_1, + min=1, default=1000 + ) + parset.mol_var2 = bpy.props.IntProperty( + name="mol_var2", + description=descriptions.VAR_2, + min=1, default=4 + ) + parset.mol_var3=bpy.props.IntProperty( + name="mol_var3", + description=descriptions.VAR_3, + min=1, default=1000 + ) + parset.mol_bakeuv = bpy.props.BoolProperty( + name="mol_bakeuv", + description=descriptions.BAKE_UV, + default=False + ) + + bpy.types.Scene.mol_timescale_active = bpy.props.BoolProperty( + name="mol_timescale_active", + description=descriptions.TIME_SCALE_ACTIVE, + default=False + ) + bpy.types.Scene.timescale = bpy.props.FloatProperty( + name="timescale", + description=descriptions.TIME_SCALE, + default=1 + ) + bpy.types.Scene.mol_substep = bpy.props.IntProperty( + name="mol_substep", + description=descriptions.SUBSTEP, + min=0, max=900, default=4 + ) + bpy.types.Scene.mol_bake = bpy.props.BoolProperty( + name="mol_bake", + description=descriptions.BAKE, + default=True + ) + bpy.types.Scene.mol_render = bpy.props.BoolProperty( + name="mol_render", + description=descriptions.RENDER, + default=False + ) + bpy.types.Scene.mol_cpu = bpy.props.IntProperty( + name="mol_cpu", + description=descriptions.CPU, + default=multiprocessing.cpu_count(), + min=1, max =multiprocessing.cpu_count() + ) bpy.types.Scene.mol_exportdata = [] bpy.types.Scene.mol_minsize = bpy.props.FloatProperty() From a675c9c8217112a8ed76923b940bb85334a9a722 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 00:41:04 +0400 Subject: [PATCH 022/129] ui: PEP8 refactor --- molecular/ui.py | 587 ++++++++++++++++++++++++++++-------------------- 1 file changed, 341 insertions(+), 246 deletions(-) diff --git a/molecular/ui.py b/molecular/ui.py index 42edcae..062cb13 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -4,7 +4,7 @@ class MolecularPanel(bpy.types.Panel): """Creates a Panel in the Object properties window""" - bl_label = "Molecular script" + bl_label = "Molecular Script" bl_idname = "OBJECT_PT_molecular" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -19,264 +19,359 @@ def draw_header(self, context): obj = context.object psys = obj.particle_systems.active row = layout.row() - if psys != None: - row.prop(psys.settings,"mol_active", text = "") + if not psys is None: + row.prop(psys.settings, "mol_active", text='') def draw(self, context): layout = self.layout scn = bpy.context.scene obj = context.object psys = obj.particle_systems.active - if psys != None: - layout.enabled = psys.settings.mol_active - row = layout.row() - row.label(text = "Density:") - box = layout.box() - box.prop(psys.settings,"mol_density_active", text = "Calculate particles weight by density") - subbox = box.box() - subbox.enabled = psys.settings.mol_density_active - row = subbox.row() - row.prop(psys.settings,"mol_matter",text = "Preset:") - row = subbox.row() - if int(psys.settings.mol_matter) == 0: - row.enabled = True - elif int(psys.settings.mol_matter) >= 1: - row.enabled = False - row.prop(psys.settings, "mol_density", text = "Kg per CubeMeter:") - #subsubbox = subbox.box() - #row = subsubbox.row() - #row.label(text = "Particle info:") - #row = subsubbox.row() - #row.label(icon = "INFO",text = "size: " + str(round(psys.settings.particle_size,5)) + " m") - #row.label(icon = "INFO",text = "volume: " + str(round(psys.settings.particle_size**3,5)) + " m3") - #row = subsubbox.row() - pmass = (psys.settings.particle_size**3) * psys.settings.mol_density - #row.label(icon = "INFO",text = "mass: " + str(round(pmass,5)) + " kg") - row = subbox.row() - row.label(icon = "INFO",text = "Total system approx weight: " + str(round(len(psys.particles) * pmass,4)) + " kg") - row = layout.row() - row.label(text = "Collision:") - box = layout.box() - box.prop(psys.settings,"mol_selfcollision_active", text = "Activate Self Collision") - box.prop(psys.settings,"mol_othercollision_active", text = "Activate Collision with others") - box.prop(psys.settings,"mol_collision_group",text = " Collide only with:") - box.prop(psys.settings,"mol_friction",text = " Friction:") - box.prop(psys.settings,"mol_collision_damp",text = " Damping:") + if psys is None: + return + layout.enabled = psys.settings.mol_active + row = layout.row() + row.label(text = "Density:") + box = layout.box() + box.prop( + psys.settings, + "mol_density_active", + text="Calculate particles weight by density" + ) + subbox = box.box() + subbox.enabled = psys.settings.mol_density_active + row = subbox.row() + row.prop(psys.settings, "mol_matter", text="Preset:") + row = subbox.row() - row = layout.row() - row.label(text = "Links:") - box = layout.box() - box.prop(psys.settings,"mol_links_active", text = "Activate Particles linking") - box.prop(psys.settings,"mol_other_link_active", text = "Activate Particles linking with Others") - box.prop(psys.settings,"mol_link_group",text = " Linking only with:") + if int(psys.settings.mol_matter) == 0: + row.enabled = True + elif int(psys.settings.mol_matter) >= 1: + row.enabled = False - subbox = box.box() - subbox.enabled = psys.settings.mol_links_active - subbox.label(text = "Initial Linking (at birth):") - row = subbox.row() - row.prop(psys.settings,"mol_link_length",text = "search length") - row.prop(psys.settings,"mol_link_rellength",text = "Relative") - row = subbox.row() - row.prop(psys.settings,"mol_link_max",text = "Max links") - row = subbox.row() - row.prop(psys.settings,"mol_link_friction",text = "Link friction") - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_link_tension",text = "Tension") - row.prop(psys.settings,"mol_link_tensionrand",text = "Rand Tension") - row = subbox.row() - row.prop(psys.settings,"mol_link_stiff",text = "Stiff") - row.prop(psys.settings,"mol_link_stiffrand",text = "Rand Stiff") - #row = subbox.row() - #row.prop(psys.settings,"mol_link_stiffexp",text = "Exponent") - #row.label(text = "") - row = subbox.row() - row.prop(psys.settings,"mol_link_damp",text = "Damping") - row.prop(psys.settings,"mol_link_damprand",text = "Rand Damping") - row = subbox.row() - row.prop(psys.settings,"mol_link_broken",text = "broken") - row.prop(psys.settings,"mol_link_brokenrand",text = "Rand Broken") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_link_samevalue", text = "Same values for compression/expansion") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_estiff",text = "E Stiff") - row.prop(psys.settings,"mol_link_estiffrand",text = "Rand E Stiff") - #row = subbox.row() - #row.enabled = not psys.settings.mol_link_samevalue - #row.prop(psys.settings,"mol_link_estiffexp",text = "E Exponent") - #row.label(text = "") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_edamp",text = "E Damping") - row.prop(psys.settings,"mol_link_edamprand",text = "Rand E Damping") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings,"mol_link_ebroken",text = "E broken") - row.prop(psys.settings,"mol_link_ebrokenrand",text = "Rand E Broken") + row.prop(psys.settings, "mol_density", text = "Kg per CubeMeter:") + pmass = (psys.settings.particle_size ** 3) * psys.settings.mol_density + row = subbox.row() + weight_text = "Total system approx weight: {0:.4} kg".format( + len(psys.particles) * pmass + ) + row.label(icon ="INFO", text=weight_text) + row = layout.row() + row.label(text = "Collision:") + box = layout.box() + box.prop( + psys.settings, + "mol_selfcollision_active", + text="Activate Self Collision" + ) + box.prop( + psys.settings, + "mol_othercollision_active", + text="Activate Collision with others" + ) + box.prop( + psys.settings, + "mol_collision_group", + text="Collide only with:" + ) + box.prop( + psys.settings, + "mol_friction", + text="Friction:" + ) + box.prop( + psys.settings, + "mol_collision_damp", + text = "Damping:" + ) - subbox = box.box() - subbox.active = psys.settings.mol_links_active - subbox.label(text = "New Linking (at collision):") - row = subbox.row() - row.prop(psys.settings,"mol_relink_group",text = "Only links with:") - row = subbox.row() - row.prop(psys.settings,"mol_relink_chance",text = "% linking") - row.prop(psys.settings,"mol_relink_chancerand",text = "Rand % linking") - row = subbox.row() - row.prop(psys.settings,"mol_relink_max",text = "Max links") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_relink_tension",text = "Tension") - row.prop(psys.settings,"mol_relink_tensionrand",text = "Rand Tension") - row = subbox.row() - row.prop(psys.settings,"mol_relink_stiff",text = "Stiff") - row.prop(psys.settings,"mol_relink_stiffrand",text = "Rand Stiff") - #row = subbox.row() - #row.prop(psys.settings,"mol_relink_stiffexp",text = "Exp") - #row.label(text = "") - row = subbox.row() - row.prop(psys.settings,"mol_relink_damp",text = "Damping") - row.prop(psys.settings,"mol_relink_damprand",text = "Rand Damping") - row = subbox.row() - row.prop(psys.settings,"mol_relink_broken",text = "broken") - row.prop(psys.settings,"mol_relink_brokenrand",text = "Rand broken") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop(psys.settings,"mol_relink_samevalue", text = "Same values for compression/expansion") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_estiff",text = "E Stiff") - row.prop(psys.settings,"mol_relink_estiffrand",text = "Rand E Stiff") - #row = subbox.row() - #row.enabled = not psys.settings.mol_relink_samevalue - #row.prop(psys.settings,"mol_relink_estiffexp",text = "Exp") - #row.label(text = "") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_edamp",text = "E Damping") - row.prop(psys.settings,"mol_relink_edamprand",text = "Rand E Damping") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings,"mol_relink_ebroken",text = "E broken") - row.prop(psys.settings,"mol_relink_ebrokenrand",text = "Rand E broken") + row = layout.row() + row.label(text="Links:") + box = layout.box() + box.prop( + psys.settings, + "mol_links_active", + text="Activate Particles linking" + ) + box.prop( + psys.settings, + "mol_other_link_active", + text="Activate Particles linking with Others" + ) + box.prop( + psys.settings, + "mol_link_group", + text="Linking only with:" + ) - row = layout.row() - row.label(text = "UV's:") - box = layout.box() - row = box.row() - if obj.data.uv_layers.active != None: - row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: " + str(obj.data.uv_textures.active.name) + ")" ) - else: - row.active = False - row.prop(psys.settings,"mol_bakeuv",text = "Bake UV at ending (current: None)" ) + subbox = box.box() + subbox.enabled = psys.settings.mol_links_active + subbox.label(text="Initial Linking (at birth):") + row = subbox.row() + row.prop(psys.settings, "mol_link_length", text="search length") + row.prop(psys.settings, "mol_link_rellength", text="Relative") + row = subbox.row() + row.prop(psys.settings, "mol_link_max", text="Max links") + row = subbox.row() + row.prop(psys.settings, "mol_link_friction", text="Link friction") + layout.separator() + row = subbox.row() + row.prop(psys.settings, "mol_link_tension", text="Tension") + row.prop(psys.settings, "mol_link_tensionrand", text="Rand Tension") + row = subbox.row() + row.prop(psys.settings, "mol_link_stiff", text="Stiff") + row.prop(psys.settings, "mol_link_stiffrand", text="Rand Stiff") + #row = subbox.row() + #row.prop(psys.settings, "mol_link_stiffexp", text="Exponent") + row = subbox.row() + row.prop(psys.settings, "mol_link_damp", text="Damping") + row.prop(psys.settings, "mol_link_damprand", text="Rand Damping") + row = subbox.row() + row.prop(psys.settings, "mol_link_broken", text="broken") + row.prop(psys.settings, "mol_link_brokenrand", text="Rand Broken") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop( + psys.settings, + "mol_link_samevalue", + text="Same values for compression/expansion" + ) + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_estiff", text="E Stiff") + row.prop(psys.settings, "mol_link_estiffrand", text="Rand E Stiff") + #row = subbox.row() + #row.enabled = not psys.settings.mol_link_samevalue + #row.prop(psys.settings, "mol_link_estiffexp", text="E Exponent") + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_edamp", text="E Damping") + row.prop(psys.settings, "mol_link_edamprand", text="Rand E Damping") + row = subbox.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_ebroken", text="E broken") + row.prop(psys.settings, "mol_link_ebrokenrand", text="Rand E Broken") + subbox = box.box() + subbox.active = psys.settings.mol_links_active + subbox.label(text="New Linking (at collision):") + row = subbox.row() + row.prop(psys.settings, "mol_relink_group", text="Only links with:") + row = subbox.row() + row.prop(psys.settings, "mol_relink_chance", text="% linking") + row.prop(psys.settings, "mol_relink_chancerand", text="Rand % linking") + row = subbox.row() + row.prop(psys.settings, "mol_relink_max", text="Max links") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop(psys.settings,"mol_relink_tension",text = "Tension") + row.prop(psys.settings,"mol_relink_tensionrand",text = "Rand Tension") + row = subbox.row() + row.prop(psys.settings,"mol_relink_stiff",text = "Stiff") + row.prop(psys.settings,"mol_relink_stiffrand",text = "Rand Stiff") + #row = subbox.row() + #row.prop(psys.settings, "mol_relink_stiffexp", text="Exp") + row = subbox.row() + row.prop(psys.settings, "mol_relink_damp", text="Damping") + row.prop(psys.settings, "mol_relink_damprand", text="Rand Damping") + row = subbox.row() + row.prop(psys.settings, "mol_relink_broken", text="broken") + row.prop(psys.settings, "mol_relink_brokenrand", text="Rand broken") + row = subbox.row() + layout.separator() + row = subbox.row() + row.prop( + psys.settings, + "mol_relink_samevalue", + text="Same values for compression/expansion" + ) + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings, "mol_relink_estiff",text="E Stiff") + row.prop(psys.settings, "mol_relink_estiffrand",text="Rand E Stiff") + #row = subbox.row() + #row.enabled = not psys.settings.mol_relink_samevalue + #row.prop(psys.settings, "mol_relink_estiffexp", text="Exp") + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings, "mol_relink_edamp", text="E Damping") + row.prop(psys.settings, "mol_relink_edamprand", text="Rand E Damping") + row = subbox.row() + row.enabled = not psys.settings.mol_relink_samevalue + row.prop(psys.settings, "mol_relink_ebroken", text="E broken") + row.prop(psys.settings, "mol_relink_ebrokenrand", text="Rand E broken") + + row = layout.row() + row.label(text="UV's:") + box = layout.box() + row = box.row() + + if obj.data.uv_layers.active != None: + row.prop( + psys.settings, + "mol_bakeuv", + text="Bake UV at ending (current: \"{0}\")".format( + obj.data.uv_textures.active.name + ) + ) + else: + row.active = False + row.prop( + psys.settings, + "mol_bakeuv", + text="Bake UV at ending (current: None)" + ) + + row = layout.row() + row.label(text='') + row = layout.row() + row.label(text="Simulate") + row = layout.row() + row.prop(scn, "frame_start", text="Start Frame") + row.prop(scn, "frame_end", text="End Frame") + #row = layout.row() + #row.prop(scn,"mol_timescale_active",text = "Activate TimeScaling") + #row = layout.row() + #row.enabled = scn.mol_timescale_active + #row.prop(scn,"timescale",text = "TimeScale") + row = layout.row() + row.prop(scn, "mol_substep", text="Substeps") + row.label(text='') + row = layout.row() + row.label(text = "CPU used:") + row.prop(scn, "mol_cpu", text="CPU") + row = layout.row() + row.prop(scn, "mol_bake", text="Bake all at ending") + row.prop(scn, "mol_render", text="Render at ending") + row = layout.row() + + if scn.mol_simrun == False and psys.point_cache.is_baked == False: + row.enabled = True + row.operator( + "object.mol_simulate", + icon='RADIO', + text="Start Molecular Simulation" + ) row = layout.row() - row.label(text = "") - row = layout.row() - row.label(text = "Simulate") - row = layout.row() - row.prop(scn,"frame_start",text = "Start Frame") - row.prop(scn,"frame_end",text = "End Frame") - #row = layout.row() - #row.prop(scn,"mol_timescale_active",text = "Activate TimeScaling") - #row = layout.row() - #row.enabled = scn.mol_timescale_active - #row.prop(scn,"timescale",text = "TimeScale") - #row.label(text = "") - row = layout.row() - row.prop(scn,"mol_substep",text = "mol_substep") - row.label(text = "") - row = layout.row() - row.label(text = "CPU used:") - row.prop(scn,"mol_cpu",text = "CPU") + row.enabled = False + row.operator("ptcache.free_bake_all", text="Free All Bakes") + + if psys.point_cache.is_baked == True and scn.mol_simrun == False: + row.enabled = False + row.operator( + "object.mol_simulate", + icon = 'RADIO', + text="Simulation baked" + ) row = layout.row() - row.prop(scn,"mol_bake",text = "Bake all at ending") - row.prop(scn,"mol_render",text = "Render at ending") + row.enabled = True + row.operator("ptcache.free_bake_all", text="Free All Bakes") + + if scn.mol_simrun == True: + row.enabled = False + row.operator( + "object.mol_simulate", + icon = 'RADIO', + text="Process: {} left".format(scn.mol_timeremain) + ) row = layout.row() - if scn.mol_simrun == False and psys.point_cache.is_baked == False: - row.enabled = True - row.operator("object.mol_simulate",icon = 'RADIO',text = "Start Molecular Simulation") - row = layout.row() - row.enabled = False - row.operator("ptcache.free_bake_all", text="Free All Bakes") - if psys.point_cache.is_baked == True and scn.mol_simrun == False: - row.enabled = False - row.operator("object.mol_simulate",icon = 'RADIO',text = "Simulation baked") - row = layout.row() - row.enabled = True - row.operator("ptcache.free_bake_all", text="Free All Bakes") - if scn.mol_simrun == True: - row.enabled = False - row.operator("object.mol_simulate",icon = 'RADIO',text = "Process: " + scn.mol_timeremain + " left") - row = layout.row() - row.enabled = False - row.operator("ptcache.free_bake_all", text="Free All Bakes") + row.enabled = False + row.operator("ptcache.free_bake_all", text="Free All Bakes") + + box = layout.box() + row = box.row() + box.enabled = True + row.label(text="Molecular Tools:", icon='MODIFIER') + subbox = box.box() + row = subbox.row() + row.label(text="Particle UV:") + row = subbox.row() + row.alignment = 'CENTER' + row.label(icon='INFO', text="Set current particles position") + row = subbox.row() + row.alignment = 'CENTER' + row.label(text="Has global or current uv in angular velocity") + row = subbox.row() + row.alignment = 'CENTER' + row.label(text="Retrieve it with Cycles particle info node") + row = subbox.row() + row.operator( + "object.mol_set_global_uv", + icon='GROUP_UVS', + text="Set Global UV" + ) + row = subbox.row() + + if obj.data.uv_layers.active != None: + row.operator( + "object.mol_set_active_uv", + icon='GROUP_UVS', + text = "Set Active UV (current: \"{0}\")".format( + obj.data.uv_textures.active.name + ) + ) + else: + row.active = False + row.operator( + "object.mol_set_active_uv", + icon='GROUP_UVS', + text="Set Active UV ( no uvs found)" + ) - box = layout.box() - row = box.row() - box.enabled = True - row.label(text = "Molecular Tools:",icon = 'MODIFIER') - subbox = box.box() - row = subbox.row() - row.label(text = "Particle UV:") - row = subbox.row() - row.alignment = 'CENTER' - row.label(icon = 'INFO',text = "Set current particles position ") - row = subbox.row() - row.alignment = 'CENTER' - row.label(text = "has global or current uv in angular velocity.") - row = subbox.row() - row.alignment = 'CENTER' - row.label(text = " Retrieve it with Cycles particle info node") - row = subbox.row() - row.operator("object.mol_set_global_uv",icon = 'GROUP_UVS',text = "Set Global UV") - row = subbox.row() - if obj.data.uv_layers.active != None: - row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV (current: " + str(obj.data.uv_textures.active.name) + ")" ) - else: - row.active = False - row.operator("object.mol_set_active_uv",icon = 'GROUP_UVS',text = "Set Active UV ( no uvs found)") - subbox = box.box() - row = subbox.row() - row.label(text = "SUBSTEPS CALCULATOR:") - row = subbox.row() - row.label(icon = 'INFO',text = "Current systems have: " + str(len(psys.particles)) + " particles") - row = subbox.row() - row.prop(psys.settings,"mol_var1",text = "Current numbers of particles") - row = subbox.row() - row.prop(psys.settings,"mol_var2",text = "Current substep") - row = subbox.row() - row.prop(psys.settings,"mol_var3",text = "Targeted numbers of particles") - diff = (psys.settings.mol_var3 / psys.settings.mol_var1) - factor = (psys.settings.mol_var3**(1/3) / psys.settings.mol_var1**(1/3)) - newsubstep = int(round(factor * psys.settings.mol_var2)) - row = subbox.row() - row.label(icon = 'FORWARD',text = "You must set new substep to: " + str(newsubstep)) - row = subbox.row() - row.label(icon = 'ERROR',text = "Multiply particles size by: " + str(round(1/factor,5))) - row = subbox.row() - row.label(icon = 'ERROR',text = "Multiply others sys particle number by: " + str(round(diff,5))) + subbox = box.box() + row = subbox.row() + row.label(text = "SUBSTEPS CALCULATOR:") + row = subbox.row() + row.label( + icon='INFO', + text="Current systems have: {} particles".format(psys.particles) + ) + row = subbox.row() + row.prop(psys.settings, "mol_var1", text="Current numbers of particles") + row = subbox.row() + row.prop(psys.settings,"mol_var2",text = "Current substep") + row = subbox.row() + row.prop(psys.settings,"mol_var3", text="Targeted numbers of particles") + diff = (psys.settings.mol_var3 / psys.settings.mol_var1) + factor = psys.settings.mol_var3 ** (1/3) / psys.settings.mol_var1 ** (1/3) + newsubstep = int(round(factor * psys.settings.mol_var2)) + row = subbox.row() + row.label( + icon='FORWARD', + text="You must set new substep to: {}".format(newsubstep) + ) + row = subbox.row() + row.label( + icon='ERROR', + text="Multiply particles size by: {}".format(round(1 / factor, 5)) + ) + row = subbox.row() + row.label( + icon='ERROR', + text="Multiply others sys particle number by: {}".format(round(diff, 5)) + ) - box = layout.box() - row = box.row() - box.active = False - box.alert = False - row.alignment = 'CENTER' - row.label(text = "THANKS TO ALL DONATORS !") - row = box.row() - row.alignment = 'CENTER' - row.label(text = "If you want donate to support my work") - row = box.row() - row.alignment = 'CENTER' - row.operator("wm.url_open", text=" click here to Donate ", icon='URL').url = "www.pyroevil.com/donate/" - row = box.row() - row.alignment = 'CENTER' - row.label(text = "or visit: ") - row = box.row() - row.alignment = 'CENTER' - row.label(text = "www.pyroevil.com/donate/") + box = layout.box() + row = box.row() + box.active = False + box.alert = False + row.alignment = 'CENTER' + row.label(text="THANKS TO ALL DONATORS !") + row = box.row() + row.alignment = 'CENTER' + row.label(text="If you want donate to support my work") + row = box.row() + row.alignment = 'CENTER' + row.operator( + "wm.url_open", + text="click here to Donate", + icon='URL' + ).url = "www.pyroevil.com/donate/" + row = box.row() + row.alignment = 'CENTER' + row.label(text="or visit: ") + row = box.row() + row.alignment = 'CENTER' + row.label(text = "www.pyroevil.com/donate/") From 2ddfc17959561464f7167b6642f17b75b59e7f5b Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 00:50:17 +0400 Subject: [PATCH 023/129] operators: PEP8 refactor --- molecular/operators.py | 60 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index bb0cb0e..5ca8aad 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -18,7 +18,6 @@ class MolSimulate(bpy.types.Operator): bl_idname = "object.mol_simulate" bl_label = "Mol Simulate" - def execute(self, context): print("Molecular Sim start--------------------------------------------------") mol_stime = clock() @@ -31,58 +30,58 @@ def execute(self, context): scene.mol_totaldeadlink = 0 scene.mol_timeremain = "...Simulating..." object = bpy.context.object - scene.frame_set(frame = scene.frame_start) + scene.frame_set(frame=scene.frame_start) scene.mol_old_endframe = scene.frame_end mol_substep = scene.mol_substep scene.render.frame_map_old = 1 scene.render.frame_map_new = mol_substep + 1 scene.frame_end *= mol_substep + 1 - + if scene.mol_timescale_active == True: fps = scene.render.fps / scene.timescale else: fps = scene.render.fps + cpu = scene.mol_cpu mol_exportdata = bpy.context.scene.mol_exportdata mol_exportdata.clear() - mol_exportdata.append([fps,mol_substep,0,0,cpu]) + mol_exportdata.append([fps, mol_substep, 0, 0, cpu]) mol_stime = clock() simulate.pack_data(True) #print("sys number",mol_exportdata[0][2]) etime = clock() - print(" " + "PackData take " + str(round(etime - mol_stime,3)) + "sec") + print(" PackData take " + str(round(etime - mol_stime, 3)) + "sec") mol_stime = clock() mol_report = cmolcore.init(mol_exportdata) etime = clock() - print(" " + "Export time take " + str(round(etime - mol_stime,3)) + "sec") + print(" Export time take " + str(round(etime - mol_stime, 3)) + "sec") print(" total numbers of particles: " + str(mol_report)) print(" start processing:") bpy.ops.wm.mol_simulate_modal() return {'FINISHED'} - + + class MolSetGlobalUV(bpy.types.Operator): """Tooltip""" bl_idname = "object.mol_set_global_uv" bl_label = "Mol Set UV" - def execute(self, context): scene = bpy.context.scene object = bpy.context.object psys = object.particle_systems.active - coord = [0,0,0] * len(psys.particles) - psys.particles.foreach_get("location",coord) - psys.particles.foreach_set("angular_velocity",coord) - + coord = [0, 0, 0] * len(psys.particles) + psys.particles.foreach_get("location", coord) + psys.particles.foreach_set("angular_velocity", coord) + return {'FINISHED'} - - + + class MolSetActiveUV(bpy.types.Operator): """Tooltip""" bl_idname = "object.mol_set_active_uv" bl_label = "Mol Set Active UV" - def execute(self, context): scene = context.scene scene.mol_objuvbake = context.object.name @@ -94,16 +93,16 @@ def execute(self, context): print(' start bake uv from:',object.name) #object2 = object.copy() - + obdata = object.data.copy() - object2 = bpy.data.objects.new(name="mol_uv_temp",object_data = obdata) + object2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) object2.matrix_world = object.matrix_world - + context.scene.objects.link(object2) - mod = object2.modifiers.new("tri_for_uv","TRIANGULATE") + mod = object2.modifiers.new("tri_for_uv", "TRIANGULATE") mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' - newmesh = object2.to_mesh(bpy.context.scene,True,"RENDER",True,False) + newmesh = object2.to_mesh(bpy.context.scene, True, "RENDER", True, False) object2.data = newmesh context.scene.update() """ @@ -145,7 +144,7 @@ def execute(self, context): newuv = barycentric(p,v1,v2,v3,uv1,uv2,uv3) #print('New UVs:',newuv) parloc = par.location * object2.matrix_world - dist = (Vector((parloc[0] - p[0],parloc[1] - p[1],parloc[2] - p[2]))).length + dist = (Vector((parloc[0] - p[0], parloc[1] - p[1], parloc[2] - p[2]))).length newuv[2] = dist newuv = newuv.to_tuple() par.angular_velocity = newuv @@ -153,9 +152,10 @@ def execute(self, context): bpy.data.objects.remove(object2) bpy.data.meshes.remove(newmesh) print(' uv baked on:',psys.settings.name) - + return {'FINISHED'} + class MolSimulateModal(bpy.types.Operator): """Operator which runs its self from a timer""" bl_idname = "wm.mol_simulate_modal" @@ -177,7 +177,7 @@ def modal(self, context, event): bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 scene.frame_end = scene.mol_old_endframe - + for obj in bpy.data.objects: for psys in obj.particle_systems: for psys in obj.particle_systems: @@ -188,10 +188,10 @@ def modal(self, context, event): scene.frame_set(frame = psys.settings.frame_start) bpy.context.scene.update() bpy.ops.object.mol_set_active_uv() - + if frame_current == frame_end and scene.mol_render == True: bpy.ops.render.render(animation=True) - + scene.frame_set(frame = scene.frame_start) cmolcore.memfree() @@ -221,17 +221,17 @@ def modal(self, context, event): i += 1 #print("inject new velocity time",clock() - stimex,"sec") mol_substep = scene.mol_substep - framesubstep = frame_current/(mol_substep+1) + framesubstep = frame_current/(mol_substep + 1) if framesubstep == int(framesubstep): etime = clock() print(" frame " + str(framesubstep + 1) + ":") print(" links created:", scene.mol_newlink) if scene.mol_totallink != 0: print(" links broked :", scene.mol_deadlink) - print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100),2),"%)") - print(" Molecular Script: " + str(round(etime - scene.mol_stime,3)) + " sec") + print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100), 2), "%)") + print(" Molecular Script: " + str(round(etime - scene.mol_stime, 3)) + " sec") remain = (((etime - scene.mol_stime) * (scene.mol_old_endframe - framesubstep - 1))) - days = int(strftime('%d',gmtime(remain))) - 1 + days = int(strftime('%d', gmtime(remain))) - 1 scene.mol_timeremain = strftime(str(days) + ' days %H hours %M mins %S secs', gmtime(remain)) print(" Remaining estimated:", scene.mol_timeremain) scene.mol_newlink = 0 @@ -245,7 +245,7 @@ def modal(self, context, event): scene.frame_set(frame = frame_current + 1) if framesubstep == int(framesubstep): etime2 = clock() - print(" Blender: " + str(round(etime2 - stime2,3)) + " sec") + print(" Blender: " + str(round(etime2 - stime2, 3)) + " sec") stime2 = clock() return {'PASS_THROUGH'} From c0db8f9636cff669c0771f28bc5b798e52381d70 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 10:58:24 +0400 Subject: [PATCH 024/129] ui: fix bug in particles number --- molecular/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/molecular/ui.py b/molecular/ui.py index 062cb13..c17b45b 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -317,7 +317,7 @@ def draw(self, context): row.operator( "object.mol_set_active_uv", icon='GROUP_UVS', - text="Set Active UV ( no uvs found)" + text="Set Active UV (no uvs found)" ) subbox = box.box() @@ -326,7 +326,7 @@ def draw(self, context): row = subbox.row() row.label( icon='INFO', - text="Current systems have: {} particles".format(psys.particles) + text="Current systems have: {} particles".format(len(psys.particles)) ) row = subbox.row() row.prop(psys.settings, "mol_var1", text="Current numbers of particles") From fa1ef3f0ba8a19467c0a993ab1afabf2313122e9 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 11:06:51 +0400 Subject: [PATCH 025/129] ui: enable props when others links property --- molecular/ui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/molecular/ui.py b/molecular/ui.py index c17b45b..76c7070 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -105,7 +105,8 @@ def draw(self, context): ) subbox = box.box() - subbox.enabled = psys.settings.mol_links_active + subbox.enabled = psys.settings.mol_links_active or \ + psys.settings.mol_other_link_active subbox.label(text="Initial Linking (at birth):") row = subbox.row() row.prop(psys.settings, "mol_link_length", text="search length") From 9b935ca6a5fe9042a5c6b03c0a4c9d35d8cbb7bb Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 12:20:53 +0400 Subject: [PATCH 026/129] minor edits --- molecular/operators.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index 5ca8aad..cb82b3b 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -67,8 +67,8 @@ class MolSetGlobalUV(bpy.types.Operator): bl_label = "Mol Set UV" def execute(self, context): - scene = bpy.context.scene - object = bpy.context.object + scene = context.scene + object = context.object psys = object.particle_systems.active coord = [0, 0, 0] * len(psys.particles) psys.particles.foreach_get("location", coord) @@ -84,9 +84,9 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): scene = context.scene - scene.mol_objuvbake = context.object.name - scene.mol_psysuvbake = context.object.particle_systems.active.name - object = bpy.data.objects[scene.mol_objuvbake] + object = context.object + scene.mol_objuvbake = object.name + scene.mol_psysuvbake = object.particle_systems.active.name if not object.data.uv_layers.active: return {'FINISHED'} @@ -102,7 +102,7 @@ def execute(self, context): mod = object2.modifiers.new("tri_for_uv", "TRIANGULATE") mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' - newmesh = object2.to_mesh(bpy.context.scene, True, "RENDER", True, False) + newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) object2.data = newmesh context.scene.update() """ @@ -113,7 +113,7 @@ def execute(self, context): mod.use_beauty = False bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name) """ - psys = context.object.particle_systems[scene.mol_psysuvbake] + psys = object.particle_systems[scene.mol_psysuvbake] #print('-------------start------------') for par in psys.particles: parloc = (par.location * object2.matrix_world) - object2.location @@ -141,7 +141,7 @@ def execute(self, context): uv2 = Vector(uv2) uv3 = Vector(uv3) #print(a,b,c,uv1,uv2,uv3,p) - newuv = barycentric(p,v1,v2,v3,uv1,uv2,uv3) + newuv = barycentric(p, v1, v2, v3, uv1, uv2, uv3) #print('New UVs:',newuv) parloc = par.location * object2.matrix_world dist = (Vector((parloc[0] - p[0], parloc[1] - p[1], parloc[2] - p[2]))).length @@ -151,7 +151,8 @@ def execute(self, context): scene.objects.unlink(object2) bpy.data.objects.remove(object2) bpy.data.meshes.remove(newmesh) - print(' uv baked on:',psys.settings.name) + bpy.data.meshes.remove(obdata) + print(' uv baked on:', psys.settings.name) return {'FINISHED'} From 806d221d3cb2c7651cd2094ac20ede46b292a74c Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 12:46:41 +0400 Subject: [PATCH 027/129] minor edits --- molecular/operators.py | 36 ++++++--------------------- molecular/simulate.py | 56 ++++++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 53 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index cb82b3b..887f46e 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -14,14 +14,13 @@ class MolSimulate(bpy.types.Operator): - """Tooltip""" bl_idname = "object.mol_simulate" bl_label = "Mol Simulate" def execute(self, context): print("Molecular Sim start--------------------------------------------------") mol_stime = clock() - scene = bpy.context.scene + scene = context.scene scene.mol_simrun = True scene.mol_minsize = 1000000000.0 scene.mol_newlink = 0 @@ -29,7 +28,7 @@ def execute(self, context): scene.mol_totallink = 0 scene.mol_totaldeadlink = 0 scene.mol_timeremain = "...Simulating..." - object = bpy.context.object + object = context.object scene.frame_set(frame=scene.frame_start) scene.mol_old_endframe = scene.frame_end mol_substep = scene.mol_substep @@ -43,12 +42,11 @@ def execute(self, context): fps = scene.render.fps cpu = scene.mol_cpu - mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata = context.scene.mol_exportdata mol_exportdata.clear() mol_exportdata.append([fps, mol_substep, 0, 0, cpu]) mol_stime = clock() simulate.pack_data(True) - #print("sys number",mol_exportdata[0][2]) etime = clock() print(" PackData take " + str(round(etime - mol_stime, 3)) + "sec") mol_stime = clock() @@ -62,7 +60,6 @@ def execute(self, context): class MolSetGlobalUV(bpy.types.Operator): - """Tooltip""" bl_idname = "object.mol_set_global_uv" bl_label = "Mol Set UV" @@ -78,7 +75,6 @@ def execute(self, context): class MolSetActiveUV(bpy.types.Operator): - """Tooltip""" bl_idname = "object.mol_set_active_uv" bl_label = "Mol Set Active UV" @@ -92,7 +88,6 @@ def execute(self, context): return {'FINISHED'} print(' start bake uv from:',object.name) - #object2 = object.copy() obdata = object.data.copy() object2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) @@ -105,20 +100,11 @@ def execute(self, context): newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) object2.data = newmesh context.scene.update() - """ - oldmesh = object.data - newmesh = object.data.copy() - object.data = newmesh - mod = object.modifiers.new("tri_for_uv","TRIANGULATE") - mod.use_beauty = False - bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name) - """ psys = object.particle_systems[scene.mol_psysuvbake] - #print('-------------start------------') + for par in psys.particles: parloc = (par.location * object2.matrix_world) - object2.location point = object2.closest_point_on_mesh(parloc) - #print('closest:',par.location,point[0],point[2]) vindex1 = object2.data.polygons[point[3]].vertices[0] vindex2 = object2.data.polygons[point[3]].vertices[1] vindex3 = object2.data.polygons[point[3]].vertices[2] @@ -131,8 +117,6 @@ def execute(self, context): uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() - #print(vertices1.co,vertices2.co,vertices3.co) - #print(uv1,uv2,uv3) p = object2.matrix_world * point[1] v1 = Vector(v1) v2 = Vector(v2) @@ -140,14 +124,13 @@ def execute(self, context): uv1 = Vector(uv1) uv2 = Vector(uv2) uv3 = Vector(uv3) - #print(a,b,c,uv1,uv2,uv3,p) newuv = barycentric(p, v1, v2, v3, uv1, uv2, uv3) - #print('New UVs:',newuv) parloc = par.location * object2.matrix_world dist = (Vector((parloc[0] - p[0], parloc[1] - p[1], parloc[2] - p[2]))).length newuv[2] = dist newuv = newuv.to_tuple() par.angular_velocity = newuv + scene.objects.unlink(object2) bpy.data.objects.remove(object2) bpy.data.meshes.remove(newmesh) @@ -164,7 +147,6 @@ class MolSimulateModal(bpy.types.Operator): _timer = None def modal(self, context, event): - #mol_stime = clock() scene = bpy.context.scene frame_end = scene.frame_end frame_current = scene.frame_current @@ -207,20 +189,16 @@ def modal(self, context, event): scene.mol_stime = clock() mol_exportdata = bpy.context.scene.mol_exportdata mol_exportdata.clear() - #stimex = clock() simulate.pack_data(False) - #print("packdata time",clock() - stimex,"sec") mol_importdata = cmolcore.simulate(mol_exportdata) i = 0 - #stimex = clock() + for obj in bpy.data.objects: for psys in obj.particle_systems: if psys.settings.mol_active == True and len(psys.particles) > 0: - #print(len(mol_importdata[i][1])) - #print(len(psys.particles)) psys.particles.foreach_set('velocity',mol_importdata[1][i]) i += 1 - #print("inject new velocity time",clock() - stimex,"sec") + mol_substep = scene.mol_substep framesubstep = frame_current/(mol_substep + 1) if framesubstep == int(framesubstep): diff --git a/molecular/simulate.py b/molecular/simulate.py index 2a1fb70..a94768a 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -1,5 +1,5 @@ -from math import pi +import math import bpy @@ -12,10 +12,10 @@ def pack_data(initiate): for psys in obj.particle_systems: if psys.settings.mol_matter != "-1": psys.settings.mol_density = float(psys.settings.mol_matter) - if psys.settings.mol_active == True and len(psys.particles) > 0: + if psys.settings.mol_active and len(psys.particles): parlen = len(psys.particles) - par_loc = [0,0,0] * parlen - par_vel = [0,0,0] * parlen + par_loc = [0, 0, 0] * parlen + par_vel = [0, 0, 0] * parlen par_size = [0] * parlen par_alive = [] for par in psys.particles: @@ -26,32 +26,32 @@ def pack_data(initiate): par_alive.append(0) if par.alive_state == "DEAD": par_alive.append(3) - - psys.particles.foreach_get('location',par_loc) - psys.particles.foreach_get('velocity',par_vel) - + + psys.particles.foreach_get('location', par_loc) + psys.particles.foreach_get('velocity', par_vel) + if initiate: par_mass = [] - + if psys.settings.mol_density_active: for par in psys.particles: - par_mass.append(psys.settings.mol_density * (4/3*pi*((par.size/2)**3))) + par_mass.append(psys.settings.mol_density * (4 / 3 * math.pi * ((par.size / 2) ** 3))) else: for par in psys.particles: par_mass.append(psys.settings.mass) + """ if scene.mol_timescale_active == True: psys.settings.timestep = 1 / (scene.render.fps / scene.timescale) else: psys.settings.timestep = 1 / scene.render.fps """ - #psys.settings.count = psys.settings.count - psys.point_cache.frame_step = psys.point_cache.frame_step + psyslen += 1 - psys.particles.foreach_get('size',par_size) + psys.particles.foreach_get('size', par_size) if bpy.context.scene.mol_minsize > min(par_size): bpy.context.scene.mol_minsize = min(par_size) - + if psys.settings.mol_link_samevalue: psys.settings.mol_link_estiff = psys.settings.mol_link_stiff psys.settings.mol_link_estiffrand = psys.settings.mol_link_stiffrand @@ -60,7 +60,7 @@ def pack_data(initiate): psys.settings.mol_link_edamprand = psys.settings.mol_link_damprand psys.settings.mol_link_ebroken = psys.settings.mol_link_broken psys.settings.mol_link_ebrokenrand = psys.settings.mol_link_brokenrand - + if psys.settings.mol_relink_samevalue: psys.settings.mol_relink_estiff = psys.settings.mol_relink_stiff psys.settings.mol_relink_estiffrand = psys.settings.mol_relink_stiffrand @@ -69,18 +69,21 @@ def pack_data(initiate): psys.settings.mol_relink_edamprand = psys.settings.mol_relink_damprand psys.settings.mol_relink_ebroken = psys.settings.mol_relink_broken psys.settings.mol_relink_ebrokenrand = psys.settings.mol_relink_brokenrand - + params = [0] * 47 + params[0] = psys.settings.mol_selfcollision_active params[1] = psys.settings.mol_othercollision_active params[2] = psys.settings.mol_collision_group params[3] = psys.settings.mol_friction params[4] = psys.settings.mol_collision_damp params[5] = psys.settings.mol_links_active - if psys.settings.mol_link_rellength == True: + + if psys.settings.mol_link_rellength: params[6] = psys.settings.particle_size * psys.settings.mol_link_length else: params[6] = psys.settings.mol_link_length + params[7] = psys.settings.mol_link_max params[8] = psys.settings.mol_link_tension params[9] = psys.settings.mol_link_tensionrand @@ -121,15 +124,20 @@ def pack_data(initiate): params[44] = psys.settings.mol_link_friction params[45] = psys.settings.mol_link_group params[46] = psys.settings.mol_other_link_active - + mol_exportdata = bpy.context.scene.mol_exportdata + if initiate: mol_exportdata[0][2] = psyslen mol_exportdata[0][3] = parnum - #print(par_loc) - mol_exportdata.append((parlen,par_loc,par_vel,par_size,par_mass,par_alive,params)) - pass + mol_exportdata.append(( + parlen, + par_loc, + par_vel, + par_size, + par_mass, + par_alive, + params + )) else: - #print(par_loc) - mol_exportdata.append((par_loc,par_vel,par_alive)) - pass + mol_exportdata.append((par_loc, par_vel, par_alive)) From e6598ecdc87ed63daf65cf99c01f5a07341e391b Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 12:59:57 +0400 Subject: [PATCH 028/129] minor edits --- molecular/operators.py | 43 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index 887f46e..58a8bd2 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -147,15 +147,15 @@ class MolSimulateModal(bpy.types.Operator): _timer = None def modal(self, context, event): - scene = bpy.context.scene + scene = context.scene frame_end = scene.frame_end frame_current = scene.frame_current if event.type == 'ESC' or frame_current == frame_end: - if frame_current == frame_end and scene.mol_bake == True: - fake_context = bpy.context.copy() + if frame_current == frame_end and scene.mol_bake: + fake_context = context.copy() for obj in bpy.data.objects: for psys in obj.particle_systems: - if psys.settings.mol_active == True and len(psys.particles) > 0: + if psys.settings.mol_active and len(psys.particles): fake_context["point_cache"] = psys.point_cache bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 @@ -163,19 +163,17 @@ def modal(self, context, event): for obj in bpy.data.objects: for psys in obj.particle_systems: - for psys in obj.particle_systems: - if psys.settings.mol_bakeuv == True: - scene.mol_objuvbake = obj.name - mol_psysuvbake = psys.name - bpy.context.scene.update() - scene.frame_set(frame = psys.settings.frame_start) - bpy.context.scene.update() - bpy.ops.object.mol_set_active_uv() - - if frame_current == frame_end and scene.mol_render == True: + if psys.settings.mol_bakeuv: + scene.mol_objuvbake = obj.name + context.scene.update() + scene.frame_set(frame=psys.settings.frame_start) + bpy.context.scene.update() + bpy.ops.object.mol_set_active_uv() + + if frame_current == frame_end and scene.mol_render: bpy.ops.render.render(animation=True) - scene.frame_set(frame = scene.frame_start) + scene.frame_set(frame=scene.frame_start) cmolcore.memfree() scene.mol_simrun = False @@ -187,25 +185,25 @@ def modal(self, context, event): if event.type == 'TIMER': if frame_current == scene.frame_start: scene.mol_stime = clock() - mol_exportdata = bpy.context.scene.mol_exportdata + mol_exportdata = context.scene.mol_exportdata mol_exportdata.clear() simulate.pack_data(False) mol_importdata = cmolcore.simulate(mol_exportdata) - i = 0 + i = 0 for obj in bpy.data.objects: for psys in obj.particle_systems: - if psys.settings.mol_active == True and len(psys.particles) > 0: - psys.particles.foreach_set('velocity',mol_importdata[1][i]) + if psys.settings.mol_active and len(psys.particles): + psys.particles.foreach_set('velocity', mol_importdata[1][i]) i += 1 mol_substep = scene.mol_substep - framesubstep = frame_current/(mol_substep + 1) + framesubstep = frame_current / (mol_substep + 1) if framesubstep == int(framesubstep): etime = clock() print(" frame " + str(framesubstep + 1) + ":") print(" links created:", scene.mol_newlink) - if scene.mol_totallink != 0: + if scene.mol_totallink: print(" links broked :", scene.mol_deadlink) print(" total links:", scene.mol_totallink - scene.mol_totaldeadlink ,"/", scene.mol_totallink," (",round((((scene.mol_totallink - scene.mol_totaldeadlink) / scene.mol_totallink) * 100), 2), "%)") print(" Molecular Script: " + str(round(etime - scene.mol_stime, 3)) + " sec") @@ -221,11 +219,12 @@ def modal(self, context, event): scene.mol_deadlink += mol_importdata[3] scene.mol_totallink = mol_importdata[4] scene.mol_totaldeadlink = mol_importdata[5] - scene.frame_set(frame = frame_current + 1) + scene.frame_set(frame=frame_current + 1) if framesubstep == int(framesubstep): etime2 = clock() print(" Blender: " + str(round(etime2 - stime2, 3)) + " sec") stime2 = clock() + return {'PASS_THROUGH'} def execute(self, context): From fe9f1736c51a74b3b11762906df57d535ca9c1d8 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 16:18:06 +0400 Subject: [PATCH 029/129] move labels text in module --- molecular/names.py | 20 ++++++++++++++++++++ molecular/ui.py | 40 +++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 molecular/names.py diff --git a/molecular/names.py b/molecular/names.py new file mode 100644 index 0000000..fdef040 --- /dev/null +++ b/molecular/names.py @@ -0,0 +1,20 @@ + +# Labels text +DENSITY = 'Density:' +COLLISION = 'Collision:' +LINKS = 'Links:' +INITIAL_LINKING = 'Initial Linking (at birth):' +NEW_LINKING = 'New Linking (at collision):' +UVS = 'UV\'s:' +SIMULATE = 'Simulate' +CPU_USED = 'CPU used:' +MOLECULAR_TOOLS = 'Molecular Tools:' +PARTICLE_UV = 'Particle UV:' +SET_POSITION = 'Set current particles position' +UV_HELP = 'Has global or current uv in angular velocity' +CYCLES_HELP = 'Retrieve it with Cycles particle info node' +SUBSTEPS_CALCULATOR = 'Substeps Calculator:' +THANKS = 'THANKS TO ALL DONATORS!' +SUPPORT_WORK = 'If you want donate to support my work' +VISIT = 'or visit:' +SITE = 'www.pyroevil.com/donate/' diff --git a/molecular/ui.py b/molecular/ui.py index 76c7070..973911f 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -1,6 +1,8 @@ import bpy +from . import names + class MolecularPanel(bpy.types.Panel): """Creates a Panel in the Object properties window""" @@ -31,7 +33,7 @@ def draw(self, context): return layout.enabled = psys.settings.mol_active row = layout.row() - row.label(text = "Density:") + row.label(text=names.DENSITY) box = layout.box() box.prop( psys.settings, @@ -55,9 +57,9 @@ def draw(self, context): weight_text = "Total system approx weight: {0:.4} kg".format( len(psys.particles) * pmass ) - row.label(icon ="INFO", text=weight_text) + row.label(icon="INFO", text=weight_text) row = layout.row() - row.label(text = "Collision:") + row.label(text=names.COLLISION) box = layout.box() box.prop( psys.settings, @@ -86,7 +88,7 @@ def draw(self, context): ) row = layout.row() - row.label(text="Links:") + row.label(text=names.LINKS) box = layout.box() box.prop( psys.settings, @@ -107,7 +109,7 @@ def draw(self, context): subbox = box.box() subbox.enabled = psys.settings.mol_links_active or \ psys.settings.mol_other_link_active - subbox.label(text="Initial Linking (at birth):") + subbox.label(text=names.INITIAL_LINKING) row = subbox.row() row.prop(psys.settings, "mol_link_length", text="search length") row.prop(psys.settings, "mol_link_rellength", text="Relative") @@ -156,7 +158,7 @@ def draw(self, context): subbox = box.box() subbox.active = psys.settings.mol_links_active - subbox.label(text="New Linking (at collision):") + subbox.label(text=names.NEW_LINKING) row = subbox.row() row.prop(psys.settings, "mol_relink_group", text="Only links with:") row = subbox.row() @@ -205,7 +207,7 @@ def draw(self, context): row.prop(psys.settings, "mol_relink_ebrokenrand", text="Rand E broken") row = layout.row() - row.label(text="UV's:") + row.label(text=names.UVS) box = layout.box() row = box.row() @@ -228,7 +230,7 @@ def draw(self, context): row = layout.row() row.label(text='') row = layout.row() - row.label(text="Simulate") + row.label(text=names.SIMULATE) row = layout.row() row.prop(scn, "frame_start", text="Start Frame") row.prop(scn, "frame_end", text="End Frame") @@ -241,7 +243,7 @@ def draw(self, context): row.prop(scn, "mol_substep", text="Substeps") row.label(text='') row = layout.row() - row.label(text = "CPU used:") + row.label(text=names.CPU_USED) row.prop(scn, "mol_cpu", text="CPU") row = layout.row() row.prop(scn, "mol_bake", text="Bake all at ending") @@ -284,19 +286,19 @@ def draw(self, context): box = layout.box() row = box.row() box.enabled = True - row.label(text="Molecular Tools:", icon='MODIFIER') + row.label(text=names.MOLECULAR_TOOLS, icon='MODIFIER') subbox = box.box() row = subbox.row() - row.label(text="Particle UV:") + row.label(text=names.PARTICLE_UV) row = subbox.row() row.alignment = 'CENTER' - row.label(icon='INFO', text="Set current particles position") + row.label(icon='INFO', text=names.SET_POSITION) row = subbox.row() row.alignment = 'CENTER' - row.label(text="Has global or current uv in angular velocity") + row.label(text=names.UV_HELP) row = subbox.row() row.alignment = 'CENTER' - row.label(text="Retrieve it with Cycles particle info node") + row.label(text=names.CYCLES_HELP) row = subbox.row() row.operator( "object.mol_set_global_uv", @@ -323,7 +325,7 @@ def draw(self, context): subbox = box.box() row = subbox.row() - row.label(text = "SUBSTEPS CALCULATOR:") + row.label(text=names.SUBSTEPS_CALCULATOR) row = subbox.row() row.label( icon='INFO', @@ -359,10 +361,10 @@ def draw(self, context): box.active = False box.alert = False row.alignment = 'CENTER' - row.label(text="THANKS TO ALL DONATORS !") + row.label(text=names.THANKS) row = box.row() row.alignment = 'CENTER' - row.label(text="If you want donate to support my work") + row.label(text=names.SUPPORT_WORK) row = box.row() row.alignment = 'CENTER' row.operator( @@ -372,7 +374,7 @@ def draw(self, context): ).url = "www.pyroevil.com/donate/" row = box.row() row.alignment = 'CENTER' - row.label(text="or visit: ") + row.label(text=names.VISIT) row = box.row() row.alignment = 'CENTER' - row.label(text = "www.pyroevil.com/donate/") + row.label(text=names.SITE) From 2c2913c3c3724a2bb46c41ad8afe9851c601e1c2 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 16:45:37 +0400 Subject: [PATCH 030/129] move props text in props_define function --- molecular/properties.py | 126 +++++++++++++++++++++------------------ molecular/ui.py | 129 ++++++++++++++++++---------------------- 2 files changed, 126 insertions(+), 129 deletions(-) diff --git a/molecular/properties.py b/molecular/properties.py index c8aff09..d23139a 100644 --- a/molecular/properties.py +++ b/molecular/properties.py @@ -16,7 +16,8 @@ def define_props(): name="mol_refresh", description=descriptions.REFRESH, default=True ) parset.mol_density_active = bpy.props.BoolProperty( - name="mol_density_active", description=descriptions.DENSITY_ACTIVE, + name="Calculate particles weight by density", + description=descriptions.DENSITY_ACTIVE, default=False ) @@ -28,266 +29,273 @@ def define_props(): ] parset.mol_matter = bpy.props.EnumProperty( - items=matter_items, description=descriptions.MATTER + name='Preset', + items=matter_items, + description=descriptions.MATTER ) parset.mol_density = bpy.props.FloatProperty( - name="mol_density", description=descriptions.DENSITY, + name="Kg per CubeMeter:", description=descriptions.DENSITY, default=1000, min=0.001 ) parset.mol_selfcollision_active = bpy.props.BoolProperty( - name="mol_selfcollision_active", + name="Activate Self Collision", description=descriptions.SELF_COLLISION_ACTIVE, default=False ) parset.mol_othercollision_active = bpy.props.BoolProperty( - name="mol_othercollision_active", + name="Activate Collision with others", description=descriptions.OTHER_COLLISION_ACTIVE, default=False ) parset.mol_friction = bpy.props.FloatProperty( - name="mol_friction", description=descriptions.FRICTION, + name='Friction:', description=descriptions.FRICTION, default=0.005, min=0, max=1, precision=6, subtype='FACTOR' ) parset.mol_collision_damp = bpy.props.FloatProperty( - name="mol_collision_damp", description=descriptions.COLLISION_DAMPING, + name="Damping:", description=descriptions.COLLISION_DAMPING, default=0.005, min=0, max=1, precision=6, subtype='FACTOR' ) parset.mol_collision_group = bpy.props.IntProperty( - default=1, min=1, description=descriptions.COLLISION_GROUP + name='Collide only with:', default=1, min=1, + description=descriptions.COLLISION_GROUP ) parset.mol_links_active = bpy.props.BoolProperty( - name="mol_links_active", description=descriptions.LINKS_ACTIVE, + name="Activate Particles linking", + description=descriptions.LINKS_ACTIVE, default=False ) parset.mol_other_link_active = bpy.props.BoolProperty( - name="mol_other_link_active", + name="Activate Particles linking with Others", description=descriptions.LINK_OTHER_ACTIVE, default=False ) parset.mol_link_group = bpy.props.IntProperty( - default=1, min=1, description=descriptions.LINK_GROUP + name='Linking only with:', default=1, min=1, + description=descriptions.LINK_GROUP ) parset.mol_link_rellength = bpy.props.BoolProperty( - name="mol_link_rellength", + name="Relative", description=descriptions.LINK_RELATIVE_LENGTH, default=True ) parset.mol_link_friction = bpy.props.FloatProperty( - name="mol_link_friction", description=descriptions.LINK_FRICTION, + name="Link friction", description=descriptions.LINK_FRICTION, min=0, max=1, default=0.005, precision=6, subtype='FACTOR' ) parset.mol_link_length = bpy.props.FloatProperty( - name="mol_link_length", description=descriptions.LINK_LENGTH, + name="Search Length", description=descriptions.LINK_LENGTH, min=0, precision=6, default=1 ) parset.mol_link_tension = bpy.props.FloatProperty( - name="mol_link_tension", description=descriptions.LINK_TENSION, + name="Tension", description=descriptions.LINK_TENSION, min=0, precision=6, default=1 ) parset.mol_link_tensionrand = bpy.props.FloatProperty( - name="mol_link_tensionrand", + name="Rand Tension", description=descriptions.LINK_TENSION_RANDOM, min=0, max=1, precision=6, default=0, subtype='FACTOR' ) parset.mol_link_max = bpy.props.IntProperty( - name="mol_link_max", description=descriptions.LINK_MAX, + name="Max links", description=descriptions.LINK_MAX, min=0, default=16 ) parset.mol_link_stiff = bpy.props.FloatProperty( - name="mol_link_stiff", description=descriptions.LINK_STIFFNESS, + name="Stiff", description=descriptions.LINK_STIFFNESS, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_link_stiffrand = bpy.props.FloatProperty( - name="mol_link_stiffrand", + name="Rand Stiff", description = descriptions.LINK_STIFFNESS_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_link_stiffexp = bpy.props.IntProperty( - name="mol_link_stiffexp", + name="Exponent", description=descriptions.LINK_STIFFNESS_EXPONENT, default=1, min=1, max=10 ) parset.mol_link_damp = bpy.props.FloatProperty( - name="mol_link_damp", description=descriptions.LINK_DAMPING, + name="Damping", description=descriptions.LINK_DAMPING, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_link_damprand = bpy.props.FloatProperty( - name="mol_link_damprand", description=descriptions.LINK_DAMPING_RANDOM, + name="Rand Damping", description=descriptions.LINK_DAMPING_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_link_broken = bpy.props.FloatProperty( - name="mol_link_broken", description=descriptions.LINK_BROKEN, + name="Broken", description=descriptions.LINK_BROKEN, min=0, default=0.5, precision=6 ) parset.mol_link_brokenrand = bpy.props.FloatProperty( - name="mol_link_brokenrand", + name="Rand Broken", description=descriptions.LINK_BROKEN_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_link_samevalue = bpy.props.BoolProperty( - name="mol_link_samevalue", description=descriptions.LINK_SAME_VALUE, + name="Same values for compression/expansion", + description=descriptions.LINK_SAME_VALUE, default=True ) parset.mol_link_estiff = bpy.props.FloatProperty( - name="mol_link_estiff", + name="E Stiff", description=descriptions.LINK_EXPENSION_STIFFNESS, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_link_estiffrand = bpy.props.FloatProperty( - name="mol_link_estiffrand", + name="Rand E Stiff", description=descriptions.LINK_EXPENSION_STIFFNESS_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_link_estiffexp = bpy.props.IntProperty( - name="mol_link_estiffexp", + name="E Exponent", description=descriptions.LINK_EXPENSION_STIFFNESS_EXPONENT, default=1, min=1, max=10 ) parset.mol_link_edamp = bpy.props.FloatProperty( - name="mol_link_edamp", description=descriptions.LINK_EXPENSION_DAMPING, + name="E Damping", description=descriptions.LINK_EXPENSION_DAMPING, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_link_edamprand = bpy.props.FloatProperty( - name="mol_link_edamprand", + name="Rand E Damping", description=descriptions.LINK_EXPENSION_DAMPING_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_link_ebroken = bpy.props.FloatProperty( - name="mol_link_ebroken", + name="E Broken", description=descriptions.LINK_EXPENSION_BROKEN, min=0, default=0.5, precision=6 ) parset.mol_link_ebrokenrand = bpy.props.FloatProperty( - name="mol_link_ebrokenrand", + name="Rand E Broken", description=descriptions.LINK_EXPENSION_BROKEN_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_group = bpy.props.IntProperty( + name='Only links with:', default=1, min=1, description=descriptions.RELINK_GROUP ) parset.mol_relink_chance = bpy.props.FloatProperty( - name="mol_relink_chance", + name="% Linking", description=descriptions.RELINK_CHANCE, min=0, max=100, default=0, precision=6 ) parset.mol_relink_chancerand = bpy.props.FloatProperty( - name="mol_relink_chancerand", + name="Rand % Linking", description=descriptions.RELINK_CHANCE_RANDOM, default=0, min=0, max=1, precision=6, subtype='FACTOR' ) parset.mol_relink_tension = bpy.props.FloatProperty( - name="mol_relink_tension", + name="Tension", description=descriptions.RELINK_TENSION, min=0, precision=6, default=1 ) parset.mol_relink_tensionrand = bpy.props.FloatProperty( - name="mol_relink_tensionrand", + name="Rand Tension", description=descriptions.RELINK_TENSION_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_max = bpy.props.IntProperty( - name="mol_relink_max", + name="Max links", description=descriptions.RELINK_MAX, min=0, default=16 ) parset.mol_relink_stiff = bpy.props.FloatProperty( - name="mol_relink_stiff", + name="Stiff", description=descriptions.RELINK_STIFFNESS, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_relink_stiffrand = bpy.props.FloatProperty( - name="mol_relink_stiffrand", + name="Rand Stiff", description=descriptions.RELINK_STIFFNESS_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_stiffexp = bpy.props.IntProperty( - name="mol_relink_stiffexp", + name="Exponent", description=descriptions.RELINK_STIFFNESS_EXPONENT, min=1, max=10, default=1 ) parset.mol_relink_damp = bpy.props.FloatProperty( - name="mol_relink_damp", + name="Damping", description=descriptions.RELINK_DAMPING, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_relink_damprand = bpy.props.FloatProperty( - name="mol_relink_damprand", + name="Rand Damping", description=descriptions.RELINK_DAMPING_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_broken = bpy.props.FloatProperty( - name="mol_relink_broken", + name="Broken", description=descriptions.RELINK_BROKEN, min=0, default=0.5, precision=6 ) parset.mol_relink_brokenrand = bpy.props.FloatProperty( - name="mol_relink_brokenrand", + name="Rand Broken", description=descriptions.RELINK_BROKEN_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_samevalue = bpy.props.BoolProperty( - name="mol_relink_samevalue", + name="Same values for compression/expansion", description=descriptions.RELINK_SAME_VALUE, default=True ) parset.mol_relink_estiff = bpy.props.FloatProperty( - name="mol_relink_estiff", + name="E Stiff", description=descriptions.RELINK_EXPENSION_STIFFNESS, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_relink_estiffrand = bpy.props.FloatProperty( - name="mol_relink_estiffrand", + name="Rand E Stiff", description=descriptions.RELINK_EXPENSION_STIFFNESS_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_estiffexp = bpy.props.IntProperty( - name="mol_relink_estiffexp", + name="Exponent", description=descriptions.RELINK_EXPENSION_STIFFNESS_EXPONENT, min=1, max=10, default=1 ) parset.mol_relink_edamp = bpy.props.FloatProperty( - name="mol_relink_edamp", + name="E Damping", description=descriptions.RELINK_EXPENSION_DAMPING, min=0, max=1, default=1, precision=6, subtype='FACTOR' ) parset.mol_relink_edamprand = bpy.props.FloatProperty( - name="mol_relink_deamprand", + name="Rand E Damping", description=descriptions.RELINK_EXPENSION_DAMPING_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_relink_ebroken = bpy.props.FloatProperty( - name="mol_relink_ebroken", + name="E Broken", description=descriptions.RELINK_EXPENSION_BROKEN, min=0, default=0.5, precision=6 ) parset.mol_relink_ebrokenrand = bpy.props.FloatProperty( - name="mol_relink_ebrokenrand", + name="Rand E Broken", description=descriptions.RELINK_EXPENSION_BROKEN_RANDOM, min=0, max=1, default=0, precision=6, subtype='FACTOR' ) parset.mol_var1 = bpy.props.IntProperty( - name="mol_var1", + name="Current numbers of particles", description=descriptions.VAR_1, min=1, default=1000 ) parset.mol_var2 = bpy.props.IntProperty( - name="mol_var2", + name="Current substep", description=descriptions.VAR_2, min=1, default=4 ) parset.mol_var3=bpy.props.IntProperty( - name="mol_var3", + name="Targeted numbers of particles", description=descriptions.VAR_3, min=1, default=1000 ) @@ -308,22 +316,22 @@ def define_props(): default=1 ) bpy.types.Scene.mol_substep = bpy.props.IntProperty( - name="mol_substep", + name="Substeps", description=descriptions.SUBSTEP, min=0, max=900, default=4 ) bpy.types.Scene.mol_bake = bpy.props.BoolProperty( - name="mol_bake", + name="Bake all at ending", description=descriptions.BAKE, default=True ) bpy.types.Scene.mol_render = bpy.props.BoolProperty( - name="mol_render", + name="Render at ending", description=descriptions.RENDER, default=False ) bpy.types.Scene.mol_cpu = bpy.props.IntProperty( - name="mol_cpu", + name="CPU", description=descriptions.CPU, default=multiprocessing.cpu_count(), min=1, max =multiprocessing.cpu_count() diff --git a/molecular/ui.py b/molecular/ui.py index 973911f..f4485bd 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -37,13 +37,12 @@ def draw(self, context): box = layout.box() box.prop( psys.settings, - "mol_density_active", - text="Calculate particles weight by density" + "mol_density_active" ) subbox = box.box() subbox.enabled = psys.settings.mol_density_active row = subbox.row() - row.prop(psys.settings, "mol_matter", text="Preset:") + row.prop(psys.settings, "mol_matter") row = subbox.row() if int(psys.settings.mol_matter) == 0: @@ -51,7 +50,7 @@ def draw(self, context): elif int(psys.settings.mol_matter) >= 1: row.enabled = False - row.prop(psys.settings, "mol_density", text = "Kg per CubeMeter:") + row.prop(psys.settings, "mol_density") pmass = (psys.settings.particle_size ** 3) * psys.settings.mol_density row = subbox.row() weight_text = "Total system approx weight: {0:.4} kg".format( @@ -63,28 +62,23 @@ def draw(self, context): box = layout.box() box.prop( psys.settings, - "mol_selfcollision_active", - text="Activate Self Collision" + "mol_selfcollision_active" ) box.prop( psys.settings, - "mol_othercollision_active", - text="Activate Collision with others" + "mol_othercollision_active" ) box.prop( psys.settings, "mol_collision_group", - text="Collide only with:" ) box.prop( psys.settings, "mol_friction", - text="Friction:" ) box.prop( psys.settings, - "mol_collision_damp", - text = "Damping:" + "mol_collision_damp" ) row = layout.row() @@ -92,18 +86,15 @@ def draw(self, context): box = layout.box() box.prop( psys.settings, - "mol_links_active", - text="Activate Particles linking" + "mol_links_active" ) box.prop( psys.settings, - "mol_other_link_active", - text="Activate Particles linking with Others" + "mol_other_link_active" ) box.prop( psys.settings, - "mol_link_group", - text="Linking only with:" + "mol_link_group" ) subbox = box.box() @@ -111,100 +102,98 @@ def draw(self, context): psys.settings.mol_other_link_active subbox.label(text=names.INITIAL_LINKING) row = subbox.row() - row.prop(psys.settings, "mol_link_length", text="search length") - row.prop(psys.settings, "mol_link_rellength", text="Relative") + row.prop(psys.settings, "mol_link_length") + row.prop(psys.settings, "mol_link_rellength") row = subbox.row() - row.prop(psys.settings, "mol_link_max", text="Max links") + row.prop(psys.settings, "mol_link_max") row = subbox.row() - row.prop(psys.settings, "mol_link_friction", text="Link friction") + row.prop(psys.settings, "mol_link_friction") layout.separator() row = subbox.row() - row.prop(psys.settings, "mol_link_tension", text="Tension") - row.prop(psys.settings, "mol_link_tensionrand", text="Rand Tension") + row.prop(psys.settings, "mol_link_tension") + row.prop(psys.settings, "mol_link_tensionrand") row = subbox.row() - row.prop(psys.settings, "mol_link_stiff", text="Stiff") - row.prop(psys.settings, "mol_link_stiffrand", text="Rand Stiff") + row.prop(psys.settings, "mol_link_stiff") + row.prop(psys.settings, "mol_link_stiffrand") #row = subbox.row() - #row.prop(psys.settings, "mol_link_stiffexp", text="Exponent") + #row.prop(psys.settings, "mol_link_stiffexp") row = subbox.row() - row.prop(psys.settings, "mol_link_damp", text="Damping") - row.prop(psys.settings, "mol_link_damprand", text="Rand Damping") + row.prop(psys.settings, "mol_link_damp") + row.prop(psys.settings, "mol_link_damprand") row = subbox.row() - row.prop(psys.settings, "mol_link_broken", text="broken") - row.prop(psys.settings, "mol_link_brokenrand", text="Rand Broken") + row.prop(psys.settings, "mol_link_broken") + row.prop(psys.settings, "mol_link_brokenrand") row = subbox.row() layout.separator() row = subbox.row() row.prop( psys.settings, - "mol_link_samevalue", - text="Same values for compression/expansion" + "mol_link_samevalue" ) row = subbox.row() row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_estiff", text="E Stiff") - row.prop(psys.settings, "mol_link_estiffrand", text="Rand E Stiff") + row.prop(psys.settings, "mol_link_estiff") + row.prop(psys.settings, "mol_link_estiffrand") #row = subbox.row() #row.enabled = not psys.settings.mol_link_samevalue - #row.prop(psys.settings, "mol_link_estiffexp", text="E Exponent") + #row.prop(psys.settings, "mol_link_estiffexp") row = subbox.row() row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_edamp", text="E Damping") - row.prop(psys.settings, "mol_link_edamprand", text="Rand E Damping") + row.prop(psys.settings, "mol_link_edamp") + row.prop(psys.settings, "mol_link_edamprand") row = subbox.row() row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_ebroken", text="E broken") - row.prop(psys.settings, "mol_link_ebrokenrand", text="Rand E Broken") + row.prop(psys.settings, "mol_link_ebroken") + row.prop(psys.settings, "mol_link_ebrokenrand") subbox = box.box() subbox.active = psys.settings.mol_links_active subbox.label(text=names.NEW_LINKING) row = subbox.row() - row.prop(psys.settings, "mol_relink_group", text="Only links with:") + row.prop(psys.settings, "mol_relink_group") row = subbox.row() - row.prop(psys.settings, "mol_relink_chance", text="% linking") - row.prop(psys.settings, "mol_relink_chancerand", text="Rand % linking") + row.prop(psys.settings, "mol_relink_chance") + row.prop(psys.settings, "mol_relink_chancerand") row = subbox.row() - row.prop(psys.settings, "mol_relink_max", text="Max links") + row.prop(psys.settings, "mol_relink_max") row = subbox.row() layout.separator() row = subbox.row() - row.prop(psys.settings,"mol_relink_tension",text = "Tension") - row.prop(psys.settings,"mol_relink_tensionrand",text = "Rand Tension") + row.prop(psys.settings,"mol_relink_tension") + row.prop(psys.settings,"mol_relink_tensionrand") row = subbox.row() - row.prop(psys.settings,"mol_relink_stiff",text = "Stiff") - row.prop(psys.settings,"mol_relink_stiffrand",text = "Rand Stiff") + row.prop(psys.settings,"mol_relink_stiff") + row.prop(psys.settings,"mol_relink_stiffrand") #row = subbox.row() - #row.prop(psys.settings, "mol_relink_stiffexp", text="Exp") + #row.prop(psys.settings, "mol_relink_stiffexp") row = subbox.row() - row.prop(psys.settings, "mol_relink_damp", text="Damping") - row.prop(psys.settings, "mol_relink_damprand", text="Rand Damping") + row.prop(psys.settings, "mol_relink_damp") + row.prop(psys.settings, "mol_relink_damprand") row = subbox.row() - row.prop(psys.settings, "mol_relink_broken", text="broken") - row.prop(psys.settings, "mol_relink_brokenrand", text="Rand broken") + row.prop(psys.settings, "mol_relink_broken") + row.prop(psys.settings, "mol_relink_brokenrand") row = subbox.row() layout.separator() row = subbox.row() row.prop( psys.settings, - "mol_relink_samevalue", - text="Same values for compression/expansion" + "mol_relink_samevalue" ) row = subbox.row() row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_estiff",text="E Stiff") - row.prop(psys.settings, "mol_relink_estiffrand",text="Rand E Stiff") + row.prop(psys.settings, "mol_relink_estiff") + row.prop(psys.settings, "mol_relink_estiffrand") #row = subbox.row() #row.enabled = not psys.settings.mol_relink_samevalue - #row.prop(psys.settings, "mol_relink_estiffexp", text="Exp") + #row.prop(psys.settings, "mol_relink_estiffexp") row = subbox.row() row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_edamp", text="E Damping") - row.prop(psys.settings, "mol_relink_edamprand", text="Rand E Damping") + row.prop(psys.settings, "mol_relink_edamp") + row.prop(psys.settings, "mol_relink_edamprand") row = subbox.row() row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_ebroken", text="E broken") - row.prop(psys.settings, "mol_relink_ebrokenrand", text="Rand E broken") + row.prop(psys.settings, "mol_relink_ebroken") + row.prop(psys.settings, "mol_relink_ebrokenrand") row = layout.row() row.label(text=names.UVS) @@ -240,14 +229,14 @@ def draw(self, context): #row.enabled = scn.mol_timescale_active #row.prop(scn,"timescale",text = "TimeScale") row = layout.row() - row.prop(scn, "mol_substep", text="Substeps") + row.prop(scn, "mol_substep") row.label(text='') row = layout.row() row.label(text=names.CPU_USED) - row.prop(scn, "mol_cpu", text="CPU") + row.prop(scn, "mol_cpu") row = layout.row() - row.prop(scn, "mol_bake", text="Bake all at ending") - row.prop(scn, "mol_render", text="Render at ending") + row.prop(scn, "mol_bake") + row.prop(scn, "mol_render") row = layout.row() if scn.mol_simrun == False and psys.point_cache.is_baked == False: @@ -332,13 +321,13 @@ def draw(self, context): text="Current systems have: {} particles".format(len(psys.particles)) ) row = subbox.row() - row.prop(psys.settings, "mol_var1", text="Current numbers of particles") + row.prop(psys.settings, "mol_var1") row = subbox.row() - row.prop(psys.settings,"mol_var2",text = "Current substep") + row.prop(psys.settings,"mol_var2") row = subbox.row() - row.prop(psys.settings,"mol_var3", text="Targeted numbers of particles") + row.prop(psys.settings,"mol_var3") diff = (psys.settings.mol_var3 / psys.settings.mol_var1) - factor = psys.settings.mol_var3 ** (1/3) / psys.settings.mol_var1 ** (1/3) + factor = psys.settings.mol_var3 ** (1 / 3) / psys.settings.mol_var1 ** (1 / 3) newsubstep = int(round(factor * psys.settings.mol_var2)) row = subbox.row() row.label( From bc2fcca5ca6772c1b8b4fcf264e4e7f42589e6c9 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 17:02:07 +0400 Subject: [PATCH 031/129] rename cmolcore to core --- .gitignore | 2 +- molecular/operators.py | 10 +++++----- sources/{cmolcore.pyx => core.pyx} | 0 sources/setup32.py | 3 +-- sources/setup64.py | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) rename sources/{cmolcore.pyx => core.pyx} (100%) diff --git a/.gitignore b/.gitignore index bd4b95a..04d9989 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ __pycache__ -cmolcore.pyd +core.pyd diff --git a/molecular/operators.py b/molecular/operators.py index 58a8bd2..d5a5336 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -8,9 +8,9 @@ from . import simulate try: - from . import cmolcore + from . import core except: - print("cmolcore not working") + print("core not working") class MolSimulate(bpy.types.Operator): @@ -50,7 +50,7 @@ def execute(self, context): etime = clock() print(" PackData take " + str(round(etime - mol_stime, 3)) + "sec") mol_stime = clock() - mol_report = cmolcore.init(mol_exportdata) + mol_report = core.init(mol_exportdata) etime = clock() print(" Export time take " + str(round(etime - mol_stime, 3)) + "sec") print(" total numbers of particles: " + str(mol_report)) @@ -175,7 +175,7 @@ def modal(self, context, event): scene.frame_set(frame=scene.frame_start) - cmolcore.memfree() + core.memfree() scene.mol_simrun = False mol_exportdata = scene.mol_exportdata mol_exportdata.clear() @@ -188,7 +188,7 @@ def modal(self, context, event): mol_exportdata = context.scene.mol_exportdata mol_exportdata.clear() simulate.pack_data(False) - mol_importdata = cmolcore.simulate(mol_exportdata) + mol_importdata = core.simulate(mol_exportdata) i = 0 for obj in bpy.data.objects: diff --git a/sources/cmolcore.pyx b/sources/core.pyx similarity index 100% rename from sources/cmolcore.pyx rename to sources/core.pyx diff --git a/sources/setup32.py b/sources/setup32.py index 3134d22..92df046 100644 --- a/sources/setup32.py +++ b/sources/setup32.py @@ -5,8 +5,7 @@ Cython.Compiler.Options.annotate = True -#ext_modules = [Extension("cmolcore", ["cmolcore.pyx"],extra_compile_args=['-march=i686','-fopenmp'],extra_link_args=['-fopenmp'])] -ext_modules = [Extension("cmolcore", ["cmolcore.pyx"],extra_compile_args=['-march=i686','-O3','-ffast-math','-fopenmp'],extra_link_args=['-fopenmp'])] +ext_modules = [Extension("core", ["core.pyx"],extra_compile_args=['-march=i686','-O3','-ffast-math','-fopenmp'],extra_link_args=['-fopenmp'])] setup( name = 'Molecular script', diff --git a/sources/setup64.py b/sources/setup64.py index 39306e1..7b3fed3 100644 --- a/sources/setup64.py +++ b/sources/setup64.py @@ -5,7 +5,7 @@ Cython.Compiler.Options.annotate = True -ext_modules = [Extension("cmolcore", ["cmolcore.pyx"],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] +ext_modules = [Extension("core", ["core.pyx"],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] setup( name = 'Molecular script', From ba7ef6d432b634e07c9d87e244592bb0defff9cf Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 21:42:43 +0400 Subject: [PATCH 032/129] free memory --- sources/core.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/core.pyx b/sources/core.pyx index 0d1d85b..65119a5 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -1490,10 +1490,10 @@ cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: newlinks += 1 # free(link) # free(neighbours) - # free(fakepar) - # free(link) - # free(par) - # free(par2) + free(fakepar) + free(link) + free(par) + free(par2) cdef struct Links: From 1adadee77a49e3c94eb58b6bf6796b07ece78508 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 21:53:42 +0400 Subject: [PATCH 033/129] fix bug in memory free --- sources/core.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/core.pyx b/sources/core.pyx index 65119a5..06c77f0 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -1492,8 +1492,8 @@ cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: # free(neighbours) free(fakepar) free(link) - free(par) - free(par2) + # free(par) + # free(par2) cdef struct Links: From 5ccd791507ea5385c5805d3c0aa02f28e1a3577d Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 8 Oct 2018 21:56:25 +0400 Subject: [PATCH 034/129] 1.0.5 --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 9cbfb6c..08a65cc 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", - "version": (1, 0, 4), + "version": (1, 0, 5), "blender": (2, 7, 9), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), From 410d782f280918924c696b553721236ed0956a76 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 2 Mar 2019 15:20:56 +0300 Subject: [PATCH 035/129] support python 3.7 (blender daily build) --- .gitignore | 2 +- molecular/operators.py | 18 ++++++++++++++---- sources/setup.bat | 29 +++++++++++++++++++++++++++++ sources/setup.py | 29 +++++++++++++++++++++++++++++ sources/setup32.bat | 1 - sources/setup32.py | 14 -------------- sources/setup64.bat | 1 - sources/setup64.py | 14 -------------- 8 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 sources/setup.bat create mode 100644 sources/setup.py delete mode 100644 sources/setup32.bat delete mode 100644 sources/setup32.py delete mode 100644 sources/setup64.bat delete mode 100644 sources/setup64.py diff --git a/.gitignore b/.gitignore index 04d9989..94a8638 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ __pycache__ -core.pyd +*.pyd diff --git a/molecular/operators.py b/molecular/operators.py index d5a5336..8b9a3cf 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -1,4 +1,6 @@ +import sys +import platform from time import clock, sleep, strftime, gmtime import bpy @@ -7,10 +9,18 @@ from . import simulate -try: - from . import core -except: - print("core not working") + +bit_depth = platform.architecture()[0] +if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': + from . import core_35_64 as core +elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '64bit': + from . import core_37_64 as core +elif sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '32bit': + from . import core_35_32 as core +elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '32bit': + from . import core_37_32 as core +else: + raise BaseException('Unsupported python version') class MolSimulate(bpy.types.Operator): diff --git a/sources/setup.bat b/sources/setup.bat new file mode 100644 index 0000000..f706d74 --- /dev/null +++ b/sources/setup.bat @@ -0,0 +1,29 @@ +del core.html +del core.c +rd /s /q build + +"C:\Program Project\Python 3.5.4 64 bit\python.exe" setup.py build_ext --inplace +del core.html +del core.c +rd /s /q build +ren core_35_64.cp35-win_amd64.pyd core_35_64.pyd + +"C:\Program Project\Python 3.7.2 64 bit\python.exe" setup.py build_ext --inplace +del core.html +del core.c +rd /s /q build +ren core_37_64.cp37-win_amd64.pyd core_37_64.pyd + +"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup.py build_ext --inplace +del core.html +del core.c +rd /s /q build +ren core_35_32.cp35-win_amd32.pyd core_35_32.pyd + +"C:\Program Project\Python 3.7.2 32 bit\python.exe" setup.py build_ext --inplace +del core.html +del core.c +rd /s /q build +ren core_37_32.cp37-win_amd32.pyd core_37_32.pyd + +pause \ No newline at end of file diff --git a/sources/setup.py b/sources/setup.py new file mode 100644 index 0000000..ded1a23 --- /dev/null +++ b/sources/setup.py @@ -0,0 +1,29 @@ +import sys +import platform +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext +import Cython.Compiler.Options + +Cython.Compiler.Options.annotate = True + +bit_depth = platform.architecture()[0] + +if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': + module_name = 'core_35_64' +elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '64bit': + module_name = 'core_37_64' +elif sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '32bit': + module_name = 'core_35_32' +elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '32bit': + module_name = 'core_37_32' +else: + raise BaseException('Unsupported python version') + +ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] + +setup( +name = 'Molecular script', +cmdclass = {'build_ext': build_ext}, +ext_modules = ext_modules +) diff --git a/sources/setup32.bat b/sources/setup32.bat deleted file mode 100644 index c5bb9f7..0000000 --- a/sources/setup32.bat +++ /dev/null @@ -1 +0,0 @@ -"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup32.py build_ext --inplace \ No newline at end of file diff --git a/sources/setup32.py b/sources/setup32.py deleted file mode 100644 index 92df046..0000000 --- a/sources/setup32.py +++ /dev/null @@ -1,14 +0,0 @@ -from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext -import Cython.Compiler.Options - -Cython.Compiler.Options.annotate = True - -ext_modules = [Extension("core", ["core.pyx"],extra_compile_args=['-march=i686','-O3','-ffast-math','-fopenmp'],extra_link_args=['-fopenmp'])] - -setup( - name = 'Molecular script', - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) diff --git a/sources/setup64.bat b/sources/setup64.bat deleted file mode 100644 index 8499930..0000000 --- a/sources/setup64.bat +++ /dev/null @@ -1 +0,0 @@ -"C:\Program Project\Python 3.5.4 64 bit\python.exe" setup64.py build_ext --inplace \ No newline at end of file diff --git a/sources/setup64.py b/sources/setup64.py deleted file mode 100644 index 7b3fed3..0000000 --- a/sources/setup64.py +++ /dev/null @@ -1,14 +0,0 @@ -from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext -import Cython.Compiler.Options - -Cython.Compiler.Options.annotate = True - -ext_modules = [Extension("core", ["core.pyx"],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] - -setup( - name = 'Molecular script', - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) From 40563fcad76c137e86316021b0f93568bbc11a8c Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 2 Mar 2019 17:12:15 +0300 Subject: [PATCH 036/129] support win 32 bit --- sources/setup.bat | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sources/setup.bat b/sources/setup.bat index f706d74..00e0fdd 100644 --- a/sources/setup.bat +++ b/sources/setup.bat @@ -2,28 +2,32 @@ del core.html del core.c rd /s /q build +del core_35_64.pyd "C:\Program Project\Python 3.5.4 64 bit\python.exe" setup.py build_ext --inplace del core.html del core.c rd /s /q build ren core_35_64.cp35-win_amd64.pyd core_35_64.pyd +del core_37_64.pyd "C:\Program Project\Python 3.7.2 64 bit\python.exe" setup.py build_ext --inplace del core.html del core.c rd /s /q build ren core_37_64.cp37-win_amd64.pyd core_37_64.pyd +del core_35_32.pyd "C:\Program Project\Python 3.5.4 32 bit\python.exe" setup.py build_ext --inplace del core.html del core.c rd /s /q build -ren core_35_32.cp35-win_amd32.pyd core_35_32.pyd +ren core_35_32.cp35-win32.pyd core_35_32.pyd +del core_37_32.pyd "C:\Program Project\Python 3.7.2 32 bit\python.exe" setup.py build_ext --inplace del core.html del core.c rd /s /q build -ren core_37_32.cp37-win_amd32.pyd core_37_32.pyd +ren core_37_32.cp37-win32.pyd core_37_32.pyd pause \ No newline at end of file From d79e000692cfb74c6cfa5430357f6efaa0090301 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 2 Mar 2019 17:29:11 +0300 Subject: [PATCH 037/129] make release script --- make_release.py | 12 ++++++++++++ molecular/__init__.py | 20 ++++++++++++++------ sources/setup.bat | 5 +++++ 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 make_release.py diff --git a/make_release.py b/make_release.py new file mode 100644 index 0000000..70e6a33 --- /dev/null +++ b/make_release.py @@ -0,0 +1,12 @@ + +from molecular import bl_info +from zipfile import ZipFile, ZIP_DEFLATED +from os import path, walk + + +with ZipFile('molecular_{}_win'.format(('.'.join(map(str, bl_info['version'])))) + '.zip', 'w') as z: + for root, _, files in walk('molecular'): + for file in files: + if not file.endswith('.py') and not file.endswith('.pyd'): + continue + z.write(path.join(root, file), compress_type=ZIP_DEFLATED) diff --git a/molecular/__init__.py b/molecular/__init__.py index 08a65cc..34c959e 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -26,17 +26,18 @@ "warning": "", # used for warning icon and text in addons panel "wiki_url": "http://pyroevil.com/molecular-script-docs/", "tracker_url": "http://pyroevil.com/contact/" , - "category": "Object"} + "category": "Object" +} -import bpy +def register(): -from . import properties -from . import ui -from . import operators + import bpy + from . import properties + from . import ui + from . import operators -def register(): properties.define_props() bpy.utils.register_class(operators.MolSimulateModal) bpy.utils.register_class(operators.MolSimulate) @@ -46,6 +47,13 @@ def register(): def unregister(): + + import bpy + + from . import properties + from . import ui + from . import operators + bpy.utils.unregister_class(operators.MolSimulateModal) bpy.utils.unregister_class(operators.MolSimulate) bpy.utils.unregister_class(operators.MolSetGlobalUV) diff --git a/sources/setup.bat b/sources/setup.bat index 00e0fdd..ab6c972 100644 --- a/sources/setup.bat +++ b/sources/setup.bat @@ -30,4 +30,9 @@ del core.c rd /s /q build ren core_37_32.cp37-win32.pyd core_37_32.pyd +move core_35_64.pyd ..\molecular\core_35_64.pyd +move core_37_64.pyd ..\molecular\core_37_64.pyd +move core_35_32.pyd ..\molecular\core_35_32.pyd +move core_37_32.pyd ..\molecular\core_37_32.pyd + pause \ No newline at end of file From 78a50ee01da69844e8ace90a1c490dece9f3d274 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sat, 2 Mar 2019 17:30:47 +0300 Subject: [PATCH 038/129] 1.0.6 --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 34c959e..22b7642 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", - "version": (1, 0, 5), + "version": (1, 0, 6), "blender": (2, 7, 9), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), From 68e643b4de8e3bcdc9b19a6fd7517b0201c6fcd9 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 4 Mar 2019 20:13:46 +0300 Subject: [PATCH 039/129] support blender 2.80 --- molecular/__init__.py | 2 +- molecular/operators.py | 92 +++++++++++++++++++++++++++++++++--------- molecular/simulate.py | 6 +++ molecular/ui.py | 16 +++++--- molecular/utils.py | 6 +++ 5 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 molecular/utils.py diff --git a/molecular/__init__.py b/molecular/__init__.py index 22b7642..106ae59 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -20,7 +20,7 @@ "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", "version": (1, 0, 6), - "blender": (2, 7, 9), + "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), "warning": "", # used for warning icon and text in addons panel diff --git a/molecular/operators.py b/molecular/operators.py index 8b9a3cf..615c56f 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -8,6 +8,7 @@ from mathutils.geometry import barycentric_transform as barycentric from . import simulate +from .utils import is_blender_28 bit_depth = platform.architecture()[0] @@ -75,8 +76,12 @@ class MolSetGlobalUV(bpy.types.Operator): def execute(self, context): scene = context.scene - object = context.object - psys = object.particle_systems.active + obj = context.object + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + + psys = obj.particle_systems.active coord = [0, 0, 0] * len(psys.particles) psys.particles.foreach_get("location", coord) psys.particles.foreach_set("angular_velocity", coord) @@ -90,44 +95,71 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): scene = context.scene - object = context.object - scene.mol_objuvbake = object.name - scene.mol_psysuvbake = object.particle_systems.active.name + obj = context.object + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + + scene.mol_objuvbake = obj.name + scene.mol_psysuvbake = obj.particle_systems.active.name - if not object.data.uv_layers.active: + if not obj.data.uv_layers.active: return {'FINISHED'} - print(' start bake uv from:',object.name) + print(' start bake uv from:', obj.name) - obdata = object.data.copy() + obdata = obj.data.copy() object2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) - object2.matrix_world = object.matrix_world + object2.matrix_world = obj.matrix_world - context.scene.objects.link(object2) + if is_blender_28(): + context.scene.collection.objects.link(object2) + else: + context.scene.objects.link(object2) mod = object2.modifiers.new("tri_for_uv", "TRIANGULATE") mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' - newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) + if is_blender_28(): + newmesh = object2.to_mesh(bpy.context.depsgraph, True) + else: + newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) object2.data = newmesh context.scene.update() - psys = object.particle_systems[scene.mol_psysuvbake] + psys = obj.particle_systems[scene.mol_psysuvbake] for par in psys.particles: - parloc = (par.location * object2.matrix_world) - object2.location + + if is_blender_28(): + parloc = (par.location @ object2.matrix_world) - object2.location + else: + parloc = (par.location * object2.matrix_world) - object2.location + point = object2.closest_point_on_mesh(parloc) vindex1 = object2.data.polygons[point[3]].vertices[0] vindex2 = object2.data.polygons[point[3]].vertices[1] vindex3 = object2.data.polygons[point[3]].vertices[2] - v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() - v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() - v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() + + if is_blender_28(): + v1 = (object2.matrix_world @ object2.data.vertices[vindex1].co).to_tuple() + v2 = (object2.matrix_world @ object2.data.vertices[vindex2].co).to_tuple() + v3 = (object2.matrix_world @ object2.data.vertices[vindex3].co).to_tuple() + else: + v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() + v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() + v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() + uvindex1 = object2.data.polygons[point[3]].loop_start + 0 uvindex2 = object2.data.polygons[point[3]].loop_start + 1 uvindex3 = object2.data.polygons[point[3]].loop_start + 2 uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() - p = object2.matrix_world * point[1] + + if is_blender_28(): + p = object2.matrix_world @ point[1] + else: + p = object2.matrix_world * point[1] + v1 = Vector(v1) v2 = Vector(v2) v3 = Vector(v3) @@ -135,13 +167,21 @@ def execute(self, context): uv2 = Vector(uv2) uv3 = Vector(uv3) newuv = barycentric(p, v1, v2, v3, uv1, uv2, uv3) - parloc = par.location * object2.matrix_world + + if is_blender_28(): + parloc = par.location @ object2.matrix_world + else: + parloc = par.location * object2.matrix_world + dist = (Vector((parloc[0] - p[0], parloc[1] - p[1], parloc[2] - p[2]))).length newuv[2] = dist newuv = newuv.to_tuple() par.angular_velocity = newuv - scene.objects.unlink(object2) + if is_blender_28(): + scene.collection.objects.unlink(object2) + else: + scene.objects.unlink(object2) bpy.data.objects.remove(object2) bpy.data.meshes.remove(newmesh) bpy.data.meshes.remove(obdata) @@ -164,6 +204,10 @@ def modal(self, context, event): if frame_current == frame_end and scene.mol_bake: fake_context = context.copy() for obj in bpy.data.objects: + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): fake_context["point_cache"] = psys.point_cache @@ -172,6 +216,10 @@ def modal(self, context, event): scene.frame_end = scene.mol_old_endframe for obj in bpy.data.objects: + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + for psys in obj.particle_systems: if psys.settings.mol_bakeuv: scene.mol_objuvbake = obj.name @@ -202,6 +250,10 @@ def modal(self, context, event): i = 0 for obj in bpy.data.objects: + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): psys.particles.foreach_set('velocity', mol_importdata[1][i]) @@ -238,7 +290,7 @@ def modal(self, context, event): return {'PASS_THROUGH'} def execute(self, context): - self._timer = context.window_manager.event_timer_add(0.000000001, context.window) + self._timer = context.window_manager.event_timer_add(0.000000001, window=context.window) context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} diff --git a/molecular/simulate.py b/molecular/simulate.py index a94768a..233092c 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -3,12 +3,18 @@ import bpy +from .utils import is_blender_28 + def pack_data(initiate): psyslen = 0 parnum = 0 scene = bpy.context.scene for obj in bpy.data.objects: + + if is_blender_28(): + obj = bpy.context.depsgraph.objects.get(obj.name) + for psys in obj.particle_systems: if psys.settings.mol_matter != "-1": psys.settings.mol_density = float(psys.settings.mol_matter) diff --git a/molecular/ui.py b/molecular/ui.py index f4485bd..46a2988 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -2,6 +2,7 @@ import bpy from . import names +from .utils import is_blender_28 class MolecularPanel(bpy.types.Panel): @@ -205,7 +206,7 @@ def draw(self, context): psys.settings, "mol_bakeuv", text="Bake UV at ending (current: \"{0}\")".format( - obj.data.uv_textures.active.name + obj.data.uv_layers.active.name ) ) else: @@ -239,11 +240,16 @@ def draw(self, context): row.prop(scn, "mol_render") row = layout.row() + if is_blender_28(): + icon = 'PARTICLE_DATA' + else: + icon = 'RADIO' + if scn.mol_simrun == False and psys.point_cache.is_baked == False: row.enabled = True row.operator( "object.mol_simulate", - icon='RADIO', + icon=icon, text="Start Molecular Simulation" ) row = layout.row() @@ -254,7 +260,7 @@ def draw(self, context): row.enabled = False row.operator( "object.mol_simulate", - icon = 'RADIO', + icon=icon, text="Simulation baked" ) row = layout.row() @@ -265,7 +271,7 @@ def draw(self, context): row.enabled = False row.operator( "object.mol_simulate", - icon = 'RADIO', + icon=icon, text="Process: {} left".format(scn.mol_timeremain) ) row = layout.row() @@ -301,7 +307,7 @@ def draw(self, context): "object.mol_set_active_uv", icon='GROUP_UVS', text = "Set Active UV (current: \"{0}\")".format( - obj.data.uv_textures.active.name + obj.data.uv_layers.active.name ) ) else: diff --git a/molecular/utils.py b/molecular/utils.py new file mode 100644 index 0000000..7c7c331 --- /dev/null +++ b/molecular/utils.py @@ -0,0 +1,6 @@ + +import bpy + + +def is_blender_28(): + return bpy.data.version[0] == 2 and bpy.data.version[1] >= 80 From bba0e7759d2595b3891a0f695c9d08cec97bb8b8 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Mon, 4 Mar 2019 20:16:34 +0300 Subject: [PATCH 040/129] 1.0.7 --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 106ae59..578f3a0 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", - "version": (1, 0, 6), + "version": (1, 0, 7), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), From cd716707bb8d42144ac62fcb7cb447a89620aba0 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Sun, 21 Apr 2019 20:02:53 +0400 Subject: [PATCH 041/129] fix errors in 2.80 --- molecular/operators.py | 6 ++++++ molecular/simulate.py | 2 ++ 2 files changed, 8 insertions(+) diff --git a/molecular/operators.py b/molecular/operators.py index 615c56f..2a7be89 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -207,6 +207,8 @@ def modal(self, context, event): if is_blender_28(): obj = bpy.context.depsgraph.objects.get(obj.name) + if not obj: + continue for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): @@ -219,6 +221,8 @@ def modal(self, context, event): if is_blender_28(): obj = bpy.context.depsgraph.objects.get(obj.name) + if not obj: + continue for psys in obj.particle_systems: if psys.settings.mol_bakeuv: @@ -253,6 +257,8 @@ def modal(self, context, event): if is_blender_28(): obj = bpy.context.depsgraph.objects.get(obj.name) + if not obj: + continue for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): diff --git a/molecular/simulate.py b/molecular/simulate.py index 233092c..50552ee 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -14,6 +14,8 @@ def pack_data(initiate): if is_blender_28(): obj = bpy.context.depsgraph.objects.get(obj.name) + if not obj: + continue for psys in obj.particle_systems: if psys.settings.mol_matter != "-1": From 0eae152b6d9600bd4bf2ff2b0aefe5805b6074a6 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 12 May 2019 13:23:51 +0200 Subject: [PATCH 042/129] adapt setup.py for mac (and linux) Note, under mac it is not so trivial to use openmp, so omitting here for now. --- sources/setup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index ded1a23..c89a713 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -8,6 +8,7 @@ Cython.Compiler.Options.annotate = True bit_depth = platform.architecture()[0] +os_name = platform.architecture()[1] if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': module_name = 'core_35_64' @@ -20,8 +21,11 @@ else: raise BaseException('Unsupported python version') -ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] - +if os_name == "WindowsPE": + ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] +else: + #ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['-O3','-fopenmp','-msse4.2','-ffast-math'])] + ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['-O3','-msse4.2','-ffast-math'])] setup( name = 'Molecular script', cmdclass = {'build_ext': build_ext}, From da838174e1aa6717ad4170d73d28b5725cd2ffdb Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 12 May 2019 13:27:39 +0200 Subject: [PATCH 043/129] Create make_release_linux_mac.py Note, hardcoded for python 3.7 and 64bits for now, tested under mac only --- make_release_linux_mac.py | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 make_release_linux_mac.py diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py new file mode 100644 index 0000000..6f9cc17 --- /dev/null +++ b/make_release_linux_mac.py @@ -0,0 +1,40 @@ +from molecular import bl_info +from zipfile import ZipFile, ZIP_DEFLATED +from os import path, walk, remove, chdir, getcwd +import shutil +import platform +from subprocess import Popen, PIPE + +is_linux = platform.architecture()[1] == "ELF" + +name = 'mac' +if is_linux: + name = 'linux' + +chdir(getcwd()+"/sources") + +try: + remove("core.html") + remove("core.c") + shutil.rmtree("build") +except: + pass + +#TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN +#into the include folder of blenders python, too + +with Popen(["python3.7m", "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: + print(proc.stdout.read()) + if is_linux: #TODO, test + shutil.move("core_37_64.cpython-37m.so", "../molecular/core_37_64.cpython-37m.so") + else: + shutil.move("core_37_64.cpython-37m-darwin.so", "../molecular/core_37_64.cpython-37m-darwin.so") + + chdir("..") + + with ZipFile('molecular_{}_'.format(('.'.join(map(str, bl_info['version'])))) + name +'.zip', 'w') as z: + for root, _, files in walk('molecular'): + for file in files: + if not file.endswith('.py') and not file.endswith('.so'): + continue + z.write(path.join(root, file), compress_type=ZIP_DEFLATED) From bc9edf792904dfa152e72230ad5fde2756a2e558 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 12 May 2019 13:28:15 +0200 Subject: [PATCH 044/129] Rename make_release.py to make_release_win.py --- make_release.py => make_release_win.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename make_release.py => make_release_win.py (100%) diff --git a/make_release.py b/make_release_win.py similarity index 100% rename from make_release.py rename to make_release_win.py From dccfacf3ec1696bd1b2e92433ce7af8e8cb91264 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 12 May 2019 14:42:31 +0200 Subject: [PATCH 045/129] add platform.system() == "Linux" check just in case platform.architecture()[1] is not "ELF" for some reason --- make_release_linux_mac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py index 6f9cc17..ea24cc7 100644 --- a/make_release_linux_mac.py +++ b/make_release_linux_mac.py @@ -5,7 +5,7 @@ import platform from subprocess import Popen, PIPE -is_linux = platform.architecture()[1] == "ELF" +is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" name = 'mac' if is_linux: From c8c0d2f117bac852a13b87047aa7af734d3d79f6 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 12 May 2019 15:45:56 +0200 Subject: [PATCH 046/129] fix, use "expected" linux .so name now needs to have x86_64-linux-gnu in its name --- make_release_linux_mac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py index ea24cc7..8468551 100644 --- a/make_release_linux_mac.py +++ b/make_release_linux_mac.py @@ -26,7 +26,7 @@ with Popen(["python3.7m", "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) if is_linux: #TODO, test - shutil.move("core_37_64.cpython-37m.so", "../molecular/core_37_64.cpython-37m.so") + shutil.move("core_37_64.cpython-37m-x86_64-linux-gnu.so", "../molecular/core_37_64.cpython-37m-x86_64-linux-gnu.so") else: shutil.move("core_37_64.cpython-37m-darwin.so", "../molecular/core_37_64.cpython-37m-darwin.so") From 64d17d5be2ebd58813a2d2dbf4db84e7f29791cc Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Mon, 17 Jun 2019 18:07:51 +0200 Subject: [PATCH 047/129] molecular should work again now in 2.8 --- .gitignore | 4 ++++ make_release_linux_mac.py | 14 ++++++++++++ molecular/operators.py | 47 +++++++++++++-------------------------- molecular/simulate.py | 14 +++++------- molecular/ui.py | 9 +++++--- molecular/utils.py | 9 ++++++++ sources/core.pyx | 12 +++++++++- 7 files changed, 64 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index 94a8638..cc5b7b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ __pycache__ *.pyd +build +*.c +*.html +.vscode diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py index 8468551..1154b79 100644 --- a/make_release_linux_mac.py +++ b/make_release_linux_mac.py @@ -14,6 +14,10 @@ chdir(getcwd()+"/sources") try: + if is_linux: + remove("core_37_64.cpython-37m-x86_64-linux-gnu.so") + else: + remove("core_37_64.cpython-37m-darwin.so") remove("core.html") remove("core.c") shutil.rmtree("build") @@ -38,3 +42,13 @@ if not file.endswith('.py') and not file.endswith('.so'): continue z.write(path.join(root, file), compress_type=ZIP_DEFLATED) + + chdir(getcwd()+"/molecular") + try: + if is_linux: + remove("core_37_64.cpython-37m-x86_64-linux-gnu.so") + else: + remove("core_37_64.cpython-37m-darwin.so") + except: + pass + chdir("..") diff --git a/molecular/operators.py b/molecular/operators.py index 2a7be89..80f0803 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -8,7 +8,7 @@ from mathutils.geometry import barycentric_transform as barycentric from . import simulate -from .utils import is_blender_28 +from .utils import is_blender_28, get_object bit_depth = platform.architecture()[0] @@ -57,7 +57,7 @@ def execute(self, context): mol_exportdata.clear() mol_exportdata.append([fps, mol_substep, 0, 0, cpu]) mol_stime = clock() - simulate.pack_data(True) + simulate.pack_data(context, True) etime = clock() print(" PackData take " + str(round(etime - mol_stime, 3)) + "sec") mol_stime = clock() @@ -76,10 +76,7 @@ class MolSetGlobalUV(bpy.types.Operator): def execute(self, context): scene = context.scene - obj = context.object - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) + obj = get_object(context, context.object) psys = obj.particle_systems.active coord = [0, 0, 0] * len(psys.particles) @@ -95,10 +92,7 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): scene = context.scene - obj = context.object - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) + obj = get_object(context, context.object) scene.mol_objuvbake = obj.name scene.mol_psysuvbake = obj.particle_systems.active.name @@ -120,7 +114,8 @@ def execute(self, context): mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' if is_blender_28(): - newmesh = object2.to_mesh(bpy.context.depsgraph, True) + depsgraph = bpy.context.evaluated_depsgraph_get() + newmesh = object2.to_mesh(True, depsgraph) else: newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) object2.data = newmesh @@ -203,26 +198,17 @@ def modal(self, context, event): if event.type == 'ESC' or frame_current == frame_end: if frame_current == frame_end and scene.mol_bake: fake_context = context.copy() - for obj in bpy.data.objects: - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) - if not obj: - continue - + for ob in bpy.data.objects: + obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): fake_context["point_cache"] = psys.point_cache bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 scene.frame_end = scene.mol_old_endframe - - for obj in bpy.data.objects: - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) - if not obj: - continue + #scene.update() + for ob in bpy.data.objects: + obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_bakeuv: @@ -245,20 +231,17 @@ def modal(self, context, event): return self.cancel(context) if event.type == 'TIMER': + #scene.update() if frame_current == scene.frame_start: scene.mol_stime = clock() mol_exportdata = context.scene.mol_exportdata mol_exportdata.clear() - simulate.pack_data(False) + simulate.pack_data(context, False) mol_importdata = core.simulate(mol_exportdata) i = 0 - for obj in bpy.data.objects: - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) - if not obj: - continue + for ob in bpy.data.objects: + obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): diff --git a/molecular/simulate.py b/molecular/simulate.py index 50552ee..d15fb27 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -3,19 +3,15 @@ import bpy -from .utils import is_blender_28 +from .utils import is_blender_28, get_object -def pack_data(initiate): +def pack_data(context, initiate): psyslen = 0 parnum = 0 - scene = bpy.context.scene - for obj in bpy.data.objects: - - if is_blender_28(): - obj = bpy.context.depsgraph.objects.get(obj.name) - if not obj: - continue + scene = context.scene + for ob in bpy.data.objects: + obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_matter != "-1": diff --git a/molecular/ui.py b/molecular/ui.py index 46a2988..62ae924 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -2,7 +2,7 @@ import bpy from . import names -from .utils import is_blender_28 +from .utils import is_blender_28, get_object class MolecularPanel(bpy.types.Panel): @@ -32,6 +32,9 @@ def draw(self, context): psys = obj.particle_systems.active if psys is None: return + #for the data + psys_eval = get_object(context, context.object).particle_systems.active + layout.enabled = psys.settings.mol_active row = layout.row() row.label(text=names.DENSITY) @@ -55,7 +58,7 @@ def draw(self, context): pmass = (psys.settings.particle_size ** 3) * psys.settings.mol_density row = subbox.row() weight_text = "Total system approx weight: {0:.4} kg".format( - len(psys.particles) * pmass + len(psys_eval.particles) * pmass ) row.label(icon="INFO", text=weight_text) row = layout.row() @@ -324,7 +327,7 @@ def draw(self, context): row = subbox.row() row.label( icon='INFO', - text="Current systems have: {} particles".format(len(psys.particles)) + text="Current systems have: {} particles".format(len(psys_eval.particles)) ) row = subbox.row() row.prop(psys.settings, "mol_var1") diff --git a/molecular/utils.py b/molecular/utils.py index 7c7c331..2b628df 100644 --- a/molecular/utils.py +++ b/molecular/utils.py @@ -4,3 +4,12 @@ def is_blender_28(): return bpy.data.version[0] == 2 and bpy.data.version[1] >= 80 + +def get_object(context, obj, update=True): + if is_blender_28(): + if update: + context.view_layer.update() + depsgraph = context.evaluated_depsgraph_get() + return obj.evaluated_get(depsgraph) + else: + return obj diff --git a/sources/core.pyx b/sources/core.pyx index 06c77f0..14197d2 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -41,7 +41,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.01") +print("cmolcore imported with success! v1.07") cpdef init(importdata): @@ -954,6 +954,14 @@ cdef void solve_link(Particle *par)nogil: Force2[2] = -ForceZ ratio1 = (par2.mass/(par1.mass + par2.mass)) ratio2 = (par1.mass/(par1.mass + par2.mass)) + + if par1.state == 3: #dead particle, correct velocity ratio of alive partner + ratio1 = 0 + ratio2 = 1 + elif par2.state == 3: + ratio1 = 1 + ratio2 = 0 + par1.vel[0] += Force1[0] * ratio1 par1.vel[1] += Force1[1] * ratio1 par1.vel[2] += Force1[2] * ratio1 @@ -1381,6 +1389,8 @@ cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: neighboursnum = 1 for ii in xrange(neighboursnum): + if par.links_activnum >= max_link: + break if parothers_id == -1: par2 = &parlist[neighbours[ii]] tension = (par.sys.link_tension + par2.sys.link_tension) / 2 From 90986134b75158310c96d0a91e980b81249483b1 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Mon, 17 Jun 2019 18:28:20 +0200 Subject: [PATCH 048/129] attempt to automate windows build, too --- make_release_win.py | 43 +++++++++++++++++++++++++++++++++++-------- sources/setup.py | 1 + 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/make_release_win.py b/make_release_win.py index 70e6a33..13bf77c 100644 --- a/make_release_win.py +++ b/make_release_win.py @@ -1,12 +1,39 @@ - from molecular import bl_info from zipfile import ZipFile, ZIP_DEFLATED -from os import path, walk +from os import path, walk, remove, chdir, getcwd +import shutil +from subprocess import Popen, PIPE + +chdir(getcwd()+"\\sources") + +try: + remove("core_37_64.cp37-win_amd64.pyd") + remove("core.html") + remove("core.c") + shutil.rmtree("build") +except: + pass + +#TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN +#into the include folder of blenders python, too + +with Popen(["python3.7", "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: + print(proc.stdout.read()) + + shutil.move("core_37_64.cp37-win_amd64.pyd", "..\\molecular\\core_37_64.cp37-win_amd64.pyd") + + chdir("..") + with ZipFile('molecular_{}_'.format(('.'.join(map(str, bl_info['version'])))) + 'win.zip', 'w') as z: + for root, _, files in walk('molecular'): + for file in files: + if not file.endswith('.py') and not file.endswith('.pyd'): + continue + z.write(path.join(root, file), compress_type=ZIP_DEFLATED) -with ZipFile('molecular_{}_win'.format(('.'.join(map(str, bl_info['version'])))) + '.zip', 'w') as z: - for root, _, files in walk('molecular'): - for file in files: - if not file.endswith('.py') and not file.endswith('.pyd'): - continue - z.write(path.join(root, file), compress_type=ZIP_DEFLATED) + chdir(getcwd()+"\\molecular") + try: + remove("core_37_64.cp37-win_amd64.pyd") + except: + pass + chdir("..") diff --git a/sources/setup.py b/sources/setup.py index c89a713..626cb5d 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -1,5 +1,6 @@ import sys import platform +import setuptools from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext From 6251559f41e089b0c823c67615e18f990853baa9 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Mon, 17 Jun 2019 19:21:44 +0200 Subject: [PATCH 049/129] use sys.executable for subprocess --- make_release_linux_mac.py | 3 ++- make_release_win.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py index 1154b79..fa59891 100644 --- a/make_release_linux_mac.py +++ b/make_release_linux_mac.py @@ -3,6 +3,7 @@ from os import path, walk, remove, chdir, getcwd import shutil import platform +import sys from subprocess import Popen, PIPE is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" @@ -27,7 +28,7 @@ #TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN #into the include folder of blenders python, too -with Popen(["python3.7m", "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: +with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) if is_linux: #TODO, test shutil.move("core_37_64.cpython-37m-x86_64-linux-gnu.so", "../molecular/core_37_64.cpython-37m-x86_64-linux-gnu.so") diff --git a/make_release_win.py b/make_release_win.py index 13bf77c..2c41167 100644 --- a/make_release_win.py +++ b/make_release_win.py @@ -2,6 +2,7 @@ from zipfile import ZipFile, ZIP_DEFLATED from os import path, walk, remove, chdir, getcwd import shutil +import sys from subprocess import Popen, PIPE chdir(getcwd()+"\\sources") @@ -17,7 +18,7 @@ #TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN #into the include folder of blenders python, too -with Popen(["python3.7", "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: +with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) shutil.move("core_37_64.cp37-win_amd64.pyd", "..\\molecular\\core_37_64.cp37-win_amd64.pyd") From e388c9c79a0a5e35e7d39f777997f95db2b650b7 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Mon, 17 Jun 2019 22:19:13 +0200 Subject: [PATCH 050/129] fix for linux build script, and added author --- molecular/__init__.py | 2 +- sources/setup.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 578f3a0..ed39d46 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -18,7 +18,7 @@ bl_info = { "name": "Molecular script", - "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend", + "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend, Martin Felke(scorpion81)", "version": (1, 0, 7), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", diff --git a/sources/setup.py b/sources/setup.py index 626cb5d..c34b2bb 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -1,6 +1,13 @@ import sys import platform -import setuptools + +bit_depth = platform.architecture()[0] +os_name = platform.architecture()[1] + +if os_name == "WindowsPE": + #only needed under windows + import setuptools + from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext @@ -8,9 +15,6 @@ Cython.Compiler.Options.annotate = True -bit_depth = platform.architecture()[0] -os_name = platform.architecture()[1] - if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': module_name = 'core_35_64' elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '64bit': From 6ef533013a602b0767c0b116a27cc4863e8be913 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Tue, 18 Jun 2019 16:25:30 +0200 Subject: [PATCH 051/129] fix to reset particle cache prior to resimulation --- molecular/__init__.py | 2 +- molecular/operators.py | 5 ++++- molecular/utils.py | 12 +++++++++--- sources/core.pyx | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index ed39d46..21fcaf2 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend, Martin Felke(scorpion81)", - "version": (1, 0, 7), + "version": (1, 0, 8), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), diff --git a/molecular/operators.py b/molecular/operators.py index 80f0803..2c27d36 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -8,7 +8,7 @@ from mathutils.geometry import barycentric_transform as barycentric from . import simulate -from .utils import is_blender_28, get_object +from .utils import is_blender_28, get_object, destroy_caches bit_depth = platform.architecture()[0] @@ -29,6 +29,9 @@ class MolSimulate(bpy.types.Operator): bl_label = "Mol Simulate" def execute(self, context): + for ob in bpy.data.objects: + destroy_caches(ob) + print("Molecular Sim start--------------------------------------------------") mol_stime = clock() scene = context.scene diff --git a/molecular/utils.py b/molecular/utils.py index 2b628df..4f28bac 100644 --- a/molecular/utils.py +++ b/molecular/utils.py @@ -5,11 +5,17 @@ def is_blender_28(): return bpy.data.version[0] == 2 and bpy.data.version[1] >= 80 -def get_object(context, obj, update=True): +def get_object(context, obj): if is_blender_28(): - if update: - context.view_layer.update() depsgraph = context.evaluated_depsgraph_get() return obj.evaluated_get(depsgraph) else: return obj + +def destroy_caches(obj): + for psys in obj.particle_systems: + #attempt to destroy cache prior to resimulation + #by provoking an internal RNA update call, this will also update the psys for get_object + if psys.settings.mol_active: + step = psys.point_cache.frame_step + psys.point_cache.frame_step = step diff --git a/sources/core.pyx b/sources/core.pyx index 14197d2..f9e43fb 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -41,7 +41,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.07") +print("cmolcore imported with success! v1.08") cpdef init(importdata): From 7005e563c4bf51c93565508812dc7aa514662cd8 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Aug 2019 12:03:33 +0200 Subject: [PATCH 052/129] minor fixes for missing context.scene.update and set active uv operators as well as for Bake UV after ending --- molecular/operators.py | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index 2c27d36..5f03e40 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -117,12 +117,20 @@ def execute(self, context): mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' if is_blender_28(): - depsgraph = bpy.context.evaluated_depsgraph_get() - newmesh = object2.to_mesh(True, depsgraph) + #depsgraph = bpy.context.evaluated_depsgraph_get() + #newmesh = object2.to_mesh(True, depsgraph) + ctx = bpy.context.copy() + ctx["object"] = object2 + bpy.ops.object.modifier_apply(ctx, modifier=mod.name) else: newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) - object2.data = newmesh - context.scene.update() + object2.data = newmesh + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + psys = obj.particle_systems[scene.mol_psysuvbake] for par in psys.particles: @@ -181,7 +189,8 @@ def execute(self, context): else: scene.objects.unlink(object2) bpy.data.objects.remove(object2) - bpy.data.meshes.remove(newmesh) + if not is_blender_28(): + bpy.data.meshes.remove(newmesh) bpy.data.meshes.remove(obdata) print(' uv baked on:', psys.settings.name) @@ -209,16 +218,31 @@ def modal(self, context, event): bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 scene.frame_end = scene.mol_old_endframe - #scene.update() + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + for ob in bpy.data.objects: obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_bakeuv: scene.mol_objuvbake = obj.name - context.scene.update() + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + scene.frame_set(frame=psys.settings.frame_start) - bpy.context.scene.update() + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + bpy.ops.object.mol_set_active_uv() if frame_current == frame_end and scene.mol_render: From 151fdcdcc132026b07f417f233d0eeda906cd4cc Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Aug 2019 12:04:41 +0200 Subject: [PATCH 053/129] version bump due to a few fixes --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 21fcaf2..223f439 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend, Martin Felke(scorpion81)", - "version": (1, 0, 8), + "version": (1, 0, 9), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), From b7fe1eb13f35e19de6d50c984b5d9125e4f57b40 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Thu, 15 Aug 2019 17:18:33 +0200 Subject: [PATCH 054/129] fixed baked UV rendering forced the angular velocities to be written into the pointcache as well --- molecular/__init__.py | 2 +- molecular/operators.py | 80 +++++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 223f439..9352ef9 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Molecular script", "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend, Martin Felke(scorpion81)", - "version": (1, 0, 9), + "version": (1, 1, 0), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": ("Molecular script"), diff --git a/molecular/operators.py b/molecular/operators.py index 5f03e40..1d3c367 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -95,6 +95,11 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): scene = context.scene + + #dont use rotation data here from cache, only for render mode + psys_orig = context.object.particle_systems.active + psys_orig.settings.use_rotations = False + obj = get_object(context, context.object) scene.mol_objuvbake = obj.name @@ -117,8 +122,6 @@ def execute(self, context): mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' if is_blender_28(): - #depsgraph = bpy.context.evaluated_depsgraph_get() - #newmesh = object2.to_mesh(True, depsgraph) ctx = bpy.context.copy() ctx["object"] = object2 bpy.ops.object.modifier_apply(ctx, modifier=mod.name) @@ -132,6 +135,7 @@ def execute(self, context): context.scene.update() psys = obj.particle_systems[scene.mol_psysuvbake] + par_uv = [] for par in psys.particles: @@ -183,6 +187,7 @@ def execute(self, context): newuv[2] = dist newuv = newuv.to_tuple() par.angular_velocity = newuv + par_uv.append(newuv) if is_blender_28(): scene.collection.objects.unlink(object2) @@ -193,7 +198,8 @@ def execute(self, context): bpy.data.meshes.remove(newmesh) bpy.data.meshes.remove(obdata) print(' uv baked on:', psys.settings.name) - + context.object["par_uv"] = par_uv + return {'FINISHED'} @@ -202,6 +208,47 @@ class MolSimulateModal(bpy.types.Operator): bl_idname = "wm.mol_simulate_modal" bl_label = "Simulate Molecular" _timer = None + + def check_write_uv_cache(self, context): + for ob in bpy.data.objects: + obj = get_object(context, ob) + + for psys in obj.particle_systems: + + #prepare object as in "open" the cache for angular velocity data + if context.scene.frame_current == context.scene.frame_start: + psys.settings.use_rotations = True + psys.settings.angular_velocity_mode = 'RAND' + + if psys.settings.mol_bakeuv and "par_uv" in ob: + par_uv = ob["par_uv"] + print("Writing UV data...") + for k, par in enumerate(psys.particles): + par.angular_velocity = par_uv[k] + + def check_bake_uv(self, context): + #bake the UV in the beginning, and store coordinates in custom property + for ob in bpy.data.objects: + obj = get_object(context, ob) + + for psys in obj.particle_systems: + if psys.settings.mol_bakeuv: + + context.scene.mol_objuvbake = obj.name + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + + context.scene.frame_set(frame=psys.settings.frame_start) + + if is_blender_28(): + context.view_layer.update() + else: + context.scene.update() + + bpy.ops.object.mol_set_active_uv() def modal(self, context, event): scene = context.scene @@ -224,26 +271,7 @@ def modal(self, context, event): else: context.scene.update() - for ob in bpy.data.objects: - obj = get_object(context, ob) - - for psys in obj.particle_systems: - if psys.settings.mol_bakeuv: - scene.mol_objuvbake = obj.name - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() - - scene.frame_set(frame=psys.settings.frame_start) - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() - - bpy.ops.object.mol_set_active_uv() + #self.check_bake_uv(context) if frame_current == frame_end and scene.mol_render: bpy.ops.render.render(animation=True) @@ -258,7 +286,6 @@ def modal(self, context, event): return self.cancel(context) if event.type == 'TIMER': - #scene.update() if frame_current == scene.frame_start: scene.mol_stime = clock() mol_exportdata = context.scene.mol_exportdata @@ -297,7 +324,10 @@ def modal(self, context, event): scene.mol_deadlink += mol_importdata[3] scene.mol_totallink = mol_importdata[4] scene.mol_totaldeadlink = mol_importdata[5] + + self.check_write_uv_cache(context) scene.frame_set(frame=frame_current + 1) + if framesubstep == int(framesubstep): etime2 = clock() print(" Blender: " + str(round(etime2 - stime2, 3)) + " sec") @@ -306,6 +336,8 @@ def modal(self, context, event): return {'PASS_THROUGH'} def execute(self, context): + + self.check_bake_uv(context) self._timer = context.window_manager.event_timer_add(0.000000001, window=context.window) context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} From 030a6ac69480fc47485a2cf1a3258bd12a8c8318 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 22 Apr 2020 11:08:03 +0300 Subject: [PATCH 055/129] refactor --- molecular/__init__.py | 21 ++--- molecular/descriptions.py | 1 - molecular/names.py | 1 - molecular/operators.py | 169 +++++++++++++------------------------- molecular/properties.py | 1 - molecular/simulate.py | 3 +- molecular/ui.py | 20 ++--- molecular/utils.py | 16 ++-- sources/setup.bat | 36 ++------ sources/setup.py | 45 ++++------ 10 files changed, 111 insertions(+), 202 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 9352ef9..96fc650 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -17,16 +17,21 @@ #======================= END GPL LICENSE BLOCK ======================== bl_info = { - "name": "Molecular script", - "author": "Jean-Francois Gallant(PyroEvil), Pavel_Blend, Martin Felke(scorpion81)", + "name": "Molecular", + "author": + "Jean-Francois Gallant (PyroEvil), " + "Pavel_Blend, " + "Martin Felke (scorpion81)", "version": (1, 1, 0), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", - "description": ("Molecular script"), + "description": + "Addon for calculating collisions " + "and for creating links between particles", "warning": "", # used for warning icon and text in addons panel "wiki_url": "http://pyroevil.com/molecular-script-docs/", "tracker_url": "http://pyroevil.com/contact/" , - "category": "Object" + "category": "Physics" } @@ -34,9 +39,7 @@ def register(): import bpy - from . import properties - from . import ui - from . import operators + from . import properties, ui, operators properties.define_props() bpy.utils.register_class(operators.MolSimulateModal) @@ -50,9 +53,7 @@ def unregister(): import bpy - from . import properties - from . import ui - from . import operators + from . import properties, ui, operators bpy.utils.unregister_class(operators.MolSimulateModal) bpy.utils.unregister_class(operators.MolSimulate) diff --git a/molecular/descriptions.py b/molecular/descriptions.py index 32450a2..4834068 100644 --- a/molecular/descriptions.py +++ b/molecular/descriptions.py @@ -1,4 +1,3 @@ - # Matter descriptions MATTER_CUSTOM = 'put your parameter below' MATTER_SAND = '1555kg per meter cu' diff --git a/molecular/names.py b/molecular/names.py index fdef040..0452c3d 100644 --- a/molecular/names.py +++ b/molecular/names.py @@ -1,4 +1,3 @@ - # Labels text DENSITY = 'Density:' COLLISION = 'Collision:' diff --git a/molecular/operators.py b/molecular/operators.py index 1d3c367..0df7d55 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -1,38 +1,22 @@ - -import sys -import platform from time import clock, sleep, strftime, gmtime import bpy from mathutils import Vector from mathutils.geometry import barycentric_transform as barycentric -from . import simulate -from .utils import is_blender_28, get_object, destroy_caches - - -bit_depth = platform.architecture()[0] -if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': - from . import core_35_64 as core -elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '64bit': - from . import core_37_64 as core -elif sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '32bit': - from . import core_35_32 as core -elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '32bit': - from . import core_37_32 as core -else: - raise BaseException('Unsupported python version') +from . import simulate, core +from .utils import get_object, destroy_caches class MolSimulate(bpy.types.Operator): bl_idname = "object.mol_simulate" - bl_label = "Mol Simulate" + bl_label = 'Simulate' def execute(self, context): for ob in bpy.data.objects: destroy_caches(ob) - print("Molecular Sim start--------------------------------------------------") + print('Molecular Sim Start' + '-' * 50) mol_stime = clock() scene = context.scene scene.mol_simrun = True @@ -42,7 +26,6 @@ def execute(self, context): scene.mol_totallink = 0 scene.mol_totaldeadlink = 0 scene.mol_timeremain = "...Simulating..." - object = context.object scene.frame_set(frame=scene.frame_start) scene.mol_old_endframe = scene.frame_end mol_substep = scene.mol_substep @@ -51,7 +34,7 @@ def execute(self, context): scene.frame_end *= mol_substep + 1 if scene.mol_timescale_active == True: - fps = scene.render.fps / scene.timescale + fps = scene.render.fps * scene.timescale else: fps = scene.render.fps @@ -95,11 +78,11 @@ class MolSetActiveUV(bpy.types.Operator): def execute(self, context): scene = context.scene - + #dont use rotation data here from cache, only for render mode psys_orig = context.object.particle_systems.active psys_orig.settings.use_rotations = False - + obj = get_object(context, context.object) scene.mol_objuvbake = obj.name @@ -111,64 +94,45 @@ def execute(self, context): print(' start bake uv from:', obj.name) obdata = obj.data.copy() - object2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) - object2.matrix_world = obj.matrix_world + obj2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) + obj2.matrix_world = obj.matrix_world - if is_blender_28(): - context.scene.collection.objects.link(object2) - else: - context.scene.objects.link(object2) - mod = object2.modifiers.new("tri_for_uv", "TRIANGULATE") + context.scene.collection.objects.link(obj2) + mod = obj2.modifiers.new("tri_for_uv", "TRIANGULATE") mod.ngon_method = 'BEAUTY' mod.quad_method = 'BEAUTY' - if is_blender_28(): - ctx = bpy.context.copy() - ctx["object"] = object2 - bpy.ops.object.modifier_apply(ctx, modifier=mod.name) - else: - newmesh = object2.to_mesh(context.scene, True, "RENDER", True, False) - object2.data = newmesh - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() + + ctx = bpy.context.copy() + ctx["object"] = obj2 + bpy.ops.object.modifier_apply(ctx, modifier=mod.name) + + context.view_layer.update() psys = obj.particle_systems[scene.mol_psysuvbake] par_uv = [] + me = obj2.data for par in psys.particles: - if is_blender_28(): - parloc = (par.location @ object2.matrix_world) - object2.location - else: - parloc = (par.location * object2.matrix_world) - object2.location - - point = object2.closest_point_on_mesh(parloc) - vindex1 = object2.data.polygons[point[3]].vertices[0] - vindex2 = object2.data.polygons[point[3]].vertices[1] - vindex3 = object2.data.polygons[point[3]].vertices[2] - - if is_blender_28(): - v1 = (object2.matrix_world @ object2.data.vertices[vindex1].co).to_tuple() - v2 = (object2.matrix_world @ object2.data.vertices[vindex2].co).to_tuple() - v3 = (object2.matrix_world @ object2.data.vertices[vindex3].co).to_tuple() - else: - v1 = (object2.matrix_world * object2.data.vertices[vindex1].co).to_tuple() - v2 = (object2.matrix_world * object2.data.vertices[vindex2].co).to_tuple() - v3 = (object2.matrix_world * object2.data.vertices[vindex3].co).to_tuple() - - uvindex1 = object2.data.polygons[point[3]].loop_start + 0 - uvindex2 = object2.data.polygons[point[3]].loop_start + 1 - uvindex3 = object2.data.polygons[point[3]].loop_start + 2 - uv1 = object2.data.uv_layers.active.data[uvindex1].uv.to_3d() - uv2 = object2.data.uv_layers.active.data[uvindex2].uv.to_3d() - uv3 = object2.data.uv_layers.active.data[uvindex3].uv.to_3d() - - if is_blender_28(): - p = object2.matrix_world @ point[1] - else: - p = object2.matrix_world * point[1] + parloc = (par.location @ obj2.matrix_world) - obj2.location + + point = obj2.closest_point_on_mesh(parloc) + vindex1 = me.polygons[point[3]].vertices[0] + vindex2 = me.polygons[point[3]].vertices[1] + vindex3 = me.polygons[point[3]].vertices[2] + + v1 = (obj2.matrix_world @ me.vertices[vindex1].co).to_tuple() + v2 = (obj2.matrix_world @ me.vertices[vindex2].co).to_tuple() + v3 = (obj2.matrix_world @ me.vertices[vindex3].co).to_tuple() + + uvindex1 = me.polygons[point[3]].loop_start + 0 + uvindex2 = me.polygons[point[3]].loop_start + 1 + uvindex3 = me.polygons[point[3]].loop_start + 2 + uv1 = me.uv_layers.active.data[uvindex1].uv.to_3d() + uv2 = me.uv_layers.active.data[uvindex2].uv.to_3d() + uv3 = me.uv_layers.active.data[uvindex3].uv.to_3d() + + p = obj2.matrix_world @ point[1] v1 = Vector(v1) v2 = Vector(v2) @@ -178,28 +142,25 @@ def execute(self, context): uv3 = Vector(uv3) newuv = barycentric(p, v1, v2, v3, uv1, uv2, uv3) - if is_blender_28(): - parloc = par.location @ object2.matrix_world - else: - parloc = par.location * object2.matrix_world + parloc = par.location @ obj2.matrix_world + + dist = (Vector(( + parloc[0] - p[0], + parloc[1] - p[1], + parloc[2] - p[2] + ))).length - dist = (Vector((parloc[0] - p[0], parloc[1] - p[1], parloc[2] - p[2]))).length newuv[2] = dist newuv = newuv.to_tuple() par.angular_velocity = newuv par_uv.append(newuv) - if is_blender_28(): - scene.collection.objects.unlink(object2) - else: - scene.objects.unlink(object2) - bpy.data.objects.remove(object2) - if not is_blender_28(): - bpy.data.meshes.remove(newmesh) + scene.collection.objects.unlink(obj2) + bpy.data.objects.remove(obj2) bpy.data.meshes.remove(obdata) print(' uv baked on:', psys.settings.name) context.object["par_uv"] = par_uv - + return {'FINISHED'} @@ -214,12 +175,12 @@ def check_write_uv_cache(self, context): obj = get_object(context, ob) for psys in obj.particle_systems: - - #prepare object as in "open" the cache for angular velocity data + + # prepare object as in "open" the cache for angular velocity data if context.scene.frame_current == context.scene.frame_start: psys.settings.use_rotations = True psys.settings.angular_velocity_mode = 'RAND' - + if psys.settings.mol_bakeuv and "par_uv" in ob: par_uv = ob["par_uv"] print("Writing UV data...") @@ -227,7 +188,7 @@ def check_write_uv_cache(self, context): par.angular_velocity = par_uv[k] def check_bake_uv(self, context): - #bake the UV in the beginning, and store coordinates in custom property + # bake the UV in the beginning, and store coordinates in custom property for ob in bpy.data.objects: obj = get_object(context, ob) @@ -235,19 +196,11 @@ def check_bake_uv(self, context): if psys.settings.mol_bakeuv: context.scene.mol_objuvbake = obj.name - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() - + context.view_layer.update() + context.scene.frame_set(frame=psys.settings.frame_start) - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() - + context.view_layer.update() + bpy.ops.object.mol_set_active_uv() def modal(self, context, event): @@ -265,13 +218,9 @@ def modal(self, context, event): bpy.ops.ptcache.bake_from_cache(fake_context) scene.render.frame_map_new = 1 scene.frame_end = scene.mol_old_endframe - - if is_blender_28(): - context.view_layer.update() - else: - context.scene.update() - - #self.check_bake_uv(context) + context.view_layer.update() + + # self.check_bake_uv(context) if frame_current == frame_end and scene.mol_render: bpy.ops.render.render(animation=True) @@ -282,7 +231,7 @@ def modal(self, context, event): scene.mol_simrun = False mol_exportdata = scene.mol_exportdata mol_exportdata.clear() - print("--------------------------------------------------Molecular Sim end") + print('-' * 50 + 'Molecular Sim end') return self.cancel(context) if event.type == 'TIMER': diff --git a/molecular/properties.py b/molecular/properties.py index d23139a..8d57ab7 100644 --- a/molecular/properties.py +++ b/molecular/properties.py @@ -1,4 +1,3 @@ - import multiprocessing import bpy diff --git a/molecular/simulate.py b/molecular/simulate.py index d15fb27..e8d7d92 100644 --- a/molecular/simulate.py +++ b/molecular/simulate.py @@ -1,9 +1,8 @@ - import math import bpy -from .utils import is_blender_28, get_object +from .utils import get_object def pack_data(context, initiate): diff --git a/molecular/ui.py b/molecular/ui.py index 62ae924..22ff11e 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -1,8 +1,7 @@ - import bpy from . import names -from .utils import is_blender_28, get_object +from .utils import get_object class MolecularPanel(bpy.types.Panel): @@ -227,11 +226,13 @@ def draw(self, context): row = layout.row() row.prop(scn, "frame_start", text="Start Frame") row.prop(scn, "frame_end", text="End Frame") - #row = layout.row() - #row.prop(scn,"mol_timescale_active",text = "Activate TimeScaling") - #row = layout.row() - #row.enabled = scn.mol_timescale_active - #row.prop(scn,"timescale",text = "TimeScale") + + # row = layout.row() + # row.prop(scn,"mol_timescale_active", text="Activate TimeScaling") + # row = layout.row() + # row.enabled = scn.mol_timescale_active + # row.prop(scn, "timescale", text="Time Scale") + row = layout.row() row.prop(scn, "mol_substep") row.label(text='') @@ -243,10 +244,7 @@ def draw(self, context): row.prop(scn, "mol_render") row = layout.row() - if is_blender_28(): - icon = 'PARTICLE_DATA' - else: - icon = 'RADIO' + icon = 'PARTICLE_DATA' if scn.mol_simrun == False and psys.point_cache.is_baked == False: row.enabled = True diff --git a/molecular/utils.py b/molecular/utils.py index 4f28bac..a092b47 100644 --- a/molecular/utils.py +++ b/molecular/utils.py @@ -1,21 +1,15 @@ - import bpy -def is_blender_28(): - return bpy.data.version[0] == 2 and bpy.data.version[1] >= 80 - def get_object(context, obj): - if is_blender_28(): - depsgraph = context.evaluated_depsgraph_get() - return obj.evaluated_get(depsgraph) - else: - return obj + depsgraph = context.evaluated_depsgraph_get() + return obj.evaluated_get(depsgraph) + def destroy_caches(obj): for psys in obj.particle_systems: - #attempt to destroy cache prior to resimulation - #by provoking an internal RNA update call, this will also update the psys for get_object + # attempt to destroy cache prior to resimulation + # by provoking an internal RNA update call, this will also update the psys for get_object if psys.settings.mol_active: step = psys.point_cache.frame_step psys.point_cache.frame_step = step diff --git a/sources/setup.bat b/sources/setup.bat index ab6c972..dac1fe7 100644 --- a/sources/setup.bat +++ b/sources/setup.bat @@ -1,38 +1,18 @@ +rem delete old files del core.html del core.c rd /s /q build +del core.cp37-win_amd64.pyd -del core_35_64.pyd -"C:\Program Project\Python 3.5.4 64 bit\python.exe" setup.py build_ext --inplace -del core.html -del core.c -rd /s /q build -ren core_35_64.cp35-win_amd64.pyd core_35_64.pyd - -del core_37_64.pyd -"C:\Program Project\Python 3.7.2 64 bit\python.exe" setup.py build_ext --inplace -del core.html -del core.c -rd /s /q build -ren core_37_64.cp37-win_amd64.pyd core_37_64.pyd - -del core_35_32.pyd -"C:\Program Project\Python 3.5.4 32 bit\python.exe" setup.py build_ext --inplace -del core.html -del core.c -rd /s /q build -ren core_35_32.cp35-win32.pyd core_35_32.pyd +rem compiling +"C:\Program Project\Python 3.7.7\python.exe" setup.py build_ext --inplace -del core_37_32.pyd -"C:\Program Project\Python 3.7.2 32 bit\python.exe" setup.py build_ext --inplace +rem delete unnecessary files after compilation del core.html del core.c rd /s /q build -ren core_37_32.cp37-win32.pyd core_37_32.pyd -move core_35_64.pyd ..\molecular\core_35_64.pyd -move core_37_64.pyd ..\molecular\core_37_64.pyd -move core_35_32.pyd ..\molecular\core_35_32.pyd -move core_37_32.pyd ..\molecular\core_37_32.pyd +rem move the core to the blender addon folder +move core.cp37-win_amd64.pyd ..\molecular\core.cp37-win_amd64.pyd -pause \ No newline at end of file +pause diff --git a/sources/setup.py b/sources/setup.py index c34b2bb..8fcf891 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -1,38 +1,29 @@ -import sys import platform - -bit_depth = platform.architecture()[0] -os_name = platform.architecture()[1] - -if os_name == "WindowsPE": - #only needed under windows - import setuptools - from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext -import Cython.Compiler.Options +import Cython.Compiler.Options -Cython.Compiler.Options.annotate = True -if sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '64bit': - module_name = 'core_35_64' -elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '64bit': - module_name = 'core_37_64' -elif sys.version_info.major == 3 and sys.version_info.minor == 5 and bit_depth == '32bit': - module_name = 'core_35_32' -elif sys.version_info.major == 3 and sys.version_info.minor == 7 and bit_depth == '32bit': - module_name = 'core_37_32' -else: - raise BaseException('Unsupported python version') +os_name = platform.architecture()[1] +Cython.Compiler.Options.annotate = True +module_name = 'core' if os_name == "WindowsPE": - ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'])] + ext_modules = [Extension( + module_name, + ['core' + '.pyx'], + extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'] + )] else: - #ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['-O3','-fopenmp','-msse4.2','-ffast-math'])] - ext_modules = [Extension(module_name, ['core' + '.pyx'],extra_compile_args=['-O3','-msse4.2','-ffast-math'])] + ext_modules = [Extension( + module_name, + ['core' + '.pyx'], + extra_compile_args=['-O3','-msse4.2','-ffast-math'] + )] + setup( -name = 'Molecular script', -cmdclass = {'build_ext': build_ext}, -ext_modules = ext_modules + name = 'Molecular script', + cmdclass = {'build_ext': build_ext}, + ext_modules = ext_modules ) From 2ec794be3f924991221ec921cd1ea2ed23008841 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 22 Apr 2020 11:16:38 +0300 Subject: [PATCH 056/129] refactor make release script --- .gitignore | 1 + make_release_win.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index cc5b7b0..f849c7e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build *.c *.html .vscode +*.zip diff --git a/make_release_win.py b/make_release_win.py index 2c41167..72847f5 100644 --- a/make_release_win.py +++ b/make_release_win.py @@ -8,7 +8,7 @@ chdir(getcwd()+"\\sources") try: - remove("core_37_64.cp37-win_amd64.pyd") + remove("core.cp37-win_amd64.pyd") remove("core.html") remove("core.c") shutil.rmtree("build") @@ -21,7 +21,7 @@ with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) - shutil.move("core_37_64.cp37-win_amd64.pyd", "..\\molecular\\core_37_64.cp37-win_amd64.pyd") + shutil.move("core.cp37-win_amd64.pyd", "..\\molecular\\core.cp37-win_amd64.pyd") chdir("..") @@ -34,7 +34,7 @@ chdir(getcwd()+"\\molecular") try: - remove("core_37_64.cp37-win_amd64.pyd") + remove("core.cp37-win_amd64.pyd") except: pass chdir("..") From 148a6e6788ed233813e4bbf7db35069eca627b9c Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 22 Apr 2020 20:07:09 +0300 Subject: [PATCH 057/129] refactor ui --- molecular/__init__.py | 6 +- molecular/names.py | 20 +- molecular/operators.py | 3 +- molecular/ui.py | 460 +++++++++++++++++++++++++---------------- 4 files changed, 292 insertions(+), 197 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 96fc650..5ddd3a4 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -46,7 +46,8 @@ def register(): bpy.utils.register_class(operators.MolSimulate) bpy.utils.register_class(operators.MolSetGlobalUV) bpy.utils.register_class(operators.MolSetActiveUV) - bpy.utils.register_class(ui.MolecularPanel) + for panel in ui.panel_classes: + bpy.utils.register_class(panel) def unregister(): @@ -59,7 +60,8 @@ def unregister(): bpy.utils.unregister_class(operators.MolSimulate) bpy.utils.unregister_class(operators.MolSetGlobalUV) bpy.utils.unregister_class(operators.MolSetActiveUV) - bpy.utils.unregister_class(ui.MolecularPanel) + for panel in reversed(ui.panel_classes): + bpy.utils.unregister_class(panel) if __name__ == "__main__": diff --git a/molecular/names.py b/molecular/names.py index 0452c3d..cc0219f 100644 --- a/molecular/names.py +++ b/molecular/names.py @@ -1,18 +1,18 @@ # Labels text -DENSITY = 'Density:' -COLLISION = 'Collision:' -LINKS = 'Links:' -INITIAL_LINKING = 'Initial Linking (at birth):' -NEW_LINKING = 'New Linking (at collision):' -UVS = 'UV\'s:' +DENSITY = 'Density' +COLLISION = 'Collision' +LINKS = 'Links' +INITIAL_LINKING = 'Initial Linking (at birth)' +NEW_LINKING = 'New Linking (at collision)' +UVS = 'UV\'s' SIMULATE = 'Simulate' -CPU_USED = 'CPU used:' -MOLECULAR_TOOLS = 'Molecular Tools:' -PARTICLE_UV = 'Particle UV:' +CPU_USED = 'CPU used' +MOLECULAR_TOOLS = 'Molecular Tools' +PARTICLE_UV = 'Particle UV' SET_POSITION = 'Set current particles position' UV_HELP = 'Has global or current uv in angular velocity' CYCLES_HELP = 'Retrieve it with Cycles particle info node' -SUBSTEPS_CALCULATOR = 'Substeps Calculator:' +SUBSTEPS_CALCULATOR = 'Substeps Calculator' THANKS = 'THANKS TO ALL DONATORS!' SUPPORT_WORK = 'If you want donate to support my work' VISIT = 'or visit:' diff --git a/molecular/operators.py b/molecular/operators.py index 0df7d55..8c1ccd9 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -208,7 +208,7 @@ def modal(self, context, event): frame_end = scene.frame_end frame_current = scene.frame_current if event.type == 'ESC' or frame_current == frame_end: - if frame_current == frame_end and scene.mol_bake: + if scene.mol_bake: fake_context = context.copy() for ob in bpy.data.objects: obj = get_object(context, ob) @@ -285,7 +285,6 @@ def modal(self, context, event): return {'PASS_THROUGH'} def execute(self, context): - self.check_bake_uv(context) self._timer = context.window_manager.event_timer_add(0.000000001, window=context.window) context.window_manager.modal_handler_add(self) diff --git a/molecular/ui.py b/molecular/ui.py index 22ff11e..eee6bda 100644 --- a/molecular/ui.py +++ b/molecular/ui.py @@ -4,25 +4,59 @@ from .utils import get_object -class MolecularPanel(bpy.types.Panel): - """Creates a Panel in the Object properties window""" - bl_label = "Molecular Script" - bl_idname = "OBJECT_PT_molecular" +class MolecularBasePanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "particle" + bl_options = {'DEFAULT_CLOSED', } @classmethod def poll(cls, context): return context.object.particle_systems.active - def draw_header(self, context): + +class MolecularDensityPanel(MolecularBasePanel): + bl_label = names.DENSITY + bl_idname = "OBJECT_PT_molecular_density" + bl_parent_id = 'OBJECT_PT_molecular' + + def draw(self, context): layout = self.layout + scn = bpy.context.scene obj = context.object psys = obj.particle_systems.active - row = layout.row() - if not psys is None: - row.prop(psys.settings, "mol_active", text='') + if psys is None: + return + layout.enabled = psys.settings.mol_active + # for the data + psys_eval = get_object(context, context.object).particle_systems.active + + layout.prop(psys.settings, "mol_density_active", toggle=True) + + if not psys.settings.mol_density_active: + return + + layout.prop(psys.settings, "mol_matter") + + if int(psys.settings.mol_matter) >= 1: + weight_text = "Total system approx weight: {0:.4} kg".format( + psys.settings.mol_matter + ) + layout.label(icon="INFO", text=weight_text) + return + + layout.prop(psys.settings, "mol_density") + pmass = (psys.settings.particle_size ** 3) * psys.settings.mol_density + weight_text = "Total system approx weight: {0:.2f} kg".format( + len(psys_eval.particles) * pmass + ) + layout.label(icon="INFO", text=weight_text) + + +class MolecularCollisionPanel(MolecularBasePanel): + bl_label = names.COLLISION + bl_idname = "OBJECT_PT_molecular_collision" + bl_parent_id = 'OBJECT_PT_molecular' def draw(self, context): layout = self.layout @@ -31,177 +65,196 @@ def draw(self, context): psys = obj.particle_systems.active if psys is None: return - #for the data + # particle system settings + stg = psys.settings + + layout.enabled = stg.mol_active + # for the data psys_eval = get_object(context, context.object).particle_systems.active - + + layout.prop(stg, "mol_selfcollision_active", toggle=True) + layout.prop(stg, "mol_othercollision_active", toggle=True) + if stg.mol_othercollision_active: + layout.prop(stg, "mol_collision_group") + if stg.mol_selfcollision_active or stg.mol_othercollision_active: + layout.prop(stg, "mol_friction") + layout.prop(stg, "mol_collision_damp") + + +class MolecularLinksPanel(MolecularBasePanel): + bl_label = names.LINKS + bl_idname = "OBJECT_PT_molecular_links" + bl_parent_id = 'OBJECT_PT_molecular' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return layout.enabled = psys.settings.mol_active - row = layout.row() - row.label(text=names.DENSITY) - box = layout.box() - box.prop( - psys.settings, - "mol_density_active" - ) - subbox = box.box() - subbox.enabled = psys.settings.mol_density_active - row = subbox.row() - row.prop(psys.settings, "mol_matter") - row = subbox.row() - if int(psys.settings.mol_matter) == 0: - row.enabled = True - elif int(psys.settings.mol_matter) >= 1: - row.enabled = False + layout.prop(psys.settings, "mol_links_active", toggle=True) + layout.prop(psys.settings, "mol_other_link_active", toggle=True) + if psys.settings.mol_other_link_active: + layout.prop(psys.settings, "mol_link_group") - row.prop(psys.settings, "mol_density") - pmass = (psys.settings.particle_size ** 3) * psys.settings.mol_density - row = subbox.row() - weight_text = "Total system approx weight: {0:.4} kg".format( - len(psys_eval.particles) * pmass - ) - row.label(icon="INFO", text=weight_text) - row = layout.row() - row.label(text=names.COLLISION) - box = layout.box() - box.prop( - psys.settings, - "mol_selfcollision_active" - ) - box.prop( - psys.settings, - "mol_othercollision_active" - ) - box.prop( - psys.settings, - "mol_collision_group", - ) - box.prop( - psys.settings, - "mol_friction", - ) - box.prop( - psys.settings, - "mol_collision_damp" - ) - row = layout.row() - row.label(text=names.LINKS) - box = layout.box() - box.prop( - psys.settings, - "mol_links_active" - ) - box.prop( - psys.settings, - "mol_other_link_active" - ) - box.prop( - psys.settings, - "mol_link_group" +class MolecularInitLinksPanel(MolecularBasePanel): + bl_label = names.INITIAL_LINKING + bl_idname = "OBJECT_PT_molecular_init_links" + bl_parent_id = 'OBJECT_PT_molecular_links' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + stg = psys.settings + layout.enabled = stg.mol_active and ( + stg.mol_links_active or stg.mol_other_link_active ) - subbox = box.box() - subbox.enabled = psys.settings.mol_links_active or \ - psys.settings.mol_other_link_active - subbox.label(text=names.INITIAL_LINKING) - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_length") row.prop(psys.settings, "mol_link_rellength") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_max") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_friction") layout.separator() - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_tension") row.prop(psys.settings, "mol_link_tensionrand") - row = subbox.row() + row = layout.row() + row.prop(psys.settings, "mol_link_samevalue", toggle=True) + if not psys.settings.mol_link_samevalue: + layout.label(text='Compression:') + row = layout.row() row.prop(psys.settings, "mol_link_stiff") row.prop(psys.settings, "mol_link_stiffrand") - #row = subbox.row() + #row = layout.row() #row.prop(psys.settings, "mol_link_stiffexp") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_damp") row.prop(psys.settings, "mol_link_damprand") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_link_broken") row.prop(psys.settings, "mol_link_brokenrand") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop( - psys.settings, - "mol_link_samevalue" + if not psys.settings.mol_link_samevalue: + layout.label(text='Expansion:') + row = layout.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_estiff") + row.prop(psys.settings, "mol_link_estiffrand") + #row = layout.row() + #row.enabled = not psys.settings.mol_link_samevalue + #row.prop(psys.settings, "mol_link_estiffexp") + row = layout.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_edamp") + row.prop(psys.settings, "mol_link_edamprand") + row = layout.row() + row.enabled = not psys.settings.mol_link_samevalue + row.prop(psys.settings, "mol_link_ebroken") + row.prop(psys.settings, "mol_link_ebrokenrand") + + +class MolecularNewLinksPanel(MolecularBasePanel): + bl_label = names.NEW_LINKING + bl_idname = "OBJECT_PT_molecular_new_links" + bl_parent_id = 'OBJECT_PT_molecular_links' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + stg = psys.settings + + layout.enabled = stg.mol_active and ( + stg.mol_links_active or stg.mol_other_link_active ) - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_estiff") - row.prop(psys.settings, "mol_link_estiffrand") - #row = subbox.row() - #row.enabled = not psys.settings.mol_link_samevalue - #row.prop(psys.settings, "mol_link_estiffexp") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_edamp") - row.prop(psys.settings, "mol_link_edamprand") - row = subbox.row() - row.enabled = not psys.settings.mol_link_samevalue - row.prop(psys.settings, "mol_link_ebroken") - row.prop(psys.settings, "mol_link_ebrokenrand") - - subbox = box.box() - subbox.active = psys.settings.mol_links_active - subbox.label(text=names.NEW_LINKING) - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_relink_group") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_relink_chance") row.prop(psys.settings, "mol_relink_chancerand") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_relink_max") - row = subbox.row() + row = layout.row() layout.separator() - row = subbox.row() + row = layout.row() row.prop(psys.settings,"mol_relink_tension") row.prop(psys.settings,"mol_relink_tensionrand") - row = subbox.row() + row = layout.row() + row.prop(psys.settings, "mol_relink_samevalue", toggle=True) + if not psys.settings.mol_relink_samevalue: + layout.label(text='Compression:') + row = layout.row() row.prop(psys.settings,"mol_relink_stiff") row.prop(psys.settings,"mol_relink_stiffrand") - #row = subbox.row() + #row = layout.row() #row.prop(psys.settings, "mol_relink_stiffexp") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_relink_damp") row.prop(psys.settings, "mol_relink_damprand") - row = subbox.row() + row = layout.row() row.prop(psys.settings, "mol_relink_broken") row.prop(psys.settings, "mol_relink_brokenrand") - row = subbox.row() - layout.separator() - row = subbox.row() - row.prop( - psys.settings, - "mol_relink_samevalue" - ) - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_estiff") - row.prop(psys.settings, "mol_relink_estiffrand") - #row = subbox.row() - #row.enabled = not psys.settings.mol_relink_samevalue - #row.prop(psys.settings, "mol_relink_estiffexp") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_edamp") - row.prop(psys.settings, "mol_relink_edamprand") - row = subbox.row() - row.enabled = not psys.settings.mol_relink_samevalue - row.prop(psys.settings, "mol_relink_ebroken") - row.prop(psys.settings, "mol_relink_ebrokenrand") + row = layout.row() + if not psys.settings.mol_relink_samevalue: + layout.label(text='Expansion:') + row = layout.row() + row.prop(psys.settings, "mol_relink_estiff") + row.prop(psys.settings, "mol_relink_estiffrand") + #row = layout.row() + #row.enabled = not psys.settings.mol_relink_samevalue + #row.prop(psys.settings, "mol_relink_estiffexp") + row = layout.row() + row.prop(psys.settings, "mol_relink_edamp") + row.prop(psys.settings, "mol_relink_edamprand") + row = layout.row() + row.prop(psys.settings, "mol_relink_ebroken") + row.prop(psys.settings, "mol_relink_ebrokenrand") + + +class MolecularSimulatePanel(MolecularBasePanel): + bl_label = names.SIMULATE + bl_idname = "OBJECT_PT_molecular_simulate" + bl_parent_id = 'OBJECT_PT_molecular' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + layout.enabled = psys.settings.mol_active + # for the data + psys_eval = get_object(context, context.object).particle_systems.active + + layout.prop(scn, "frame_start", text="Start Frame") + layout.prop(scn, "frame_end", text="End Frame") + + # row = layout.row() + # row.prop(scn,"mol_timescale_active", text="Activate TimeScaling") + # row = layout.row() + # row.enabled = scn.mol_timescale_active + # row.prop(scn, "timescale", text="Time Scale") + + layout.prop(scn, "mol_substep") + layout.prop(scn, "mol_cpu", text=names.CPU_USED) + layout.prop(scn, "mol_bake") + layout.prop(scn, "mol_render") row = layout.row() - row.label(text=names.UVS) - box = layout.box() - row = box.row() if obj.data.uv_layers.active != None: row.prop( @@ -220,30 +273,6 @@ def draw(self, context): ) row = layout.row() - row.label(text='') - row = layout.row() - row.label(text=names.SIMULATE) - row = layout.row() - row.prop(scn, "frame_start", text="Start Frame") - row.prop(scn, "frame_end", text="End Frame") - - # row = layout.row() - # row.prop(scn,"mol_timescale_active", text="Activate TimeScaling") - # row = layout.row() - # row.enabled = scn.mol_timescale_active - # row.prop(scn, "timescale", text="Time Scale") - - row = layout.row() - row.prop(scn, "mol_substep") - row.label(text='') - row = layout.row() - row.label(text=names.CPU_USED) - row.prop(scn, "mol_cpu") - row = layout.row() - row.prop(scn, "mol_bake") - row.prop(scn, "mol_render") - row = layout.row() - icon = 'PARTICLE_DATA' if scn.mol_simrun == False and psys.point_cache.is_baked == False: @@ -279,29 +308,42 @@ def draw(self, context): row.enabled = False row.operator("ptcache.free_bake_all", text="Free All Bakes") + +class MolecularToolsPanel(MolecularBasePanel): + bl_label = names.MOLECULAR_TOOLS + bl_idname = "OBJECT_PT_molecular_tools" + bl_parent_id = 'OBJECT_PT_molecular' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + layout.enabled = psys.settings.mol_active + # for the data + psys_eval = get_object(context, context.object).particle_systems.active + box = layout.box() row = box.row() - box.enabled = True - row.label(text=names.MOLECULAR_TOOLS, icon='MODIFIER') - subbox = box.box() - row = subbox.row() row.label(text=names.PARTICLE_UV) - row = subbox.row() + row = box.row() row.alignment = 'CENTER' row.label(icon='INFO', text=names.SET_POSITION) - row = subbox.row() + row = box.row() row.alignment = 'CENTER' row.label(text=names.UV_HELP) - row = subbox.row() + row = box.row() row.alignment = 'CENTER' row.label(text=names.CYCLES_HELP) - row = subbox.row() + row = box.row() row.operator( "object.mol_set_global_uv", icon='GROUP_UVS', text="Set Global UV" ) - row = subbox.row() + row = box.row() if obj.data.uv_layers.active != None: row.operator( @@ -319,39 +361,56 @@ def draw(self, context): text="Set Active UV (no uvs found)" ) - subbox = box.box() - row = subbox.row() + box = layout.box() + row = box.row() row.label(text=names.SUBSTEPS_CALCULATOR) - row = subbox.row() + row = box.row() row.label( icon='INFO', text="Current systems have: {} particles".format(len(psys_eval.particles)) ) - row = subbox.row() + row = box.row() row.prop(psys.settings, "mol_var1") - row = subbox.row() + row = box.row() row.prop(psys.settings,"mol_var2") - row = subbox.row() + row = box.row() row.prop(psys.settings,"mol_var3") diff = (psys.settings.mol_var3 / psys.settings.mol_var1) factor = psys.settings.mol_var3 ** (1 / 3) / psys.settings.mol_var1 ** (1 / 3) newsubstep = int(round(factor * psys.settings.mol_var2)) - row = subbox.row() + row = box.row() row.label( icon='FORWARD', text="You must set new substep to: {}".format(newsubstep) ) - row = subbox.row() + row = box.row() row.label( icon='ERROR', text="Multiply particles size by: {}".format(round(1 / factor, 5)) ) - row = subbox.row() + row = box.row() row.label( icon='ERROR', text="Multiply others sys particle number by: {}".format(round(diff, 5)) ) + +class MolecularAboutPanel(MolecularBasePanel): + bl_label = 'About' + bl_idname = "OBJECT_PT_molecular_about" + bl_parent_id = 'OBJECT_PT_molecular' + + def draw(self, context): + layout = self.layout + scn = bpy.context.scene + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + layout.enabled = psys.settings.mol_active + # for the data + psys_eval = get_object(context, context.object).particle_systems.active + box = layout.box() row = box.row() box.active = False @@ -374,3 +433,38 @@ def draw(self, context): row = box.row() row.alignment = 'CENTER' row.label(text=names.SITE) + + +class MolecularPanel(MolecularBasePanel): + """Creates a Panel in the Object properties window""" + bl_label = "Molecular" + bl_idname = "OBJECT_PT_molecular" + + def draw_header(self, context): + layout = self.layout + obj = context.object + psys = obj.particle_systems.active + row = layout.row() + if not psys is None: + row.prop(psys.settings, "mol_active", text='') + + def draw(self, context): + layout = self.layout + obj = context.object + psys = obj.particle_systems.active + if psys is None: + return + layout.enabled = psys.settings.mol_active + + +panel_classes = ( + MolecularPanel, + MolecularSimulatePanel, + MolecularDensityPanel, + MolecularCollisionPanel, + MolecularLinksPanel, + MolecularInitLinksPanel, + MolecularNewLinksPanel, + MolecularToolsPanel, + MolecularAboutPanel +) From bfe110303f18276517b291bde36c1a7f09ba73d2 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 22 Apr 2020 20:13:21 +0300 Subject: [PATCH 058/129] fix tools panel name --- molecular/names.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/names.py b/molecular/names.py index cc0219f..c1582d0 100644 --- a/molecular/names.py +++ b/molecular/names.py @@ -7,7 +7,7 @@ UVS = 'UV\'s' SIMULATE = 'Simulate' CPU_USED = 'CPU used' -MOLECULAR_TOOLS = 'Molecular Tools' +MOLECULAR_TOOLS = 'Tools' PARTICLE_UV = 'Particle UV' SET_POSITION = 'Set current particles position' UV_HELP = 'Has global or current uv in angular velocity' From 7db9567986cc8d8363ff7c72c1c36b1586db2403 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 29 Apr 2020 10:35:51 +0300 Subject: [PATCH 059/129] total time info --- molecular/operators.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/molecular/operators.py b/molecular/operators.py index 8c1ccd9..e6aafdb 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -1,4 +1,4 @@ -from time import clock, sleep, strftime, gmtime +from time import clock, sleep, strftime, gmtime, time import bpy from mathutils import Vector @@ -164,6 +164,28 @@ def execute(self, context): return {'FINISHED'} +def convert_time_to_string(total_time): + HOUR_IN_SECONDS = 60 * 60 + MINUTE_IN_SCEONDS = 60 + time_string = '' + if total_time > 10.0: + total_time = int(total_time) + if total_time > MINUTE_IN_SCEONDS and total_time <= HOUR_IN_SECONDS: + minutes = total_time // MINUTE_IN_SCEONDS + seconds = total_time - minutes * MINUTE_IN_SCEONDS + time_string = '{0} min {1} sec'.format(minutes, seconds) + elif total_time <= MINUTE_IN_SCEONDS: + time_string = '{0} seconds'.format(total_time) + elif total_time > HOUR_IN_SECONDS: + hours = total_time // HOUR_IN_SECONDS + minutes = total_time - (total_time // HOUR_IN_SECONDS) * HOUR_IN_SECONDS + time_string = '{0} hours {1} min'.format(hours, minutes) + else: + seconds = round(total_time, 2) + time_string = '{0} seconds'.format(seconds) + return time_string + + class MolSimulateModal(bpy.types.Operator): """Operator which runs its self from a timer""" bl_idname = "wm.mol_simulate_modal" @@ -232,6 +254,11 @@ def modal(self, context, event): mol_exportdata = scene.mol_exportdata mol_exportdata.clear() print('-' * 50 + 'Molecular Sim end') + # total time + tt = time() - self.st + # total time string + tt_s = convert_time_to_string(tt) + self.report({'INFO'}, 'Total time: {0}'.format(tt_s)) return self.cancel(context) if event.type == 'TIMER': @@ -285,6 +312,8 @@ def modal(self, context, event): return {'PASS_THROUGH'} def execute(self, context): + # start time + self.st = time() self.check_bake_uv(context) self._timer = context.window_manager.event_timer_add(0.000000001, window=context.window) context.window_manager.modal_handler_add(self) From a04ce123d32531bc77c43116e4f4db231aba5ef0 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Wed, 29 Apr 2020 16:06:51 +0200 Subject: [PATCH 060/129] adapt release file for linux/mac and version is 1.11 now --- make_release_linux_mac.py | 12 ++++++------ molecular/__init__.py | 2 +- sources/core.pyx | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/make_release_linux_mac.py b/make_release_linux_mac.py index fa59891..8d5944b 100644 --- a/make_release_linux_mac.py +++ b/make_release_linux_mac.py @@ -16,9 +16,9 @@ try: if is_linux: - remove("core_37_64.cpython-37m-x86_64-linux-gnu.so") + remove("core.cpython-37m-x86_64-linux-gnu.so") else: - remove("core_37_64.cpython-37m-darwin.so") + remove("core.cpython-37m-darwin.so") remove("core.html") remove("core.c") shutil.rmtree("build") @@ -31,9 +31,9 @@ with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) if is_linux: #TODO, test - shutil.move("core_37_64.cpython-37m-x86_64-linux-gnu.so", "../molecular/core_37_64.cpython-37m-x86_64-linux-gnu.so") + shutil.move("core.cpython-37m-x86_64-linux-gnu.so", "../molecular/core.cpython-37m-x86_64-linux-gnu.so") else: - shutil.move("core_37_64.cpython-37m-darwin.so", "../molecular/core_37_64.cpython-37m-darwin.so") + shutil.move("core.cpython-37m-darwin.so", "../molecular/core.cpython-37m-darwin.so") chdir("..") @@ -47,9 +47,9 @@ chdir(getcwd()+"/molecular") try: if is_linux: - remove("core_37_64.cpython-37m-x86_64-linux-gnu.so") + remove("core.cpython-37m-x86_64-linux-gnu.so") else: - remove("core_37_64.cpython-37m-darwin.so") + remove("core.cpython-37m-darwin.so") except: pass chdir("..") diff --git a/molecular/__init__.py b/molecular/__init__.py index 5ddd3a4..afa1775 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,7 +22,7 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 0), + "version": (1, 1, 1), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": diff --git a/sources/core.pyx b/sources/core.pyx index f9e43fb..3e5e25b 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -41,7 +41,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.08") +print("cmolcore imported with success! v1.11") cpdef init(importdata): From 10d1fb17c981ac3745b4d2edfc6ca97bdb65b6c0 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Wed, 29 Apr 2020 19:39:17 +0200 Subject: [PATCH 061/129] unified release script --- make_release_linux_mac.py => make_release.py | 41 ++++++++++++-------- make_release_win.py | 40 ------------------- 2 files changed, 24 insertions(+), 57 deletions(-) rename make_release_linux_mac.py => make_release.py (63%) delete mode 100644 make_release_win.py diff --git a/make_release_linux_mac.py b/make_release.py similarity index 63% rename from make_release_linux_mac.py rename to make_release.py index 8d5944b..b5691f3 100644 --- a/make_release_linux_mac.py +++ b/make_release.py @@ -4,26 +4,19 @@ import shutil import platform import sys +import pathlib from subprocess import Popen, PIPE is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" +is_windows = platform.architecture()[1] == "WindowsPE" or platform.system() == "Windows" name = 'mac' if is_linux: name = 'linux' +elif is_windows: + name = 'win' -chdir(getcwd()+"/sources") - -try: - if is_linux: - remove("core.cpython-37m-x86_64-linux-gnu.so") - else: - remove("core.cpython-37m-darwin.so") - remove("core.html") - remove("core.c") - shutil.rmtree("build") -except: - pass +chdir(getcwd()+"//sources") #TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN #into the include folder of blenders python, too @@ -31,25 +24,39 @@ with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) if is_linux: #TODO, test - shutil.move("core.cpython-37m-x86_64-linux-gnu.so", "../molecular/core.cpython-37m-x86_64-linux-gnu.so") + shutil.move("core.cpython-37m-x86_64-linux-gnu.so", "..//molecular//core.cpython-37m-x86_64-linux-gnu.so") + elif is_windows: + shutil.move("core.cp37-win_amd64.pyd", "..//molecular//core.cp37-win_amd64.pyd") else: - shutil.move("core.cpython-37m-darwin.so", "../molecular/core.cpython-37m-darwin.so") + shutil.move("core.cpython-37m-darwin.so", "..//molecular//core.cpython-37m-darwin.so") chdir("..") with ZipFile('molecular_{}_'.format(('.'.join(map(str, bl_info['version'])))) + name +'.zip', 'w') as z: for root, _, files in walk('molecular'): for file in files: - if not file.endswith('.py') and not file.endswith('.so'): + if not file.endswith('.py') and not file.endswith('.so') and not file.endswith('.pyd'): continue z.write(path.join(root, file), compress_type=ZIP_DEFLATED) - - chdir(getcwd()+"/molecular") + #cleanup + chdir(getcwd()+"//molecular") try: if is_linux: remove("core.cpython-37m-x86_64-linux-gnu.so") + elif is_windows: + remove("core.cp37-win_amd64.pyd") else: remove("core.cpython-37m-darwin.so") except: pass chdir("..") + chdir(getcwd()+"//sources") + + try: + remove("core.html") + remove("core.c") + shutil.rmtree("build") + except: + pass + + chdir("..") diff --git a/make_release_win.py b/make_release_win.py deleted file mode 100644 index 72847f5..0000000 --- a/make_release_win.py +++ /dev/null @@ -1,40 +0,0 @@ -from molecular import bl_info -from zipfile import ZipFile, ZIP_DEFLATED -from os import path, walk, remove, chdir, getcwd -import shutil -import sys -from subprocess import Popen, PIPE - -chdir(getcwd()+"\\sources") - -try: - remove("core.cp37-win_amd64.pyd") - remove("core.html") - remove("core.c") - shutil.rmtree("build") -except: - pass - -#TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN -#into the include folder of blenders python, too - -with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: - print(proc.stdout.read()) - - shutil.move("core.cp37-win_amd64.pyd", "..\\molecular\\core.cp37-win_amd64.pyd") - - chdir("..") - - with ZipFile('molecular_{}_'.format(('.'.join(map(str, bl_info['version'])))) + 'win.zip', 'w') as z: - for root, _, files in walk('molecular'): - for file in files: - if not file.endswith('.py') and not file.endswith('.pyd'): - continue - z.write(path.join(root, file), compress_type=ZIP_DEFLATED) - - chdir(getcwd()+"\\molecular") - try: - remove("core.cp37-win_amd64.pyd") - except: - pass - chdir("..") From 59909cb55b337ebdcc00bd3ca9e6c85f5c6692b4 Mon Sep 17 00:00:00 2001 From: PavelBlend Date: Wed, 29 Apr 2020 18:48:27 +0300 Subject: [PATCH 062/129] fix uv baking --- molecular/operators.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index e6aafdb..71535c7 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -211,20 +211,25 @@ def check_write_uv_cache(self, context): def check_bake_uv(self, context): # bake the UV in the beginning, and store coordinates in custom property + scene = context.scene + frame_old = scene.frame_current + for ob in bpy.data.objects: obj = get_object(context, ob) for psys in obj.particle_systems: if psys.settings.mol_bakeuv: - context.scene.mol_objuvbake = obj.name + scene.mol_objuvbake = obj.name context.view_layer.update() - context.scene.frame_set(frame=psys.settings.frame_start) + scene.frame_set(frame=psys.settings.frame_start) context.view_layer.update() bpy.ops.object.mol_set_active_uv() + scene.frame_set(frame=frame_old) + def modal(self, context, event): scene = context.scene frame_end = scene.frame_end From 6796b2300223e71c5c2e27901e5dfe51db0bc1b4 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Sat, 2 May 2020 21:11:04 +0200 Subject: [PATCH 063/129] removed hardcoded 37m, use major minor abiflags instead --- make_release.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/make_release.py b/make_release.py index b5691f3..f33b621 100644 --- a/make_release.py +++ b/make_release.py @@ -9,6 +9,7 @@ is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" is_windows = platform.architecture()[1] == "WindowsPE" or platform.system() == "Windows" +v = str(sys.version_info.major) + str(sys.version_info.minor) + sys.abiflags name = 'mac' if is_linux: @@ -24,11 +25,11 @@ with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: print(proc.stdout.read()) if is_linux: #TODO, test - shutil.move("core.cpython-37m-x86_64-linux-gnu.so", "..//molecular//core.cpython-37m-x86_64-linux-gnu.so") + shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: - shutil.move("core.cp37-win_amd64.pyd", "..//molecular//core.cp37-win_amd64.pyd") + shutil.move("core.cp{}-win_amd64.pyd".format(v), "..//molecular//core.cp{}-win_amd64.pyd").format(v) else: - shutil.move("core.cpython-37m-darwin.so", "..//molecular//core.cpython-37m-darwin.so") + shutil.move("core.cpython-{}-darwin.so".format(v), "..//molecular//core.cpython-{}-darwin.so".format(v)) chdir("..") @@ -42,11 +43,11 @@ chdir(getcwd()+"//molecular") try: if is_linux: - remove("core.cpython-37m-x86_64-linux-gnu.so") + remove("core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: - remove("core.cp37-win_amd64.pyd") + remove("core.cp{}-win_amd64.pyd".format(v)) else: - remove("core.cpython-37m-darwin.so") + remove("core.cpython-{}-darwin.so".format(v)) except: pass chdir("..") From 88a68f2377b3786f349e30e9d9088d71e5ff972d Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:23:17 +0200 Subject: [PATCH 064/129] Create molecular-build.yml --- .github/workflows/molecular-build.yml | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/molecular-build.yml diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml new file mode 100644 index 0000000..34056b4 --- /dev/null +++ b/.github/workflows/molecular-build.yml @@ -0,0 +1,39 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: Python application + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: [ubuntu-16.04, windows-latest, macos-latest] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 pytest cython + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Build with Cython + run: | + python make_release.py + - name: Test with pytest + run: | + pytest From 838e2e2deb40b4a6e957b5e90fd5114526b14601 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:25:46 +0200 Subject: [PATCH 065/129] create 3 building jobs, one for each os --- .github/workflows/molecular-build.yml | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 34056b4..20fd232 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -10,9 +10,65 @@ on: branches: [ master ] jobs: - build: + build_windows: - runs-on: [ubuntu-16.04, windows-latest, macos-latest] + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 pytest cython + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Build with Cython + run: | + python make_release.py + - name: Test with pytest + run: | + pytest + + build_linux: + + runs-on: ubuntu-16.04 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 pytest cython + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Build with Cython + run: | + python make_release.py + - name: Test with pytest + run: | + pytest + + build_macos: + + runs-on: macos-latest steps: - uses: actions/checkout@v2 From d0c52cc6c57d0c7efe4054697d57ed8d7b067a61 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:28:41 +0200 Subject: [PATCH 066/129] trying to get the build job working --- .github/workflows/molecular-build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 20fd232..7dba981 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -1,7 +1,7 @@ # This workflow will install Python dependencies, run tests and lint with a single version of Python # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions -name: Python application +name: Molecular Addon for Blender on: push: @@ -24,7 +24,7 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 pytest cython - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + # if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names @@ -52,7 +52,6 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 pytest cython - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names @@ -80,7 +79,6 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 pytest cython - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names From e8e4b1e900fdec0e207054d49044e1d988a6de8c Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:31:48 +0200 Subject: [PATCH 067/129] fix attempt for build system --- .github/workflows/molecular-build.yml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 7dba981..fc7ec97 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -33,11 +33,8 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython run: | - python make_release.py - - name: Test with pytest - run: | - pytest - + python make_release.py + build_linux: runs-on: ubuntu-16.04 @@ -60,10 +57,7 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython run: | - python make_release.py - - name: Test with pytest - run: | - pytest + python make_release.py build_macos: @@ -87,7 +81,4 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython run: | - python make_release.py - - name: Test with pytest - run: | - pytest + python make_release.py From ac2bf3229e97645206bbbc002395ee1e569ba19b Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:41:14 +0200 Subject: [PATCH 068/129] add language level 3 for cython --- sources/setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index 8fcf891..0e4bbb7 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -13,13 +13,15 @@ ext_modules = [Extension( module_name, ['core' + '.pyx'], - extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'] + extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'], + compiler_directives={'language_level' : "3"} )] else: ext_modules = [Extension( module_name, ['core' + '.pyx'], - extra_compile_args=['-O3','-msse4.2','-ffast-math'] + extra_compile_args=['-O3','-msse4.2','-ffast-math'], + compiler_directives={'language_level' : "3"} )] setup( From efa8a7162e721b82c9d42f29e0fe54671f0adaee Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 11:45:56 +0200 Subject: [PATCH 069/129] hopefully this fixes the language level warning --- sources/setup.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index 0e4bbb7..b698cca 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -1,7 +1,6 @@ import platform from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext +from Cython.Distutils import build_ext, Extension import Cython.Compiler.Options @@ -14,14 +13,14 @@ module_name, ['core' + '.pyx'], extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'], - compiler_directives={'language_level' : "3"} + cython_directives={'language_level' : "3"} )] else: ext_modules = [Extension( module_name, ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math'], - compiler_directives={'language_level' : "3"} + cython_directives={'language_level' : "3"} )] setup( From 41e21dfd4cca0b0ab5a80583c3d994a89c344ed3 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 12:22:24 +0200 Subject: [PATCH 070/129] fix for build error in windows with python 3.8.x according to the documentation sys.abiflags shall return an empty string, but it is not even defined in under windows. --- make_release.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index f33b621..c3d3107 100644 --- a/make_release.py +++ b/make_release.py @@ -9,7 +9,14 @@ is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" is_windows = platform.architecture()[1] == "WindowsPE" or platform.system() == "Windows" -v = str(sys.version_info.major) + str(sys.version_info.minor) + sys.abiflags + +#in python 3.8.x, sys.abiflags attribute doesnt seem to exist any more instead of returning empty string. +#so better check for existence here before accessing it. +abiflags = '' +if hasattr(sys, 'abiflags'): + abiflags = sys.abiflags + +v = str(sys.version_info.major) + str(sys.version_info.minor) + abiflags name = 'mac' if is_linux: From 006cd84c717c819c325c8be8119e943a7ed64605 Mon Sep 17 00:00:00 2001 From: MarBasso Date: Tue, 6 Oct 2020 12:00:25 +0200 Subject: [PATCH 071/129] Update time library for Python 3.3+ Updated the code to be compliant with Python 3.3+ distributions, in which the time.clock module is deprecated and replaced by time.perf_counter. To minimize the modifications, I imported the perf_counter module and locally named it as clock. With this approach, the rest of the code is untouched. --- molecular/operators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/operators.py b/molecular/operators.py index 71535c7..b837737 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -1,4 +1,4 @@ -from time import clock, sleep, strftime, gmtime, time +from time import perf_counter as clock, sleep, strftime, gmtime, time import bpy from mathutils import Vector From 16fb14355b0097e9ff00f32423c48a38ebf7d374 Mon Sep 17 00:00:00 2001 From: MarBasso Date: Tue, 6 Oct 2020 12:01:34 +0200 Subject: [PATCH 072/129] Update time library for Python 3.3+ Updated the code to be compliant with Python 3.3+ distributions, in which the time.clock module is deprecated and replaced by time.perf_counter. To minimize the modifications, I imported the perf_counter module and locally named it as clock. With this approach, the rest of the code is untouched. --- sources/core.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/core.pyx b/sources/core.pyx index 3e5e25b..6472e9b 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -7,7 +7,7 @@ cimport cython -from time import clock +from time import perf_counter as clock from cython.parallel import parallel, prange, threadid from libc.stdlib cimport malloc, realloc, free, rand, srand, abs From 1282e3efcb67946a30b7b86030fc0251888d0d54 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 12:33:02 +0200 Subject: [PATCH 073/129] bump version of core.pyx --- sources/core.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/core.pyx b/sources/core.pyx index 6472e9b..60c214e 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -41,7 +41,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.11") +print("cmolcore imported with success! v1.12") cpdef init(importdata): From 84dc688028999e6e96ab2b1ad54818590395a89d Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 12:34:09 +0200 Subject: [PATCH 074/129] bump version of addon to 1.1.2 --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index afa1775..bd7fae4 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,7 +22,7 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 1), + "version": (1, 1, 2), "blender": (2, 80, 0), "location": "Properties editor > Particles Tabs", "description": From 9dc0089447dad725287146ea9143b33fd2e10bb0 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 12:58:24 +0200 Subject: [PATCH 075/129] attempt to get correct version for packaging --- .github/workflows/molecular-build.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index fc7ec97..7a1a202 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -9,6 +9,9 @@ on: pull_request: branches: [ master ] +env: + version: '1.1.2' #override in job, but set as fallback here + jobs: build_windows: @@ -32,8 +35,13 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython - run: | - python make_release.py + run: | + env.version = ${{ python make_release.py }} + - name: Upload windows zip + uses: actions/upload-artifact@v2 + with: + name: molecular_${{env.version}}_win.zip + path: molecular_${{env.version}}_win.zip build_linux: From 6e7e309116f7751a082f1b5514e089b66686bcf9 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:00:56 +0200 Subject: [PATCH 076/129] how does this work.... --- .github/workflows/molecular-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 7a1a202..5e29ff7 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -36,7 +36,7 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython run: | - env.version = ${{ python make_release.py }} + env.version = ${{ "python make_release.py" }} - name: Upload windows zip uses: actions/upload-artifact@v2 with: From 574bdc67187c174e5e777b0a6e3c9c54ec8867e6 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:07:54 +0200 Subject: [PATCH 077/129] another try --- .github/workflows/molecular-build.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 5e29ff7..8a4f41b 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -9,9 +9,6 @@ on: pull_request: branches: [ master ] -env: - version: '1.1.2' #override in job, but set as fallback here - jobs: build_windows: @@ -35,13 +32,13 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython - run: | - env.version = ${{ "python make_release.py" }} + id: build + run: echo "::set-output name=version::$(python make_release.py)" - name: Upload windows zip uses: actions/upload-artifact@v2 with: - name: molecular_${{env.version}}_win.zip - path: molecular_${{env.version}}_win.zip + name: molecular_${{steps.build.outputs.version}}_win.zip + path: molecular_${{steps.build.outputs.version}}_win.zip build_linux: From 546d18ac95babf616e9e58740236c9de2701eb8f Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:18:24 +0200 Subject: [PATCH 078/129] another fix attempt for getting a version --- .github/workflows/molecular-build.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 8a4f41b..6e9d00a 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -31,14 +31,17 @@ jobs: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Get current version string + id: version + run: echo "::set-output name=version::$(python -c \"from molecular import bl_info; print(bl_info['version'])\")" - name: Build with Cython - id: build - run: echo "::set-output name=version::$(python make_release.py)" + run: | + python make_release.py - name: Upload windows zip uses: actions/upload-artifact@v2 with: - name: molecular_${{steps.build.outputs.version}}_win.zip - path: molecular_${{steps.build.outputs.version}}_win.zip + name: molecular_${{steps.version.outputs.version}}_win.zip + path: molecular_${{steps.version.outputs.version}}_win.zip build_linux: From 4112a0ffa9df92fb1dc6ed480a6103f5c1f3772c Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:22:35 +0200 Subject: [PATCH 079/129] string tinkering... --- .github/workflows/molecular-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 6e9d00a..6f23e14 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -33,7 +33,7 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Get current version string id: version - run: echo "::set-output name=version::$(python -c \"from molecular import bl_info; print(bl_info['version'])\")" + run: echo "::set-output name=version::$(python -c '''from molecular import bl_info; print(bl_info['version'])''' )" - name: Build with Cython run: | python make_release.py From 777649d01fd4d210138e9dd2a8824a638fcee533 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:29:06 +0200 Subject: [PATCH 080/129] another approach to get the version --- make_release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index c3d3107..b9939a3 100644 --- a/make_release.py +++ b/make_release.py @@ -30,7 +30,8 @@ #into the include folder of blenders python, too with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: - print(proc.stdout.read()) + #print(proc.stdout.read()) + print(bl_info['version']) if is_linux: #TODO, test shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: From fb20d03ba132ef171c89902c90dfaec56dcd1b36 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:32:22 +0200 Subject: [PATCH 081/129] hrmpf... --- .github/workflows/molecular-build.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 6f23e14..8a4f41b 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -31,17 +31,14 @@ jobs: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Get current version string - id: version - run: echo "::set-output name=version::$(python -c '''from molecular import bl_info; print(bl_info['version'])''' )" - name: Build with Cython - run: | - python make_release.py + id: build + run: echo "::set-output name=version::$(python make_release.py)" - name: Upload windows zip uses: actions/upload-artifact@v2 with: - name: molecular_${{steps.version.outputs.version}}_win.zip - path: molecular_${{steps.version.outputs.version}}_win.zip + name: molecular_${{steps.build.outputs.version}}_win.zip + path: molecular_${{steps.build.outputs.version}}_win.zip build_linux: From a9d253480130361aace21aadcbac3346d6634f36 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:37:06 +0200 Subject: [PATCH 082/129] and another try... --- make_release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index b9939a3..0cce5a3 100644 --- a/make_release.py +++ b/make_release.py @@ -31,7 +31,6 @@ with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: #print(proc.stdout.read()) - print(bl_info['version']) if is_linux: #TODO, test shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: @@ -69,3 +68,5 @@ pass chdir("..") + +print(bl_info['version']) From b14c9d334151d584365baaf2f04efd23dfd47acd Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:39:12 +0200 Subject: [PATCH 083/129] broken pipe ? wtf... --- make_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index 0cce5a3..852e790 100644 --- a/make_release.py +++ b/make_release.py @@ -30,7 +30,7 @@ #into the include folder of blenders python, too with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: - #print(proc.stdout.read()) + proc.stdout.read() if is_linux: #TODO, test shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: From be987ad2cd09200685d4f5e4b52f28e5b3c490b7 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:43:24 +0200 Subject: [PATCH 084/129] test --- make_release.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index 852e790..65b7f81 100644 --- a/make_release.py +++ b/make_release.py @@ -29,6 +29,8 @@ #TODO, blenders (or a compatible) python bin needs to be in $PATH, and if you use blender's you need to copy the python includes from SVN #into the include folder of blenders python, too +version = '.'.join(map(str, bl_info['version'])) + with Popen([sys.executable, "setup.py", "build_ext", "--inplace"], stdout=PIPE) as proc: proc.stdout.read() if is_linux: #TODO, test @@ -69,4 +71,4 @@ chdir("..") -print(bl_info['version']) +print(version) From f448b6ae42c6b4a00f9ef491e96818a590cbaa47 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:54:17 +0200 Subject: [PATCH 085/129] fix for file name glitch (hopefully) --- make_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index 65b7f81..7743401 100644 --- a/make_release.py +++ b/make_release.py @@ -36,7 +36,7 @@ if is_linux: #TODO, test shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: - shutil.move("core.cp{}-win_amd64.pyd".format(v), "..//molecular//core.cp{}-win_amd64.pyd").format(v) + shutil.move("core.cp{}-win_amd64.pyd".format(v), "..//molecular//core.cp{}-win_amd64.pyd").format(v)) else: shutil.move("core.cpython-{}-darwin.so".format(v), "..//molecular//core.cpython-{}-darwin.so".format(v)) From f5cdda58a1b20ea836325cd584b762e0f18fd381 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 13:59:04 +0200 Subject: [PATCH 086/129] damn parenthesis... --- make_release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release.py b/make_release.py index 7743401..bd0991b 100644 --- a/make_release.py +++ b/make_release.py @@ -36,7 +36,7 @@ if is_linux: #TODO, test shutil.move("core.cpython-{}-x86_64-linux-gnu.so".format(v), "..//molecular//core.cpython-{}-x86_64-linux-gnu.so".format(v)) elif is_windows: - shutil.move("core.cp{}-win_amd64.pyd".format(v), "..//molecular//core.cp{}-win_amd64.pyd").format(v)) + shutil.move("core.cp{}-win_amd64.pyd".format(v), "..//molecular//core.cp{}-win_amd64.pyd".format(v)) else: shutil.move("core.cpython-{}-darwin.so".format(v), "..//molecular//core.cpython-{}-darwin.so".format(v)) From eea04eb17a35ddd8dfdaad3d6093b652d3c11705 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 14:08:16 +0200 Subject: [PATCH 087/129] update artifact creation rules for mac and linux --- .github/workflows/molecular-build.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 8a4f41b..11f4620 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -61,8 +61,13 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython - run: | - python make_release.py + id: build + run: echo "::set-output name=version::$(python make_release.py)" + - name: Upload linux zip + uses: actions/upload-artifact@v2 + with: + name: molecular_${{steps.build.outputs.version}}_linux.zip + path: molecular_${{steps.build.outputs.version}}_linux.zip build_macos: @@ -85,5 +90,10 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython - run: | - python make_release.py + id: build + run: echo "::set-output name=version::$(python make_release.py)" + - name: Upload mac zip + uses: actions/upload-artifact@v2 + with: + name: molecular_${{steps.build.outputs.version}}_mac.zip + path: molecular_${{steps.build.outputs.version}}_mac.zip From add0be0559a823d081b07722fadbd3af52afdc5f Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 14:28:51 +0200 Subject: [PATCH 088/129] fix for loading error (undefined symbols) errors with undefined functions from math.h may occur on loading the linux version of molecular. So hopefully '-fno-builtin' compiler switch will fix this. --- sources/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/setup.py b/sources/setup.py index b698cca..dde7c98 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -19,7 +19,7 @@ ext_modules = [Extension( module_name, ['core' + '.pyx'], - extra_compile_args=['-O3','-msse4.2','-ffast-math'], + extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], cython_directives={'language_level' : "3"} )] From 2c83d83c2ae0ffcdace1a59a3bffd5476248dde6 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 14:37:59 +0200 Subject: [PATCH 089/129] change linux runner to ubuntu 18.04 --- .github/workflows/molecular-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 11f4620..65eeed9 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -42,7 +42,7 @@ jobs: build_linux: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 From d4cd1bd7ecb9b969ca5b095538cc7711efa68925 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 14:50:46 +0200 Subject: [PATCH 090/129] try to additionally link math lib (lm) --- sources/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/setup.py b/sources/setup.py index dde7c98..1c9aaef 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -20,6 +20,7 @@ module_name, ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], + extra_link_args=['-lm'], cython_directives={'language_level' : "3"} )] From c6e0203d9fb43c34697a45f1a919b4413e9a1434 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 9 Oct 2020 15:22:03 +0200 Subject: [PATCH 091/129] put status badge into readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d55fa15..0f185d5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Molecular Addon for Blender](https://github.com/scorpion81/Blender-Molecular-Script/workflows/Molecular%20Addon%20for%20Blender/badge.svg) + Blender-Molecular-Script ======================== From 60385f589d3d31261cfb51802a915dd0355d500c Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 11 Oct 2020 11:15:28 +0200 Subject: [PATCH 092/129] hrmpf, blender 2.90.1 still uses python 3.7 was assuming the switch to 3.8 was already made. Trying to adapt this now in the builders. --- .github/workflows/molecular-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 65eeed9..84edd88 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.7 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.7 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -46,10 +46,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.7 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.7 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -75,10 +75,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.7 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.7 - name: Install dependencies run: | python -m pip install --upgrade pip From 5f931c76af1d5c55541b8d7a1618c6dd14851a73 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 15 Jan 2021 14:48:11 +0100 Subject: [PATCH 093/129] linux: attempt to statically link against python for some weird reason, there is no dynamic python library included in blenders linux release build So in order to run molecular there, try to link statically against the according python version which should be included in blender. --- sources/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/setup.py b/sources/setup.py index 1c9aaef..b67698b 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -20,7 +20,7 @@ module_name, ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], - extra_link_args=['-lm'], + extra_link_args=['-lm', '-static'], cython_directives={'language_level' : "3"} )] From cba4ce658279935f97ae07a2b5138f47a00b828f Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 15 Jan 2021 17:04:09 +0100 Subject: [PATCH 094/129] Revert "linux: attempt to statically link against python" This reverts commit 5f931c76af1d5c55541b8d7a1618c6dd14851a73. --- sources/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/setup.py b/sources/setup.py index b67698b..1c9aaef 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -20,7 +20,7 @@ module_name, ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], - extra_link_args=['-lm', '-static'], + extra_link_args=['-lm'], cython_directives={'language_level' : "3"} )] From 04e7cb235f3157229a02f38149e063093ded1bc6 Mon Sep 17 00:00:00 2001 From: Will Date: Mon, 26 Oct 2020 14:40:49 +0200 Subject: [PATCH 095/129] fix english grammar --- molecular/descriptions.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/molecular/descriptions.py b/molecular/descriptions.py index 4834068..a0450db 100644 --- a/molecular/descriptions.py +++ b/molecular/descriptions.py @@ -22,44 +22,44 @@ LINK_OTHER_ACTIVE = '' LINK_GROUP = '' LINK_RELATIVE_LENGTH = 'Activate search distance relative to particles radius' -LINK_FRICTION = 'Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full of friction' +LINK_FRICTION = 'Friction in links , a kind of viscosity. Slow down tangent velocity. 0 = no friction , 1.0 = full friction' LINK_LENGTH = 'Searching range to make a link between particles' LINK_TENSION = 'Make link bigger or smaller than it\'s created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)' LINK_TENSION_RANDOM = 'Tension random' -LINK_MAX = 'Maximum of links per particles' +LINK_MAX = 'Maximum number of links per particles' LINK_STIFFNESS = 'Stiffness of links between particles' LINK_STIFFNESS_RANDOM = 'Random variation for stiffness' -LINK_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +LINK_STIFFNESS_EXPONENT = 'Give an exponent force to the spring links' LINK_DAMPING = 'Damping effect on spring links' LINK_DAMPING_RANDOM = 'Random variation on damping' -LINK_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +LINK_BROKEN = 'How much links can stretch before they are broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' LINK_BROKEN_RANDOM = 'Give a random variation to the stretch limit' LINK_SAME_VALUE = 'When active , expansion and compression of the spring have same value' LINK_EXPENSION_STIFFNESS = 'Expension stiffness of links between particles' LINK_EXPENSION_STIFFNESS_RANDOM = 'Random variation for expansion stiffness' -LINK_EXPENSION_STIFFNESS_EXPONENT = 'Give a exponent force to the expension spring links' +LINK_EXPENSION_STIFFNESS_EXPONENT = 'Give an exponent force to the expension spring links' LINK_EXPENSION_DAMPING = 'Damping effect on expension spring links' LINK_EXPENSION_DAMPING_RANDOM = 'Random variation on expension damping' -LINK_EXPENSION_BROKEN = 'How much link can expand before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +LINK_EXPENSION_BROKEN = 'How much links can expand before they are broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' LINK_EXPENSION_BROKEN_RANDOM = 'Give a random variation to the expension stretch limit' RELINK_GROUP = 'Choose a group that new link are possible' -RELINK_CHANCE = 'Chance of a new link are created on collision. 0 = off , 100 = 100% of chance' +RELINK_CHANCE = 'Chance of a new link created on collision. 0 = off , 100 = 100% chance' RELINK_CHANCE_RANDOM = 'Give a random variation to the chance of new link' RELINK_TENSION = 'Make link bigger or smaller than it\'s created (1 = normal , 0.9 = 10% smaller , 1.15 = 15% bigger)' RELINK_TENSION_RANDOM = 'Tension random' -RELINK_MAX = 'Maximum of links per particles' +RELINK_MAX = 'Maximum number of links per particles' RELINK_STIFFNESS = 'Stiffness of links between particles' RELINK_STIFFNESS_RANDOM = 'Random variation for stiffness' -RELINK_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +RELINK_STIFFNESS_EXPONENT = 'Give an exponent force to the spring links' RELINK_DAMPING = 'Damping effect on spring links' RELINK_DAMPING_RANDOM = 'Random variation on damping' -RELINK_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' +RELINK_BROKEN = 'How much links can stretch before they are broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' RELINK_BROKEN_RANDOM = 'Give a random variation to the stretch limit' RELINK_SAME_VALUE = 'When active , expansion and compression of the spring have same value' RELINK_EXPENSION_STIFFNESS = 'Stiffness of links expension between particles' RELINK_EXPENSION_STIFFNESS_RANDOM = 'Random variation for expension stiffness' -RELINK_EXPENSION_STIFFNESS_EXPONENT = 'Give a exponent force to the spring links' +RELINK_EXPENSION_STIFFNESS_EXPONENT = 'Give an exponent force to the spring links' RELINK_EXPENSION_DAMPING = 'Damping effect on expension spring links' RELINK_EXPENSION_DAMPING_RANDOM = 'Random variation on damping' RELINK_EXPENSION_BROKEN = 'How much link can stretch before they broken. 0.01 = 1% , 0.5 = 50% , 2.0 = 200% ...' @@ -68,11 +68,11 @@ VAR_1 = 'Current number of particles to calculate substep' VAR_2 = 'Current substep' VAR_3 = 'Targeted number of particles you want to increase or decrease from current system to calculate substep you need to achieve similar effect' -BAKE_UV = 'Bake uv when finish' +BAKE_UV = 'Bake uv when finished' TIME_SCALE_ACTIVE = 'Activate TimeScaling' TIME_SCALE = 'SpeedUp or Slow down the simulation with this multiplier' -SUBSTEP = 'mol_substep. Higher equal more stable and accurate but more slower' -BAKE = 'Bake simulation when finish' -RENDER = 'Start rendering animation when simulation is finish. WARNING: It\'s freeze blender until render is finish.' -CPU = 'Numbers of cpu\'s included for process the simulation' +SUBSTEP = 'mol_substep. Higher is more stable and accurate, but slower' +BAKE = 'Bake simulation when finished' +RENDER = 'Start rendering animation when simulation is finished. WARNING: This will freeze blender until the render is finished.' +CPU = 'Number of cpu\'s included to process the simulation' From fe11cab93ca9fae0b6f2adc1045e8db17ce939e3 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 16 Jul 2021 15:45:32 +0200 Subject: [PATCH 096/129] compile against python 3.9 for blender 2.93+ update python version against which this addon is being compiled --- .github/workflows/molecular-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 84edd88..b799f24 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -46,10 +46,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -75,10 +75,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip From 6f6bdfc2b9b5f8b919fab436c3fbf8d1d386080f Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 16 Jul 2021 19:03:53 +0200 Subject: [PATCH 097/129] attempt installing libpython.a for linux try calling into apt get with a custom ppa in order to setup libpython.a / libpython3-devel package --- .github/workflows/molecular-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index b799f24..75c55df 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -52,6 +52,10 @@ jobs: python-version: 3.9 - name: Install dependencies run: | + # attempt to install libpython.a for 3.9 + add-apt-repository ppa:deadsnakes/ppa + apt update + apt install libpython3-devel python -m pip install --upgrade pip pip install flake8 pytest cython - name: Lint with flake8 From e47fb96af1d42c8d26f3bbba4ff0399bb603bf45 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 16 Jul 2021 19:06:31 +0200 Subject: [PATCH 098/129] fix: forgot sudo --- .github/workflows/molecular-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 75c55df..1947d61 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -53,9 +53,9 @@ jobs: - name: Install dependencies run: | # attempt to install libpython.a for 3.9 - add-apt-repository ppa:deadsnakes/ppa - apt update - apt install libpython3-devel + sudo add-apt-repository ppa:deadsnakes/ppa + sudo apt update + sudo apt install libpython3-devel python -m pip install --upgrade pip pip install flake8 pytest cython - name: Lint with flake8 From cd5896c69353619765259431fd079df5dc1f3b8b Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 16 Jul 2021 19:12:31 +0200 Subject: [PATCH 099/129] fix: corrected package name --- .github/workflows/molecular-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 1947d61..3cae83f 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -55,7 +55,7 @@ jobs: # attempt to install libpython.a for 3.9 sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update - sudo apt install libpython3-devel + sudo apt install libpython3.9-dev python -m pip install --upgrade pip pip install flake8 pytest cython - name: Lint with flake8 From dc4db01e88cb3d115bd94b4da1f0a797b4c2e73e Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 16:28:18 +0200 Subject: [PATCH 100/129] update used python version to 3.10 --- .github/workflows/molecular-build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 3cae83f..61b8b2c 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.10 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -46,16 +46,16 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.10 - name: Install dependencies run: | - # attempt to install libpython.a for 3.9 + # attempt to install libpython.a for 3.10 sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update - sudo apt install libpython3.9-dev + sudo apt install libpython3.10-dev python -m pip install --upgrade pip pip install flake8 pytest cython - name: Lint with flake8 @@ -79,10 +79,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.10 - name: Install dependencies run: | python -m pip install --upgrade pip From 54d565d80430a9fca9eb155dfd5b1ec91f9cb8b4 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 16:32:02 +0200 Subject: [PATCH 101/129] fix syntax error with python 3.10 --- .github/workflows/molecular-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 61b8b2c..d1dfb24 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -49,7 +49,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: "3.10" - name: Install dependencies run: | # attempt to install libpython.a for 3.10 @@ -82,7 +82,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip From 2f932a08d5b48e9ddfdf766350bc1ccfd17ab8aa Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 16:36:01 +0200 Subject: [PATCH 102/129] version bump --- molecular/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index bd7fae4..9373b2f 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,8 +22,8 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 2), - "blender": (2, 80, 0), + "version": (1, 1, 3), + "blender": (3, 0, 0), "location": "Properties editor > Particles Tabs", "description": "Addon for calculating collisions " From 1f6400d0b83b92c516df397cf8ecdf6b1f19a92b Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 18:42:43 +0200 Subject: [PATCH 103/129] build a "fat" binary for mac os --- sources/setup.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index 1c9aaef..c6e08ea 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -7,6 +7,7 @@ os_name = platform.architecture()[1] Cython.Compiler.Options.annotate = True module_name = 'core' +is_linux = platform.architecture()[1] == "ELF" or platform.system() == "Linux" if os_name == "WindowsPE": ext_modules = [Extension( @@ -15,14 +16,25 @@ extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'], cython_directives={'language_level' : "3"} )] -else: - ext_modules = [Extension( +elif is_linux: + ext_modules = [Extension( module_name, ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], extra_link_args=['-lm'], cython_directives={'language_level' : "3"} )] +else: + # under mac OS, with the advent of the M1 ARM chips, its necessary to build an universal intel/arm binary. + # this is done by passing -arch arm64 -arch x86_64 from here to clang, the default mac OS compiler. + + ext_modules = [Extension( + module_name, + ['core' + '.pyx'], + extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64','-arch','x86_64'], + extra_link_args=['-lm','-arch','arm64','-arch','x86_64'], + cython_directives={'language_level' : "3"} + )] setup( name = 'Molecular script', From cc8cc23019793b41de292c8db1c61b5a08502cc5 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 19:04:39 +0200 Subject: [PATCH 104/129] removed dead links --- README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0f185d5..92505f7 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,9 @@ Blender-Molecular-Script ======================== -This is my molecular python script for blender. Inspired from the 2d simulator Really (1998) and Lagoa Multiphysic in Softimage. +This is the molecular python script for blender, originally coded py Pyroevil. Inspired from the 2d simulator Really (1998) and Lagoa Multiphysic in Softimage. -To download the latest version go on my blog: - -http://pyroevil.com/molecular-script-download/ +To download the latest version go to the release section of this repository. The script can be installed like any other addons in Blender: First way: @@ -26,6 +24,3 @@ To activate the plugins: - Go in File > User Preferences > Addons tab - In the "Object" categories, you must find "Molecular" - Check it , close the "Blender user preferences" windows and have fun. - - -Visit my blog about this script for donation, comments or more detail : http://pyroevil.com From ee0c68363716305b98e84335ba2773704c964d3d Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 14 May 2022 22:22:41 +0200 Subject: [PATCH 105/129] Hmm, M1 seems to be arm64e, not arm64 --- sources/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index c6e08ea..2e3426a 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -31,8 +31,8 @@ ext_modules = [Extension( module_name, ['core' + '.pyx'], - extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64','-arch','x86_64'], - extra_link_args=['-lm','-arch','arm64','-arch','x86_64'], + extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64e','-arch','x86_64'], + extra_link_args=['-lm','-arch','arm64e','-arch','x86_64'], cython_directives={'language_level' : "3"} )] From c94b0a178a583b5890271fc709f6556acca3ab7e Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 10:59:01 +0200 Subject: [PATCH 106/129] attempt to automate draft releases --- .github/workflows/molecular-build.yml | 52 ++++++++++++++++++--------- .github/workflows/release.py | 49 +++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.py diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index d1dfb24..b7230e4 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -34,12 +34,13 @@ jobs: - name: Build with Cython id: build run: echo "::set-output name=version::$(python make_release.py)" - - name: Upload windows zip - uses: actions/upload-artifact@v2 - with: - name: molecular_${{steps.build.outputs.version}}_win.zip - path: molecular_${{steps.build.outputs.version}}_win.zip - + - name: Cache windows zip + - uses: actions/cache@v2 + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_win.zip + key: ${{ github.sha }} + build_linux: runs-on: ubuntu-18.04 @@ -67,11 +68,12 @@ jobs: - name: Build with Cython id: build run: echo "::set-output name=version::$(python make_release.py)" - - name: Upload linux zip - uses: actions/upload-artifact@v2 - with: - name: molecular_${{steps.build.outputs.version}}_linux.zip - path: molecular_${{steps.build.outputs.version}}_linux.zip + - name: Cache linux zip + - uses: actions/cache@v2 + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_linux.zip + key: ${{ github.sha }} build_macos: @@ -96,8 +98,26 @@ jobs: - name: Build with Cython id: build run: echo "::set-output name=version::$(python make_release.py)" - - name: Upload mac zip - uses: actions/upload-artifact@v2 - with: - name: molecular_${{steps.build.outputs.version}}_mac.zip - path: molecular_${{steps.build.outputs.version}}_mac.zip + - name: Cache mac zip + - uses: actions/cache@v2 + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_mac.zip + key: ${{ github.sha }} + + upload_draft: + name: Upload zips as draft release assets + runs-on: ubuntu-latest + needs: [build_windows, build_linux, build_macos] + + steps: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + - uses: actions/cache@v2 + id: zip-cache + with: + path: ./* + key: ${{ github.sha }} + #- run: python .github/workflows/release.py --path . --files py_modifier.zip + - run: ls *.zip diff --git a/.github/workflows/release.py b/.github/workflows/release.py new file mode 100644 index 0000000..27747e8 --- /dev/null +++ b/.github/workflows/release.py @@ -0,0 +1,49 @@ +import requests, argparse, json, os + +parser = argparse.ArgumentParser(description='Parameters.') +parser.add_argument('--path', metavar='path', type=str, nargs='+', + help='path where to search for files') +parser.add_argument('--files', metavar='files', type=str, nargs='+', + help='name of files to upload') +args = parser.parse_args() +d = vars(args) + +r = os.environ['GITHUB_REPOSITORY'] +t = os.environ['GITHUB_TOKEN'] +p = d['path'][0] +fi = d['files'] + +owner = r.split("/")[0] +name = r.split("/")[1] + +j = {"tag_name":"v1.0.0", # can be manually edited on publishing this draft ! + "target_commitish":"master", + "name": name, + "body":"Autogenerated release package", + "draft":True, + "prerelease":False, + "generate_release_notes":False}, + +js = json.dumps(j[0]) + +r = requests.post( + headers={'Accept': 'application/vnd.github.v3+json', + 'Authorization': 'token {token}'.format(token=t)}, + url='https://api.github.com/repos/{owner}/{name}/releases'.format(owner=owner, name=name), + data=js, +) + +if "upload_url" in r.json(): + u = r.json()["upload_url"].split("{")[0] + +for f in fi: + pr = os.path.realpath(p) + pa = os.path.join(pr, f) + with open(pa, 'rb') as data: + r = requests.post( + headers={'Content-Type': 'application/zip', + 'Authorization': 'token {token}'.format(token=t)}, + url=u+'?name={name}'.format(name=f), + data=data.read() + ) + From 30b747c34e5e7de7ca784ffcf4946a355cb5c043 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:06:42 +0200 Subject: [PATCH 107/129] action yml syntax error fixes --- .github/workflows/molecular-build.yml | 37 ++++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index b7230e4..ee27196 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -36,10 +36,10 @@ jobs: run: echo "::set-output name=version::$(python make_release.py)" - name: Cache windows zip - uses: actions/cache@v2 - id: zip-cache - with: - path: ./molecular_${{steps.build.outputs.version}}_win.zip - key: ${{ github.sha }} + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_win.zip + key: ${{ github.sha }} build_linux: @@ -70,10 +70,10 @@ jobs: run: echo "::set-output name=version::$(python make_release.py)" - name: Cache linux zip - uses: actions/cache@v2 - id: zip-cache - with: - path: ./molecular_${{steps.build.outputs.version}}_linux.zip - key: ${{ github.sha }} + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_linux.zip + key: ${{ github.sha }} build_macos: @@ -100,10 +100,10 @@ jobs: run: echo "::set-output name=version::$(python make_release.py)" - name: Cache mac zip - uses: actions/cache@v2 - id: zip-cache - with: - path: ./molecular_${{steps.build.outputs.version}}_mac.zip - key: ${{ github.sha }} + id: zip-cache + with: + path: ./molecular_${{steps.build.outputs.version}}_mac.zip + key: ${{ github.sha }} upload_draft: name: Upload zips as draft release assets @@ -111,13 +111,14 @@ jobs: needs: [build_windows, build_linux, build_macos] steps: + - name: Uploading env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPOSITORY: $GITHUB_REPOSITORY - - uses: actions/cache@v2 - id: zip-cache - with: - path: ./* - key: ${{ github.sha }} + - uses: actions/cache@v2 + id: zip-cache + with: + path: ./* + key: ${{ github.sha }} #- run: python .github/workflows/release.py --path . --files py_modifier.zip - - run: ls *.zip + - run: ls *.zip From bcbd5c96060a843cd4750a64032e8f870f67db26 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:09:53 +0200 Subject: [PATCH 108/129] fix workflow logic --- .github/workflows/molecular-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index ee27196..bfc2ab7 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -111,14 +111,14 @@ jobs: needs: [build_windows, build_linux, build_macos] steps: - - name: Uploading - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: $GITHUB_REPOSITORY - uses: actions/cache@v2 id: zip-cache with: path: ./* key: ${{ github.sha }} - #- run: python .github/workflows/release.py --path . --files py_modifier.zip - - run: ls *.zip + - name: Uploading + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + run: ls *.zip + #run: python .github/workflows/release.py --path . --files py_modifier.zip From 462460d791c06dcbfbe248f2560f5e6915a1d0a8 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:13:05 +0200 Subject: [PATCH 109/129] yet another fix --- .github/workflows/molecular-build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index bfc2ab7..b953e86 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -35,7 +35,7 @@ jobs: id: build run: echo "::set-output name=version::$(python make_release.py)" - name: Cache windows zip - - uses: actions/cache@v2 + uses: actions/cache@v2 id: zip-cache with: path: ./molecular_${{steps.build.outputs.version}}_win.zip @@ -69,7 +69,7 @@ jobs: id: build run: echo "::set-output name=version::$(python make_release.py)" - name: Cache linux zip - - uses: actions/cache@v2 + uses: actions/cache@v2 id: zip-cache with: path: ./molecular_${{steps.build.outputs.version}}_linux.zip @@ -99,13 +99,14 @@ jobs: id: build run: echo "::set-output name=version::$(python make_release.py)" - name: Cache mac zip - - uses: actions/cache@v2 + uses: actions/cache@v2 id: zip-cache with: path: ./molecular_${{steps.build.outputs.version}}_mac.zip key: ${{ github.sha }} upload_draft: + name: Upload zips as draft release assets runs-on: ubuntu-latest needs: [build_windows, build_linux, build_macos] From 1dd167cd10eceabba97a0d779e6bd365d86dcb90 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:29:01 +0200 Subject: [PATCH 110/129] hrm, cache doesnt work here, using artifacts again --- .github/workflows/molecular-build.yml | 44 +++++++++++++++------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index b953e86..9de7c47 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -33,13 +33,12 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython id: build - run: echo "::set-output name=version::$(python make_release.py)" - - name: Cache windows zip - uses: actions/cache@v2 - id: zip-cache + run: echo "::set-output name=version::$(python make_release.py)" + - name: Upload windows zip + uses: actions/upload-artifact@v3 with: - path: ./molecular_${{steps.build.outputs.version}}_win.zip - key: ${{ github.sha }} + path: molecular_${{steps.build.outputs.version}}_win.zip + name: molecular_win build_linux: @@ -68,12 +67,11 @@ jobs: - name: Build with Cython id: build run: echo "::set-output name=version::$(python make_release.py)" - - name: Cache linux zip - uses: actions/cache@v2 - id: zip-cache + - name: Upload linux zip + uses: actions/upload-artifact@v3 with: - path: ./molecular_${{steps.build.outputs.version}}_linux.zip - key: ${{ github.sha }} + path: molecular_${{steps.build.outputs.version}}_linux.zip + name: molecular_linux build_macos: @@ -98,12 +96,11 @@ jobs: - name: Build with Cython id: build run: echo "::set-output name=version::$(python make_release.py)" - - name: Cache mac zip - uses: actions/cache@v2 - id: zip-cache + - name: Upload mac zip + uses: actions/upload-artifact@v3 with: - path: ./molecular_${{steps.build.outputs.version}}_mac.zip - key: ${{ github.sha }} + path: molecular_${{steps.build.outputs.version}}_mac.zip + name: molecular_mac upload_draft: @@ -112,11 +109,18 @@ jobs: needs: [build_windows, build_linux, build_macos] steps: - - uses: actions/cache@v2 - id: zip-cache + - uses: actions/download-artifact@v3 + with: + name: molecular_win + + - uses: actions/download-artifact@v3 + with: + name: molecular_linux + + - uses: actions/download-artifact@v3 with: - path: ./* - key: ${{ github.sha }} + name: molecular_mac + - name: Uploading env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From e3482db45372d3f5e2c0829aea6d246cf6001b34 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:35:58 +0200 Subject: [PATCH 111/129] try to upload this now --- .github/workflows/molecular-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 9de7c47..5012924 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -125,5 +125,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPOSITORY: $GITHUB_REPOSITORY - run: ls *.zip - #run: python .github/workflows/release.py --path . --files py_modifier.zip + run: python .github/workflows/release.py --path . --files `ls *.zip` From 9a55a132d37d527e83171751e270d3bed052d184 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 21 May 2022 11:42:55 +0200 Subject: [PATCH 112/129] gah, forgot to checkout the repo --- .github/workflows/molecular-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 5012924..d555660 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -109,6 +109,8 @@ jobs: needs: [build_windows, build_linux, build_macos] steps: + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 with: name: molecular_win From 675953a0b8d97313b6328ef6c9b0fae3bb4d5c6d Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 12 Aug 2022 16:33:53 +0200 Subject: [PATCH 113/129] fixes for type error and crash and version bump --- molecular/__init__.py | 2 +- molecular/operators.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 9373b2f..4e74df3 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,7 +22,7 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 3), + "version": (1, 1, 4), "blender": (3, 0, 0), "location": "Properties editor > Particles Tabs", "description": diff --git a/molecular/operators.py b/molecular/operators.py index b837737..3fea5ea 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -93,7 +93,9 @@ def execute(self, context): print(' start bake uv from:', obj.name) - obdata = obj.data.copy() + # take the original object as source for copying the data, + # else the materials are not copied properly and context.view_layer.update() crashes + obdata = context.object.data.copy() obj2 = bpy.data.objects.new(name="mol_uv_temp", object_data=obdata) obj2.matrix_world = obj.matrix_world @@ -222,8 +224,8 @@ def check_bake_uv(self, context): scene.mol_objuvbake = obj.name context.view_layer.update() - - scene.frame_set(frame=psys.settings.frame_start) + # cast float value psys.settings.frame_start to int here because frame_set accepts only ints now. + scene.frame_set(frame=int(psys.settings.frame_start)) context.view_layer.update() bpy.ops.object.mol_set_active_uv() From 831b3f4f9a6de21a8359f98175e3c5a8d7fc5abe Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 12 Aug 2022 16:59:43 +0200 Subject: [PATCH 114/129] added some UV Baking information to the readme Addes some short explanation and example blend file on how to add UVs to the particle system instances. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 92505f7..e052f45 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,36 @@ To activate the plugins: - Go in File > User Preferences > Addons tab - In the "Object" categories, you must find "Molecular" - Check it , close the "Blender user preferences" windows and have fun. + + +How to add UVs to molecular particle instances: +---------------------------------------------- + +This didnt seem to work in blender 3.2.x any more and was fixed in 1.1.4. +Should also apply to blender 3.1.x but that was not tested by me. + +- Original Link: +https://blenderartists.org/t/moleculars-physics/521682/269 + +- Example File: +[test_UV_molecular.zip](https://github.com/scorpion81/Blender-Molecular-Script/files/9320719/test_UV_molecular.zip) + +When the UV data is being baked during the simulation, it will be written into the angular velocity cache part +of the particle system at the moment. + +Hence you can retrieve it via a particle info node later on in order to feed it into the vector socket of the +texture node. + +Example with 10x10x10 Grid: +![molecular_bake_uv](https://user-images.githubusercontent.com/1172149/184380338-b07cb5de-4d54-45e0-9fa8-2967f4fb29cc.jpeg) + +Same Example with 30x30x30 Grid +![molecular_bake_uv_high](https://user-images.githubusercontent.com/1172149/184380364-9e4a1ff9-8924-4619-9d77-f191950c52e7.jpeg) + +In order to display the texture both on the emitter object (the cube in this example), just disconnect the angular velocity to texture connection. +The particles should keep their texture and the emitter is properly textured again then, too. + +Remarks: +- only in cycles +- only in rendered viewport and render +- need to re-bake the sim for UVs after loading (not persistent, it seems) From c0a0ff4ce320ffc83492163c56772543c437f31c Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sun, 21 Aug 2022 20:57:35 +0200 Subject: [PATCH 115/129] some clarification attempt attempt to clarify the proper usage of the particle info node --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e052f45..87f4b1d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,9 @@ When the UV data is being baked during the simulation, it will be written into t of the particle system at the moment. Hence you can retrieve it via a particle info node later on in order to feed it into the vector socket of the -texture node. +texture node. Note that the Particle Info Node belongs to the Material on the Sphere aka the object which is being instanced. +In the example blend file there is also a Particle Info Node on the Cube material, but it doesnt really belong there. Rather +it was added by mistake. Example with 10x10x10 Grid: ![molecular_bake_uv](https://user-images.githubusercontent.com/1172149/184380338-b07cb5de-4d54-45e0-9fa8-2967f4fb29cc.jpeg) @@ -50,9 +52,6 @@ Example with 10x10x10 Grid: Same Example with 30x30x30 Grid ![molecular_bake_uv_high](https://user-images.githubusercontent.com/1172149/184380364-9e4a1ff9-8924-4619-9d77-f191950c52e7.jpeg) -In order to display the texture both on the emitter object (the cube in this example), just disconnect the angular velocity to texture connection. -The particles should keep their texture and the emitter is properly textured again then, too. - Remarks: - only in cycles - only in rendered viewport and render From b07427598493a070419570370a3a43aab7785645 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 2 Sep 2022 12:21:45 +0200 Subject: [PATCH 116/129] update fat binary for arm64 --- sources/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index 2e3426a..ef5319a 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -31,8 +31,8 @@ ext_modules = [Extension( module_name, ['core' + '.pyx'], - extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64e','-arch','x86_64'], - extra_link_args=['-lm','-arch','arm64e','-arch','x86_64'], + extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64e','-arch','x86_64','-arch','arm64'], + extra_link_args=['-lm','-arch','arm64e','-arch','x86_64','-arch','arm64'], cython_directives={'language_level' : "3"} )] From 50b75b80cbd44cad13c8385b5787d6070cd72de5 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Fri, 2 Sep 2022 12:40:11 +0200 Subject: [PATCH 117/129] added some readme how to build manually --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 87f4b1d..166de38 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,25 @@ To activate the plugins: - In the "Object" categories, you must find "Molecular" - Check it , close the "Blender user preferences" windows and have fun. +How to manually build Molecular: +-------------------------------- + +In order for a manual recompilation clone this repo and just run + +`python make_release.py` + +from within the "Blender-Molecular-Script" folder on your desired platform, + +with a python version matching blender's own being installed. +(and cython, too. install with pip for example) + + +Or alternatively, run + +`python setup.py build_ext --inplace` + +from the "sources" folder. + How to add UVs to molecular particle instances: ---------------------------------------------- From 14ce062eed5de11955995d22a23c865f2b4cb420 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Sat, 20 Apr 2024 20:29:45 +0200 Subject: [PATCH 118/129] update/recompilation to Python 3.11, used in Blender 4.1 --- .github/workflows/molecular-build.yml | 22 +++++++++++----------- molecular/__init__.py | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index d555660..389e03f 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -16,14 +16,14 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v2 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest cython + pip install flake8 pytest cython==3.0.0 # if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | @@ -46,18 +46,18 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v2 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | - # attempt to install libpython.a for 3.10 + # attempt to install libpython.a for 3.11 sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update - sudo apt install libpython3.10-dev + sudo apt install libpython3.11-dev python -m pip install --upgrade pip - pip install flake8 pytest cython + pip install flake8 pytest cython==3.0.0 - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names @@ -79,14 +79,14 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v2 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest cython + pip install flake8 pytest cython==3.0.0 - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names diff --git a/molecular/__init__.py b/molecular/__init__.py index 4e74df3..4aa4ba7 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,8 +22,8 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 4), - "blender": (3, 0, 0), + "version": (1, 1, 5), + "blender": (4, 1, 0), "location": "Properties editor > Particles Tabs", "description": "Addon for calculating collisions " From 54fd98a070dc710fbc656692ec325f9a4a281291 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Sat, 20 Apr 2024 20:34:16 +0200 Subject: [PATCH 119/129] build linux version on ubuntu 22.04 runner --- .github/workflows/molecular-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 389e03f..a9a5747 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -42,7 +42,7 @@ jobs: build_linux: - runs-on: ubuntu-18.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 From 9040f80d531be69aee45981cdb07789926af1b73 Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Sat, 20 Apr 2024 20:49:45 +0200 Subject: [PATCH 120/129] fix to adapt to changes in blender API related to contexts --- molecular/operators.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/molecular/operators.py b/molecular/operators.py index 3fea5ea..421d50d 100644 --- a/molecular/operators.py +++ b/molecular/operators.py @@ -106,7 +106,8 @@ def execute(self, context): ctx = bpy.context.copy() ctx["object"] = obj2 - bpy.ops.object.modifier_apply(ctx, modifier=mod.name) + with context.temp_override(**ctx): + bpy.ops.object.modifier_apply(modifier=mod.name) context.view_layer.update() @@ -244,7 +245,8 @@ def modal(self, context, event): for psys in obj.particle_systems: if psys.settings.mol_active and len(psys.particles): fake_context["point_cache"] = psys.point_cache - bpy.ops.ptcache.bake_from_cache(fake_context) + with context.temp_override(**fake_context): + bpy.ops.ptcache.bake_from_cache() scene.render.frame_map_new = 1 scene.frame_end = scene.mol_old_endframe context.view_layer.update() From 06445ad85a4e72afb104c403ccfbdd9c1ec6cd20 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:02:56 +0100 Subject: [PATCH 121/129] Update core.pyx revert pow operator usage to old behavior with cpow(True) otherwise there may be errors --- sources/core.pyx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sources/core.pyx b/sources/core.pyx index 60c214e..3e0053f 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -10,6 +10,7 @@ cimport cython from time import perf_counter as clock from cython.parallel import parallel, prange, threadid from libc.stdlib cimport malloc, realloc, free, rand, srand, abs +from cython.operator cimport cpow cdef extern from *: @@ -41,7 +42,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.12") +print("cmolcore imported with success! v1.13") cpdef init(importdata): @@ -646,6 +647,7 @@ cpdef memfree(): #@cython.cdivision(True) +@cpow(True) cdef void collide(Particle *par)nogil: global kdtree global deltatime @@ -860,7 +862,7 @@ cdef void collide(Particle *par)nogil: create_link(par.id,par.sys.link_max * 2, par2.id) - +@cpow(True) cdef void solve_link(Particle *par)nogil: global parlist global deltatime @@ -1346,7 +1348,7 @@ cdef void KDTree_rnn_search( depth + 1 ) - +@cpow(True) cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: global kdtree global parlist From d01a76adb49270262c4a76521d04f33e529312eb Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:03:48 +0100 Subject: [PATCH 122/129] Update __init__.py version bump --- molecular/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 4aa4ba7..046ab42 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,8 +22,8 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 5), - "blender": (4, 1, 0), + "version": (1, 1, 6), + "blender": (4, 3, 2), "location": "Properties editor > Particles Tabs", "description": "Addon for calculating collisions " From 0efcd6c76bbcf7a2aaa5670f42e3d3f459ebf668 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:27:20 +0100 Subject: [PATCH 123/129] Update molecular-build.yml replace set-output directives by using GITHUB_OUTPUT environment files, because set-output is about to be deprecated --- .github/workflows/molecular-build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index a9a5747..5d7bbdb 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -33,7 +33,8 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython id: build - run: echo "::set-output name=version::$(python make_release.py)" + # run: echo "::set-output name=version::$(python make_release.py)" + run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload windows zip uses: actions/upload-artifact@v3 with: @@ -66,7 +67,8 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython id: build - run: echo "::set-output name=version::$(python make_release.py)" + #run: echo "::set-output name=version::$(python make_release.py)" + run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload linux zip uses: actions/upload-artifact@v3 with: @@ -95,7 +97,8 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Build with Cython id: build - run: echo "::set-output name=version::$(python make_release.py)" + #run: echo "::set-output name=version::$(python make_release.py)" + run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload mac zip uses: actions/upload-artifact@v3 with: From 75417507da12ec7f9ccb3328c56d2d61da6f6c36 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:34:23 +0100 Subject: [PATCH 124/129] Update core.pyx revert cpow changes, compile error on windows --- sources/core.pyx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sources/core.pyx b/sources/core.pyx index 3e0053f..d2157e8 100644 --- a/sources/core.pyx +++ b/sources/core.pyx @@ -10,7 +10,6 @@ cimport cython from time import perf_counter as clock from cython.parallel import parallel, prange, threadid from libc.stdlib cimport malloc, realloc, free, rand, srand, abs -from cython.operator cimport cpow cdef extern from *: @@ -42,7 +41,7 @@ cdef Particle *parlist = NULL cdef SParticle *parlistcopy = NULL cdef ParSys *psys = NULL cdef KDTree *kdtree = NULL -print("cmolcore imported with success! v1.13") +print("cmolcore imported with success! v1.12") cpdef init(importdata): @@ -647,7 +646,6 @@ cpdef memfree(): #@cython.cdivision(True) -@cpow(True) cdef void collide(Particle *par)nogil: global kdtree global deltatime @@ -862,7 +860,6 @@ cdef void collide(Particle *par)nogil: create_link(par.id,par.sys.link_max * 2, par2.id) -@cpow(True) cdef void solve_link(Particle *par)nogil: global parlist global deltatime @@ -1348,7 +1345,6 @@ cdef void KDTree_rnn_search( depth + 1 ) -@cpow(True) cdef void create_link(int par_id, int max_link, int parothers_id=-1)nogil: global kdtree global parlist From ac06b6eec9ae498f6b0dac1464c2f58ff9c4b65b Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:39:58 +0100 Subject: [PATCH 125/129] Update setup.py attempt to set cpow to True via compiler directive --- sources/setup.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index ef5319a..c5bfd3d 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -14,7 +14,8 @@ module_name, ['core' + '.pyx'], extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'], - cython_directives={'language_level' : "3"} + cython_directives={'language_level' : "3"}, + compiler_directives={'cpow': True}, )] elif is_linux: ext_modules = [Extension( @@ -22,7 +23,8 @@ ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], extra_link_args=['-lm'], - cython_directives={'language_level' : "3"} + cython_directives={'language_level' : "3"}, + compiler_directives={'cpow': True}, )] else: # under mac OS, with the advent of the M1 ARM chips, its necessary to build an universal intel/arm binary. @@ -33,7 +35,8 @@ ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64e','-arch','x86_64','-arch','arm64'], extra_link_args=['-lm','-arch','arm64e','-arch','x86_64','-arch','arm64'], - cython_directives={'language_level' : "3"} + cython_directives={'language_level' : "3"}, + compiler_directives={'cpow': True}, )] setup( From 8100938f4252332b280468415118bc2a94449e85 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:44:50 +0100 Subject: [PATCH 126/129] Update molecular-build.yml attempt to fix build file using v4 artifact actions and proper usage of outputs.version --- .github/workflows/molecular-build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 5d7bbdb..5aaadd8 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -36,9 +36,9 @@ jobs: # run: echo "::set-output name=version::$(python make_release.py)" run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload windows zip - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - path: molecular_${{steps.build.outputs.version}}_win.zip + path: molecular_${{ steps.build.outputs.version }}_win.zip name: molecular_win build_linux: @@ -70,9 +70,9 @@ jobs: #run: echo "::set-output name=version::$(python make_release.py)" run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload linux zip - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - path: molecular_${{steps.build.outputs.version}}_linux.zip + path: molecular_${{ steps.build.outputs.version }}_linux.zip name: molecular_linux build_macos: @@ -100,9 +100,9 @@ jobs: #run: echo "::set-output name=version::$(python make_release.py)" run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload mac zip - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - path: molecular_${{steps.build.outputs.version}}_mac.zip + path: molecular_${{ steps.build.outputs.version }}_mac.zip name: molecular_mac upload_draft: @@ -114,15 +114,15 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: molecular_win - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: molecular_linux - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: molecular_mac From 1151ae80be938cc24092733538a5c2199bd6dc73 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 15:53:26 +0100 Subject: [PATCH 127/129] Update setup.py compiler_directives is unknown , try cython_directives --- sources/setup.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sources/setup.py b/sources/setup.py index c5bfd3d..6b09d80 100644 --- a/sources/setup.py +++ b/sources/setup.py @@ -14,8 +14,7 @@ module_name, ['core' + '.pyx'], extra_compile_args=['/Ox','/openmp','/GT','/arch:SSE2','/fp:fast'], - cython_directives={'language_level' : "3"}, - compiler_directives={'cpow': True}, + cython_directives={'language_level' : "3", 'cpow': True} )] elif is_linux: ext_modules = [Extension( @@ -23,8 +22,7 @@ ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin'], extra_link_args=['-lm'], - cython_directives={'language_level' : "3"}, - compiler_directives={'cpow': True}, + cython_directives={'language_level' : "3", 'cpow': True} )] else: # under mac OS, with the advent of the M1 ARM chips, its necessary to build an universal intel/arm binary. @@ -35,8 +33,7 @@ ['core' + '.pyx'], extra_compile_args=['-O3','-msse4.2','-ffast-math','-fno-builtin','-arch','arm64e','-arch','x86_64','-arch','arm64'], extra_link_args=['-lm','-arch','arm64e','-arch','x86_64','-arch','arm64'], - cython_directives={'language_level' : "3"}, - compiler_directives={'cpow': True}, + cython_directives={'language_level' : "3", 'cpow': True} )] setup( From 8f8ad0e1c98d71e9a5c1621a46d88b415b0219e4 Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 16:03:03 +0100 Subject: [PATCH 128/129] Update molecular-build.yml attempt to use bash shell syntax on windows runner as well --- .github/workflows/molecular-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/molecular-build.yml b/.github/workflows/molecular-build.yml index 5aaadd8..b6a6bb5 100644 --- a/.github/workflows/molecular-build.yml +++ b/.github/workflows/molecular-build.yml @@ -34,6 +34,8 @@ jobs: - name: Build with Cython id: build # run: echo "::set-output name=version::$(python make_release.py)" + # force bash shell on windows too + shell: bash run: echo "version=$(python make_release.py)" >> $GITHUB_OUTPUT - name: Upload windows zip uses: actions/upload-artifact@v4 From 2a70cbc98511c1fb4fe4d96808a75923ed87dbcb Mon Sep 17 00:00:00 2001 From: scorpion81 Date: Sat, 11 Jan 2025 16:07:58 +0100 Subject: [PATCH 129/129] Update __init__.py bump to correct version --- molecular/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecular/__init__.py b/molecular/__init__.py index 046ab42..ae03137 100644 --- a/molecular/__init__.py +++ b/molecular/__init__.py @@ -22,7 +22,7 @@ "Jean-Francois Gallant (PyroEvil), " "Pavel_Blend, " "Martin Felke (scorpion81)", - "version": (1, 1, 6), + "version": (1, 1, 5), "blender": (4, 3, 2), "location": "Properties editor > Particles Tabs", "description":