2025-07-01
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# #### 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 #####
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from .utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
|
||||
|
||||
def _build_section_free_user(cTB) -> None:
|
||||
w_label = cTB.width_draw_ui - 20 * get_ui_scale(cTB)
|
||||
|
||||
box_free = cTB.vBase.box()
|
||||
col = box_free.column()
|
||||
|
||||
msg = _t("Access 3,000+ studio quality assets")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False)
|
||||
msg = _t("Unused asset balance rolls over each month")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False, icon="CHECKMARK")
|
||||
msg = _t("Commercial & personal use license")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False, icon="CHECKMARK")
|
||||
msg = _t("Redownload even if your subscription ends")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False, icon="CHECKMARK")
|
||||
msg = _t("Cancel or pause at any time in a few clicks")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False, icon="CHECKMARK")
|
||||
msg = _t("50% discount for students and teachers")
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False, icon="CHECKMARK")
|
||||
|
||||
op = col.operator("poliigon.poliigon_link", text=_t("View Pricing"))
|
||||
op.mode = "subscribe"
|
||||
# TODO(Andreas): Figma did not contain any tooltips...
|
||||
op.tooltip = _t("View Poliigon Pricing Online")
|
||||
|
||||
|
||||
def _build_section_paid_plan(cTB) -> None:
|
||||
w_label = cTB.width_draw_ui - 20 * get_ui_scale(cTB)
|
||||
|
||||
box_free = cTB.vBase.box()
|
||||
col = box_free.column()
|
||||
|
||||
name_plan = cTB.user.plan.plan_name
|
||||
wrapped_label(cTB, w_label, name_plan, col, add_padding=False)
|
||||
|
||||
if not cTB.is_unlimited_user():
|
||||
credits = cTB.user.plan.plan_credit
|
||||
msg = _t("Assets per month: {0}").format(credits)
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False)
|
||||
|
||||
next_renew = cTB.user.plan.next_subscription_renewal_date
|
||||
msg = _t("Renewal Date: {0}").format(next_renew)
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False)
|
||||
|
||||
is_paused = cTB.is_paused_subscription()
|
||||
status = _t("Paused") if is_paused else _t("Active")
|
||||
msg = _t("Status: {0}").format(status)
|
||||
wrapped_label(cTB, w_label, msg, col, add_padding=False)
|
||||
|
||||
op = col.operator("poliigon.poliigon_link", text=_t("View Details"))
|
||||
op.mode = "credits"
|
||||
# TODO(Andreas): Figma did not contain any tooltips...
|
||||
op.tooltip = _t("View Details of Your Plan Online")
|
||||
|
||||
|
||||
def _build_still_loading(cTB) -> None:
|
||||
box_free = cTB.vBase.box()
|
||||
col = box_free.column()
|
||||
w_label = cTB.width_draw_ui - 20 * get_ui_scale(cTB)
|
||||
wrapped_label(
|
||||
cTB, w_label, "Fetching user data...", col, add_padding=False)
|
||||
|
||||
|
||||
def build_user(cTB) -> None:
|
||||
cTB.logger_ui.debug("build_user")
|
||||
|
||||
cTB.vBase.label(text=_t("Your Plan"))
|
||||
|
||||
if cTB.fetching_user_data:
|
||||
_build_still_loading(cTB)
|
||||
return
|
||||
|
||||
if cTB.is_free_user() or cTB.user.plan.plan_name is None:
|
||||
_build_section_free_user(cTB)
|
||||
else:
|
||||
_build_section_paid_plan(cTB)
|
||||
|
||||
cTB.vBase.separator()
|
||||
op = cTB.vBase.operator("poliigon.poliigon_user", text=_t("Log Out"))
|
||||
op.mode = "logout"
|
||||
op.tooltip = _t("Log Out of Poliigon")
|
||||
@@ -0,0 +1,47 @@
|
||||
# #### 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 #####
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
|
||||
|
||||
def append_poliigon_groups_node_add(self, context) -> None:
|
||||
"""Appending to add node menu, for Poliigon node groups"""
|
||||
|
||||
self.layout.menu('POLIIGON_MT_add_node_groups')
|
||||
|
||||
|
||||
class POLIIGON_MT_add_node_groups(bpy.types.Menu):
|
||||
"""Menu for the Poliigon Shader node groups"""
|
||||
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_label = _t("Poliigon Node Groups")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
col = layout.column(align=True)
|
||||
if bpy.app.version >= (2, 90):
|
||||
col.operator("poliigon.add_converter_node",
|
||||
text=_t("Mosaic")
|
||||
).node_type = "Mosaic_UV_Mapping"
|
||||
col.operator("poliigon.add_converter_node",
|
||||
text=_t("PBR mixer")
|
||||
).node_type = "Poliigon_Mixer"
|
||||
|
||||
col.separator()
|
||||
@@ -0,0 +1,124 @@
|
||||
# #### 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 #####
|
||||
|
||||
from ..modules.poliigon_core.api_remote_control_params import (
|
||||
CATEGORY_ALL,
|
||||
KEY_TAB_ONLINE)
|
||||
from ..modules.poliigon_core.assets import (
|
||||
AssetType,
|
||||
ASSET_TYPE_TO_CATEGORY_NAME)
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from .utils_dlg import get_ui_scale
|
||||
|
||||
|
||||
# TODO(Andreas): This will be an exciting module in terms of multilingual
|
||||
# TODO(Andreas): Would like to refactor this module
|
||||
|
||||
|
||||
# @timer
|
||||
def build_categories(cTB):
|
||||
cTB.logger_ui.debug("build_categories")
|
||||
|
||||
categories_selected = []
|
||||
categories = []
|
||||
subcategories = []
|
||||
if cTB.vAssetType != CATEGORY_ALL:
|
||||
for _asset_type in cTB.vCategories["poliigon"].keys():
|
||||
if cTB.vAssetType in [CATEGORY_ALL, _asset_type]:
|
||||
categories += cTB.vCategories["poliigon"][_asset_type].keys()
|
||||
categories = sorted(list(set(categories)))
|
||||
|
||||
if len(categories) > 0:
|
||||
category = ""
|
||||
categories_selected = []
|
||||
for _idx_sel in range(1, len(cTB.vActiveCat)):
|
||||
category += "/" + cTB.vActiveCat[_idx_sel]
|
||||
categories_selected.append(category)
|
||||
|
||||
subcategories = [
|
||||
_cat.split("/")[-1]
|
||||
for _cat in categories
|
||||
if _cat.startswith(category) and _cat != category
|
||||
]
|
||||
if len(subcategories) > 0:
|
||||
categories_selected.append("sub")
|
||||
|
||||
col_categories = cTB.vBase.column()
|
||||
|
||||
width_factor = len(categories_selected) + 1
|
||||
if cTB.width_draw_ui >= max(width_factor, 2) * 160 * get_ui_scale(cTB):
|
||||
row_categories = col_categories.row()
|
||||
else:
|
||||
row_categories = col_categories
|
||||
|
||||
row_sub_cat = row_categories.row(align=True)
|
||||
|
||||
type_hdri = ASSET_TYPE_TO_CATEGORY_NAME[AssetType.HDRI]
|
||||
type_model = ASSET_TYPE_TO_CATEGORY_NAME[AssetType.MODEL]
|
||||
type_tex = ASSET_TYPE_TO_CATEGORY_NAME[AssetType.TEXTURE]
|
||||
list_types = [CATEGORY_ALL, type_tex, type_model, type_hdri]
|
||||
|
||||
area = cTB.settings["area"]
|
||||
if cTB.search_free and area == KEY_TAB_ONLINE:
|
||||
lbl_button_cat = _t("Free")
|
||||
elif cTB.vAssetType == CATEGORY_ALL:
|
||||
lbl_button_cat = _t("Select Category")
|
||||
else:
|
||||
lbl_button_cat = cTB.vAssetType
|
||||
op = row_sub_cat.operator(
|
||||
"poliigon.poliigon_category", text=lbl_button_cat, icon="TRIA_DOWN"
|
||||
)
|
||||
op.data = "0@" + "@".join(list_types)
|
||||
|
||||
if len(categories_selected) == 0:
|
||||
col_categories.separator()
|
||||
return
|
||||
|
||||
for _idx_sel, _cat_sel in enumerate(categories_selected):
|
||||
row_sub_cat = row_categories.row(align=True)
|
||||
|
||||
if _idx_sel == 0:
|
||||
selected_categories = [
|
||||
_cat.split("/")[-1]
|
||||
for _cat in categories
|
||||
if len(_cat.split("/")) == 2
|
||||
]
|
||||
elif _cat_sel == "sub":
|
||||
selected_categories = subcategories
|
||||
else:
|
||||
cat_parent = "/".join(_cat_sel.split("/")[:-1])
|
||||
selected_categories = [
|
||||
_cat.split("/")[-1]
|
||||
for _cat in categories
|
||||
if _cat.startswith(cat_parent) and _cat != cat_parent
|
||||
]
|
||||
|
||||
selected_categories = sorted(list(set(selected_categories)))
|
||||
|
||||
lbl_button = _cat_sel.split("/")[-1]
|
||||
if _cat_sel == "sub":
|
||||
lbl_button = "All " + cTB.vActiveCat[-1]
|
||||
|
||||
selected_categories.insert(0, "All " + cTB.vActiveCat[_idx_sel])
|
||||
data_op = f"{_idx_sel + 1}@{'@'.join(selected_categories)}"
|
||||
op = row_sub_cat.operator(
|
||||
"poliigon.poliigon_category", text=lbl_button, icon="TRIA_DOWN"
|
||||
)
|
||||
op.data = data_op
|
||||
|
||||
col_categories.separator()
|
||||
@@ -0,0 +1,282 @@
|
||||
# #### 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 #####
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from ..modules.poliigon_core.notifications import ActionType
|
||||
from ..constants import URLS_BLENDER
|
||||
from .utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
# from .. import reporting
|
||||
|
||||
|
||||
def build_mode(url, action, id_notice):
|
||||
return "notify@{}@{}@{}".format(url, action, id_notice)
|
||||
|
||||
|
||||
def _draw_notification_open_url_single_row(cTB, notice, first_row, icon) -> None:
|
||||
# Single row with text + button.
|
||||
# TODO: generalize this for notification message and length,
|
||||
# and if dismiss is included.
|
||||
# During SOFT-780 this has been changed for POPUP_MESSAGE in a
|
||||
# very simplistic way
|
||||
# (commit: https://github.com/poliigon/poliigon-addon-blender/pull/278/commits/00296ab70288893a023a6705d52eb4505ce36897).
|
||||
# When addressing this properly,
|
||||
# make sure to address it for all notification types.
|
||||
first_row.alert = True
|
||||
first_row.label(text=notice.title)
|
||||
first_row.alert = False
|
||||
op = first_row.operator(
|
||||
"poliigon.poliigon_link",
|
||||
icon=icon,
|
||||
text=notice.label,
|
||||
)
|
||||
if notice.tooltip != "":
|
||||
op.tooltip = notice.tooltip
|
||||
op.mode = build_mode(
|
||||
notice.url,
|
||||
notice.label,
|
||||
notice.id_notice)
|
||||
|
||||
|
||||
def _draw_notification_open_url_two_rows(
|
||||
cTB, notice, first_row, main_col, icon) -> None:
|
||||
# Two rows (or more, if text wrapping).
|
||||
col = first_row.column(align=True)
|
||||
col.alert = True
|
||||
# Empirically found squaring worked best for 1 & 2x displays,
|
||||
# which accounts for the box+panel padding and the 'x' button.
|
||||
if notice.allow_dismiss:
|
||||
padding_width = 32 * get_ui_scale(cTB)
|
||||
else:
|
||||
padding_width = 17 * get_ui_scale(cTB)
|
||||
wrapped_label(
|
||||
cTB, cTB.width_draw_ui - padding_width, notice.title, col)
|
||||
col.alert = False
|
||||
|
||||
second_row = main_col.row(align=True)
|
||||
second_row.scale_y = 1.0
|
||||
op = second_row.operator(
|
||||
"poliigon.poliigon_link",
|
||||
icon=icon,
|
||||
text=notice.label,
|
||||
)
|
||||
if notice.tooltip != "":
|
||||
op.tooltip = notice.tooltip
|
||||
op.mode = build_mode(
|
||||
notice.url,
|
||||
notice.label,
|
||||
notice.id_notice)
|
||||
|
||||
|
||||
def _draw_notification_open_url(
|
||||
cTB, notice, first_row, main_col, panel_width, icon) -> None:
|
||||
# Empirical for width for "Beta addon: [Take survey]" specifically.
|
||||
single_row_width = 250
|
||||
if panel_width > single_row_width:
|
||||
_draw_notification_open_url_single_row(cTB, notice, first_row, icon)
|
||||
else:
|
||||
_draw_notification_open_url_two_rows(
|
||||
cTB, notice, first_row, main_col, icon)
|
||||
|
||||
|
||||
def _draw_notification_update_ready_single_row(cTB, notice, first_row, icon) -> None:
|
||||
# Single row with text + button.
|
||||
first_row.alert = True
|
||||
first_row.label(text=notice.title)
|
||||
first_row.alert = False
|
||||
splitrow = first_row.split(factor=0.7, align=True)
|
||||
splitcol = splitrow.split(align=True)
|
||||
|
||||
label = notice.label
|
||||
if label == "":
|
||||
label = notice.title
|
||||
|
||||
op = splitcol.operator(
|
||||
"poliigon.poliigon_link",
|
||||
icon=icon,
|
||||
text=label,
|
||||
)
|
||||
if notice.tooltip != "":
|
||||
op.tooltip = notice.tooltip
|
||||
op.mode = build_mode(
|
||||
notice.download_url, notice.label, notice.id_notice)
|
||||
|
||||
splitcol = splitrow.split(align=True)
|
||||
op = splitcol.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text="Logs",
|
||||
)
|
||||
# if notice.tooltip is not None:
|
||||
op.tooltip = _t("See changes in this version")
|
||||
op.mode = build_mode(
|
||||
URLS_BLENDER["changelog"], "Logs", notice.id_notice)
|
||||
|
||||
|
||||
def _draw_notification_update_ready_two_rows(
|
||||
cTB, notice, first_row, main_col, icon) -> None:
|
||||
# Two rows (or more, if text wrapping).
|
||||
col = first_row.column(align=True)
|
||||
col.alert = True
|
||||
if notice.allow_dismiss:
|
||||
padding_width = 32 * get_ui_scale(cTB)
|
||||
else:
|
||||
padding_width = 17 * get_ui_scale(cTB)
|
||||
wrapped_label(
|
||||
cTB, cTB.width_draw_ui - padding_width, notice.title, col)
|
||||
col.alert = False
|
||||
|
||||
label = notice.label
|
||||
if label == "":
|
||||
label = notice.title
|
||||
|
||||
second_row = main_col.row(align=True)
|
||||
splitrow = second_row.split(factor=0.7, align=True)
|
||||
splitcol = splitrow.split(align=True)
|
||||
op = splitcol.operator(
|
||||
"poliigon.poliigon_link",
|
||||
icon=icon,
|
||||
text=label,
|
||||
)
|
||||
if notice.tooltip != "":
|
||||
op.tooltip = notice.tooltip
|
||||
op.mode = build_mode(
|
||||
notice.download_url, notice.label, notice.id_notice)
|
||||
splitcol = splitrow.split(align=True)
|
||||
op = splitcol.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text="Logs",
|
||||
)
|
||||
op.tooltip = _t("See changes in this version")
|
||||
op.mode = build_mode(
|
||||
URLS_BLENDER["changelog"], "Logs", notice.id_notice)
|
||||
|
||||
|
||||
def _draw_notification_update_ready(
|
||||
cTB, notice, first_row, main_col, panel_width, icon) -> None:
|
||||
# Empirical for width for "Update ready: Download | logs".
|
||||
single_row_width = 300
|
||||
if panel_width > single_row_width:
|
||||
_draw_notification_update_ready_single_row(
|
||||
cTB, notice, first_row, icon)
|
||||
else:
|
||||
_draw_notification_update_ready_two_rows(
|
||||
cTB, notice, first_row, main_col, icon)
|
||||
|
||||
|
||||
def _draw_notification_popup_message_two_rows(
|
||||
cTB, notice, first_row, main_col, icon) -> bpy.types.Operator:
|
||||
# Two rows (or more, if text wrapping).
|
||||
col = first_row.column(align=True)
|
||||
col.alert = notice.alert
|
||||
# Empirically found squaring worked best for 1 & 2x displays,
|
||||
# which accounts for the box+panel padding and the 'x' button.
|
||||
if notice.allow_dismiss:
|
||||
padding_width = 32 * get_ui_scale(cTB)
|
||||
else:
|
||||
padding_width = 17 * get_ui_scale(cTB)
|
||||
wrapped_label(
|
||||
cTB, cTB.width_draw_ui - padding_width, notice.title, col)
|
||||
col.alert = False
|
||||
|
||||
second_row = main_col.row(align=True)
|
||||
second_row.scale_y = 1.0
|
||||
op = second_row.operator(
|
||||
"poliigon.popup_message",
|
||||
icon=icon,
|
||||
text="View",
|
||||
)
|
||||
return op
|
||||
|
||||
|
||||
def _draw_notification_popup_message(
|
||||
cTB, notice, first_row, main_col, panel_width, icon) -> None:
|
||||
op = _draw_notification_popup_message_two_rows(
|
||||
cTB, notice, first_row, main_col, icon)
|
||||
|
||||
op.message_body = notice.body
|
||||
op.notice_id = notice.id_notice
|
||||
if notice.tooltip != "":
|
||||
op.tooltip = notice.tooltip
|
||||
if notice.url != "":
|
||||
op.message_url = notice.url
|
||||
|
||||
|
||||
def _draw_notification_run_operator(cTB, notice, first_row, icon) -> None:
|
||||
# Single row with only a button.
|
||||
op = first_row.operator(
|
||||
"poliigon.notice_operator",
|
||||
text=notice.title,
|
||||
icon=icon,
|
||||
)
|
||||
op.notice_id = notice.id_notice
|
||||
op.ops_name = notice.ops_name
|
||||
op.tooltip = notice.tooltip
|
||||
|
||||
|
||||
# TODO(Andreas): deactivated reporting here, as I needed a third parameter and
|
||||
# was not able to quickly make handle_draw() work
|
||||
# @reporting.handle_draw()
|
||||
def notification_banner(cTB, layout):
|
||||
"""General purpose notification banner UI draw element."""
|
||||
|
||||
notice = cTB.notify.get_top_notice()
|
||||
|
||||
if notice is None:
|
||||
return
|
||||
|
||||
box = layout.box()
|
||||
row = box.row(align=True)
|
||||
main_col = row.column(align=True)
|
||||
|
||||
scale = max(get_ui_scale(cTB), 1)
|
||||
panel_width = cTB.width_draw_ui / scale
|
||||
|
||||
first_row = main_col.row(align=False)
|
||||
x_row = first_row # x_row is the row to add the x button to, if there.
|
||||
|
||||
# Only purpose is to trigger view signal (only once)
|
||||
cTB.notify.notification_popup(notice, do_signal_view=True)
|
||||
|
||||
icon = notice.icon
|
||||
if icon is None:
|
||||
icon = "NONE"
|
||||
|
||||
if notice.action == ActionType.OPEN_URL:
|
||||
_draw_notification_open_url(
|
||||
cTB, notice, first_row, main_col, panel_width, icon)
|
||||
elif notice.action == ActionType.UPDATE_READY:
|
||||
_draw_notification_update_ready(
|
||||
cTB, notice, first_row, main_col, panel_width, icon)
|
||||
elif notice.action == ActionType.POPUP_MESSAGE:
|
||||
_draw_notification_popup_message(
|
||||
cTB, notice, first_row, main_col, panel_width, icon)
|
||||
elif notice.action == ActionType.RUN_OPERATOR:
|
||||
_draw_notification_run_operator(cTB, notice, first_row, icon)
|
||||
else:
|
||||
main_col.label(text=notice.title)
|
||||
cTB.logger_ui.error("Invalid notifcation type")
|
||||
|
||||
if notice.allow_dismiss:
|
||||
right_col = x_row.column(align=True)
|
||||
right_col.operator(
|
||||
"poliigon.close_notification", icon="X", text="", emboss=False)
|
||||
|
||||
layout.separator()
|
||||
@@ -0,0 +1,139 @@
|
||||
# #### 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 #####
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.api_remote_control_params import (
|
||||
KEY_TAB_IMPORTED,
|
||||
KEY_TAB_MY_ASSETS,
|
||||
KEY_TAB_ONLINE)
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
|
||||
|
||||
def _draw_unlimited_icon(cTB, *, row: bpy.types.UILayout) -> None:
|
||||
icon_value = cTB.ui_icons["LOGO_unlimited"].icon_id
|
||||
op_icon = row.operator(
|
||||
"poliigon.poliigon_setting", text="", emboss=True, icon_value=icon_value)
|
||||
op_icon.mode = "show_user"
|
||||
# TODO(Andreas): Tooltip???
|
||||
op_icon.tooltip = _t("Switch to your account details")
|
||||
|
||||
|
||||
def _draw_asset_balance(cTB, *, row: bpy.types.UILayout) -> None:
|
||||
if cTB.is_unlimited_user():
|
||||
_draw_unlimited_icon(cTB, row=row)
|
||||
return
|
||||
|
||||
# Asset balance
|
||||
credits = cTB.get_user_credits()
|
||||
balance_icon = cTB.ui_icons["ICON_asset_balance"].icon_id
|
||||
if cTB.is_paused_subscription() and credits <= 0:
|
||||
balance_icon = cTB.ui_icons["ICON_subscription_paused"].icon_id
|
||||
|
||||
op_credits = row.operator(
|
||||
"poliigon.poliigon_setting",
|
||||
text=str(credits),
|
||||
icon_value=balance_icon # TODO: use new asset icon
|
||||
)
|
||||
op_credits.tooltip = _t(
|
||||
"Your asset balance shows how many assets you can\n"
|
||||
"purchase. Free assets and downloading assets you\n"
|
||||
"already own doesn’t affect your balance")
|
||||
op_credits.mode = "show_user"
|
||||
|
||||
|
||||
def _add_asset_tab(cTB,
|
||||
row: bpy.types.UILayout,
|
||||
*,
|
||||
tab: str,
|
||||
mode: str,
|
||||
icon: str = "NONE",
|
||||
icon_value: int = 0,
|
||||
tooltip: str = ""
|
||||
) -> None:
|
||||
no_user = not cTB.settings["show_user"]
|
||||
no_settings = not cTB.settings["show_settings"]
|
||||
no_user_or_settings = no_user and no_settings
|
||||
|
||||
col = row.column(align=True)
|
||||
is_tab_active = cTB.settings["area"] == tab
|
||||
op = col.operator(
|
||||
"poliigon.poliigon_setting",
|
||||
text="",
|
||||
icon=icon,
|
||||
icon_value=icon_value,
|
||||
depress=is_tab_active and no_user_or_settings,
|
||||
)
|
||||
op.mode = mode
|
||||
op.tooltip = tooltip
|
||||
|
||||
|
||||
# @timer
|
||||
def build_areas(cTB):
|
||||
cTB.logger_ui.debug("build_areas")
|
||||
cTB.initial_view_screen()
|
||||
|
||||
row = cTB.vBase.row(align=True)
|
||||
row.scale_x = 1.1
|
||||
row.scale_y = 1.1
|
||||
|
||||
_add_asset_tab(
|
||||
cTB,
|
||||
row,
|
||||
tab=KEY_TAB_ONLINE,
|
||||
mode="area_poliigon",
|
||||
icon="HOME",
|
||||
tooltip=_t("Show Poliigon Assets"))
|
||||
_add_asset_tab(
|
||||
cTB,
|
||||
row,
|
||||
tab=KEY_TAB_MY_ASSETS,
|
||||
mode="area_my_assets",
|
||||
icon_value=cTB.ui_icons["ICON_myassets"].icon_id,
|
||||
tooltip=_t("Show My Assets"))
|
||||
_add_asset_tab(
|
||||
cTB,
|
||||
row,
|
||||
tab=KEY_TAB_IMPORTED,
|
||||
mode="area_imported",
|
||||
icon="OUTLINER_OB_GROUP_INSTANCE",
|
||||
tooltip=_t("Show Imported Assets"))
|
||||
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_setting",
|
||||
text="",
|
||||
icon_value=cTB.ui_icons["ICON_poliigon"].icon_id,
|
||||
depress=cTB.settings["show_user"],
|
||||
)
|
||||
op.mode = "my_account"
|
||||
op.tooltip = _t("Show Your Account Details")
|
||||
|
||||
row.separator()
|
||||
|
||||
row_prefs = row.row(align=True)
|
||||
row_prefs.alignment = "RIGHT"
|
||||
|
||||
_draw_asset_balance(cTB, row=row_prefs)
|
||||
|
||||
_ = row_prefs.operator(
|
||||
"poliigon.open_preferences",
|
||||
text="",
|
||||
icon="PREFERENCES",
|
||||
).set_focus = "all"
|
||||
|
||||
cTB.vBase.separator()
|
||||
@@ -0,0 +1,141 @@
|
||||
# #### 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 #####
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from ..modules.poliigon_core.upgrade_content import UpgradeContent
|
||||
from ..dialogs.utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
|
||||
|
||||
def _draw_banner(cTB, upgrade_content: UpgradeContent) -> None:
|
||||
"""Draws the actual banner and its buttons."""
|
||||
|
||||
width = cTB.width_draw_ui - 42 * get_ui_scale(cTB)
|
||||
|
||||
row = cTB.vBase.row(align=True)
|
||||
row.scale_x = 1.1
|
||||
row.scale_y = 1.1
|
||||
|
||||
box = row.box()
|
||||
col = box.column()
|
||||
|
||||
text = upgrade_content.banner_primary_text
|
||||
label = upgrade_content.banner_button_text
|
||||
key_icon = upgrade_content.icon_path
|
||||
|
||||
wrapped_label(
|
||||
cTB, width=width, text=text, container=col)
|
||||
|
||||
row_buttons = col.row(align=True)
|
||||
if upgrade_content.open_popup:
|
||||
op = row_buttons.operator(
|
||||
"poliigon.popup_change_plan",
|
||||
text=label,
|
||||
icon_value=cTB.ui_icons[key_icon].icon_id)
|
||||
op.tooltip = _t("By clicking here, we will change the subscription "
|
||||
"plan as shown above")
|
||||
if upgrade_content.allow_dismiss:
|
||||
op = row_buttons.operator(
|
||||
"poliigon.popup_change_plan_dismiss",
|
||||
text="",
|
||||
icon="PANEL_CLOSE")
|
||||
else:
|
||||
op = row_buttons.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text=label,
|
||||
icon_value=cTB.ui_icons[key_icon].icon_id)
|
||||
op.mode = "subscribe_banner"
|
||||
|
||||
|
||||
def _draw_banner_in_progress(cTB, upgrade_content: UpgradeContent) -> None:
|
||||
"""Draws an 'upgrade in progress' banner."""
|
||||
|
||||
width = cTB.width_draw_ui - 42 * get_ui_scale(cTB)
|
||||
|
||||
row = cTB.vBase.row(align=True)
|
||||
row.scale_x = 1.1
|
||||
row.scale_y = 1.1
|
||||
|
||||
box = row.box()
|
||||
col = box.column()
|
||||
|
||||
primary = upgrade_content.upgrading_primary_text
|
||||
secondary = upgrade_content.upgrading_secondary_text
|
||||
text = f"{primary} {secondary}" # three spaces are deliberate
|
||||
wrapped_label(cTB, width=width, text=text, container=col)
|
||||
|
||||
|
||||
def _draw_banner_finished(cTB, upgrade_content: UpgradeContent) -> None:
|
||||
"""Draws the final sucess/error banner."""
|
||||
|
||||
width = cTB.width_draw_ui - 42 * get_ui_scale(cTB)
|
||||
|
||||
row = cTB.vBase.row(align=True)
|
||||
row.scale_x = 1.1
|
||||
row.scale_y = 1.1
|
||||
|
||||
box = row.box()
|
||||
col = box.column()
|
||||
|
||||
if cTB.msg_plan_upgrade_finished is not None:
|
||||
text = cTB.msg_plan_upgrade_finished
|
||||
elif cTB.error_plan_upgrade is not None:
|
||||
head = upgrade_content.error_popup_title
|
||||
text = upgrade_content.error_popup_text.format(
|
||||
cTB.error_plan_upgrade)
|
||||
text = f"{head}: {text}"
|
||||
else:
|
||||
head = upgrade_content.success_popup_title
|
||||
text = upgrade_content.success_popup_text
|
||||
text = f"{head}: {text}"
|
||||
|
||||
cTB.msg_plan_upgrade_finished = text
|
||||
wrapped_label(cTB, width=width, text=text, container=col)
|
||||
row.operator(
|
||||
"poliigon.banner_finish_dismiss",
|
||||
text="",
|
||||
icon="PANEL_CLOSE")
|
||||
|
||||
|
||||
# @timer
|
||||
def build_upgrade_banner(cTB) -> None:
|
||||
"""Draws an 'upgrade subscription plan' banner, including a progress
|
||||
banner and a success/error banner.
|
||||
"""
|
||||
|
||||
cTB.logger_ui.debug("build_upgrade_paths")
|
||||
|
||||
if cTB.user is None:
|
||||
return
|
||||
if cTB.upgrade_manager is None:
|
||||
return
|
||||
if cTB.upgrade_manager.content is None:
|
||||
return
|
||||
|
||||
upgrade_content = cTB.upgrade_manager.content
|
||||
if cTB.plan_upgrade_finished:
|
||||
_draw_banner_finished(cTB, upgrade_content)
|
||||
elif cTB.plan_upgrade_in_progress:
|
||||
_draw_banner_in_progress(cTB, upgrade_content)
|
||||
elif cTB.upgrade_manager.check_show_banner():
|
||||
_draw_banner(cTB, upgrade_content)
|
||||
else:
|
||||
return
|
||||
|
||||
cTB.vBase.separator()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
||||
# #### 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 #####
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from .utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
|
||||
|
||||
# @timer
|
||||
def build_library(cTB):
|
||||
cTB.logger_ui.debug("build_library")
|
||||
factor_space = 1.0 / cTB.width_draw_ui
|
||||
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
_t("Welcome to the Poliigon Addon!"),
|
||||
cTB.vBase
|
||||
)
|
||||
|
||||
cTB.vBase.separator()
|
||||
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
_t("Select where you will store Poliigon assets."),
|
||||
cTB.vBase
|
||||
)
|
||||
|
||||
cTB.vBase.separator()
|
||||
|
||||
box_row = cTB.vBase.box().row()
|
||||
box_row.separator(factor=factor_space)
|
||||
col = box_row.column()
|
||||
box_row.separator(factor=factor_space)
|
||||
|
||||
col.label(text=_t("Library Location"))
|
||||
|
||||
label_library = cTB.settings["set_library"]
|
||||
if label_library == "":
|
||||
label_library = _t("Select Location")
|
||||
|
||||
op = col.operator(
|
||||
"poliigon.poliigon_library",
|
||||
icon="FILE_FOLDER",
|
||||
text=label_library,
|
||||
)
|
||||
op.mode = "set_library"
|
||||
op.directory = cTB.settings["set_library"]
|
||||
op.tooltip = _t("Select Location")
|
||||
|
||||
col.separator()
|
||||
row_confirm = col.row()
|
||||
row_confirm.scale_y = 1.5
|
||||
|
||||
op = row_confirm.operator(
|
||||
"poliigon.poliigon_setting", text=_t("Confirm"))
|
||||
op.mode = "set_library"
|
||||
op.tooltip = _t("Confirm Library location")
|
||||
|
||||
col.separator()
|
||||
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui - 30 * get_ui_scale(cTB),
|
||||
_t("You can change this and add more directories in the settings "
|
||||
"at any time."),
|
||||
col
|
||||
)
|
||||
|
||||
col.separator()
|
||||
cTB.vBase.separator()
|
||||
@@ -0,0 +1,312 @@
|
||||
# #### 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 #####
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from .utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
from ..toolbox import c_Toolbox
|
||||
|
||||
|
||||
ERR_CREDS_FORMAT = _t("Invalid email format/password length.")
|
||||
# TODO(Andreas): Currently not sure about this error
|
||||
ERR_LOGIN_TIMEOUT = _t("Login with website timed out, please try again")
|
||||
|
||||
|
||||
def _draw_welcome_or_error(cTB: c_Toolbox, layout: bpy.types.UILayout) -> None:
|
||||
if cTB.user_invalidated() and not cTB.login_in_progress:
|
||||
layout.separator()
|
||||
|
||||
if cTB.last_login_error == ERR_LOGIN_TIMEOUT:
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
cTB.last_login_error,
|
||||
layout,
|
||||
icon="ERROR"
|
||||
)
|
||||
else:
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
_t("Warning : You have been logged out as this account was "
|
||||
"signed in on another device."),
|
||||
layout,
|
||||
icon="ERROR"
|
||||
)
|
||||
|
||||
else:
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
_t("Welcome to the Poliigon Addon!"),
|
||||
layout
|
||||
)
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
def _draw_share_addon_errors(cTB: c_Toolbox,
|
||||
layout: bpy.types.UILayout,
|
||||
enabled: bool = True) -> None:
|
||||
# Show terms of service, optin/out.
|
||||
row_opt = layout.row()
|
||||
row_opt.alignment = "LEFT"
|
||||
row_opt.enabled = enabled
|
||||
# __spec__.parent since __package__ got deprecated
|
||||
# Since this module moved into dialogs,
|
||||
# we need to split off .dialogs
|
||||
spec_parent = __spec__.parent
|
||||
spec_parent = spec_parent.split(".")[0]
|
||||
prefs = bpy.context.preferences.addons.get(spec_parent, None)
|
||||
row_opt.prop(prefs.preferences, "reporting_opt_in", text="")
|
||||
twidth = cTB.width_draw_ui - 42 * get_ui_scale(cTB)
|
||||
wrapped_label(cTB, twidth, _t("Share addon errors / usage"), row_opt)
|
||||
|
||||
|
||||
def _draw_switch_email_login(col: bpy.types.UILayout,
|
||||
enabled: bool = True) -> None:
|
||||
row_login_email = col.row()
|
||||
row_login_email.enabled = enabled
|
||||
op_login_email = row_login_email.operator("poliigon.poliigon_user",
|
||||
text=_t("Login via email"),
|
||||
emboss=False)
|
||||
op_login_email.mode = "login_switch_to_email"
|
||||
op_login_email.tooltip = _t("Login via email")
|
||||
|
||||
|
||||
def _draw_browser_login(cTB: c_Toolbox, col: bpy.types.UILayout) -> None:
|
||||
if cTB.login_in_progress:
|
||||
_draw_share_addon_errors(cTB, col, enabled=False)
|
||||
|
||||
row_buttons = col.row(align=True)
|
||||
row_buttons.scale_y = 1.25
|
||||
|
||||
col1 = row_buttons.column(align=True)
|
||||
op_login_website = col1.operator("poliigon.poliigon_user",
|
||||
text=_t("Opening browser..."),
|
||||
depress=True)
|
||||
op_login_website.mode = "none"
|
||||
op_login_website.tooltip = _t("Complete login via opened webpage")
|
||||
col1.enabled = False
|
||||
|
||||
col2 = row_buttons.column(align=True)
|
||||
op_login_cancel = col2.operator("poliigon.poliigon_user",
|
||||
text="",
|
||||
icon="X")
|
||||
op_login_cancel.mode = "login_cancel"
|
||||
op_login_cancel.tooltip = _t("Cancel Log In")
|
||||
|
||||
col.separator()
|
||||
|
||||
_draw_switch_email_login(col, enabled=False)
|
||||
else:
|
||||
_draw_share_addon_errors(cTB, col)
|
||||
|
||||
row_button = col.row()
|
||||
row_button.scale_y = 1.25
|
||||
|
||||
op_login_website = row_button.operator("poliigon.poliigon_user",
|
||||
text=_t("Login via Browser"))
|
||||
op_login_website.mode = "login_with_website"
|
||||
op_login_website.tooltip = _t("Login via Browser")
|
||||
|
||||
col.separator()
|
||||
|
||||
_draw_switch_email_login(col)
|
||||
|
||||
|
||||
def _draw_email_login(cTB: c_Toolbox, col: bpy.types.UILayout) -> None:
|
||||
vProps = bpy.context.window_manager.poliigon_props
|
||||
|
||||
col.label(text="Email")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(vProps, "vEmail")
|
||||
|
||||
col_x = row.column(align=True)
|
||||
op = col_x.operator("poliigon.poliigon_setting",
|
||||
text="",
|
||||
icon="X")
|
||||
op.tooltip = _t("Clear Email")
|
||||
op.mode = "clear_email"
|
||||
|
||||
error_credentials = False
|
||||
has_login_error = cTB.last_login_error is not None
|
||||
error_login = has_login_error and cTB.last_login_error != ERR_LOGIN_TIMEOUT
|
||||
if error_login and "@" not in vProps.vEmail:
|
||||
error_credentials = True
|
||||
|
||||
col.separator()
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui - 40 * get_ui_scale(cTB),
|
||||
_t("Email format is invalid e.g. john@example.org"),
|
||||
col,
|
||||
icon="ERROR")
|
||||
col.separator()
|
||||
|
||||
col.label(text=_t("Password"))
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
if cTB.settings["show_pass"]:
|
||||
row.prop(vProps, "vPassShow")
|
||||
vPass = vProps.vPassShow
|
||||
|
||||
else:
|
||||
row.prop(vProps, "vPassHide")
|
||||
vPass = vProps.vPassHide
|
||||
|
||||
col_x = row.column(align=True)
|
||||
|
||||
op = col_x.operator("poliigon.poliigon_setting",
|
||||
text="",
|
||||
icon="X")
|
||||
op.tooltip = _t("Clear Password")
|
||||
op.mode = "clear_pass"
|
||||
|
||||
if error_login and len(vPass) < 6:
|
||||
error_credentials = True
|
||||
|
||||
col.separator()
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui - 40 * get_ui_scale(cTB),
|
||||
_t("Password should be at least 6 characters."),
|
||||
col,
|
||||
icon="ERROR")
|
||||
col.separator()
|
||||
|
||||
_draw_share_addon_errors(cTB, col)
|
||||
|
||||
enable_login_button = len(vProps.vEmail) > 0 and len(vPass) > 0
|
||||
|
||||
row = col.row()
|
||||
row.scale_y = 1.25
|
||||
|
||||
if cTB.login_in_progress:
|
||||
op_login = row.operator("poliigon.poliigon_setting",
|
||||
text=_t("Logging In..."),
|
||||
depress=enable_login_button)
|
||||
op_login.mode = "none"
|
||||
op_login.tooltip = _t("Logging In...")
|
||||
row.enabled = False
|
||||
else:
|
||||
op_login = row.operator("poliigon.poliigon_user",
|
||||
text=_t("Login via email"))
|
||||
op_login.mode = "login"
|
||||
op_login.tooltip = _t("Login via email")
|
||||
|
||||
row.enabled = enable_login_button
|
||||
|
||||
if cTB.last_login_error == ERR_CREDS_FORMAT:
|
||||
# Will draw above with more specific messages if condition true, like
|
||||
# invalid email format or password length.
|
||||
pass
|
||||
elif error_login and not error_credentials:
|
||||
col.separator()
|
||||
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui - 40 * get_ui_scale(cTB),
|
||||
cTB.last_login_error,
|
||||
col,
|
||||
icon="ERROR",
|
||||
)
|
||||
|
||||
col.separator()
|
||||
|
||||
op_forgot = col.operator("poliigon.poliigon_link",
|
||||
text=_t("Forgot Password?"),
|
||||
emboss=False)
|
||||
op_forgot.mode = "forgot"
|
||||
op_forgot.tooltip = _t("Reset your Poliigon password")
|
||||
|
||||
op_login_website = col.operator("poliigon.poliigon_user",
|
||||
text=_t("Login via Browser"),
|
||||
emboss=False)
|
||||
op_login_website.mode = "login_switch_to_browser"
|
||||
op_login_website.tooltip = _t("Login via Browser")
|
||||
|
||||
|
||||
def _draw_login(cTB, layout: bpy.types.UILayout) -> None:
|
||||
spc = 1.0 / cTB.width_draw_ui
|
||||
|
||||
box = layout.box()
|
||||
row = box.row()
|
||||
row.separator(factor=spc)
|
||||
col = row.column()
|
||||
row.separator(factor=spc)
|
||||
|
||||
twidth = cTB.width_draw_ui - 42 * get_ui_scale(cTB)
|
||||
wrapped_label(cTB, twidth, _t("Login"), col)
|
||||
col.separator()
|
||||
|
||||
if cTB.login_mode_browser:
|
||||
_draw_browser_login(cTB, col)
|
||||
|
||||
else:
|
||||
_draw_email_login(cTB, col)
|
||||
|
||||
|
||||
def _draw_signup(cTB, layout: bpy.types.UILayout) -> None:
|
||||
wrapped_label(
|
||||
cTB,
|
||||
cTB.width_draw_ui,
|
||||
_t("Don't have an account?"),
|
||||
layout,
|
||||
)
|
||||
op_signup = layout.operator("poliigon.poliigon_link",
|
||||
text=_t("Sign Up"))
|
||||
op_signup.mode = "signup"
|
||||
op_signup.tooltip = _t("Create a Poliigon account")
|
||||
|
||||
|
||||
def _draw_legal(layout: bpy.types.UILayout) -> None:
|
||||
row = layout.row()
|
||||
col = row.column(align=True)
|
||||
|
||||
op_terms = col.operator("poliigon.poliigon_link",
|
||||
text=_t("Terms & Conditions"),
|
||||
emboss=False)
|
||||
op_terms.tooltip = _t("View the terms and conditions page")
|
||||
op_terms.mode = "terms"
|
||||
|
||||
op_privacy = col.operator("poliigon.poliigon_link",
|
||||
text=_t("Privacy Policy"),
|
||||
emboss=False)
|
||||
op_privacy.tooltip = _t("View the Privacy Policy ")
|
||||
op_privacy.mode = "privacy"
|
||||
|
||||
|
||||
# @timer
|
||||
def build_login(cTB):
|
||||
cTB.logger_ui.debug("build_login")
|
||||
|
||||
if cTB.last_login_error is not None:
|
||||
cTB.login_in_progress = 0
|
||||
|
||||
_draw_welcome_or_error(cTB, cTB.vBase)
|
||||
_draw_login(cTB, cTB.vBase)
|
||||
cTB.vBase.separator()
|
||||
_draw_signup(cTB, cTB.vBase)
|
||||
cTB.vBase.separator()
|
||||
_draw_legal(cTB.vBase)
|
||||
@@ -0,0 +1,88 @@
|
||||
# #### 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 #####
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from .utils_dlg import (
|
||||
get_ui_scale,
|
||||
wrapped_label)
|
||||
|
||||
|
||||
def open_popup(cTB,
|
||||
title: str = "",
|
||||
msg: str = "",
|
||||
buttons: List[str] = [_t("OK")],
|
||||
commands: List[Optional[str]] = [None],
|
||||
mode: str = None,
|
||||
w_limit: int = 0
|
||||
) -> None:
|
||||
cTB.logger_ui.debug(f"open_popup mode={mode}, w_limit={w_limit}"
|
||||
f" title={title}, msg={msg},\n"
|
||||
f" buttons={buttons},\n"
|
||||
f" commands={commands}")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
||||
icon = "INFO"
|
||||
if mode == "question":
|
||||
icon = "QUESTION"
|
||||
elif mode == "error":
|
||||
icon = "ERROR"
|
||||
|
||||
col.label(text=title, icon=icon)
|
||||
|
||||
col.separator()
|
||||
|
||||
if w_limit == 0:
|
||||
col.label(text=msg)
|
||||
else:
|
||||
wrapped_label(cTB, w_limit * get_ui_scale(cTB), msg, col)
|
||||
|
||||
col.separator()
|
||||
col.separator()
|
||||
|
||||
vRow = col.row()
|
||||
for idx_button in range(len(buttons)):
|
||||
if commands[idx_button] in [None, "cancel"]:
|
||||
op = vRow.operator(
|
||||
"poliigon.poliigon_setting",
|
||||
text=buttons[idx_button])
|
||||
op.mode = "none"
|
||||
elif commands[idx_button] == "credits":
|
||||
op = vRow.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text=_t("Add Credits"),
|
||||
depress=1)
|
||||
op.mode = "credits"
|
||||
elif commands[idx_button] == "open_p4b_url":
|
||||
op = vRow.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text=buttons[idx_button],
|
||||
depress=1)
|
||||
op.mode = "p4b"
|
||||
elif commands[idx_button] == "check_update":
|
||||
vRow.operator("poliigon.check_update",
|
||||
text=buttons[idx_button])
|
||||
|
||||
bpy.context.window_manager.popover(draw)
|
||||
@@ -0,0 +1,376 @@
|
||||
# #### 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 #####
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.api_remote_control_params import (
|
||||
CATEGORY_ALL,
|
||||
get_search_key,
|
||||
KEY_TAB_IMPORTED)
|
||||
from ..modules.poliigon_core.assets import (
|
||||
AssetData,
|
||||
AssetType,
|
||||
ModelType)
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
from ..operators.operator_material import set_op_mat_disp_strength
|
||||
# TODO(SOFT-2421): Deactivated as it seems to have unwanted side effects.
|
||||
# from .dlg_assets import _draw_button_quick_preview
|
||||
from .utils_dlg import (
|
||||
check_convention,
|
||||
get_model_op_details,
|
||||
safe_size_apply)
|
||||
from .. import reporting
|
||||
|
||||
|
||||
def show_quick_menu(
|
||||
cTB, asset_data: AssetData, hide_detail_view: bool = False) -> None:
|
||||
"""Generates the quick options menu next to an asset in the UI grid."""
|
||||
|
||||
asset_type_data = asset_data.get_type_data()
|
||||
asset_name = asset_data.asset_name
|
||||
asset_id = asset_data.asset_id
|
||||
asset_type = asset_data.asset_type
|
||||
credits = 0 if asset_data.credits is None else asset_data.credits
|
||||
is_free = credits == 0
|
||||
|
||||
# Configuration
|
||||
if asset_data.is_purchased:
|
||||
# If downloading and already purchased.
|
||||
title = _t("Choose Texture Size")
|
||||
else:
|
||||
title = asset_name
|
||||
|
||||
in_scene = False
|
||||
|
||||
sizes = asset_type_data.get_size_list(local_only=False)
|
||||
downloaded = asset_type_data.get_size_list(
|
||||
local_only=True,
|
||||
addon_convention=cTB._asset_index.addon_convention,
|
||||
local_convention=asset_data.get_convention(local=True))
|
||||
|
||||
key = get_search_key(
|
||||
tab=KEY_TAB_IMPORTED, search="", category_list=[CATEGORY_ALL])
|
||||
query_key = cTB._asset_index._query_key_to_tuple(
|
||||
key, chunk=-1, chunk_size=1000000)
|
||||
if query_key not in cTB._asset_index.cached_queries:
|
||||
# The request is probably still be in flight
|
||||
in_scene = False
|
||||
elif asset_id in cTB._asset_index.cached_queries[query_key]:
|
||||
in_scene = True
|
||||
|
||||
prefer_blend = cTB.settings["download_prefer_blend"]
|
||||
link_blend = cTB.link_blend_session
|
||||
|
||||
blend_exists = False
|
||||
fbx_exists = False
|
||||
if asset_type == AssetType.MODEL:
|
||||
blend_exists = asset_type_data.has_mesh(
|
||||
model_type=ModelType.BLEND,
|
||||
native_only=True,
|
||||
renderer=None) # None is for legacy cycles models w/o engine name
|
||||
fbx_exists = asset_type_data.has_mesh(
|
||||
model_type=ModelType.FBX,
|
||||
native_only=False,
|
||||
renderer="")
|
||||
|
||||
any_model = blend_exists or fbx_exists
|
||||
is_linked_blend_import = prefer_blend and link_blend and blend_exists
|
||||
|
||||
def _imported_model_extras(
|
||||
context, layout: bpy.types.UILayout) -> None:
|
||||
area = cTB.settings["area"]
|
||||
if area != KEY_TAB_IMPORTED or asset_type != AssetType.MODEL:
|
||||
return
|
||||
|
||||
op = layout.operator(
|
||||
"poliigon.poliigon_select",
|
||||
text=_t("Select"),
|
||||
icon="RESTRICT_SELECT_OFF",
|
||||
)
|
||||
op.mode = "model"
|
||||
op.data = asset_name
|
||||
op.tooltip = _t("{0}\n(Select all instances)").format(asset_name)
|
||||
|
||||
layout.separator()
|
||||
|
||||
@reporting.handle_draw()
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
_imported_model_extras(context, layout)
|
||||
|
||||
# List the different resolution sizes to provide.
|
||||
if asset_data.is_purchased or is_free or cTB.is_unlimited_user():
|
||||
for size in sizes:
|
||||
if asset_type == AssetType.TEXTURE:
|
||||
draw_material_sizes(context, size, layout)
|
||||
elif asset_type == AssetType.MODEL:
|
||||
draw_model_sizes(context, size, layout)
|
||||
elif asset_type == AssetType.HDRI:
|
||||
draw_hdri_sizes(context, size, layout)
|
||||
else:
|
||||
label = _t("{0} not implemented yet").format(asset_type)
|
||||
layout.label(text=label)
|
||||
# TODO(SOFT-2421): Deactivated as it seems to have unwanted side effects.
|
||||
# else:
|
||||
# _draw_button_quick_preview(
|
||||
# cTB,
|
||||
# layout_row=layout,
|
||||
# asset_data=asset_data,
|
||||
# is_selection=True,
|
||||
# have_text_label=True
|
||||
# )
|
||||
# If else branch is activated, the following separator needs to be
|
||||
# outside if/else
|
||||
layout.separator()
|
||||
|
||||
op = layout.operator(
|
||||
"poliigon.open_preferences",
|
||||
text=_t("Open Import options in Preferences"),
|
||||
icon="PREFERENCES",
|
||||
)
|
||||
op.set_focus = "show_default_prefs"
|
||||
layout.separator()
|
||||
|
||||
# Always show view online and high res previews.
|
||||
if not hide_detail_view:
|
||||
# new detail viewer design is unstable on OSX and fails for awhile
|
||||
# for the remainder of the session. For consistency, we disable it
|
||||
# outright for all OSX users until a better solution is found.
|
||||
is_osx = bpy.app.build_platform.lower() == b"darwin"
|
||||
if bpy.app.version >= (4, 2) and not is_osx:
|
||||
op_name = "poliigon.detail_view_open"
|
||||
op_text = _t("View Asset Details")
|
||||
else:
|
||||
op_name = "poliigon.view_thumbnail"
|
||||
op_text = _t("View Large Preview")
|
||||
|
||||
op = layout.operator(
|
||||
op_name,
|
||||
text=op_text,
|
||||
icon="OUTLINER_OB_IMAGE",
|
||||
)
|
||||
op.asset_id = asset_data.asset_id
|
||||
|
||||
op = layout.operator(
|
||||
"poliigon.poliigon_link",
|
||||
text=_t("View online"),
|
||||
icon_value=cTB.ui_icons["ICON_poliigon"].icon_id,
|
||||
)
|
||||
op.mode = str(asset_id)
|
||||
op.tooltip = _t("View on Poliigon.com")
|
||||
|
||||
# If already local, support opening the folder location.
|
||||
if not downloaded:
|
||||
return
|
||||
|
||||
op = layout.operator(
|
||||
"poliigon.poliigon_folder",
|
||||
text=_t("Open folder location"),
|
||||
icon="FILE_FOLDER")
|
||||
op.asset_id = asset_id
|
||||
|
||||
# ... and provide option to sync with asset browser
|
||||
# TODO(Andreas): Asset Browser integration and AssetIndex
|
||||
# in_asset_browser = asset_data.get("in_asset_browser", False)
|
||||
in_asset_browser = asset_data.runtime.is_in_asset_browser()
|
||||
is_feature_avail = bpy.app.version >= (3, 0)
|
||||
missing_local_model = asset_type == AssetType.MODEL and not any_model
|
||||
if not is_feature_avail or missing_local_model:
|
||||
return
|
||||
|
||||
client_starting = cTB.lock_client_start.locked()
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
op = row.operator(
|
||||
"poliigon.update_asset_browser",
|
||||
text=_t("Synchronize with Asset Browser"),
|
||||
icon="FILE_REFRESH")
|
||||
op.asset_id = asset_id
|
||||
row.enabled = not in_asset_browser and not client_starting
|
||||
|
||||
def draw_material_sizes(
|
||||
context, size: str, layout: bpy.types.UILayout) -> None:
|
||||
"""Draw the menu row for a materials' single resolution size."""
|
||||
|
||||
row = layout.row()
|
||||
imported = f"{asset_name}_{size}" in bpy.data.materials
|
||||
|
||||
if asset_data.get_convention() >= 1:
|
||||
all_expected_maps_for_size = asset_type_data.all_expected_maps_local(
|
||||
cTB.user.map_preferences, size)
|
||||
else:
|
||||
all_expected_maps_for_size = size in downloaded
|
||||
|
||||
if imported or all_expected_maps_for_size:
|
||||
# Action: Load and apply it
|
||||
if imported:
|
||||
label = _t("{0} (apply material)").format(size)
|
||||
tip = _t("Apply {0} Material\n{1}").format(size, asset_name)
|
||||
elif context.selected_objects:
|
||||
label = _t("{0} (import + apply)").format(size)
|
||||
tip = _t("Apply {0} Material\n{1}").format(size, asset_name)
|
||||
else:
|
||||
label = _t("{0} (import)").format(size)
|
||||
tip = _t("Import {0} Material\n{1}").format(size, asset_name)
|
||||
|
||||
# If nothing is selected and this size is already importing,
|
||||
# then there's nothing to do.
|
||||
if imported and not context.selected_objects:
|
||||
row.enabled = False
|
||||
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_material",
|
||||
text=label,
|
||||
icon="TRACKING_REFINE_BACKWARDS")
|
||||
# Order is relevant here. vType needs to be set before vSize!
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
op.mapping = "UV"
|
||||
op.scale = 1.0
|
||||
op.use_16bit = cTB.settings["use_16"]
|
||||
op.reuse_material = True
|
||||
op.tooltip = tip
|
||||
set_op_mat_disp_strength(op, asset_name, op.mode_disp)
|
||||
else:
|
||||
# Action: Download
|
||||
# (for free assets this is purchase + implicit auto-download)
|
||||
if check_convention(asset_data):
|
||||
label = _t("{0} (download)").format(size)
|
||||
else:
|
||||
label = _t("{size} (Update needed)").format(size)
|
||||
row.enabled = False
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_download",
|
||||
text=label,
|
||||
icon="IMPORT")
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
if is_free and not asset_data.is_purchased:
|
||||
op.mode = "purchase"
|
||||
else:
|
||||
op.mode = "download"
|
||||
op.tooltip = _t("Download {0} Material\n{1}").format(
|
||||
size, asset_name)
|
||||
|
||||
def draw_model_sizes(
|
||||
context, size: str, layout: bpy.types.UILayout) -> None:
|
||||
"""Draw the menu row for a model's single resolution size."""
|
||||
row = layout.row()
|
||||
|
||||
if size in downloaded and any_model:
|
||||
# Action: Load and apply it
|
||||
lod, label, tip = get_model_op_details(
|
||||
cTB, asset_data, size)
|
||||
if is_linked_blend_import:
|
||||
label += _t(" (disable link .blend to import size)")
|
||||
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_model",
|
||||
text=label,
|
||||
icon="TRACKING_REFINE_BACKWARDS")
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
op.tooltip = tip
|
||||
op.lod = lod if len(lod) > 0 else "NONE"
|
||||
row.enabled = not is_linked_blend_import
|
||||
else:
|
||||
# Action: Download
|
||||
if check_convention(asset_data):
|
||||
label = _t("{0} (download)").format(size)
|
||||
else:
|
||||
label = _t("{0} (Update needed)").format(size)
|
||||
row.enabled = False
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_download",
|
||||
text=label,
|
||||
icon="IMPORT")
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
if is_free and not asset_data.is_purchased:
|
||||
op.mode = "purchase"
|
||||
else:
|
||||
op.mode = "download"
|
||||
op.tooltip = _t("Download {0} textures\n{1}").format(
|
||||
size, asset_name)
|
||||
|
||||
def draw_hdri_sizes(
|
||||
context, size: str, layout: bpy.types.UILayout) -> None:
|
||||
"""Draw the menu row for an HDRI's single resolution size."""
|
||||
row = layout.row()
|
||||
|
||||
size_light = ""
|
||||
if in_scene:
|
||||
image_name_light = asset_name + "_Light"
|
||||
if image_name_light in bpy.data.images.keys():
|
||||
path_light = bpy.data.images[image_name_light].filepath
|
||||
filename = os.path.basename(path_light)
|
||||
match_object = re.search(r"_(\d+K)[_\.]", filename)
|
||||
size_light = match_object.group(1) if match_object else cTB.settings["hdri"]
|
||||
|
||||
if size in downloaded:
|
||||
# Action: Load and apply it
|
||||
if size == size_light:
|
||||
label = _t("{0} (apply HDRI)").format(size)
|
||||
tip = _t("Apply {0} HDRI\n{1}").format(size, asset_name)
|
||||
else:
|
||||
label = _t("{0} (import HDRI)").format(size)
|
||||
tip = _t("Import {0} HDRI\n{1}").format(size, asset_name)
|
||||
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_hdri",
|
||||
text=label,
|
||||
icon="TRACKING_REFINE_BACKWARDS")
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
if cTB.settings["hdri_use_jpg_bg"]:
|
||||
size_bg = cTB.settings["hdrib"]
|
||||
size_bg = asset_type_data.get_size(
|
||||
size_bg,
|
||||
local_only=True,
|
||||
addon_convention=cTB.addon_convention,
|
||||
local_convention=asset_data.get_convention(local=True))
|
||||
op.size_bg = f"{size_bg}_JPG"
|
||||
else:
|
||||
op.size_bg = f"{size}_EXR"
|
||||
op.tooltip = tip
|
||||
|
||||
else:
|
||||
# Action: Download
|
||||
if check_convention(asset_data):
|
||||
label = _t("{0} (download)").format(size)
|
||||
else:
|
||||
label = _t("{0} (Update needed)").format(size)
|
||||
row.enabled = False
|
||||
op = row.operator(
|
||||
"poliigon.poliigon_download",
|
||||
text=label,
|
||||
icon="IMPORT")
|
||||
op.asset_id = asset_id
|
||||
safe_size_apply(cTB, op, size, asset_name)
|
||||
if is_free and not asset_data.is_purchased:
|
||||
op.mode = "purchase"
|
||||
else:
|
||||
op.mode = "download"
|
||||
op.tooltip = _t("Download {0}\n{1}").format(size, asset_name)
|
||||
|
||||
# Generate the popup menu.
|
||||
bpy.context.window_manager.popup_menu(draw, title=title, icon="QUESTION")
|
||||
@@ -0,0 +1,220 @@
|
||||
# #### 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 #####
|
||||
|
||||
from typing import Optional, Tuple
|
||||
|
||||
import bpy
|
||||
|
||||
from ..modules.poliigon_core.assets import (
|
||||
AssetData,
|
||||
ModelType)
|
||||
from ..modules.poliigon_core.multilingual import _t
|
||||
|
||||
from ..constants import SUPPORTED_CONVENTION
|
||||
from ..utils import construct_model_name
|
||||
|
||||
|
||||
def check_convention(asset_data: AssetData, local: bool = False) -> bool:
|
||||
asset_convention = asset_data.get_convention(local=local)
|
||||
|
||||
if asset_convention is None:
|
||||
return False
|
||||
elif asset_convention > SUPPORTED_CONVENTION:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def get_model_op_details(
|
||||
cTB, asset_data: AssetData, size: str) -> Tuple[str, str, str]:
|
||||
"""Get details to use in the ui for a given model and size."""
|
||||
|
||||
asset_type_data = asset_data.get_type_data()
|
||||
asset_name = asset_data.asset_name
|
||||
|
||||
default_lod = cTB.settings["lod"]
|
||||
downloaded = asset_type_data.get_size_list(
|
||||
local_only=True,
|
||||
addon_convention=cTB._asset_index.addon_convention,
|
||||
local_convention=asset_data.get_convention(local=True))
|
||||
|
||||
lod = asset_type_data.get_lod(default_lod)
|
||||
if lod is None:
|
||||
lod = "NONE"
|
||||
|
||||
if not asset_type_data.has_mesh(ModelType.FBX):
|
||||
lod = "NONE"
|
||||
|
||||
coll_name = construct_model_name(asset_name, size, lod)
|
||||
|
||||
coll = bpy.data.collections.get(coll_name)
|
||||
if coll:
|
||||
in_scene = True
|
||||
else:
|
||||
in_scene = False
|
||||
|
||||
label = ""
|
||||
tip = ""
|
||||
if size in downloaded:
|
||||
if in_scene:
|
||||
if lod:
|
||||
label = _t("{0} {1} (import again)").format(size, lod)
|
||||
tip = _t("Import {0} {1} again\n{2}").format(
|
||||
size, lod, asset_name)
|
||||
else:
|
||||
label = _t("{0} (import again)").format(size)
|
||||
tip = _t("Import {0} again\n{1}").format(size, asset_name)
|
||||
else:
|
||||
if lod:
|
||||
label = _t("{0} {1} (import)").format(size, lod)
|
||||
tip = _t("Import {0} {1}\n{2}").format(
|
||||
size, lod, asset_name)
|
||||
else:
|
||||
label = _t("{0} (import)").format(size)
|
||||
tip = _t("Import {0}\n{1}").format(size, asset_name)
|
||||
|
||||
return lod, label, tip
|
||||
|
||||
|
||||
def safe_size_apply(cTB,
|
||||
op_ref: bpy.types.OperatorProperties,
|
||||
size_value: str,
|
||||
asset_name: str) -> None:
|
||||
"""Applies a size value to operator draw with a safe fallback.
|
||||
|
||||
If we try to apply a size which is not recognized as local, it will fail
|
||||
and disrupt further drawing. This function mitigates this problem.
|
||||
"""
|
||||
try:
|
||||
op_ref.size = size_value
|
||||
except TypeError as e:
|
||||
# Since this is a UI draw issue, there will be multiple of these
|
||||
# these reports, but we have user-level debouncing for a max number
|
||||
# per message type.
|
||||
msg = f"Failed to assign {size_value} size for {asset_name}: {e}"
|
||||
cTB.logger_ui.error(msg)
|
||||
# TODO(SOFT-1303): Include in refactor to asset index, disabled
|
||||
# overreporting for now.
|
||||
# reporting.capture_message("failed_size_op_set", msg, "error")
|
||||
|
||||
|
||||
def check_dpi(cTB, force: bool = True) -> None:
|
||||
"""Checks the DPI of the screen to adjust the scale accordingly.
|
||||
|
||||
Used to ensure previews remain square and avoid text truncation.
|
||||
"""
|
||||
|
||||
if not force and cTB.ui_scale_checked:
|
||||
return
|
||||
|
||||
prefs = bpy.context.preferences
|
||||
cTB.settings["win_scale"] = prefs.system.ui_scale
|
||||
cTB.ui_scale_checked = True
|
||||
|
||||
|
||||
def get_ui_scale(cTB) -> float:
|
||||
"""Utility for fetching the ui scale, used in draw code."""
|
||||
|
||||
check_dpi(cTB)
|
||||
return cTB.settings["win_scale"]
|
||||
|
||||
|
||||
def _get_line_width(cTB, line: str) -> int:
|
||||
"""Returns pixel width of a string."""
|
||||
|
||||
width_line = 15
|
||||
for _char in line:
|
||||
if _char in "ABCDEFGHKLMNOPQRSTUVWXYZmw":
|
||||
width_line += 9
|
||||
elif _char in "abcdeghknopqrstuvxyz0123456789":
|
||||
width_line += 6
|
||||
elif _char in "IJfijl .":
|
||||
width_line += 3
|
||||
|
||||
width_line *= get_ui_scale(cTB)
|
||||
return width_line
|
||||
|
||||
|
||||
def wrapped_label(cTB,
|
||||
width: int,
|
||||
text: str,
|
||||
container: bpy.types.UILayout,
|
||||
icon: Optional[str] = None,
|
||||
add_padding: bool = False,
|
||||
add_padding_top: bool = False,
|
||||
add_padding_bottom: bool = False,
|
||||
) -> None:
|
||||
"""Text wrap a label based on indicated width."""
|
||||
|
||||
cTB.logger_ui.debug(f"wrapped_label width={width}, text={text}, "
|
||||
f"icon={icon}, add_padding={add_padding}")
|
||||
|
||||
list_words = [_word.replace("!@#", " ") for _word in text.split(" ")]
|
||||
|
||||
row = container.row()
|
||||
parent = row.column(align=True)
|
||||
parent.scale_y = 0.8 # To make vertical height more natural for text.
|
||||
|
||||
if add_padding or add_padding_top:
|
||||
parent.label(text="")
|
||||
|
||||
if icon is not None:
|
||||
width -= 25 * get_ui_scale(cTB)
|
||||
|
||||
line = ""
|
||||
first = True
|
||||
|
||||
for _word in list_words:
|
||||
width_line = _get_line_width(cTB, line + _word + " ")
|
||||
if width_line > width:
|
||||
if first:
|
||||
if icon is None:
|
||||
parent.label(text=line)
|
||||
else:
|
||||
parent.label(text=line, icon=icon)
|
||||
first = False
|
||||
|
||||
else:
|
||||
if icon is None:
|
||||
parent.label(text=line)
|
||||
else:
|
||||
parent.label(text=line, icon="BLANK1")
|
||||
|
||||
line = _word + " "
|
||||
|
||||
else:
|
||||
line += _word + " "
|
||||
|
||||
if line != "":
|
||||
if icon is None:
|
||||
parent.label(text=line)
|
||||
else:
|
||||
if first:
|
||||
parent.label(text=line, icon=icon)
|
||||
else:
|
||||
parent.label(text=line, icon="BLANK1")
|
||||
|
||||
if add_padding or add_padding_bottom:
|
||||
parent.label(text="")
|
||||
|
||||
|
||||
def separator_p4b(
|
||||
container: bpy.types.UILayout, *, line: bool = False) -> None:
|
||||
if line and bpy.app.version >= (4, 2):
|
||||
container.separator(type='LINE')
|
||||
else:
|
||||
container.separator()
|
||||
Reference in New Issue
Block a user