Skip to content

Instantly share code, notes, and snippets.

@cvpe
Created September 22, 2019 09:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cvpe/29870368995015b0aad8d125b5c6ecef to your computer and use it in GitHub Desktop.
Save cvpe/29870368995015b0aad8d125b5c6ecef to your computer and use it in GitHub Desktop.
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