Created
September 22, 2019 09:10
-
-
Save cvpe/29870368995015b0aad8d125b5c6ecef to your computer and use it in GitHub Desktop.
Scenekit test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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