Skip to content

Commit 6925b58

Browse files
committed
Updated for FLIP Fluids Demo version 0.0.9a!
1 parent 2d886e8 commit 6925b58

32 files changed

+1575
-231
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Want to try FLIP Fluids addon before buying the full [Blender Market Product](ht
88

99
### Getting Started
1010

11-
Download the latest FLIP Fluids Demo installation file here: [FLIP_Fluids_addon_0.0.9_demo_26_nov_2020.zip](https://github.com/rlguy/Blender-FLIP-Fluids/releases/download/v0.0.9/FLIP_Fluids_addon_0.0.9_demo_26_nov_2020.zip)
11+
Download the latest FLIP Fluids Demo installation file here: [FLIP_Fluids_addon_0.0.9a_demo_03_feb_2021.zip](https://github.com/rlguy/Blender-FLIP-Fluids/releases/download/v0.0.9/FLIP_Fluids_addon_0.0.9a_demo_03_nov_2021.zip)
1212

1313
After downloading the demo addon, follow our [Installation Instructions](https://github.com/rlguy/Blender-FLIP-Fluids/wiki/Addon-Installation-and-Uninstallation). The instructions are similar to installing any other Blender addon.
1414

cmake/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ set(CMAKE_BUILD_TYPE Release)
4747
set(FLUIDENGINE_VERSION_MAJOR 0)
4848
set(FLUIDENGINE_VERSION_MINOR 0)
4949
set(FLUIDENGINE_VERSION_REVISION 9)
50-
set(FLUIDENGINE_VERSION_LABEL "0.0.9 Demo 26-NOV-2020")
50+
set(FLUIDENGINE_VERSION_LABEL "0.0.9a Demo 03-FEB-2021")
51+
5152
if(BUILD_DEBUG)
5253
set(FLUIDENGINE_VERSION_LABEL "${FLUIDENGINE_VERSION_LABEL} (DEBUG BUILD)")
5354
endif()

src/addon/__init__.py.in

+16
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ bl_info = {
3030
if "bpy" in locals():
3131
import importlib
3232
reloadable_modules = [
33+
'filesystem',
3334
'utils',
3435
'objects',
3536
'materials',
@@ -53,6 +54,7 @@ from bpy.props import (
5354
)
5455

5556
from . import (
57+
filesystem,
5658
utils,
5759
objects,
5860
materials,
@@ -95,6 +97,18 @@ def render_cancel(scene):
9597
render.render_cancel(scene)
9698

9799

100+
@bpy.app.handlers.persistent
101+
def frame_change_pre(scene, depsgraph=None):
102+
#scene.objects["mesh_cache"].modifiers["Ocean"].time = scene.objects["mesh_cache"].evaluated_get(depsgraph).modifiers["Ocean"].time
103+
104+
dprops = scene.flip_fluid.get_domain_properties()
105+
domain_object = scene.flip_fluid.get_domain_object()
106+
if domain_object is not None:
107+
domain_object_eval = domain_object.evaluated_get(bpy.context.evaluated_depsgraph_get())
108+
dprops_eval = domain_object_eval.flip_fluid.domain
109+
dprops.render.override_frame = dprops_eval.render.override_frame
110+
111+
98112
@bpy.app.handlers.persistent
99113
def frame_change_post(scene, depsgraph=None):
100114
properties.frame_change_post(scene, depsgraph)
@@ -155,6 +169,7 @@ def register():
155169
bpy.app.handlers.render_init.append(render_init)
156170
bpy.app.handlers.render_complete.append(render_complete)
157171
bpy.app.handlers.render_cancel.append(render_cancel)
172+
bpy.app.handlers.frame_change_pre.append(frame_change_pre)
158173
bpy.app.handlers.frame_change_post.append(frame_change_post)
159174
bpy.app.handlers.render_pre.append(render_pre)
160175
bpy.app.handlers.load_pre.append(load_pre)
@@ -180,6 +195,7 @@ def unregister():
180195
bpy.app.handlers.render_init.remove(render_init)
181196
bpy.app.handlers.render_complete.remove(render_complete)
182197
bpy.app.handlers.render_cancel.remove(render_cancel)
198+
bpy.app.handlers.frame_change_pre.remove(frame_change_pre)
183199
bpy.app.handlers.frame_change_post.remove(frame_change_post)
184200
bpy.app.handlers.render_pre.remove(render_pre)
185201
bpy.app.handlers.load_pre.remove(load_pre)

src/addon/bake.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
# You should have received a copy of the GNU General Public License
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17-
import sys, os, shutil, zipfile, json, struct, traceback, math
17+
import sys, os, shutil, json, traceback, math
1818

1919
from .objects import flip_fluid_map
2020
from .objects import flip_fluid_geometry_database
2121
from .operators import bake_operators
22+
from .filesystem import filesystem_protection_layer as fpl
2223

2324
from .pyfluid import (
2425
pyfluid,
@@ -619,10 +620,11 @@ def __delete_outdated_savestates(cache_directory, savestate_id):
619620
subdirs.remove("autosave")
620621

621622
for d in subdirs:
623+
extensions = [".state", ".data"]
622624
if int(d[-6:]) > savestate_id:
623625
path = os.path.join(savestate_directory, d)
624626
try:
625-
shutil.rmtree(path)
627+
fpl.delete_files_in_directory(path, extensions, remove_directory=True)
626628
except:
627629
print("Error: unable to delete directory <" + path + "> (skipping)")
628630

@@ -636,7 +638,7 @@ def __delete_outdated_meshes(cache_directory, savestate_id):
636638
if filenum > savestate_id:
637639
path = os.path.join(bakefiles_directory, f)
638640
try:
639-
os.remove(path)
641+
fpl.delete_file(path)
640642
except:
641643
print("Error: unable to delete file <" + path + "> (skipping)")
642644

@@ -1003,7 +1005,7 @@ def __get_fluid_object_velocity(fluid_object, frameid):
10031005
elif fluid_object.fluid_velocity_mode.data == 'FLUID_VELOCITY_AXIS':
10041006
timeline_frame = __get_timeline_frame()
10051007
local_x, local_y, local_z = __extract_local_axis(fluid_object.name, timeline_frame)
1006-
axis_mode = __get_parameter_data(fluid_object.fluid_axis_mode, timeline_frame)
1008+
axis_mode = __get_parameter_data(fluid_object.fluid_axis_mode, frameid)
10071009
if axis_mode == 'LOCAL_AXIS_POS_X' or axis_mode == 0.0:
10081010
local_axis = local_x
10091011
elif axis_mode == 'LOCAL_AXIS_POS_Y' or axis_mode == 1.0:
@@ -1017,7 +1019,7 @@ def __get_fluid_object_velocity(fluid_object, frameid):
10171019
elif axis_mode == 'LOCAL_AXIS_NEG_Z' or axis_mode == 5.0:
10181020
local_axis = [-local_z[0], -local_z[1], -local_z[2]]
10191021

1020-
initial_speed = __get_parameter_data(fluid_object.initial_speed, timeline_frame)
1022+
initial_speed = __get_parameter_data(fluid_object.initial_speed, frameid)
10211023
velocity = [initial_speed * local_axis[0], initial_speed * local_axis[1], initial_speed * local_axis[2]]
10221024
return velocity
10231025

@@ -1054,7 +1056,7 @@ def __get_inflow_object_velocity(inflow_object, frameid):
10541056
elif inflow_object.inflow_velocity_mode.data == 'INFLOW_VELOCITY_AXIS':
10551057
timeline_frame = __get_timeline_frame()
10561058
local_x, local_y, local_z = __extract_local_axis(inflow_object.name, timeline_frame)
1057-
axis_mode = __get_parameter_data(inflow_object.inflow_axis_mode, timeline_frame)
1059+
axis_mode = __get_parameter_data(inflow_object.inflow_axis_mode, frameid)
10581060
if axis_mode == 'LOCAL_AXIS_POS_X' or axis_mode == 0.0:
10591061
local_axis = local_x
10601062
elif axis_mode == 'LOCAL_AXIS_POS_Y' or axis_mode == 1.0:
@@ -1068,7 +1070,7 @@ def __get_inflow_object_velocity(inflow_object, frameid):
10681070
elif axis_mode == 'LOCAL_AXIS_NEG_Z' or axis_mode == 5.0:
10691071
local_axis = [-local_z[0], -local_z[1], -local_z[2]]
10701072

1071-
inflow_speed = __get_parameter_data(inflow_object.inflow_speed, timeline_frame)
1073+
inflow_speed = __get_parameter_data(inflow_object.inflow_speed, frameid)
10721074
velocity = [inflow_speed * local_axis[0], inflow_speed * local_axis[1], inflow_speed * local_axis[2]]
10731075
return velocity
10741076

@@ -2031,12 +2033,10 @@ def __write_autosave_data(domain_data, cache_directory, fluidsim, frameno):
20312033

20322034
try:
20332035
for filepath in autosave_default_filepaths:
2034-
if os.path.exists(filepath):
2035-
os.remove(filepath)
2036+
fpl.delete_file(filepath)
20362037
if fluidsim.get_num_diffuse_particles() > 0:
20372038
for filepath in autosave_diffuse_filepaths:
2038-
if os.path.exists(filepath):
2039-
os.remove(filepath)
2039+
fpl.delete_file(filepath)
20402040
except Exception as e:
20412041
print("FLIP Fluids: OS/Filesystem Error: Unable to delete older autosave files from storage")
20422042
print("Error Message: ", e)
@@ -2062,7 +2062,7 @@ def __write_autosave_data(domain_data, cache_directory, fluidsim, frameno):
20622062
numstr = str(frameno).zfill(6)
20632063
savestate_dir = os.path.join(cache_directory, "savestates", "autosave" + numstr)
20642064
if os.path.isdir(savestate_dir):
2065-
shutil.rmtree(savestate_dir)
2065+
fpl.delete_files_in_directory(savestate_dir, [".state", ".data"], remove_directory=True)
20662066
shutil.copytree(autosave_dir, savestate_dir)
20672067

20682068

src/addon/filesystem/__init__.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Blender FLIP Fluids Add-on
2+
# Copyright (C) 2020 Ryan L. Guy
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
if "bpy" in locals():
18+
import importlib
19+
reloadable_modules = [
20+
'filesystem_protection_layer',
21+
]
22+
for module_name in reloadable_modules:
23+
if module_name in locals():
24+
importlib.reload(locals()[module_name])
25+
26+
import bpy
27+
28+
from . import (
29+
filesystem_protection_layer,
30+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Blender FLIP Fluids Add-on
2+
# Copyright (C) 2020 Ryan L. Guy
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
import bpy, os, pathlib
18+
19+
20+
__EXTENSION_WHITELIST = [
21+
".backup",
22+
".bbox",
23+
".bobj",
24+
".data",
25+
".ffd",
26+
".fpd",
27+
".info",
28+
".md",
29+
".png",
30+
".preset",
31+
".sim",
32+
".sqlite3",
33+
".state",
34+
".txt",
35+
".wwp"
36+
]
37+
38+
39+
class FilesystemProtectionError(Exception):
40+
def __init__(self, value):
41+
self.value = value
42+
def __str__(self):
43+
return repr(self.value)
44+
45+
46+
def get_extension_whitelist():
47+
global __EXTENSION_WHITELIST
48+
return __EXTENSION_WHITELIST
49+
50+
51+
def get_directory_whitelist():
52+
whitelist = []
53+
dprops = bpy.context.scene.flip_fluid.get_domain_properties()
54+
if dprops is not None:
55+
whitelist.append(dprops.cache.get_cache_abspath())
56+
57+
this_filepath = os.path.realpath(__file__)
58+
addon_filepath = os.path.dirname(os.path.dirname(this_filepath))
59+
whitelist.append(addon_filepath)
60+
61+
return whitelist
62+
63+
64+
def path_is_parent(parent_path, child_path):
65+
parent_path = os.path.abspath(parent_path)
66+
child_path = os.path.abspath(child_path)
67+
return os.path.commonpath([parent_path]) == os.path.commonpath([parent_path, child_path])
68+
69+
70+
def check_extensions_valid(extensions):
71+
extension_whitelist = get_extension_whitelist()
72+
bad_extensions = []
73+
for ext in extensions:
74+
if ext not in extension_whitelist:
75+
bad_extensions.append(ext)
76+
77+
if bad_extensions:
78+
error_msg = "Extension not in whitelist: "
79+
for ext in bad_extensions:
80+
error_msg += "<" + ext + "> "
81+
error_msg += "***Please contact the developers with this error message***"
82+
raise FilesystemProtectionError(error_msg)
83+
84+
85+
def check_directory_valid(base_directory):
86+
directory_whitelist = get_directory_whitelist()
87+
is_safe_sub_directory = False
88+
for d in directory_whitelist:
89+
if path_is_parent(d, base_directory):
90+
is_safe_sub_directory = True
91+
break
92+
93+
if not is_safe_sub_directory:
94+
error_msg = "Directory is not in whitelist: <" + base_directory + "> Whitelist: "
95+
for d in directory_whitelist:
96+
error_msg += "<" + d + "> "
97+
error_msg += "***Please contact the developers with this error message***"
98+
raise FilesystemProtectionError(error_msg)
99+
100+
101+
def delete_files_in_directory(base_directory, extensions, remove_directory=False):
102+
check_extensions_valid(extensions)
103+
check_directory_valid(base_directory)
104+
105+
if not os.path.isdir(base_directory):
106+
return
107+
108+
file_list = [f for f in os.listdir(base_directory) if os.path.isfile(os.path.join(base_directory, f))]
109+
valid_filepaths = []
110+
for f in file_list:
111+
if pathlib.Path(f).suffix in extensions:
112+
valid_filepaths.append(os.path.join(base_directory, f))
113+
114+
for f in valid_filepaths:
115+
os.remove(f)
116+
117+
if remove_directory and not os.listdir(base_directory):
118+
os.rmdir(base_directory)
119+
120+
121+
def delete_file(filepath):
122+
if not os.path.isfile(filepath):
123+
return
124+
125+
extension = pathlib.Path(filepath).suffix
126+
check_extensions_valid([extension])
127+
check_directory_valid(filepath)
128+
os.remove(filepath)
129+
130+
131+
def clear_cache_directory(cache_directory, clear_export=False, clear_logs=False, remove_directory=False):
132+
stats_filepath = os.path.join(cache_directory, "flipstats.data")
133+
delete_file(stats_filepath)
134+
135+
bakefiles_dir = os.path.join(cache_directory, "bakefiles")
136+
extensions = [".bbox", ".bobj", ".wwp", ".fpd", ".ffd"]
137+
delete_files_in_directory(bakefiles_dir, extensions, remove_directory=True)
138+
139+
temp_dir = os.path.join(cache_directory, "temp")
140+
extensions = [".data"]
141+
delete_files_in_directory(temp_dir, extensions, remove_directory=True)
142+
143+
savestates_dir = os.path.join(cache_directory, "savestates")
144+
if os.path.isdir(savestates_dir):
145+
extensions = [".data", ".state"]
146+
savestate_subdirs = [d for d in os.listdir(savestates_dir) if os.path.isdir(os.path.join(savestates_dir, d))]
147+
for subd in savestate_subdirs:
148+
if subd.startswith("autosave"):
149+
dirpath = os.path.join(savestates_dir, subd)
150+
delete_files_in_directory(dirpath, extensions, remove_directory=True)
151+
delete_files_in_directory(savestates_dir, [], remove_directory=True)
152+
153+
if clear_export:
154+
export_dir = os.path.join(cache_directory, "export")
155+
if os.path.isdir(export_dir):
156+
extensions = [".sqlite3", ".sim"]
157+
delete_files_in_directory(export_dir, extensions, remove_directory=True)
158+
159+
if clear_logs:
160+
logs_dir = os.path.join(cache_directory, "logs")
161+
if os.path.isdir(logs_dir):
162+
extensions = [".txt"]
163+
delete_files_in_directory(logs_dir, extensions, remove_directory=True)
164+
165+
if remove_directory and not os.listdir(cache_directory):
166+
os.rmdir(cache_directory)

src/addon/objects/flip_fluid_cache.py

-4
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,6 @@ def _is_load_frame_valid(self, frameno, force_load=False):
259259
if self._is_loaded_frame_up_to_date(frameno) and not force_load:
260260
return False
261261

262-
is_render_backloading = current_frame == self.loaded_frame_data.frame - 1
263-
if render.is_rendering() and self.enable_motion_blur and is_render_backloading:
264-
return False
265-
266262
return True
267263

268264

src/addon/objects/flip_fluid_geometry_database.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import bpy, os, sqlite3, math
1818

1919
from .flip_fluid_geometry_export_object import GeometryExportType, MotionExportType
20+
from ..filesystem import filesystem_protection_layer as fpl
2021

2122

2223
class GeometryDatabase():
@@ -902,7 +903,7 @@ def _generate_create_table_commands(self):
902903

903904
def _initialize_database(self, db_filepath, clear_database=False):
904905
if clear_database and os.path.isfile(db_filepath):
905-
os.remove(db_filepath)
906+
fpl.delete_file(db_filepath)
906907

907908
if os.path.isfile(db_filepath):
908909
return sqlite3.connect(db_filepath)

0 commit comments

Comments
 (0)