diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index ae26ff9f..7de94d12 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -2,7 +2,7 @@ # For more info, see https://help.github.com/en/github/administering-a-repository/displaying-a-sponsor-button-in-your-repository #github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -#patreon: # Replace with a single Patreon username +#blendermarket: # Replace with a single Blendermarket username #open_collective: # Replace with a single Open Collective username #ko_fi: # Replace with a single Ko-fi username #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel diff --git a/operators/lol/assetbar.py b/operators/lol/assetbar.py index 56264fc0..66870cce 100644 --- a/operators/lol/assetbar.py +++ b/operators/lol/assetbar.py @@ -212,7 +212,7 @@ def draw_callback_2d_search(self, context): ui_bgl.draw_rect(x - assetbar_props.highlight_margin, y - assetbar_props.highlight_margin, int(w * assets[index]['downloaded'] / 100.0), 2, green) if assets[index]['patreon']: - img = utils.get_thumbnail('patreon.png') + img = utils.get_thumbnail('blender_market.png') ui_bgl.draw_image(x + w - 24 - 2, y + w - 24 - 2, 24, 24, img, 1) if assets[index]['locked']: img = utils.get_thumbnail('locked.png') @@ -223,7 +223,7 @@ def draw_callback_2d_search(self, context): asset = assets[ui_props.active_index] licence = '\n\nLicence: royality free' if asset['patreon'] else '\n\nLicence: CC-BY-SA' tooltip = asset['name'] + '\n\nCategory: ' + asset['category'] + licence - atip = '\n\nhttps://www.patreon.com/Draviastudio\n' + atip = '\n\nhttps://blendermarket.com/creators/draviastudio\n' if asset['local']: tooltip = asset['name'] + '\n\nCategory: ' + asset['category'] @@ -260,7 +260,7 @@ def draw_tooltip(context, x, y, text='', author='', asset=None, gravatar=None): ui_props = context.scene.luxcoreOL.ui user_preferences = get_addon_preferences(context) - ttipmargin = 5 + ttipmargin = 2 textmargin = 10 font_height = int(12 * scale) @@ -341,9 +341,9 @@ def draw_tooltip(context, x, y, text='', author='', asset=None, gravatar=None): ui_bgl.draw_image(x, y - isizey - ttipmargin, isizex, isizey, img, 1) - # draw patreon logo for patreon assets and locked symbol for not purchased assets + # draw blendermarket logo for purchased assets and locked symbol for not purchased assets if asset['patreon']: - img = utils.get_thumbnail('patreon.png') + img = utils.get_thumbnail('blender_market.png') ui_bgl.draw_image(x + isizex - 52*scale - 2, y - 52*scale - ttipmargin - 2, 52*scale, 52*scale, img, 1) if asset['locked']: img = utils.get_thumbnail('locked.png') @@ -382,7 +382,8 @@ def draw_tooltip(context, x, y, text='', author='', asset=None, gravatar=None): i += 1 column_lines += 1 ui_bgl.draw_text(l, xtext, ytext, fsize, tcol) - xtext += int(isizex / ncolumns) + + xtext += int(isizex / ncolumns) - 30 column_lines = 1 for l in alines: @@ -872,7 +873,7 @@ def modal(self, context, event): ui_props.draw_snapped_bounds = False ui_props.active_index = -3 import webbrowser - webbrowser.open('https://www.patreon.com/Draviastudio') + webbrowser.open('https://blendermarket.com/creators/draviastudio') return {'RUNNING_MODAL'} @@ -937,7 +938,7 @@ def modal(self, context, event): asset_search_index = ui_bgl.get_asset_under_mouse(context, mx, my) if assets[ui_props.active_index]['patreon'] and assets[ui_props.active_index]['locked']: import webbrowser - webbrowser.open('https://www.patreon.com/Draviastudio') + webbrowser.open('https://blendermarket.com/creators/draviastudio') return {'RUNNING_MODAL'} if ui_props.asset_type in ('MATERIAL', diff --git a/operators/lol/update_ToC.py b/operators/lol/update_ToC.py new file mode 100644 index 00000000..7eabd406 --- /dev/null +++ b/operators/lol/update_ToC.py @@ -0,0 +1,69 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This code is based on the Blenderkit Addon +# Homepage: https://www.blenderkit.com/ +# Sourcecode: https://github.com/blender/blender-addons/tree/master/blenderkit +# +# ##### + +import bpy +from os.path import basename, dirname, join, isfile, splitext + +from bpy.types import Operator +from ...utils.lol import utils as utils + + +class LOLUpdateTOC(Operator): + bl_idname = 'scene.luxcore_ol_update_toc' + bl_label = 'LuxCore Online Library Update Table of Contents from Server' + bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} + + @classmethod + def description(cls, context, properties): + return "Update table of contents from server" + + def execute(self, context): + import urllib.request + import json + + name = basename(dirname(dirname(dirname(__file__)))) + user_preferences = context.preferences.addons[name].preferences + + filepath = join(user_preferences.global_dir, 'assets_model_patreon.json') + with urllib.request.urlopen(utils.LOL_HOST_URL + "/assets_model_patreon.json", timeout=60) as request: + assets = json.load(request) + + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + filepath = join(user_preferences.global_dir, 'assets_model.json') + with urllib.request.urlopen(utils.LOL_HOST_URL + "/assets_model.json", timeout=60) as request: + assets = json.load(request) + + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + filepath = join(user_preferences.global_dir, 'assets_material.json') + with urllib.request.urlopen(utils.LOL_HOST_URL + "/assets_material.json", timeout=60) as request: + assets = json.load(request) + + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + return {'FINISHED'} \ No newline at end of file diff --git a/thumbnails/blender_market.png b/thumbnails/blender_market.png new file mode 100644 index 00000000..5614f456 Binary files /dev/null and b/thumbnails/blender_market.png differ diff --git a/ui/lol/panel.py b/ui/lol/panel.py index e3e09589..c867d74a 100644 --- a/ui/lol/panel.py +++ b/ui/lol/panel.py @@ -83,6 +83,7 @@ def draw_panel_model_search(self, context): tooltip = 'Click to Show Asset Bar' assetbar_operator = layout.operator('view3d.luxcore_ol_asset_bar', text='Asset Bar', icon=icon) + assetbar_operator.keep_running = False assetbar_operator.do_search = False assetbar_operator.tooltip = tooltip @@ -174,8 +175,8 @@ def draw(self, context): col = layout.column(align=True) col.scale_x = 1.4 col.scale_y = 1.4 - op = col.operator("luxcore.open_website", icon=icons.URL, text="Donation (Patreon)") - op.url = "https://www.patreon.com/Draviastudio" + op = col.operator("luxcore.open_website", icon=icons.URL, text="Donation (Blendermarket)") + op.url = "https://blendermarket.com/creators/draviastudio" op = col.operator("luxcore.open_website", icon=icons.URL, text="Donation (Bountysource)") op.url = "https://salt.bountysource.com/teams/luxcorerender" @@ -198,6 +199,7 @@ def draw(self, context): col = layout.column(align=True) col.label(text="It's better to save the file first.") + layout.operator('scene.luxcore_ol_update_toc', text='Update ToC from server') if ui_props.asset_type == 'MODEL': draw_panel_model_search(self, context) elif ui_props.asset_type == 'SCENE': diff --git a/utils/lol/utils.py b/utils/lol/utils.py index 6368bb7f..60ccd402 100644 --- a/utils/lol/utils.py +++ b/utils/lol/utils.py @@ -72,19 +72,42 @@ def load_local_TOC(context, asset_type): def load_patreon_assets(context): name = basename(dirname(dirname(dirname(__file__)))) user_preferences = context.preferences.addons[name].preferences - with urllib.request.urlopen(LOL_HOST_URL + "/assets_model_patreon.json", timeout=60) as request: - import json - assets = json.load(request) - for asset in assets: - asset['downloaded'] = 0.0 - asset['local'] = False - asset['patreon'] = True - asset['locked'] = True - filename = asset["url"] - filepath = join(user_preferences.global_dir, "model", splitext(filename)[0] + '.blend') - if os.path.exists(filepath): - asset['locked'] = False + #check if local file is available + filepath = join(user_preferences.global_dir, 'assets_model_patreon.json') + if os.path.exists(filepath): + with open(filepath) as file_handle: + import json + assets = json.load(file_handle) + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = True + asset['locked'] = True + filename = asset["url"] + filepath = join(user_preferences.global_dir, "model", splitext(filename)[0] + '.blend') + + if os.path.exists(filepath): + asset['locked'] = False + else: + with urllib.request.urlopen(LOL_HOST_URL + "/assets_model_patreon.json", timeout=60) as request: + import json + assets = json.load(request) + + #cache file for future offline work + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = True + asset['locked'] = True + filename = asset["url"] + filepath = join(user_preferences.global_dir, 'model', splitext(filename)[0] + '.blend') + + if os.path.exists(filepath): + asset['locked'] = False return assets @@ -92,6 +115,8 @@ def load_patreon_assets(context): def download_table_of_contents(context): scene = context.scene ui_props = context.scene.luxcoreOL.ui + name = basename(dirname(dirname(dirname(__file__)))) + user_preferences = context.preferences.addons[name].preferences try: for threaddata in bg_threads: @@ -100,20 +125,38 @@ def download_table_of_contents(context): global stop_check_cache stop_check_cache = True - import urllib.request + # check if local file is available + filepath = join(user_preferences.global_dir, 'assets_model.json') + if os.path.exists(filepath): + with open(filepath) as file_handle: + import json + assets = json.load(file_handle) + + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = False + asset['locked'] = False + + else: + import urllib.request + with urllib.request.urlopen(LOL_HOST_URL + "/assets_model.json", timeout=60) as request: + import json + assets = json.load(request) + # cache file for future offline work + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = False + asset['locked'] = False - with urllib.request.urlopen(LOL_HOST_URL + "/assets_model.json", timeout=60) as request: - import json - assets = json.loads(request.read()) - for asset in assets: - asset['downloaded'] = 0.0 - asset['local'] = False - asset['patreon'] = False - asset['locked'] = False - assets.extend(load_local_TOC(context, 'model')) - assets.extend(load_patreon_assets(context)) - scene.luxcoreOL.model['assets'] = assets + assets.extend(load_local_TOC(context, 'model')) + assets.extend(load_patreon_assets(context)) + scene.luxcoreOL.model['assets'] = assets # with urllib.request.urlopen(LOL_HOST_URL + "/assets_scene.json", timeout=60) as request: # import json @@ -125,18 +168,34 @@ def download_table_of_contents(context): # assets.extend(load_local_TOC(context, 'scene')) # scene.luxcoreOL.scene['assets'] = assets - with urllib.request.urlopen(LOL_HOST_URL + "/assets_material.json", timeout=60) as request: - import json - assets = json.loads(request.read()) - for asset in assets: - asset['downloaded'] = 0.0 - asset['local'] = False - asset['patreon'] = False - asset['locked'] = False - - assets.extend(load_local_TOC(context, 'material')) - scene.luxcoreOL.material['assets'] = assets - + # check if local file is available + filepath = join(user_preferences.global_dir, 'assets_material.json') + if os.path.exists(filepath): + with open(filepath) as file_handle: + import json + assets = json.load(file_handle) + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = False + asset['locked'] = False + else: + import urllib.request + with urllib.request.urlopen(LOL_HOST_URL + "/assets_material.json", timeout=60) as request: + import json + assets = json.load(request) + # cache file for future offline work + with open(filepath, 'w') as file: + file.write(json.dumps(assets, indent=2)) + + for asset in assets: + asset['downloaded'] = 0.0 + asset['local'] = False + asset['patreon'] = False + asset['locked'] = False + + assets.extend(load_local_TOC(context, 'material')) + scene.luxcoreOL.material['assets'] = assets ui_props.ToC_loaded = True init_categories(context) @@ -472,7 +531,8 @@ def append_material(context, asset, target_object, target_slot): filepath = os.path.join(user_preferences.global_dir, "material", splitext(filename)[0] + '.blend') with bpy.data.libraries.load(filepath, link=False) as (data_from, data_to): - data_to.materials = [name for name in data_from.materials if name == asset["name"]] + data_to.materials = [name for name in data_from.materials if + name == asset["name"] or name == asset["name"].replace(" ", "_")] if len(data_to.materials) == 1: # print(target_object, target_slot, data_to.materials[0].name)