1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # mainly update functions and callbacks for ratings properties, here to avoid circular imports.
21 from blenderkit
import utils
, paths
, tasks_queue
, rerequests
23 from bpy
.props
import (
37 bk_logger
= logging
.getLogger('blenderkit')
40 def upload_rating_thread(url
, ratings
, headers
):
41 ''' Upload rating thread function / disconnected from blender data.'''
42 bk_logger
.debug('upload rating ' + url
+ str(ratings
))
43 for rating_name
, score
in ratings
:
44 if (score
!= -1 and score
!= 0):
45 rating_url
= url
+ rating_name
+ '/'
47 "score": score
, # todo this kind of mixing is too much. Should have 2 bkit structures, upload, use
51 r
= rerequests
.put(rating_url
, data
=data
, verify
=True, headers
=headers
)
53 except requests
.exceptions
.RequestException
as e
:
54 print('ratings upload failed: %s' % str(e
))
57 def send_rating_to_thread_quality(url
, ratings
, headers
):
58 '''Sens rating into thread rating, main purpose is for tasks_queue.
59 One function per property to avoid lost data due to stashing.'''
60 thread
= threading
.Thread(target
=upload_rating_thread
, args
=(url
, ratings
, headers
))
64 def send_rating_to_thread_work_hours(url
, ratings
, headers
):
65 '''Sens rating into thread rating, main purpose is for tasks_queue.
66 One function per property to avoid lost data due to stashing.'''
67 thread
= threading
.Thread(target
=upload_rating_thread
, args
=(url
, ratings
, headers
))
71 def store_rating_local_empty(asset_id
):
73 context
.window_manager
['asset ratings'] = context
.window_manager
.get('asset ratings', {})
74 context
.window_manager
['asset ratings'][asset_id
] = context
.window_manager
['asset ratings'].get(asset_id
, {})
77 def store_rating_local(asset_id
, type='quality', value
=0):
79 context
.window_manager
['asset ratings'] = context
.window_manager
.get('asset ratings', {})
80 context
.window_manager
['asset ratings'][asset_id
] = context
.window_manager
['asset ratings'].get(asset_id
, {})
81 context
.window_manager
['asset ratings'][asset_id
][type] = value
84 def get_rating(asset_id
, headers
):
86 Retrieve ratings from BlenderKit server. Can be run from a thread
94 ratings - dict of type:value ratings
96 url
= paths
.get_api_url() + 'assets/' + asset_id
+ '/rating/'
98 r
= rerequests
.get(url
, params
=params
, verify
=True, headers
=headers
)
102 # store ratings - send them to task queue
103 for r
in rj
['results']:
104 ratings
[r
['ratingType']] = r
['score']
105 tasks_queue
.add_task((store_rating_local
,(asset_id
, r
['ratingType'], r
['score'])))
106 # store_rating_local(asset_id, type = r['ratingType'], value = r['score'])
108 if len(rj
['results'])==0:
109 # store empty ratings too, so that server isn't checked repeatedly
110 tasks_queue
.add_task((store_rating_local_empty
,(asset_id
,)))
114 def get_rating_local(asset_id
):
115 context
= bpy
.context
116 context
.window_manager
['asset ratings'] = context
.window_manager
.get('asset ratings', {})
117 rating
= context
.window_manager
['asset ratings'].get(asset_id
)
119 return rating
.to_dict()
123 def update_ratings_quality(self
, context
):
124 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
125 api_key
= user_preferences
.api_key
127 headers
= utils
.get_headers(api_key
)
129 if not (hasattr(self
, 'rating_quality')):
130 # first option is for rating of assets that are from scene
132 bkit_ratings
= asset
.bkit_ratings
133 asset_id
= asset
['asset_data']['id']
135 # this part is for operator rating:
137 asset_id
= self
.asset_id
139 if bkit_ratings
.rating_quality
> 0.1:
140 url
= paths
.get_api_url() + f
'assets/{asset_id}/rating/'
142 store_rating_local(asset_id
, type='quality', value
=bkit_ratings
.rating_quality
)
144 ratings
= [('quality', bkit_ratings
.rating_quality
)]
145 tasks_queue
.add_task((send_rating_to_thread_quality
, (url
, ratings
, headers
)), wait
=2.5, only_last
=True)
148 def update_ratings_work_hours(self
, context
):
149 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
150 api_key
= user_preferences
.api_key
151 headers
= utils
.get_headers(api_key
)
152 if not (hasattr(self
, 'rating_work_hours')):
153 # first option is for rating of assets that are from scene
155 bkit_ratings
= asset
.bkit_ratings
156 asset_id
= asset
['asset_data']['id']
158 # this part is for operator rating:
160 asset_id
= self
.asset_id
162 if bkit_ratings
.rating_work_hours
> 0.45:
163 url
= paths
.get_api_url() + f
'assets/{asset_id}/rating/'
165 store_rating_local(asset_id
, type='working_hours', value
=bkit_ratings
.rating_work_hours
)
167 ratings
= [('working_hours', round(bkit_ratings
.rating_work_hours
, 1))]
168 tasks_queue
.add_task((send_rating_to_thread_work_hours
, (url
, ratings
, headers
)), wait
=2.5, only_last
=True)
171 def update_quality_ui(self
, context
):
172 '''Converts the _ui the enum into actual quality number.'''
173 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
174 if user_preferences
.api_key
== '':
175 # ui_panels.draw_not_logged_in(self, message='Please login/signup to rate assets.')
176 # bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_login_menu')
178 bpy
.ops
.wm
.blenderkit_login('INVOKE_DEFAULT',
179 message
='Please login/signup to rate assets. Clicking OK takes you to web login.')
180 # self.rating_quality_ui = '0'
181 self
.rating_quality
= int(self
.rating_quality_ui
)
184 def update_ratings_work_hours_ui(self
, context
):
185 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
186 if user_preferences
.api_key
== '':
187 # ui_panels.draw_not_logged_in(self, message='Please login/signup to rate assets.')
188 # bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_login_menu')
190 bpy
.ops
.wm
.blenderkit_login('INVOKE_DEFAULT',
191 message
='Please login/signup to rate assets. Clicking OK takes you to web login.')
192 # self.rating_work_hours_ui = '0'
193 self
.rating_work_hours
= float(self
.rating_work_hours_ui
)
196 def update_ratings_work_hours_ui_1_5(self
, context
):
197 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
198 if user_preferences
.api_key
== '':
199 # ui_panels.draw_not_logged_in(self, message='Please login/signup to rate assets.')
200 # bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_login_menu')
202 bpy
.ops
.wm
.blenderkit_login('INVOKE_DEFAULT',
203 message
='Please login/signup to rate assets. Clicking OK takes you to web login.')
204 # self.rating_work_hours_ui_1_5 = '0'
205 self
.rating_work_hours
= float(self
.rating_work_hours_ui_1_5
)
208 def update_ratings_work_hours_ui_1_10(self
, context
):
209 user_preferences
= bpy
.context
.preferences
.addons
['blenderkit'].preferences
210 if user_preferences
.api_key
== '':
211 # ui_panels.draw_not_logged_in(self, message='Please login/signup to rate assets.')
212 # bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_login_menu')
214 bpy
.ops
.wm
.blenderkit_login('INVOKE_DEFAULT',
215 message
='Please login/signup to rate assets. Clicking OK takes you to web login.')
216 # self.rating_work_hours_ui_1_5 = '0'
217 # print('updating 1-5')
218 # print(float(self.rating_work_hours_ui_1_5))
219 self
.rating_work_hours
= float(self
.rating_work_hours_ui_1_10
)
222 def stars_enum_callback(self
, context
):
223 '''regenerates the enum property used to display rating stars, so that there are filled/empty stars correctly.'''
225 for a
in range(0, 10):
226 if self
.rating_quality
< a
+ 1:
230 # has to have something before the number in the value, otherwise fails on registration.
231 items
.append((f
'{a + 1}', f
'{a + 1}', '', icon
, a
+ 1))
235 class RatingsProperties():
236 message
: StringProperty(
238 description
="message",
239 default
="Rating asset",
240 options
={'SKIP_SAVE'})
242 asset_id
: StringProperty(
243 name
="Asset Base Id",
244 description
="Unique id of the asset (hidden)",
246 options
={'SKIP_SAVE'})
248 asset_name
: StringProperty(
250 description
="Name of the asset (hidden)",
252 options
={'SKIP_SAVE'})
254 asset_type
: StringProperty(
256 description
="asset type",
258 options
={'SKIP_SAVE'})
260 rating_quality
: IntProperty(name
="Quality",
261 description
="quality of the material",
264 update
=update_ratings_quality
,
265 options
={'SKIP_SAVE'})
267 # the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily.
268 rating_quality_ui
: EnumProperty(name
='rating_quality_ui',
269 items
=stars_enum_callback
,
270 description
='Rating stars 0 - 10',
272 update
=update_quality_ui
,
273 options
={'SKIP_SAVE'})
275 rating_work_hours
: FloatProperty(name
="Work Hours",
276 description
="How many hours did this work take?",
279 update
=update_ratings_work_hours
,
280 options
={'SKIP_SAVE'}
283 high_rating_warning
= "This is a high rating, please be sure to give such rating only to amazing assets"
285 possible_wh_values
= [0,.5,1,2,3,4,5,6,8,10,15,20,30,50,100,150,200,250]
286 items_models
= [('0', '0', ''),
298 ('30', '30', high_rating_warning
),
299 ('50', '50', high_rating_warning
),
300 ('100', '100', high_rating_warning
),
301 ('150', '150', high_rating_warning
),
302 ('200', '200', high_rating_warning
),
303 ('250', '250', high_rating_warning
),
305 rating_work_hours_ui
: EnumProperty(name
="Work Hours",
306 description
="How many hours did this work take?",
308 default
='0', update
=update_ratings_work_hours_ui
,
309 options
={'SKIP_SAVE'}
311 possible_wh_values_1_5
= [0,.2, .5,1,2,3,4,5]
313 items_1_5
= [('0', '0', ''),
322 rating_work_hours_ui_1_5
: EnumProperty(name
="Work Hours",
323 description
="How many hours did this work take?",
326 update
=update_ratings_work_hours_ui_1_5
,
327 options
={'SKIP_SAVE'}
329 possible_wh_values_1_10
= [0,1,2,3,4,5,6,7,8,9,10]
331 items_1_10
= [('0', '0', ''),
343 rating_work_hours_ui_1_10
: EnumProperty(name
="Work Hours",
344 description
="How many hours did this work take?",
347 update
=update_ratings_work_hours_ui_1_10
,
348 options
={'SKIP_SAVE'}
351 def prefill_ratings(self
):
353 ratings
= get_rating_local(self
.asset_id
)
354 if ratings
and ratings
.get('quality'):
355 self
.rating_quality
= ratings
['quality']
356 if ratings
and ratings
.get('working_hours'):
357 wh
= int(ratings
['working_hours'])
359 if wh
in self
.possible_wh_values
:
360 self
.rating_work_hours_ui
= whs
361 if wh
< 6 and wh
in self
.possible_wh_values_1_5
:
362 self
.rating_work_hours_ui_1_5
= whs
363 if wh
< 11 and wh
in self
.possible_wh_values_1_10
:
364 self
.rating_work_hours_ui_1_10
= whs