Scenekit test.py
# todo | |
# - bug: remove keyboard si confirm/cancel/close | |
# - bug: cancel ne devrait pas changer les parameters | |
# - label title pour self.name | |
# - actions: simultanees | |
# - flag repeat for ever | |
# - button reset default au niveau de chaque param? ou de forme/action? | |
# - scroll_view largeur variable a calculer (ex: fields de cube) | |
# - revoir couleur fond formes puis celles des params, face puis material | |
# - video ou camera uniqt si action | |
# - video loop seek 0, play, aussi bien dans face buton que dans face geometry | |
# - camera start running | |
# - based on | |
# - omz | |
# - video | |
# - camera in sheet | |
# could be done in a very far future (in a 2nd life): | |
# - project: new/folder=name/rename/delete/open=continue/save images... | |
# - light/off/type/position/color/... | |
# - camera position/constraint/... | |
# - multiple geometries in same project | |
from objc_util import * | |
import ui | |
import math | |
import photos | |
from ImageColor import getrgb | |
from SetTextFieldPad import SetTextFieldPad | |
load_framework('SceneKit') | |
SCNView, SCNScene, SCNBox, SCNSphere, SCNPyramid,SCNTorus,SCNCone,SCNCylinder, SCNTube, SCNText, SCNShape, SCNCapsule, SCNNode, SCNMaterial, SCNCamera, SCNLookAtConstraint, SCNAction = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox','SCNSphere','SCNPyramid','SCNTorus','SCNCone', 'SCNCylinder', 'SCNTube', 'SCNText', 'SCNShape', 'SCNCapsule', 'SCNNode', 'SCNMaterial', 'SCNCamera', 'SCNLookAtConstraint', 'SCNAction' ]) | |
#print(dir(SCNAction)) | |
#https://code.tutsplus.com/tutorials/an-introduction-to-scenekit-fundamentals--cms-23847 | |
def OMColorPickerViewController(): | |
v = ui.View() | |
v.rgb = None | |
vc = ObjCInstance(v) | |
colorpicker = ObjCClass('OMColorPickerViewController').new().autorelease() | |
clview = colorpicker.view() | |
v.frame = (0,0,512,960) | |
vc.addSubview_(clview) | |
done_button = ui.ButtonItem(title='ok') | |
def tapped(sender): | |
cl = colorpicker.color() | |
v.rgb = (cl.red(),cl.green(),cl.blue()) | |
v.close() | |
done_button.action = tapped | |
v.right_button_items = [done_button] | |
v.rgb = None | |
v.present('sheet') | |
v.wait_modal() | |
return v.rgb | |
class MyView(ui.View): | |
def __init__(self,w,h): | |
self.width = w | |
self.height = h | |
self.name = 'SceneKit Demo' | |
self.background_color = 'white' | |
d_statusbar = 20 | |
d_button = 32 | |
d_between = 10 | |
# End button | |
end_button = ui.Button(name='end_button') | |
end_button.title = '❌' | |
end_button.frame = (d_between, d_statusbar, d_button, d_button) | |
end_button.font= ('Courier-Bold',20) | |
end_button.action = self.end_button_action | |
self.add_subview(end_button) | |
# Geometry button | |
geometry_button = ui.Button(name='geometry_button') | |
geometry_button.title = 'geometry' | |
#img = ui.Image.named('SceneKit Geometries.jpg') | |
#wi,hi = img.size | |
#geometry_button.image = ui.Image.named('SceneKit Geometries.jpg').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL) | |
#t_width = d_button * wi/hi | |
geometry_button.font= ('Courier-Bold',20) | |
t_width = ui.measure_string(geometry_button.title, font=geometry_button.font)[0] + 10 | |
geometry_button.frame = (self.width-d_between-t_width, d_statusbar, t_width, d_button) | |
geometry_button.action = self.geometry_button_action | |
self.add_subview(geometry_button) | |
# Faces button | |
faces_button = ui.Button(name='faces_button') | |
faces_button.title = 'faces' | |
faces_button.font= ('Courier-Bold',20) | |
t_width = ui.measure_string(faces_button.title, font=faces_button.font)[0] + 10 | |
faces_button.frame = (geometry_button.x-d_between-t_width, d_statusbar, t_width, d_button) | |
faces_button.action = self.faces_button_action | |
faces_button.enabled = False | |
self.add_subview(faces_button) | |
# Action button | |
action_button = ui.Button(name='action_button') | |
action_button.title = 'action' | |
action_button.font= ('Courier-Bold',20) | |
t_width = ui.measure_string(action_button.title, font=action_button.font)[0] + 10 | |
action_button.frame = (faces_button.x-d_between-t_width, d_statusbar, t_width, d_button) | |
action_button.action = self.action_button_action | |
action_button.enabled = False | |
self.add_subview(action_button) | |
# horizontal line | |
line_label = ui.Label() | |
y = end_button.y+end_button.height+d_between | |
line_label.frame = (0,y,self.width,1) | |
line_label.border_width = 1 | |
self.add_subview(line_label) | |
# main shield | |
main_shield = ui.Button(name='main_shield') | |
main_shield.frame = (0, 0, self.width, self.height) | |
main_shield.background_color = (1,1,1, 0.5) | |
main_shield.action = self.main_shield_action | |
main_shield.hidden = True | |
self.add_subview(main_shield) | |
# scrollview for geometries/faces/actions | |
scroll_view = ui.ScrollView(name='scroll_view') | |
scroll_view.width = 200 | |
scroll_view.border_color = 'blue' | |
scroll_view.border_width = 1 | |
scroll_view.corner_radius = 10 | |
main_shield.add_subview(scroll_view) | |
# detail shield for scroll_view | |
detail_shield = ui.View(name='detail_shield') | |
detail_shield.flex = 'WH' | |
detail_shield.frame = (0, 0, scroll_view.width, scroll_view.height) | |
detail_shield.background_color = (1,1,1, 0.5) | |
detail_shield.hidden = True | |
scroll_view.add_subview(detail_shield) | |
# tableview for details (dimensions/material type) | |
detail_tableview = ui.TableView(name='detail_tableview') | |
detail_tableview.border_color = 'blue' | |
detail_tableview.border_width = 1 | |
detail_tableview.width = scroll_view.width | |
l = [] | |
detail_tableview.data_source = ui.ListDataSource(items=l) | |
detail_tableview.row_height = 32 | |
detail_tableview.width = scroll_view.width | |
detail_tableview.height = 32# temporary | |
detail_tableview.data_source.delete_enabled = False | |
detail_tableview.delegate = self | |
detail_tableview.data_source.tableview_cell_for_row = self.tableview_cell_for_row | |
detail_tableview.hidden = True | |
scroll_view.add_subview(detail_tableview) | |
self.geometries_default = {'box':[6,{'Width':1, 'Height':1, 'Length':1, 'ChamferRadius':0.1, 'ChamferSegmentCount':100}], 'sphere':[1,{'Radius':1}], 'pyramid':[5,{'Width':1, 'Height':1, 'Length':1}], 'torus':[1,{'RingRadius':1,'PipeRadius':0.3}], 'cone':[3,{'TopRadius':1, 'BottomRadius':0.4, 'Height':2}], 'cylinder':[3,{'Radius':1, 'Height':3}], 'tube':[3,{'InnerRadius':0.8, 'OuterRadius':1, 'Height':2}], 'shape':[5,{'Flatness':0.01, 'ExtrusionDepth':1,'ChamferRadius':0.2}], 'capsule':[1,{'Radius':1,'Height':3}], 'text':[3,{'ExtrusionDepth':1,'Text':'text'}]} | |
self.geometries = self.geometries_default | |
self.actions_default = {'rotation':[False, {'ByX':0, 'ByY':360, 'ByZ':360, 'duration':10}], 'scaleBy':[False,{'By':5,'duration':10}]} | |
self.actions = self.actions_default | |
self.colors = ['rosybrown', 'antiquewhite', 'lightsteelblue', 'darkblue', 'darkviolet', 'plum', 'darkcyan', 'blanchedalmond', 'chocolate', 'sienna', 'tomato', 'peachpuff', 'lightyellow', 'bisque', 'aqua', 'oldlace', 'maroon', 'palegreen', 'chartreuse', 'darkturquoise', 'linen', 'magenta', 'lemonchiffon', 'powderblue', 'papayawhip', 'gold', 'khaki', 'lightseagreen', 'darkred', 'floralwhite', 'turquoise', 'mediumspringgreen', 'indianred', 'lightgreen', 'crimson', 'mintcream', 'lavender', 'purple', 'orchid', 'darkslateblue', 'whitesmoke', 'moccasin', 'beige', 'mistyrose', 'dodgerblue', 'hotpink', 'lightcoral', 'goldenrod', 'coral', 'cadetblue', 'black', 'mediumseagreen', 'gainsboro', 'paleturquoise', 'darkgreen', 'darkkhaki', 'mediumblue', 'dimgray', 'darkorchid', 'deeppink', 'mediumvioletred', 'lightgray', 'darkgrey', 'lightsalmon', 'lightblue', 'lightslategrey', 'slategray', 'slateblue', 'greenyellow', 'darkgray', 'lawngreen', 'cornflowerblue', 'midnightblue', 'lightpink', 'deepskyblue', 'navy', 'lightskyblue', 'darkorange', 'blueviolet', 'lightgrey', 'lightgoldenrodyellow', 'violet', 'ivory', 'mediumslateblue', 'cyan', 'rebeccapurple', 'firebrick', 'green', 'burlywood', 'wheat', 'mediumpurple', 'mediumturquoise', 'skyblue', 'peru', 'forestgreen', 'royalblue', 'aquamarine', 'silver', 'olive', 'palevioletred', 'mediumorchid', 'darkslategray', 'darkslategrey', 'steelblue', 'olivedrab', 'lime', 'orangered', 'grey', 'sandybrown', 'slategrey', 'pink', 'blue', 'palegoldenrod', 'ghostwhite', 'brown', 'darkseagreen', 'saddlebrown', 'salmon', 'cornsilk', 'red', 'snow', 'tan', 'aliceblue', 'yellow', 'yellowgreen', 'springgreen', 'thistle', 'navajowhite', 'teal', 'lightcyan', 'orange', 'darksalmon', 'mediumaquamarine', 'darkolivegreen', 'lavenderblush', 'indigo', 'fuchsia', 'honeydew', 'azure', 'lightslategray', 'seagreen', 'gray', 'dimgrey', 'limegreen', 'darkmagenta', 'darkgoldenrod', 'seashell'] | |
self.action = None | |
self.geometry_type = None | |
scene_uiview = ui.View(name='scene_uiview') | |
y = line_label.y+line_label.height | |
scene_uiview.frame = (0,y,self.width,self.height-y) | |
self.add_subview(scene_uiview) | |
self_objc = ObjCInstance(scene_uiview) | |
self.scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(scene_uiview.width, scene_uiview.height)), None).autorelease() | |
self.scene_view.setAutoresizingMask_(18) | |
self.scene_view.setAllowsCameraControl_(True) | |
self_objc.addSubview_(self.scene_view) | |
self.scene = SCNScene.scene() | |
self.scene_view.setScene_(self.scene) | |
self.root_node = self.scene.rootNode() | |
self.camera = SCNCamera.camera() | |
self.camera_node = SCNNode.node() | |
self.camera_node.setCamera(self.camera) | |
d = 6 | |
self.camera_node.setPosition((-d,d,d)) | |
self.geometry_node = None | |
self.root_node.addChildNode_(self.camera_node) | |
self.active_menu = None | |
self.face_id = None | |
def action_button_action(self,sender): | |
# Action selection | |
self.set_sub_menu(sender,self.actions.keys(),self.action_selection) | |
def geometry_button_action(self,sender): | |
# Geometry selection | |
self.set_sub_menu(sender,self.geometries.keys(),self.geometry_selection) | |
def faces_button_action(self,sender): | |
# faces selection | |
self.set_sub_menu(sender,self.faces.keys(),self.face_selection) | |
def set_sub_menu(self,sender,sub_menu_titles,sub_menu_action): | |
self.active_menu = sender | |
sv = self['main_shield']['scroll_view'] | |
# position under button, aligned at its right | |
x0 = sender.x + sender.width - sv.width | |
y0 = sender.y + sender.height - 1 | |
sv.x = x0 | |
sv.y = y0 | |
l = [] | |
y = 0 | |
i = 0 | |
for f in sorted(sub_menu_titles): | |
btn= ui.Button(name=str(i)) | |
btn.action = sub_menu_action | |
btn.tint_color = 'black' | |
btn.title = str(f) | |
btn.width = sv.width | |
h = 32 | |
if 'faces' in sender.title: | |
h = self.build_face_button(btn) | |
elif 'action' in sender.title: | |
if self.actions[f][0]: | |
check = ui.ImageView(name='check') | |
hi = btn.font[1] | |
di = int((h-hi)/2) | |
check.frame = (di,di,hi,hi) | |
check.image = ui.Image.named('emj:Checkmark_1') | |
btn.add_subview(check) | |
btn.background_color = 'white' | |
else: | |
btn.background_color = 'white' | |
btn.frame = (0,y,sv.width,h) | |
sv.add_subview(btn) | |
y = y + h | |
i = i + 1 | |
sv.content_size = (sv.width,y) | |
hs = ui.get_screen_size()[1] - 50 | |
if (y+y0) > hs: | |
y = hs - y0 | |
sv.height = y | |
sv.nbr_entries = len(sub_menu_titles) | |
self['main_shield'].hidden = False | |
self['main_shield'].bring_to_front() | |
sender.border_color = sv.border_color | |
sender.border_width = sv.border_width | |
sender.corner_radius = sv.corner_radius | |
def main_shield_action(self, sender): | |
sender.hidden = True | |
self.reset_sub_menu() | |
def reset_sub_menu(self): | |
sv = self['main_shield']['scroll_view'] | |
sv['detail_tableview'].hidden = True | |
sv['detail_shield'].hidden = True | |
self['main_shield'].hidden = True | |
for subv in sv.subviews: | |
if type(subv) is ui.Button: | |
sv.remove_subview(subv) | |
self.active_menu.border_width = 0 | |
def set_detail_menu(self,sender): | |
# show shield to protect against tapping other buttons | |
sv = self['main_shield']['scroll_view'] | |
sv['detail_shield'].hidden = False | |
sv['detail_shield'].bring_to_front() | |
# show tableview of materials just below selected face | |
vm = sv['detail_tableview'] | |
if 'geometry' in self.active_menu.title: | |
vm.allows_selection = False | |
i = int(sender.name) | |
k = sorted(self.geometries.keys())[i] | |
self.values = self.geometries[k][1] # {'p1':v1,....} | |
l =[] | |
for p in sorted(self.values.keys()): | |
l.append((p,self.values[p])) | |
elif 'faces' in self.active_menu.title: | |
vm.allows_selection = True | |
l = ['color','photo','video','front camera','rear camera'] | |
elif 'action' in self.active_menu.title: | |
vm.allows_selection = False | |
i = int(sender.name) | |
k = sorted(self.actions.keys())[i] | |
self.values = self.actions[k][1] # {'p1':v1,....} | |
l =[] | |
for p in sorted(self.values.keys()): | |
l.append((p,self.values[p])) | |
vm.data_source.items = l | |
vm.height = len(l)*vm.row_height | |
vm.y = sender.y + sender.height | |
y = vm.y + vm.height | |
i = int(sender.name) | |
for i in range(i+1,sv.nbr_entries): | |
sv[str(i)].y = y | |
y = y + sv[str(i)].height | |
sv.content_size = (sv.width,y) | |
hs = ui.get_screen_size()[1] - 50 | |
y0 = sv.y | |
if (y+y0) > hs: | |
y = hs - y0 | |
sv.height = y | |
sv['detail_shield'].height =y | |
vm.hidden = False | |
vm.bring_to_front() # to select/change details | |
sender.bring_to_front() # so we can retap to close parameters | |
def tableview_did_select(self, tableview, section, row): | |
tableview.selected = row | |
if 'faces' in self.active_menu.title: | |
self.update_material_params = (tableview.superview, tableview.data_source.items[row]) | |
ui.delay(self.update_material,0.1) | |
tableview.close() | |
def tableview_cell_for_row(self, tableview, section, row): | |
data = tableview.data_source.items[row] | |
cell = ui.TableViewCell() | |
w, h = tableview.width, tableview.row_height | |
if type(data) is tuple: | |
lbl = ui.Label() | |
lbl.frame = (0,0,w/2,h) | |
lbl.text = data[0] | |
cell.content_view.add_subview(lbl) | |
tf = ui.TextField(name=data[0]) | |
tf.frame = (lbl.width,0,w-lbl.width,h) | |
tf.text = str(self.values[data[0]]) | |
tf.delegate = self | |
SetTextFieldPad(tf,textfield_did_change=self.textfield_did_change) | |
test = tf | |
cell.content_view.add_subview(tf) | |
else: | |
cell.text_label.text = data | |
return cell | |
def textfield_did_change(self, tf): | |
try: | |
self.values[tf.name] = float(tf.text) | |
except Exception as e: | |
self.values[tf.name] = 0 | |
def set_confirm_buttons(self,sender,b_action): | |
d = 32 | |
b_confirm = ui.Button(name='confirm') | |
b_confirm.title = '✅' | |
b_confirm.frame = (sender.width-d-5,0,d,d) | |
b_confirm.action = b_action | |
sender.add_subview(b_confirm) | |
b_cancel = ui.Button(name='cancel') | |
b_cancel.title = '❌' | |
b_cancel.frame = (5,0,d,d) | |
b_cancel.action = b_action | |
sender.add_subview(b_cancel) | |
sender.enabled = False | |
def reset_confirm_buttons(self,sender): | |
sv = sender.superview | |
for subv in sv.subviews: | |
sv.remove_subview(subv) | |
sv = self['main_shield']['scroll_view'] | |
sv['detail_shield'].hidden = True | |
sv['detail_tableview'].hidden = True | |
def geometry_selection(self,sender): | |
# selection of a geometry button | |
sv = self['main_shield']['scroll_view'] | |
if sv['detail_shield'].hidden: | |
# 1st tap to display parameters of geometry | |
sender.background_color = 'lightgray' | |
self.set_detail_menu(sender) | |
self.set_confirm_buttons(sender,self.geometry_selection) | |
return | |
# 2nd tap to close the parameters and accept geometry | |
if sender.name == 'confirm': | |
i = int(sender.superview.name) | |
k = sorted(self.geometries.keys())[i] | |
self.geometries[k][1] = self.values | |
self.reset_confirm_buttons(sender) | |
elif sender.name == 'cancel': | |
self.reset_confirm_buttons(sender) | |
# simulate retap geometry | |
self.geometry_button_action(self['geometry_button']) | |
return | |
else: | |
print('on ne devrait passer ici') | |
i = int(sender.name) | |
self.reset_sub_menu() | |
if self.geometry_node: | |
self.geometry_node.removeFromParentNode() | |
self.geometry_type = sorted(self.geometries.keys())[i] | |
self.nb_faces = self.geometries[self.geometry_type][0] | |
ui.delay(self.process_geometry,0.2) | |
def face_selection(self,sender): | |
# selection of a face button | |
self.set_detail_menu(sender) | |
self.face_id = int(sender.name) | |
@on_main_thread | |
def build_face_button(self,btn): | |
face_id = int(btn.name) | |
face = self.faces[face_id] | |
val = face[1] | |
w = btn.width | |
if face[0] == 'color': | |
if type(val) is tuple: | |
r,g,b = val | |
else: | |
rgb = getrgb(val) | |
r,g,b = tuple(c/255.0 for c in rgb) | |
btn.bg_color = (r,g,b) | |
h = 64 | |
elif face[0] == 'photo': | |
ui_image = val.get_ui_image() | |
wi,hi = ui_image.size | |
h = w * (hi/wi) | |
btn.background_image = ui_image | |
elif face[0] == 'video': | |
# AVPlayer in button? | |
video_objc = ObjCInstance(val) | |
video_url = ObjCClass('AVURLAsset').alloc().initWithURL_options_(video_objc.ALAssetURL(),None) | |
AVPlayer = ObjCClass('AVPlayerItem').playerItemWithAsset_(video_url) | |
p = ObjCClass('AVPlayer').playerWithPlayerItem_(AVPlayer) | |
videolayer=ObjCClass('AVPlayerLayer').playerLayerWithPlayer_(p) | |
vi = ui.View() | |
wi,hi = val.pixel_width,val.pixel_height | |
h = w * (hi/wi) | |
vi.frame = (0,0,w,h) | |
V=ObjCInstance(vi) | |
btn.add_subview(vi) | |
videolayer.frame=V.bounds() | |
V.layer().addSublayer_(videolayer) | |
p.play() | |
elif 'camera' in face[0]: | |
vi = ui.View() | |
wi,hi = ui.get_screen_size() | |
h = w * (hi/wi) | |
vi.frame = (0,0,w,h) | |
V=ObjCInstance(vi) | |
btn.add_subview(vi) | |
_session = ObjCClass('AVCaptureSession').alloc().init() | |
_session.setSessionPreset_('AVCaptureSessionPresetHigh') | |
if 'front' in face[0]: | |
device = 1 | |
else: | |
device = 0 | |
_inputDevice = ObjCClass('AVCaptureDevice').devices()[device] | |
deviceInput = ObjCClass('AVCaptureDeviceInput').deviceInputWithDevice_error_(_inputDevice, None) | |
if _session.canAddInput_(deviceInput): | |
_session.addInput_(deviceInput) | |
_previewLayer = ObjCClass('AVCaptureVideoPreviewLayer').alloc().initWithSession_(_session) | |
_previewLayer.setVideoGravity_('AVLayerVideoGravityResizeAspectFill') | |
rootLayer = V.layer() | |
rootLayer.setMasksToBounds_(True) | |
_previewLayer.setFrame_(CGRect(CGPoint(0, 0), CGSize(w, h))) | |
rootLayer.insertSublayer_atIndex_(_previewLayer,0) | |
_session.startRunning() | |
return h | |
@on_main_thread | |
def update_material(self): | |
b_faces,type_material = self.update_material_params | |
if type_material == 'color': | |
rgb = OMColorPickerViewController() | |
if rgb == None: # tap outside color pocker | |
return | |
material = self.set_material(self.face_id, type_material, rgb) | |
elif type_material == 'photo': | |
all_assets = photos.get_assets() | |
asset = photos.pick_asset(assets=all_assets, title='pick photo for face '+str(self.face_id)) | |
if not asset: | |
# cancel by user | |
return | |
material = self.set_material(self.face_id, type_material, asset) | |
elif type_material == 'video': | |
all_videos = photos.get_assets(media_type='video') | |
video = photos.pick_asset(all_videos) | |
if not video: | |
# cancel by user | |
return | |
material = self.set_material(self.face_id, type_material, video) | |
elif type_material == 'front camera': | |
material = self.set_material(self.face_id, type_material, None) | |
elif type_material == 'rear camera': | |
material = self.set_material(self.face_id, type_material, None) | |
self.geometry.replaceMaterialAtIndex_withMaterial_(self.face_id, material) | |
# hide material tableview | |
b_faces['detail_shield'].hidden = True | |
b_faces.content_offset = (0,0) | |
b_faces['detail_tableview'].hidden = True | |
# display new face button | |
# compute new y of all buttons after | |
y = 0 | |
for f in sorted(self.faces.keys()): | |
btn = b_faces[str(f)] | |
if f == self.face_id: | |
h = self.build_face_button(btn) | |
else: | |
h = btn.height | |
btn.y = y | |
btn.height = h | |
y = y + h | |
b_faces.content_size = (b_faces.width,y) | |
hs = ui.get_screen_size()[1] | |
y0 = b_faces.y | |
if (y+y0) > hs: | |
y = hs - y0 | |
b_faces.height = y | |
@on_main_thread | |
def set_material(self,face_no,type_material,val): | |
Material = SCNMaterial.material() | |
if type_material == 'color': | |
if type(val) is tuple: | |
r,g,b = val | |
else: | |
rgb = getrgb(val) | |
r,g,b = tuple(c/255.0 for c in rgb) | |
Material.contents = ObjCClass('UIColor').colorWithRed_green_blue_alpha_(r,g,b,1.0) | |
elif type_material == 'photo': | |
Material.contents = ObjCInstance(val.get_ui_image()) | |
elif type_material == 'video': | |
video_objc = ObjCInstance(val) | |
video_url = ObjCClass('AVURLAsset').alloc().initWithURL_options_(video_objc.ALAssetURL(),None) | |
AVPlayer = ObjCClass('AVPlayerItem').playerItemWithAsset_(video_url) | |
p = ObjCClass('AVPlayer').playerWithPlayerItem_(AVPlayer) | |
Material.contents = p | |
p.play() | |
elif type_material == 'front camera': | |
inputDevice = ObjCClass('AVCaptureDevice').devices()[1] | |
Material.contents = inputDevice | |
elif type_material == 'rear camera': | |
inputDevice = ObjCClass('AVCaptureDevice').devices()[0] | |
Material.contents = inputDevice | |
self.faces[face_no] = (type_material,val) | |
return Material | |
@on_main_thread | |
def process_geometry(self): | |
dim = self.geometries[self.geometry_type][1] | |
if self.geometry_type == 'box': | |
Width = dim['Width'] | |
Height = dim['Height'] | |
Length = dim['Length'] | |
ChamferRadius = dim['ChamferRadius'] | |
ChamferSegmentCount = dim['ChamferSegmentCount'] | |
self.geometry = SCNBox.boxWithWidth_height_length_chamferRadius_(Width, Height, Length, ChamferRadius) | |
self.geometry.chamferSegmentCount = ChamferSegmentCount | |
elif self.geometry_type == 'sphere': | |
radius = dim['Radius'] | |
self.geometry = SCNSphere.sphereWithRadius_(radius) | |
elif self.geometry_type == 'pyramid': | |
Width = dim['Width'] | |
Height = dim['Height'] | |
Length = dim['Length'] | |
self.geometry = SCNPyramid.pyramidWithWidth_height_length_(Width, Height, Length) | |
elif self.geometry_type == 'torus': | |
RingRadius = dim['RingRadius'] | |
PipeRadius = dim['PipeRadius'] | |
self.geometry = SCNTorus.torusWithRingRadius_pipeRadius_(RingRadius, PipeRadius) | |
elif self.geometry_type == 'cone': | |
TopRadius = dim['TopRadius'] | |
BottomRadius = dim['BottomRadius'] | |
Height = dim['Height'] | |
self.geometry = SCNCone.coneWithTopRadius_bottomRadius_height_(TopRadius, BottomRadius, Height) | |
elif self.geometry_type == 'cylinder': | |
Radius = dim['Radius'] | |
Height = dim['Height'] | |
self.geometry = SCNCylinder.cylinderWithRadius_height_(Radius, Height) | |
elif self.geometry_type == 'tube': | |
InnerRadius = dim['InnerRadius'] | |
OuterRadius = dim['OuterRadius'] | |
Height = dim['Height'] | |
self.geometry = SCNTube.tubeWithInnerRadius_outerRadius_height_(InnerRadius, OuterRadius, Height) | |
elif self.geometry_type == 'shape': | |
ExtrusionDepth = dim['ExtrusionDepth'] | |
Flatness = dim['Flatness'] | |
ChamferRadius = dim['ChamferRadius'] | |
UIBezierPath = ObjCClass('UIBezierPath').bezierPathWithOvalInRect_(CGRect(CGPoint(-1, -1.5), CGSize(2,3))) | |
UIBezierPath.flatness = Flatness | |
self.geometry = SCNShape.shapeWithPath_extrusionDepth_(UIBezierPath, ExtrusionDepth) | |
self.geometry.chamferRadius = ChamferRadius | |
elif self.geometry_type == 'capsule': | |
Radius = dim['Radius'] | |
Height = dim['Height'] | |
self.geometry = SCNCapsule.capsuleWithCapRadius_height_(Radius,Height) | |
elif self.geometry_type == 'text': | |
Text = dim['Text'] | |
ExtrusionDepth = dim['ExtrusionDepth'] | |
self.geometry = SCNText.textWithString_extrusionDepth_(Text, ExtrusionDepth) | |
self.Material_imgs = [] | |
self.faces = {} | |
for i in range(0,self.nb_faces): | |
self.Material_imgs.append(self.set_material(i,'color',self.colors[i])) | |
self['faces_button'].enabled = True | |
self['action_button'].enabled = True | |
self.geometry.setMaterials_(self.Material_imgs) | |
self.geometry_node = SCNNode.nodeWithGeometry_(self.geometry) | |
self.root_node.addChildNode_(self.geometry_node) | |
# Add a constraint to the camera to keep it pointing to the target geometry | |
constraint = SCNLookAtConstraint.lookAtConstraintWithTarget_(self.geometry_node) | |
constraint.gimbalLockEnabled = True | |
self.camera_node.constraints = [constraint] | |
@on_main_thread | |
def action_selection(self,sender): | |
# selection of a action button | |
sv = self['main_shield']['scroll_view'] | |
if sv['detail_shield'].hidden: | |
# 1st tap to display parameters of action | |
if self.actions[sender.title][0]: | |
# action was active desactive lt | |
self.actions[sender.title][0] = False | |
# simulate retap action | |
self.action_button_action(self['action_button']) | |
else: | |
sender.background_color = 'lightgray' | |
self.set_detail_menu(sender) | |
self.set_confirm_buttons(sender,self.action_selection) | |
return | |
# 2nd tap to close the parameters and accept action | |
if sender.name == 'confirm': | |
i = int(sender.superview.name) | |
self.action = sorted(self.actions.keys())[i] | |
self.actions[self.action][1] = self.values | |
self.reset_confirm_buttons(sender) | |
self.actions[self.action][0] = True | |
elif sender.name == 'cancel': | |
self.reset_confirm_buttons(sender) | |
# simulate retap action | |
self.action_button_action(self['action_button']) | |
return | |
else: | |
print('on ne devrait passer ici') | |
i = int(sender.name) | |
self.reset_sub_menu() | |
dim = self.actions[self.action][1] | |
self.geometry_node.removeAllActions() | |
if self.action == 'rotation': | |
ByX = dim['ByX']*math.pi/180 | |
ByY = dim['ByY']*math.pi/180 | |
ByZ = dim['ByZ']*math.pi/180 | |
duration = dim['duration'] | |
action = SCNAction.repeatActionForever_(SCNAction.rotateByX_y_z_duration_(ByX, ByY, ByZ, duration)) | |
#action = SCNAction.repeatActionForever_( SCNAction.rotateByAngle_aroundAxis_duration_(math.pi*2,(0, 1, 0), 15.0 )) | |
self.geometry_node.runAction_(action) | |
elif self.action == 'scaleBy': | |
By = dim['By'] | |
duration = dim['duration'] | |
#action = SCNAction.repeatActionForever_( | |
actions = SCNAction.sequence_([SCNAction.scaleBy_duration_(By,duration), SCNAction.scaleBy_duration_(1/By,duration)]) | |
self.geometry_node.runAction_(actions) | |
def end_button_action(self,sender): | |
self.close() | |
def main(): | |
# Main code | |
w, h = ui.get_screen_size() | |
# Hide script | |
back = MyView(w,h) | |
back.present('full_screen', hide_title_bar=True) | |
# Protect against import | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment