ursina API Reference

v7.0.0

Ursina

ursina/main

Ursina(title='ursina', icon='textures/ursina.ico', borderless=False, fullscreen=False, size=None, forced_aspect_ratio=None, position=None, vsync=True, editor_ui_enabled=True, window_type='onscreen', development_mode=True, render_mode=None, show_ursina_splash=False, **kwargs)

.mouse = mouse

functions:
 input_up(key, is_raw=False) internal method for key release
 input_hold(key, is_raw=False) internal method for handling repeating input that occurs when you hold the key
 input(key, is_raw=False) internal method for handling input
 text_input(key) internal method for handling text input
 step(): # use this control the update loop yourself. call app.step() in a while loop for example, instead of app.run() use this control the update loop yourself. call app.step() in a while loop for example, instead of app.run()
 run(info=True)

example:

from ursina import * app = Ursina(development_mode=False, use_ingame_console=True) def input(key): print(key) app.run()


Entity(, metaclass=PostInitCaller)

ursina/entity

Entity(add_to_scene_entities=True, enabled=True, **kwargs)

Entity.rotation_directions = (-1,-1,1)
.name = camel_to_snake(self.__class__.__name__)
.ignore = False if True, will not try to run code.
.ignore_paused = False if True, will still run when application is paused. useful when making a pause menu for example.
.ignore_input = False
.parent = scene default parent is scene, which means it's in 3d space. to use UI space, set the parent to camera.ui instead.
.add_to_scene_entities = add_to_scene_entities set to False to be ignored by the engine, but still get rendered.
.scripts = [] add with add_script(class_instance). will assign an 'entity' variable to the script.
.animations = []
.hovered = False will return True if mouse hovers entity.
.line_definition = None returns a Traceback(filename, lineno, function, code_context, index).
.enabled = enabled

properties:
.enableddisabled entities will not be visible nor run code.
.modelset model with model='model_name' (without file type extension)
.color
.eternaleternal entities does not get destroyed on scene.clear()
.double_sided
.render_queuefor custom sorting in case of conflict. To sort things in 2d, set .z instead of using this.
.parent
.loose_parent
.world_parentchange the parent, but keep position, rotation and scale
.typesget all class names including those this inhertits from.
.visible
.visible_selfset visibility of self, without affecting children.
.colliderset to 'box'/'sphere'/'capsule'/'mesh' for auto fitted collider.
.collisiontoggle collision without changing collider.
.on_click
.origin
.origin_x
.origin_y
.origin_z
.world_position
.world_x
.world_y
.world_z
.positionright, up, forward. can also set self.x, self.y, self.z
.x
.y
.z
.Xshortcut for int(entity.x)
.Yshortcut for int(entity.y)
.Zshortcut for int(entity.z)
.world_rotation
.world_rotation_x
.world_rotation_y
.world_rotation_z
.rotationcan also set self.rotation_x, self.rotation_y, self.rotation_z
.rotation_x
.rotation_y
.rotation_z
.quaternion
.world_scale
.world_scale_x
.world_scale_y
.world_scale_z
.scalecan also set self.scale_x, self.scale_y, self.scale_z
.scale_x
.scale_y
.scale_z
.transformget/set position, rotation and scale
.world_transformget/set world_position, world_rotation and world_scale
.forwardget forward direction.
.backget backwards direction.
.rightget right direction.
.leftget left direction.
.upget up direction.
.downget down direction.
.screen_positionget screen position(ui space) from world space.
.shader
.shader_input
.materiala way to set shader, texture, texture_scale, texture_offset and shader inputs in one go
.textureset model with texture='texture_name'. requires a model to be set beforehand.
.texture_scalehow many times the texture should repeat, eg. texture_scale=(8,8).
.texture_offset
.tileset_sizeif the texture is a tileset, say how many tiles there are so it only use one tile of the texture, e.g. tileset_size=[8,4]
.tile_coordinateset the tile coordinate, starts in the lower left.
.alphashortcut for setting color's transparency/opacity
.always_on_top
.unlitset to True to ignore light and not cast shadows
.billboardset to True to make this Entity always face the camera.
.wireframeset to True to render model as wireframe
.model_bounds
.bounds
.flipped_faces
.children
.loose_children
.attributesattribute names. used by duplicate().

functions:
 enable() same as .enabled = True
 disable() same as .enabled = False
 get_shader_input(name)
 set_shader_input(name, value)
 generate_sphere_map(size=512, name=f'sphere_map_{len(scene.entities)}')
 generate_cube_map(size=512, name=f'cube_map_{len(scene.entities)}')
 get_position(relative_to=scene) get position relative to on other Entity. In most cases, use .position instead.
 set_position(value, relative_to=scene) set position relative to on other Entity. In most cases, use .position instead.
 rotate(value, relative_to=None) rotate around local axis.
 add_script(class_instance)
 combine(analyze=False, auto_destroy=True, ignore=[], ignore_disabled=True, include_normals=False)
 look_at(target, axis='forward', up=None) up defaults to self.up
 look_at_2d(target, axis='z')
 look_at_xy(target)
 look_at_xz(target)
 has_ancestor(possible_ancestor)
 has_disabled_ancestor()
 get_changes(target_class=None) returns a dict of all the changes
 animate(name, value, duration=.1, delay=0, curve=curve.in_expo, loop=False, resolution=None, interrupt='kill', time_step=None, unscaled=False, auto_play=True, auto_destroy=True)
 animate_position(value, duration=.1, **kwargs)
 animate_rotation(value, duration=.1, **kwargs)
 animate_scale(value, duration=.1, **kwargs)
 animate_{e}(value, duration=.1, delay=0, unscaled=False, **kwargs)
 shake(duration=.2, magnitude=1, speed=.05, direction=(1,1), delay=0, attr_name='position', interrupt='finish', unscaled=False)
 animate_color(value, duration=.1, interrupt='finish', unscaled=False, **kwargs)
 fade_out(value=0, duration=.5, unscaled=False, **kwargs)
 fade_in(value=1, duration=.5, **kwargs)
 blink(value=ursina.color.clear, duration=.1, delay=0, curve=curve.in_expo_boomerang, interrupt='finish', **kwargs)
 intersects(traverse_target=scene, ignore:list=None, debug=False)

example:

from ursina import * app = Ursina() e = Entity(model='quad', color=color.orange, position=(0,0,1), scale=1.5, rotation=(0,0,45), texture='brick') '''example of inheriting Entity''' class Player(Entity): def __init__(self, **kwargs): super().__init__() self.model='cube' self.color = color.red self.scale_y = 2 for key, value in kwargs.items(): setattr(self, key, value) def input(self, key): if key == 'space': self.animate_x(2, duration=1) def update(self): self.x += held_keys['d'] * time.dt * 10 self.x -= held_keys['a'] * time.dt * 10 player = Player(x=-1)


Button(Entity)

ursina/prefabs/button

Button(text='', parent=camera.ui, model=Default, radius=.1, origin=(0,0), text_origin=(0,0), text_size=1, color=Default, collider='box', highlight_scale=1, pressed_scale=1, disabled=False, **kwargs)

.origin = origin
.color = color
.highlight_color = self.color.tint(.2)
.pressed_color = self.color.tint(-.2)
.highlight_scale = highlight_scale multiplier
.pressed_scale = pressed_scale multiplier
.highlight_sound = None
.pressed_sound = None
.collider = collider
.disabled = disabled
.text_entity = None
.text_origin = text_origin

properties:
.text
.text_origin
.text_color
.icon
.icon_world_scale
.text_size
.origin

functions:
 input(key)
 on_mouse_enter()
 on_mouse_exit()
 fit_to_text(radius=.1, padding=Vec2(Text.size*1.5, Text.size))

example:

from ursina import * app = Ursina() Button.default_color = color.red b = Button(model='quad', scale=.05, x=-.5, color=color.lime, text='text scale\ntest', text_size=.5, text_color=color.black) b.text_size = .5 b.on_click = Sequence(Wait(.5), Func(print, 'aaaaaa'), ) b = Button(parent=camera.ui, text='hello world!', scale=.25) Button.default_color = color.blue b = Button(text='hello world!', icon='sword', scale=.25, text_origin=(-.5,0), x=.5) b.on_click = application.quit # assign a function to the button. b.tooltip = Tooltip('exit') par = Entity(parent=camera.ui, scale=.2, y=-.2) b = Button(parent=par, text='test', scale_x=1, origin=(-.5,.5)) b.text ='new text' print(b.text_entity) Button(text='sound', scale=.2, position=(-.25,-.2), color=color.pink, highlight_sound='blip_1', pressed_sound=Audio('coin_1', autoplay=False)) Text('Text size\nreference', x=.15) def input(key): if key == 'd': scene.clear() if key == 'space': b.text = 'updated text' app.run()


Sprite(Entity)

ursina/prefabs/sprite

Sprite(texture=None, ppu:int=None, **kwargs)

Sprite.ppu = 100
.model = 'quad'
.texture = texture
.ppu = ppu if ppu else Sprite.ppu pixels per unit

functions:
 update_scale() get called automatically on __init__, but if you change the texture or ppu, you can call this to update the scale.

example:

app = Ursina() camera.orthographic = True camera.fov = 1 Sprite.ppu = 16 Texture.default_filtering = None s = Sprite('brick', filtering=False) app.run()


Text(Entity)

ursina/text

Text(text='', start_tag=start_tag, end_tag=end_tag, ignore=True, **kwargs)

Text.size = .025
.size = Text.size
.parent = camera.ui
.shader = None
.text_nodes = []
.images = []
.origin = (-.5, .5)
.font = Text.default_font
.resolution = Text.default_resolution
.use_tags = True
.line_height = 1
.start_tag = start_tag
.end_tag = end_tag
.text_colors = {'default' : color.text_color}
.tag = Text.start_tag+'default'+Text.end_tag
.current_color = self.text_colors['default']
.scale_override = 1
.appear_sequence = None gets created when calling appear()

properties:
.text
.font
.colorsets the default color.
.line_height
.widthgets the width of the widest line.
.heightgets the height of the text
.lines
.resolution
.wordwrapset this to make the text wrap after a certain number of characters.
.origin
.background

functions:
 text(text)
 create_text_section(text, tag='', x=0, y=0)
 align()
 create_background(padding=size*2, radius=size, color=ursina.color.black66)
 appear(speed=.025)
 get_width(string, font=None)

example:

from ursina import * from ursina import Ursina, dedent, window app = Ursina() descr = dedent(''' <red>Rainstorm<default> <red>Rainstorm<default> Summon a rain storm to deal 5 <blue>water<default> damage to everyone, test including yourself. 1234 1234 1234 1234 1234 1234 2134 1234 1234 1234 1234 1234 2134 2134 1234 1234 1234 1234 Lasts for 4 rounds.''').strip() Text.default_resolution = 1080 * Text.size test = Text(text=descr, wordwrap=30) def input(key): if key == 'a': print('a') test.text = '<default><image:file_icon> <red><image:file_icon> test ' print('by', test.text) if key == 'c': test.text = '' window.fps_counter.enabled = False print('....', Text.get_width('yolo')) app.run()


Audio(Entity)

ursina/audio

Audio(sound_file_name='', volume=1, pitch=1, balance=0, loop=False, loops=1, autoplay=True, auto_destroy=False, **kwargs)

Audio.volume_multiplier = .5 #
.clip = sound_file_name
.volume = volume
.pitch = pitch
.balance = balance
.loop = loop
.autoplay = autoplay
.auto_destroy = auto_destroy

properties:
.volume
.pitch
.loop
.loops
.clip
.lengthget the duration of the audio clip.
.status
.ready
.playing
.time
.balancepan the audio. should be a value between -.5 and .5. default: 0

functions:
 play(start=0)
 pause()
 resume()
 stop(destroy=True)
 fade(value, duration=.5, delay=0, curve=curve.in_expo, resolution=None, interrupt=True)
 fade_in(value=1, duration=.5, delay=0, curve=curve.in_expo, resolution=None, interrupt='finish',)
 fade_out(value=0, duration=.5, delay=0, curve=curve.in_expo, resolution=None, interrupt='finish',)

example:

from ursina import Ursina import random app = Ursina() a = Audio('sine', loop=True, autoplay=True) a.volume = .5 print('---', a.volume) def input(key): if key == 'space': a = Audio('sine', pitch=random.uniform(.5,1), loop=True) app.run()


camera

ursina/camera

.parent = scene
.name = 'camera'
.eternal = True
.ui_size = 40
.perspective_lens_node = None
.orthographic_lens_node = None
.ui = Entity(eternal=True, name='ui', scale=(self.ui_size*.5, self.ui_size*.5), add_to_scene_entities=False)
.overlay = Entity(parent=self.ui, model='quad', scale=99, color=color.clear, eternal=True, z=-99, add_to_scene_entities=False)

properties:
.orthographic
.fov
.clip_plane_near
.clip_plane_far
.aspect_ratioget current aspect ratio. can not be set.
.shaderfor applying post-processing effects.

functions:
 set_up()
 set_shader_input(name, value)

example:

from ursina import * from ursina import Ursina, camera, Entity, EditorCamera app = Ursina() camera.orthographic = True e = Entity() e.model = 'quad' e.color = color.random_color() e.position = (-2, 0, 10) e = Entity() e.model = 'quad' e.color = color.random_color() e.position = (2, 0, 10) e = Entity() e.model = 'quad' e.color = color.random_color() e.position = (0, 0, 40) EditorCamera() from ursina.shaders import camera_grayscale_shader camera.shader = camera_grayscale_shader app.run()


mouse

ursina/mouse

.enabled = False
.visible = True
.locked = False
.position = Vec3(0,0,0)
.delta = Vec3(0,0,0) movement since you pressed a mouse button.
.prev_x = 0
.prev_y = 0
.start_x = 0
.start_y = 0
.velocity = Vec3(0,0,0)
.moving = False
.prev_click_time = time.time()
.prev_click_pos = None
.double_click_distance = .5
.double_click_movement_limit = .01
.hovered_entity = None returns the closest hovered entity with a collider.
.left = False
.right = False
.middle = False
.delta_drag = Vec3(0,0,0) movement between left mouse down and left mouse up.
.update_step = 1
.traverse_target = scene set this to None to disable collision with scene, which might be a good idea if you have lots of colliders.
.raycast = True
.collision = None
.collisions = []
.enabled = True

properties:
.x
.y
.position
.locked
.visible
.normalreturns the normal of the polygon, in local space.
.world_normalreturns the normal of the polygon, in world space.
.pointreturns the point hit, in local space
.world_pointreturns the point hit, in world space
.is_outside

functions:
 input(key)
 update()
 find_collision()
 unhover_everything_not_hit()

example:

from ursina import * from ursina import Ursina, Button, mouse app = Ursina() Button(parent=scene, text='a') def input(key): if key == 'space': mouse.locked = not mouse.locked print(mouse.velocity) Cursor() app.run()


window

ursina/window

.title = title
.icon = icon
.monitors = []
.main_monitor = None
.monitor_index = 0
.windowed_position = None gets set when entering fullscreen so position will be correct when going back to windowed mode
.show_ursina_splash = False
.top = Vec2(0, .5)
.bottom = Vec2(0, -.5)
.center = Vec2(0, 0)
.forced_aspect_ratio = None example: window.forced_aspect_ratio
.always_on_top = False
.vsync = True can't be set during play
.color = color.dark_gray
.render_modes = ('default', 'wireframe', 'colliders', 'normals')
.render_mode = 'default'
.editor_ui = None
.position = Vec2(x,y)
.editor_ui = Entity(parent=camera.ui, eternal=True, enabled=bool(application.development_mode))
.input_entity = Entity(name='window.input_entity', input=window_input, ignore_paused=True)
.exit_button = Button(parent=self.editor_ui, text='x', eternal=True, ignore_paused=True, origin=(.5, .5), enabled=self.borderless and application.development_mode, position=self.top_right, z=-999, scale=(.05, .025), color=color.red.tint(-.2), shortcuts=('control+shift+alt+q', 'alt+f4'), on_click=application.quit, name='exit_button')
.fps_counter = Text(parent=self.editor_ui, eternal=True, text='60', ignore=False, i=0, ignore_paused=True, position=((.5*self.aspect_ratio)-self.exit_button.scale_x, .47+(.02*(not self.exit_button.enabled)), -999))
.entity_counter = Text(parent=self.editor_ui, enabled=application.development_mode, eternal=True, origin=(-.5,.5), text='00', ignore=False, t=0, position=((.5*self.aspect_ratio)-self.exit_button.scale_x, .425+(.02*(not self.exit_button.enabled)), -999))
.collider_counter = Text(parent=self.editor_ui, enabled=application.development_mode, eternal=True, origin=(-.5,.5), text='00', ignore=False, t=.1, position=((.5*self.aspect_ratio)-self.exit_button.scale_x, .38+(.02*(not self.exit_button.enabled)), -999))
.cog_menu = ButtonList({ 'API Reference' : Func(webbrowser.open, 'https://www.ursinaengine.org/api_reference.html'), 'ursfx (Sound Effect Maker)' : lambda: exec('from ursina.prefabs import ursfx; ursfx.open_gui()'), 'Change Render Mode <gray>[F10]<default>' : self.next_render_mode, 'Reset Render Mode <gray>[Shift+F10]<default>' : Func(setattr, self, 'render_mode', 'default'), 'Toggle Editor Camera <gray>[Control+F10]<default>' : self.toggle_editor_camera, 'Toggle Hotreloading <gray>[F9]<default>' : application.hot_reloader.toggle_hotreloading, 'Reload Shaders <gray>[F7]<default>' : application.hot_reloader.reload_shaders, 'Reload Models <gray>[F7]<default>' : application.hot_reloader.reload_models, 'Reload Textures <gray>[F6]<default>' : application.hot_reloader.reload_textures, 'Reload Code <gray>[F5]<default>' : application.hot_reloader.reload_code,
.cog_button = Button(parent=self.editor_ui, eternal=True, model='quad', texture='cog', scale=.015, origin=(1,-1), position=self.bottom_right, ignore_paused=True, name='cog_button', enabled=application.development_mode)
.prev_size = self.size
.size = self.size
.render_mode = self.render_modes[i]

properties:
.left
.right
.top_left
.top_right
.bottom_left
.bottom_right
.position
.size
.aspect_ratio
.forced_aspect_ratio
.render_mode
.title
.icon
.borderless
.fullscreen
.always_on_top
.color
.vsync

functions:
 ready(title, icon, borderless, fullscreen, size, forced_aspect_ratio, position, vsync, editor_ui_enabled, window_type, render_mode)
 apply_settings()
 center_on_screen()
 make_editor_gui() called by main after setting up camera and application.development_mode
 window_input(key)
 update_aspect_ratio()
 next_render_mode()
 toggle_editor_camera()

example:

from ursina import * app = Ursina( title='Ursina', ) button_list = ButtonList( { 'widow.position = Vec2(0,0)': Func(setattr, window, 'position', Vec2(0,0)), 'widow.size = Vec2(512,512)': Func(setattr, window, 'size', Vec2(512,512)), 'widow.center_on_screen()': window.center_on_screen, 'widow.borderless = True': Func(setattr, window, 'borderless', True), 'widow.borderless = False': Func(setattr, window, 'borderless', False), 'widow.fullscreen = True': Func(setattr, window, 'fullscreen', True), 'widow.fullscreen = False': Func(setattr, window, 'fullscreen', False), 'widow.vsync = True': Func(setattr, window, 'vsync', True), 'widow.vsync = False': Func(setattr, window, 'vsync', False), 'application.base.win.request_properties(self)': Func(application.base.win.request_properties, window), }, y=0 ) startup_value = Text(y=.5,x=-.5) startup_value.text = f''' position: {window.position} size: {window.size} aspect_ratio: {window.aspect_ratio} window.main_monitor.width: {window.main_monitor.width} window.main_monitor.height: {window.main_monitor.height} ''' position_text = Text(y=.5,) def input(key): if key == 'space': window.center_on_screen() Entity(model='cube', color=color.green, collider='box', texture='shore') app.run()


application

ursina/application

.paused = False
.time_scale = 1
.calculate_dt = True
.sequences = []
.trace_entity_definition = False enable to set entity.line_definition
.package_folder = Path(__file__).parent
.blender_paths = dict()
.development_mode = True
.window_type = 'onscreen'
.show_ursina_splash = False
.ursina_splash = None
.gltf_no_srgb = True
.scenes_folder = asset_folder / 'scenes/'
.scripts_folder = asset_folder / 'scripts/'
.fonts_folder = asset_folder / 'fonts/'
.compressed_textures_folder = asset_folder / 'textures_compressed/'
.compressed_models_folder = asset_folder / 'models_compressed/'
.base = None this will be set once the Ursina() is created
.hot_reloader = None will be set my main if development_mode

functions:
 pause()
 resume()
 quit()
 load_settings(path=asset_folder / 'settings.py')


scene

ursina/scene

.entities = []
.collidables = set()

properties:
.fog_color
.fog_density
.children

functions:
 set_up()
 clear()
 fog_density(value)

example:

from ursina import * app = Ursina() e = Entity(model='plane', color=color.black, scale=100) EditorCamera() s = Sky() def input(key): if key == 'l': for e in scene.entities: print(e.name) if key == 'd': scene.clear() Entity(model='cube') scene.fog_density = .1 # sets exponential density scene.fog_density = (50, 200) # sets linear density start and end app.run()


color

ursina/color

.@deprecated("Use hsv(...) instead of color(...)")
.white = hsv(0, 0, 1)
.smoke = hsv(0, 0, 0.96)
.light_gray = hsv(0, 0, 0.75)
.gray = hsv(0, 0, 0.5)
.dark_gray = hsv(0, 0, 0.25)
.black = hsv(0, 0, 0)
.red = hsv(0, 1, 1)
.yellow = hsv(60, 1, 1)
.lime = hsv(90, 1, 1)
.green = hsv(120, 1, 1)
.turquoise = hsv(150, 1, 1)
.cyan = hsv(180, 1, 1)
.azure = hsv(210, 1, 1)
.blue = hsv(240, 1, 1)
.violet = hsv(270, 1, 1)
.magenta = hsv(300, 1, 1)
.pink = hsv(330, 1, 1)
.brown = rgb32(165, 42, 42)
.olive = rgb32(128, 128, 0)
.peach = rgb32(255, 218, 185)
.gold = rgb32(255, 215, 0)
.salmon = rgb32(250, 128, 114)
.clear = rgba(0, 0, 0, 0)
.white10 = rgba(1,1,1, 0.10)
.white33 = rgba(1,1,1, 0.33)
.white50 = rgba(1,1,1, 0.50)
.white66 = rgba(1,1,1, 0.66)
.black10 = rgba(0,0,0, 0.10)
.black33 = rgba(0,0,0, 0.33)
.black50 = rgba(0,0,0, 0.50)
.black66 = rgba(0,0,0, 0.66)
.black90 = rgba(0,0,0, 0.90)
.text = smoke
.light_text = smoke
.dark_text = hsv(0, 0, .1)
.text_color = light_text
.color_names = ('white', 'smoke', 'light_gray', 'gray', 'dark_gray', 'black',
.colors = dict()

functions:
 color(h,s,v,a=1)
 hsv(h, s, v, a=1)
 rgba32(r, g, b, a=255)
 rgb32(r, g, b)
 rgba(r, g, b, a)
 rgb(r, g, b)
 to_hsv(color)
 hex(value)
 rgb_to_hex(r, g, b, a=1)
 brightness(color)
 inverse(color)
 random_color()
 tint(color, amount=.2)

example:

from ursina import * from ursina import Ursina, Entity, Button, Quad, grid_layout, color app = Ursina() print(color.brightness(color.blue)) p = Entity(x=-2) for key in color.colors: print(key) b = Button(parent=p, model=Quad(0), color=color.colors[key], text=key) b.text_entity.scale *= .5 grid_layout(p.children, max_x=8) for name in ('r', 'g', 'b', 'h', 's', 'v', 'brightness'): print(name + ':', getattr(color.random_color(), name)) e = Entity(model='cube', color=color.lime) print(e.color.name) print('rgb to hex:', color.rgb_to_hex(*color.blue)) e.color = color.color(1,2,3) app.run()


Mesh(p3d.)

ursina/mesh

Mesh(vertices=None, triangles=None, colors=None, uvs=None, normals=None, static=True, mode='triangle', thickness=1, render_points_in_3d=True, vertex_buffer=None, vertex_buffer_length=None, vertex_buffer_format=None)

Mesh.}
.vertices = vertices
.triangles = triangles
.colors = colors
.uvs = uvs
.normals = normals
.static = static
.mode = mode
.thickness = thickness
.render_points_in_3d = render_points_in_3d
.vertex_buffer = vertex_buffer
.vertex_buffer_length = vertex_buffer_length
.vertex_buffer_format = vertex_buffer_format

properties:
.indices
.generated_vertices
.render_points_in_3d
.thickness

functions:
 generate()
 recipe()
 serialize(vertex_decimal_limit=4, color_decimal_limit=4, uv_decimal_limit=4, normal_decimal_limit=4)
 generate_normals(smooth=True, regenerate=True)
 colorize(left=color.white, right=color.blue, down=color.red, up=color.green, back=color.white, forward=color.white, smooth=True, world_space=True, strength=1)
 project_uvs(aspect_ratio=1, direction='forward')
 clear(regenerate=True)
 save(name='', folder:Path=Func(getattr, application, 'compressed_models_folder'), flip_faces=False, vertex_decimal_limit=5, color_decimal_limit=4)

example:

from ursina import * app = Ursina() e = Entity(position=(0,0), model=Mesh(vertices=[(-.5,0,0), (.5,0,0), (0, 1, 0)])) e = Entity(position=(1,0), model=Mesh(vertices=((-.5,0,0), (.5,0,0), (0, 1, 0)))) Text(parent=e, text='triangle mesh\nwith verts as tuple of tuples', y=1, scale=5, origin=(0,-.5)) e = Entity(position=(0,-2), model=Mesh(vertices=[[-.5,0,0], [.5,0,0], [0, 1, 0]])) Text(parent=e, text='triangle mesh\nwith verts as list of lists', y=1, scale=5, origin=(0,-.5)) e = Entity(position=(1,-2), model=Mesh( vertices=([-.5,0,0], [.5,0,0], [0, 1, 0]) )) Text(parent=e, text='triangle mesh\nwith verts as tuple of lists', y=1, scale=5, origin=(0,-.5)) e = Entity(position=(0,-4), model=Mesh( vertices=[Vec3(-.5,0,0), Vec3(.5,0,0), Vec3(0, 1, 0)], )) Text(parent=e, text='triangle mesh\nwith verts as list Vec3', y=1, scale=5, origin=(0,-.5)) e = Entity(position=(1,-4), model=Mesh( vertices=[Vec3(-.5,0,0), Vec3(.5,0,0), Vec3(0, 1, 0)], triangles = [0,1,2], )) Text(parent=e, text='triangle mesh\nwith tris as flat list', y=1, scale=5, origin=(0,-.5)) e = Entity(position=(2.5,0), model=Mesh( vertices=[Vec3(-.5,0,0), Vec3(.5,0,0), Vec3(0, 1, 0)], triangles = [(0,1,2), (2,1,0)], # should be double sided )) Text(parent=e, text='triangle mesh\nwith tris as list of triangles', y=1, scale=5, origin=(0,-.5)) continious_line = Entity(position=(4,0), model=Mesh( vertices=(Vec3(0,0,0), Vec3(.6,.3,0), Vec3(1,1,0), Vec3(.6,1.7,0), Vec3(0,2,0)), mode='line', thickness=4, ), color=color.cyan) Text(parent=continious_line, text='continious_line', y=1, scale=5) line_segments = Entity(position=(4,-2), model=Mesh( vertices=(Vec3(0,0,0), Vec3(.6,.3,0), Vec3(1,1,0), Vec3(.6,1.7,0), Vec3(0,2,0)), triangles= ((0,1), (3,4)), mode='line', thickness=4, ), color=color.magenta) Text(parent=line_segments, text='line_segments', y=1, scale=5) points = Entity(position=(6,0), model=Mesh(vertices=(Vec3(0,0,0), Vec3(.6,.3,0), Vec3(1,1,0), Vec3(.6,1.7,0), Vec3(0,2,0)), mode='point', thickness=.05), color=color.red) Text(parent=points, text='points', y=1, scale=5) points_2d = Entity(position=(6,-2), model=Mesh(vertices=(Vec3(0,0,0), Vec3(.6,.3,0), Vec3(1,1,0), Vec3(.6,1.7,0), Vec3(0,2,0)), mode='point', thickness=10, render_points_in_3d=False), color=color.red) Text(parent=points_2d, text='points_2d', y=1, scale=5) quad = Entity( position=(8,0), model=Mesh( vertices=((0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0)), uvs=((1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0)), mode='triangle'), texture='shore' ) Text(parent=quad, text='quad_with_uvs', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(8,-2), model=Mesh( vertices=((0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0)), uvs=((1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0)), normals=[(-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0)], mode='triangle'), ) Text(parent=quad, text='quad_with_normals', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(8,-4), model=Mesh( vertices=((0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0)), uvs=((1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0)), normals=[(-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0)], mode='triangle'), ) Text(parent=quad, text='quad_with_usv_and_normals', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(8,-6), model=Mesh( vertices=((0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0)), uvs=((1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0)), normals=[(-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0), (-0.0, 0.0, -1.0)], colors=[color.red, color.yellow, color.green, color.cyan, color.blue, color.magenta], mode='triangle'), ) Text(parent=quad, text='quad_with_usv_and_normals_and_vertex_colors', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(10,0), model=Mesh( vertices=((-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0)), triangles=(0,1,2, 2,3,0), mode='triangle'), ) Text(parent=quad, text='triangles flat', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(10,-2), model=Mesh( vertices=((-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0)), triangles=((0,1,2), (2,3,0)), mode='triangle'), ) Text(parent=quad, text='triangles triplets', y=1, scale=5, origin=(0,-.5)) quad = Entity( position=(10,-4), model=Mesh( vertices=((-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0)), triangles=((0,1,2,3), (0,3,2)), mode='triangle'), ) Text(parent=quad, text='triangles quad + tri', y=1, scale=5, origin=(0,-.5)) copy_test = Entity(position=(12,0), model=copy(quad.model)) Text(parent=copy_test, text='copy_test', y=1, scale=5, origin=(0,-.5)) deepcopy_test = Entity(position=(12,-2), model=deepcopy(quad.model)) Text(parent=deepcopy_test, text='deepcopy_test', y=1, scale=5, origin=(0,-.5)) clear_test = Entity(position=(12,-4), model=deepcopy(quad.model)) clear_test.model.clear() Text(parent=clear_test, text='.clear() test', y=1, scale=5, origin=(0,-.5)) window.color = color.black EditorCamera() print(load_model('sphere', application.internal_models_compressed_folder, use_deepcopy=True).serialize()) app.run()


Shader

ursina/shader

Shader(name='untitled_shader', language=GLSL, vertex=default_vertex_shader, fragment=default_fragment_shader, geometry='', **kwargs)

Shader.CG = Panda3dShader.SL_Cg
Shader.GLSL = Panda3dShader.SL_GLSL
Shader.HLSL = Panda3dShader.SL_HLSL
Shader.SPIR_V = Panda3dShader.SL_SPIR_V
.name = name
.language = language
.vertex = vertex
.fragment = fragment
.geometry = geometry
.default_input = dict()
.continuous_input = dict()
.compiled = False

functions:
 compile(shader_includes=True)
 load(cls, language=Panda3dShader.SL_GLSL, vertex=None, fragment=None, geometry=None, **kwargs)

example:

from time import perf_counter t = perf_counter() from ursina import * from ursina import Ursina, Entity, held_keys, scene, EditorCamera app = Ursina() Entity(model='cube', shader=Shader()) EditorCamera() print('ttttttttttttt', perf_counter() - t) def input(key): if held_keys['control'] and key == 'r': reload_shaders() def reload_shaders(): for e in scene.entities: if hasattr(e, '_shader'): print('-------', e.shader) app.run()


Texture

ursina/texture

Texture(value, filtering='default')

.filtering = filtering

properties:
.name
.size
.width
.height
.pixels
.filtering
.repeat

functions:
 new(size, color=(255,255,255))
 get_pixel(x, y)
 get_pixels(start, end)
 set_pixel(x, y, color)
 apply()
 save(path)

example:

from ursina import * from ursina import texture_importer app = Ursina() ''' The Texture class rarely used manually but usually instantiated when assigning a texture to an Entity texture = Texture(path / PIL.Image / panda3d.core.Texture) A texture file can be a .png, .jpg or .psd. If it's a .psd it and no compressed version exists, it will compress it automatically. ''' e = Entity(model='quad', texture='brick') e.texture.set_pixel(0, 2, color.blue) e.texture.apply()


Light(Entity)

ursina/lights

Light(**kwargs)


properties:
.color

example:

from ursina import Ursina, EditorCamera, color, Vec3 app = Ursina() from ursina.shaders import lit_with_shadows_shader # you have to apply this shader to enties for them to receive shadows. EditorCamera() Entity(model='plane', scale=10, color=color.gray, shader=lit_with_shadows_shader) Entity(model='cube', y=1, shader=lit_with_shadows_shader, color=color.light_gray) light = DirectionalLight(shadows=True) light.look_at(Vec3(1,-1,1)) dont_cast_shadow = Entity(model='cube', y=1, shader=lit_with_shadows_shader, x=2, color=color.light_gray) dont_cast_shadow.hide(0b0001) unlit_entity = Entity(model='cube', y=1,x=-2, unlit=True, color=color.light_gray) bar = Entity(model='cube', position=(0,3,-2), shader=lit_with_shadows_shader, scale=(10,.2,.2), color=color.light_gray) app.run()


DirectionalLight(Light)

ursina/lights

DirectionalLight(shadows=True, **kwargs)

.shadow_map_resolution = Vec2(1024, 1024)
.shadows = shadows

properties:
.shadows

functions:
 update_bounds(entity=scene) update the shadow area to fit the bounds of target entity, defaulted to scene.
 look_at(target, axis='forward', up=None) up defaults to self.up

example:

from ursina import Ursina, EditorCamera, color, Vec3 app = Ursina() from ursina.shaders import lit_with_shadows_shader # you have to apply this shader to enties for them to receive shadows. EditorCamera() Entity(model='plane', scale=10, color=color.gray, shader=lit_with_shadows_shader) Entity(model='cube', y=1, shader=lit_with_shadows_shader, color=color.light_gray) light = DirectionalLight(shadows=True) light.look_at(Vec3(1,-1,1)) dont_cast_shadow = Entity(model='cube', y=1, shader=lit_with_shadows_shader, x=2, color=color.light_gray) dont_cast_shadow.hide(0b0001) unlit_entity = Entity(model='cube', y=1,x=-2, unlit=True, color=color.light_gray) bar = Entity(model='cube', position=(0,3,-2), shader=lit_with_shadows_shader, scale=(10,.2,.2), color=color.light_gray) app.run()


PointLight(Light)

ursina/lights

PointLight(**kwargs)


example:

from ursina import Ursina, EditorCamera, color, Vec3 app = Ursina() from ursina.shaders import lit_with_shadows_shader # you have to apply this shader to enties for them to receive shadows. EditorCamera() Entity(model='plane', scale=10, color=color.gray, shader=lit_with_shadows_shader) Entity(model='cube', y=1, shader=lit_with_shadows_shader, color=color.light_gray) light = DirectionalLight(shadows=True) light.look_at(Vec3(1,-1,1)) dont_cast_shadow = Entity(model='cube', y=1, shader=lit_with_shadows_shader, x=2, color=color.light_gray) dont_cast_shadow.hide(0b0001) unlit_entity = Entity(model='cube', y=1,x=-2, unlit=True, color=color.light_gray) bar = Entity(model='cube', position=(0,3,-2), shader=lit_with_shadows_shader, scale=(10,.2,.2), color=color.light_gray) app.run()


AmbientLight(Light)

ursina/lights

AmbientLight(**kwargs)


example:

from ursina import Ursina, EditorCamera, color, Vec3 app = Ursina() from ursina.shaders import lit_with_shadows_shader # you have to apply this shader to enties for them to receive shadows. EditorCamera() Entity(model='plane', scale=10, color=color.gray, shader=lit_with_shadows_shader) Entity(model='cube', y=1, shader=lit_with_shadows_shader, color=color.light_gray) light = DirectionalLight(shadows=True) light.look_at(Vec3(1,-1,1)) dont_cast_shadow = Entity(model='cube', y=1, shader=lit_with_shadows_shader, x=2, color=color.light_gray) dont_cast_shadow.hide(0b0001) unlit_entity = Entity(model='cube', y=1,x=-2, unlit=True, color=color.light_gray) bar = Entity(model='cube', position=(0,3,-2), shader=lit_with_shadows_shader, scale=(10,.2,.2), color=color.light_gray) app.run()


SpotLight(Light)

ursina/lights

SpotLight(**kwargs)


example:

from ursina import Ursina, EditorCamera, color, Vec3 app = Ursina() from ursina.shaders import lit_with_shadows_shader # you have to apply this shader to enties for them to receive shadows. EditorCamera() Entity(model='plane', scale=10, color=color.gray, shader=lit_with_shadows_shader) Entity(model='cube', y=1, shader=lit_with_shadows_shader, color=color.light_gray) light = DirectionalLight(shadows=True) light.look_at(Vec3(1,-1,1)) dont_cast_shadow = Entity(model='cube', y=1, shader=lit_with_shadows_shader, x=2, color=color.light_gray) dont_cast_shadow.hide(0b0001) unlit_entity = Entity(model='cube', y=1,x=-2, unlit=True, color=color.light_gray) bar = Entity(model='cube', position=(0,3,-2), shader=lit_with_shadows_shader, scale=(10,.2,.2), color=color.light_gray) app.run()


Circle(Mesh)

ursina/models/procedural/circle

Circle(resolution=16, radius=.5, mode='ngon', **kwargs)

.vertices = list()

example:

app = Ursina() e = Entity(model=Circle(8, mode='line', thickness=10), color=color.hsv(60,1,1,.3)) print(e.model) origin = Entity(model='quad', color=color.orange, scale=(.05, .05)) ed = EditorCamera(rotation_speed = 200, panning_speed=200) app.run()


Plane(Mesh)

ursina/models/procedural/plane

Plane(subdivisions=(1,1), mode='triangle', **kwargs)

.vertices, self.triangles = list(), list()
.uvs = list()

example:

app = Ursina() front = Entity(model=Plane(subdivisions=(3,6)), texture='brick', rotation_x=-90) _ed = EditorCamera() Entity(model='cube', color=color.green, scale=.05) app.run()


Grid(Mesh)

ursina/models/procedural/grid

Grid(width, height, mode='line', thickness=1, **kwargs)

.width = width
.height = height

example:

app = Ursina() Entity(model=Grid(2, 6)) app.run()


Cone(Mesh)

ursina/models/procedural/cone

Cone(resolution=4, radius=.5, height=1, add_bottom=True, mode='triangle', **kwargs)


example:

from ursina import Ursina, Entity, color, EditorCamera app = Ursina() e = Entity(model=Cone(3), texture='brick') origin = Entity(model='quad', color=color.orange, scale=(.05, .05)) ed = EditorCamera() app.run()


Cylinder(Pipe)

ursina/models/procedural/cylinder

Cylinder(resolution=8, radius=.5, start=0, height=1, direction=(0,1,0), mode='triangle', **kwargs)


example:

app = Ursina() Entity(model=Cylinder(6, start=-.5), color=color.hsv(60,1,1,.3)) origin = Entity(model='quad', color=color.orange, scale=(5, .05)) ed = EditorCamera(rotation_speed = 200, panning_speed=200) app.run()


Pipe(Mesh)

ursina/models/procedural/pipe

Pipe(base_shape=Quad, origin=(0,0), path=((0,0,0),(0,1,0)), thicknesses=((1,1),), color_gradient=None, look_at=True, cap_ends=True, mode='triangle', **kwargs)

.base_shape = base_shape
.origin = origin
.path = path
.thicknesses = thicknesses
.look_at = look_at
.cap_ends = cap_ends
.mode = mode
.color_gradient = color_gradient
.prev = None
.curr = None

functions:
 generate()

example:

app = Ursina() path = [e*5 for e in Circle().vertices] path.append(path[0]) e = Entity(model=Pipe(path=path, cap_ends=False)) print(len(e.model.vertices), len(e.model.colors)) EditorCamera() origin = Entity(model='cube', color=color.magenta) origin.scale *= .25 app.run()


Terrain(Mesh)

ursina/models/procedural/terrain

Terrain(heightmap='', height_values=None, gradient=None, skip=1, **kwargs)

.width = len(self.height_values)
.depth = len(self.height_values[0])
.aspect_ratio = self.width / self.depth
.gradient = gradient

functions:
 generate()

example:

app = Ursina() '''Terrain using an RGB texture as input''' terrain_from_heightmap_texture = Entity(model=Terrain('heightmap_1', skip=8), scale=(40,5,20), texture='heightmap_1') ''' I'm just getting the height values from the previous terrain as an example, but you can provide your own. It should be a list of lists, where each value is between 0 and 255. ''' hv = terrain_from_heightmap_texture.model.height_values.tolist() terrain_from_list = Entity(model=Terrain(height_values=hv), scale=(40,5,20), texture='heightmap_1', x=40) terrain_bounds = Entity(model='wireframe_cube', origin_y=-.5, scale=(40,5,20), color=color.lime) def input(key): if key == 'space': # randomize the terrain terrain_from_list.model.height_values = [[random.uniform(0,255) for a in column] for column in terrain_from_list.model.height_values] terrain_from_list.model.generate() EditorCamera(rotation_x=90) camera.orthographic = True Sky() player = Entity(model='sphere', color=color.azure, scale=.2, origin_y=-.5) def update(): direction = Vec3(held_keys['d'] - held_keys['a'], 0, held_keys['w'] - held_keys['s']).normalized() player.position += direction * time.dt * 8 y = terraincast(player.world_position, terrain_from_list, terrain_from_list.model.height_values) if y is not None: player.y = y app.run()


input_handler

ursina/input_handler

.held_keys = defaultdict(lambda: 0)
.rebinds = dict()

functions:
 bind(original_key, alternative_key)
 unbind(key)
 rebind(to_key, from_key)
 input(key)
 get_combined_key(key)

example:

from ursina import * from ursina import Ursina, input_handler app = Ursina(borderless=False) input_handler.bind('z', 'w') # 'z'-key will now be registered as 'w'-key input_handler.bind('left mouse down', 'attack') # 'left mouse down'-key will now send 'attack'to input functions input_handler.bind('gamepad b', 'attack') # 'gamepad b'-key will now be registered as 'attack'-key def input(key): print('got key:', key) if key == 'attack': destroy(Entity(model='cube', color=color.blue), delay=.2) app.run()


mesh_importer

ursina/mesh_importer

.blender_scenes = dict()

functions:
 load_model(name, folder=Func(getattr, application, 'asset_folder'), file_types=('.bam', '.ursinamesh', '.obj', '.glb', '.gltf', '.blend'), use_deepcopy=False, gltf_no_srgb=Func(getattr, application, 'gltf_no_srgb'))
 load_blender_scene(name, path=Func(getattr, application, 'asset_folder'), reload=False, skip_hidden=True, models_only=False, uvs=True, vertex_colors=True, normals=True, triangulate=True, decimals=4)
 get_blender(blend_file) try to get a matching blender version in case we have multiple blender version installed
 blend_to_obj(blend_file:Path, out_folder=Func(getattr, application, 'compressed_models_folder'), export_mtl=True)
 obj_to_ursinamesh(folder=Func(getattr, application, 'compressed_models_folder'), out_folder=Func(getattr, application, 'compressed_models_folder'), name='*', return_mesh=True, save_to_file=False, delete_obj=False)
 blend_to_obj_fast(model_name=None, write_to_disk=False)
 ursina_mesh_to_obj(mesh, name='', out_path=Func(getattr, application, 'compressed_models_folder'), max_decimals=5, flip_faces=True)
 compress_internal()

example:

from ursina import * from ursina import Ursina, Entity, EditorCamera, Sky app = Ursina() m = obj_to_ursinamesh(folder=application.asset_folder.parent / 'samples', name='procedural_rock_0', save_to_file=False, delete_obj=False) print(m.serialize()) EditorCamera() Sky(texture='sky_sunset') app.run()


texture_importer

ursina/texture_importer

.file_types = ('.tif', '.jpg', '.jpeg', '.png', '.gif')
.folders = [ folder search order
.textureless = False

functions:
 load_texture(name, path=None, use_cache=True, filtering='default')
 compress_textures(name='')

example:

from ursina import * app = Ursina() Entity(model='quad', texture='white_cube') app.run()


string_utilities

ursina/string_utilities


functions:
 camel_to_snake(value)
 snake_to_camel(value)
 multireplace(string, replacements, ignore_case=False)
 printvar(var)
 print_info(str, *args)
 print_warning(str, *args)

example:

print(camel_to_snake('CamelToSnake')) print(snake_to_camel('snake_to_camel')) printvar('test')


Animation(Sprite)

ursina/prefabs/animation

Animation(name, fps=12, loop=True, autoplay=True, frame_times=None, **kwargs)

.sequence = Sequence(loop=loop, auto_destroy=False)
.frame_times = frame_times
.is_playing = False
.autoplay = autoplay

properties:
.durationget the duration of the animation. you can't set it. to do so, change the fps instead.

functions:
 start()
 pause()
 resume()
 finish()

example:

app = Ursina() ''' Loads an image sequence as a frame animation. Consider using SpriteSheetAnimation instead if possible. So if you have some frames named image_000.png, image_001.png, image_002.png and so on, you can load it like this: Animation('image') You can also load a .gif by including the file type: Animation('image.gif') ''' a = Animation('ursina_wink') app.run()


FrameAnimation3d(Entity)

ursina/prefabs/frame_animation_3d

FrameAnimation3d(name, fps=12, loop=True, autoplay=True, frame_times=None, auto_destroy=False, **kwargs)

.play = self.start
.frames = [Entity(parent=self, model=e.stem, enabled=False, add_to_scene_entities=False) for e in model_names]
.sequence = Sequence(loop=loop, auto_destroy=auto_destroy)
.autoplay = autoplay

properties:
.duration
.current_frame

functions:
 start()
 pause()
 resume()
 finish()
 on_destroy()

example:

application.asset_folder = application.asset_folder.parent.parent / 'samples' app = Ursina() ''' Loads an obj sequence as a frame animation. So if you have some frames named run_cycle_000.obj, run_cycle_001.obj, run_cycle_002.obj and so on, you can load it like this: FrameAnimation3d('run_cycle_') ''' FrameAnimation3d('blob_animation_')


SpriteSheetAnimation(Entity)

ursina/prefabs/sprite_sheet_animation

SpriteSheetAnimation(texture, animations, tileset_size=[4,1], fps=12, model='quad', autoplay=True, **kwargs)

.animations = animations should be a dict

functions:
 play_animation(animation_name)

example:

''' Sprite sheet coordinate system: (0,3) (1,3) (2,3) (3,3) (0,2) (1,2) (2,2) (3,2) (0,1) (1,1) (2,1) (3,1) (0,0) (1,0) (2,0) (3,0) ''' from ursina import Ursina app = Ursina() player_graphics = SpriteSheetAnimation('sprite_sheet', tileset_size=(4,4), fps=6, animations={ 'idle' : ((0,0), (0,0)), # makes an animation from (0,0) to (0,0), a single frame 'walk_up' : ((0,0), (3,0)), # makes an animation from (0,0) to (3,0), the bottom row 'walk_right' : ((0,1), (3,1)), 'walk_left' : ((0,2), (3,2)), 'walk_down' : ((0,3), (3,3)), } ) def input(key): if key == 'w': player_graphics.play_animation('walk_up') elif key == 's': player_graphics.play_animation('walk_down') elif key == 'd': player_graphics.play_animation('walk_right') elif key == 'a': player_graphics.play_animation('walk_left') Entity(model='quad', texture='sprite_sheet', x=-1) app.run()


Animator

ursina/prefabs/animator

Animator(animations=None, start_state='', pause_disabled=True)

.animations = animations dict
.pause_disabled = pause_disabled
.start_state = start_state
.state = start_state

properties:
.state

example:

app = Ursina() anim = Animation('ursina_wink', loop=True, autoplay=False) a = Animator( animations = { 'lol' : Entity(model='cube', color=color.red), 'yo' : Entity(model='cube', color=color.green, x=1), 'help' : anim, } ) a.state = 'yo' Text('press <red>1<default>, <green>2<default> or <violet>3<default> to toggle different animator states', origin=(0,-.5), y=-.4) def input(key): if key == '1': a.state = 'lol' if key == '2': a.state = 'yo' if key == '3': a.state = 'help' print(anim.enabled) app.run()


TrailRenderer(Entity)

ursina/prefabs/trail_renderer

TrailRenderer(size=[1,.01], segments=8, min_spacing=.05, fade_speed=0, color_gradient=[color.white, color.clear], **kwargs)

.renderer = Entity( model = Pipe( base_shape = Quad(segments=0, scale=size), path=[Vec3(0,0,i) for i in range(2)], color_gradient=color_gradient, static=False, cap_ends=False, ),
.segments = segments
.update_step = .05
.min_spacing = min_spacing
.fade_speed = fade_speed
.on_enable = self.renderer.enable
.on_disable = self.renderer.disable

functions:
 update()
 on_destroy()

example:

app = Ursina(vsync=False) window.color = color.black mouse.visible = False player = Entity(z=1) player.graphics = Entity(parent=player, scale=.1, model='circle') pivot = Entity() trail_renderers = [] for i in range(1): tr = TrailRenderer(size=[1,1], segments=8, min_spacing=.05, fade_speed=0, parent=player, color_gradient=[color.magenta, color.cyan.tint(-.5), color.clear]) trail_renderers.append(tr) def update(): player.position = lerp(player.position, mouse.position*10, time.dt*4) def input(key): if key == 'escape': for e in trail_renderers: e.enabled = not e.enabled if key == 'space': destroy(pivot) EditorCamera() Entity(model=Grid(8,8), rotation_x=90, color=color.gray, y=-3, scale=8) app.run()


curve

ursina/curve


functions:
 linear(t)
 in_sine(t)
 out_sine(t)
 in_out_sine(t)
 in_quad(t)
 out_quad(t)
 in_out_quad(t)
 in_cubic(t)
 out_cubic(t)
 in_out_cubic(t)
 in_quart(t)
 out_quart(t)
 in_out_quart(t)
 in_quint(t)
 out_quint(t)
 in_out_quint(t)
 in_expo(t)
 out_expo(t)
 in_out_expo(t)
 in_circ(t)
 out_circ(t)
 in_out_circ(t)
 in_back(t, magnitude=1.70158)
 out_back(t, magnitude=1.70158)
 in_out_back(t, magnitude=1.70158)
 in_elastic(t, magnitude=.7)
 out_elastic(t, magnitude=.7)
 in_out_elastic(t, magnitude=0.65)
 out_bounce(t)
 in_bounce(t)
 in_out_bounce(t)
 zero(t)
 one(t)
 combine(curve_a, curve_b, split_at)
 reverse(curve_function)
 {e}_boomerang(t)

example:

'''Draws a sheet with every curve and its name''' from ursina import * from ursina import Ursina, camera, window, curve, Entity, Mesh, Text, color app = Ursina() camera.orthographic = True camera.fov = 16 camera.position = (9, 6) window.color = color.black def render_curve(curve_function, name): curve_renderer = Entity(model=Mesh(vertices=[Vec3(i / 31, curve_function(i / 31), 0) for i in range(32)], mode='line', thickness=2), color=color.light_gray) label = Text(parent=curve_renderer, text=name, scale=8, color=color.gray, y=-.1) return curve_renderer c = CubicBezier(0, .5, 1, .5) print('-----------', c.calculate(.23)) window.exit_button.visible = False window.fps_counter.enabled = False custom_curve = combine(linear, reverse(in_expo), .25) render_curve(custom_curve, 'custom_curve') EditorCamera() app.run() ''' These are used by Entity when animating, like this: e = Entity() e.animate_y(1, curve=curve.in_expo) e2 = Entity(x=1.5) e2.animate_y(1, curve=curve.CubicBezier(0,.7,1,.3)) '''


ursinamath

ursinamath


functions:
 distance(a, b)
 distance_2d(a, b)
 distance_xz(a, b)
 lerp(a, b, t)
 inverselerp(a, b, t)
 lerp_angle(start_angle, end_angle, t)
 slerp(q1, q2, t)
 clamp(value, floor, ceiling)
 round_to_closest(value, step=0)
 rotate_around_point_2d(point, origin, deg)
 world_position_to_screen_position(point): # get screen position(ui space) get screen position(ui space) from world space.
 sum(l)
 make_gradient(index_color_dict) returns a list of 256 colors
 sample_gradient(list_of_values, t): # distribute list_of_values equally on a line and get the interpolated value at t (0-1) distribute list_of_values equally on a line and get the interpolated value at t (0-1).

example:

from ursina import * app = Ursina() e1 = Entity(position = (0,0,0)) e2 = Entity(position = (0,1,1)) distance(e1, e2) distance_xz(e1, e2.position) between_color = lerp(color.lime, color.magenta, .5) print(between_color) print(lerp((0,0), (0,1), .5)) print(lerp(Vec2(0,0), Vec2(0,1), .5)) print(lerp([0,0], [0,1], .5)) print(round(Vec3(.38, .1351, 353.26), 2)) p = (1,0) print(p, 'rotated ->', rotate_around_point_2d(p, (0,0), 90)) app.run()


Vec2(PandaVec2)

ursina/vec2


properties:
.x
.y
.X
.Y
.yx

example:

a = Vec2(1,1) print(a) print(round(a))


Vec3(PandaVec3)

ursina/vec3


properties:
.x
.y
.z
.xy
.yx
.xz
.yz
.X
.Y
.Z

example:

a = Vec3(1,0,0) * 2 a = Vec3(1,0,1) * Vec3(2,1,2) b = Vec3(1.252352324,0,1) b += Vec3(0,1)


Vec4(PandaVec4)

ursina/vec4


example:

a = Vec4(1,0,0,0) * 2 a = Vec4(1,0,1,1) * Vec4(2,1,2,3) b = Vec4(1.252352324,0,1,.2) b += Vec4(0,1)


CubicBezier

ursina/curve

CubicBezier(a, b, c, d)

.a = a
.b = b
.c = c
.d = d
.cx = 3.0 * a
.bx = 3.0 * (c - a) - self.cx
.ax = 1.0 - self.cx - self.bx
.cy = 3.0 * b
.by = 3.0 * (d - b) - self.cy
.ay = 1.0 - self.cy - self.by

functions:
 sample_curve_x(t)
 sample_curve_y(t)
 sample_curve_derivative_x(t)
 calculate(x, epsilon=.0001)
 solve_curve_x(t, epsilon=.0001)

example:

'''Draws a sheet with every curve and its name''' from ursina import * from ursina import Ursina, camera, window, curve, Entity, Mesh, Text, color app = Ursina() camera.orthographic = True camera.fov = 16 camera.position = (9, 6) window.color = color.black def render_curve(curve_function, name): curve_renderer = Entity(model=Mesh(vertices=[Vec3(i / 31, curve_function(i / 31), 0) for i in range(32)], mode='line', thickness=2), color=color.light_gray) label = Text(parent=curve_renderer, text=name, scale=8, color=color.gray, y=-.1) return curve_renderer c = CubicBezier(0, .5, 1, .5) print('-----------', c.calculate(.23)) window.exit_button.visible = False window.fps_counter.enabled = False custom_curve = combine(linear, reverse(in_expo), .25) render_curve(custom_curve, 'custom_curve') EditorCamera() app.run() ''' These are used by Entity when animating, like this: e = Entity() e.animate_y(1, curve=curve.in_expo) e2 = Entity(x=1.5) e2.animate_y(1, curve=curve.CubicBezier(0,.7,1,.3)) '''


ursinastuff

ursinastuff


functions:
 invoke(function, *args, **kwargs) reserved keywords: 'delay', 'unscaled'
 after(delay, unscaled=True) function for @after decorator. Use the docrator, not this.
 reset_cooldown()
 wrapper(*args, **kwargs)
 destroy(entity, delay=0)
 chunk_list(target_list, chunk_size)
 flatten_list(target_list)
 flatten_completely(target_list)
 enumerate_2d(target_2d_list): # usage: for (x, y), value in enumerate_2d(my_2d_list) usage: for (x, y), value in enumerate_2d(my_2d_list)
 enumerate_3d(target_3d_list): # usage: for (x, y, z), value in enumerate_3d(my_3d_list) usage: for (x, y, z), value in enumerate_3d(my_3d_list)
 rotate_2d_list(target_2d_list)
 list_2d_to_string(target_2d_list, characters='.#') '):
 size_list() return a list of current python objects sorted by size
 find_sequence(name, file_types, folders) find frame_0, frame_1, frame_2 and so on
 import_all_classes(path=application.asset_folder, debug=False)
 print_on_screen(text, position=(0,0), origin=(-.5,.5), scale=1, duration=1)

example:

from ursina import * app = Ursina() list_2d = [ [1,0,0,1, 0, 1,1,1,0, 0, 1,1,1,1, 0, 0,1,0,0], [1,0,0,1, 0, 1,0,0,1, 0, 1,1,1,0, 0, 0,1,0,0], [1,0,0,1, 0, 1,1,1,0, 0, 0,0,0,1, 0, 0,1,0,0], [0,1,1,0, 0, 1,0,0,1, 0, 1,1,1,1, 0, 0,1,0,0], ] print(list_2d_to_string(list_2d)) a = Audio('sine') a.play() destroy(a, delay=1) app.run()


Sequence

ursina/sequence

Sequence(*args, **kwargs)

.args = list(args)
.t = 0
.time_step = Sequence.default_time_step
.duration = 0
.funcs = []
.func_call_time = []
.func_finished_statuses = []
.paused = False
.entity = None you can assign this to make the sequence pause when the entity is disabled or .ignore is True

properties:
.finished

functions:
 generate()
 append(arg, regenerate=True)
 extend(list)
 start()
 pause()
 resume()
 finish()
 kill()
 update()

example:

from ursina import * from ursina import Ursina, Entity app = Ursina() e = Entity(model='quad') def some_func(): print('some_func') s = Sequence( some_func, 1, Func(print, 'one'), Func(e.fade_out, duration=1), Wait(1), loop=True ) for i in range(8): s.append(Func(print, i)) s.append(Wait(.2)) print(s) def input(key): actions = {'s' : s.start, 'f' : s.finish, 'p' : s.pause, 'r' : s.resume} if key in actions: actions[key]() app.run()


Func

ursina/sequence

Func(func, *args, **kwargs)

.func = func
.args = args
.kwargs = kwargs

example:

from ursina import * from ursina import Ursina, Entity app = Ursina() e = Entity(model='quad') def some_func(): print('some_func') s = Sequence( some_func, 1, Func(print, 'one'), Func(e.fade_out, duration=1), Wait(1), loop=True ) for i in range(8): s.append(Func(print, i)) s.append(Wait(.2)) print(s) def input(key): actions = {'s' : s.start, 'f' : s.finish, 'p' : s.pause, 'r' : s.resume} if key in actions: actions[key]() app.run()


Keys(Enum)

ursina/input_handler

Keys.left_mouse_down = 'left mouse down'
Keys.left_mouse_up = 'left mouse up'
Keys.middle_mouse_down = 'middle mouse down'
Keys.middle_mouse_up = 'middle mouse up'
Keys.right_mouse_down = 'right mouse down'
Keys.right_mouse_up = 'right mouse up'
Keys.double_click = 'double click'
Keys.scroll_up = 'scroll up'
Keys.scroll_down = 'scroll down'
Keys.left_arrow = 'left arrow'
Keys.left_arrow_up = 'left arrow up'
Keys.up_arrow = 'up arrow'
Keys.up_arrow_up = 'up arrow up'
Keys.down_arrow = 'down arrow'
Keys.down_arrow_up = 'down arrow up'
Keys.right_arrow = 'right arrow'
Keys.right_arrow_up = 'right arrow up'
Keys.left_control = 'left control'
Keys.right_control = 'right control'
Keys.left_shift = 'left shift'
Keys.right_shift = 'right shift'
Keys.left_alt = 'left alt'
Keys.right_alt = 'right alt'
Keys.left_control_up = 'left control up'
Keys.right_control_up = 'right control up'
Keys.left_shift_up = 'left shift up'
Keys.right_shift_up = 'right shift up'
Keys.left_alt_up = 'left alt up'
Keys.right_alt_up = 'right alt up'
Keys.page_down = 'page down'
Keys.page_down_up = 'page down up'
Keys.page_up = 'page up'
Keys.page_up_up = 'page up up'
Keys.enter = 'enter'
Keys.backspace = 'backspace'
Keys.escape = 'escape'
Keys.tab = 'tab'
Keys.gamepad_left_stick_x = 'gamepad left stick x' # held_keys only
Keys.gamepad_left_stick_y = 'gamepad left stick y' # held_keys only
Keys.gamepad_right_stick_x = 'gamepad right stick x' # held_keys only
Keys.gamepad_right_stick_y = 'gamepad right stick y' # held_keys only
Keys.gamepad_left_trigger = 'gamepad left trigger' # held_keys only
Keys.gamepad_right_trigger = 'gamepad right trigger' # held_keys only
Keys.gamepad_a = 'gamepad a'
Keys.gamepad_a_up = 'gamepad a up'
Keys.gamepad_b = 'gamepad b'
Keys.gamepad_b_up = 'gamepad b up'
Keys.gamepad_x = 'gamepad x'
Keys.gamepad_x_up = 'gamepad x up'
Keys.gamepad_y = 'gamepad y'
Keys.gamepad_y_up = 'gamepad y up'
Keys.gamepad_left_stick = 'gamepad left stick'
Keys.gamepad_left_stick_up = 'gamepad left stick up'
Keys.gamepad_right_stick = 'gamepad right stick'
Keys.gamepad_right_stick_up = 'gamepad right stick up'
Keys.gamepad_back = 'gamepad back'
Keys.gamepad_back_up = 'gamepad back up'
Keys.gamepad_start = 'gamepad start'
Keys.gamepad_dpad_down = 'gamepad dpad down'
Keys.gamepad_dpad_down_up = 'gamepad dpad down up'
Keys.gamepad_dpad_up = 'gamepad dpad up'
Keys.gamepad_dpad_up_up = 'gamepad dpad up up'
Keys.gamepad_dpad_left = 'gamepad dpad left'
Keys.gamepad_dpad_left_up = 'gamepad dpad left up'
Keys.gamepad_dpad_right = 'gamepad dpad right'
Keys.gamepad_dpad_right_up = 'gamepad dpad right up'
Keys.gamepad_left_shoulder = 'gamepad left shoulder'
Keys.gamepad_left_shoulder_up = 'gamepad left shoulder up'
Keys.gamepad_right_shoulder = 'gamepad right shoulder'
Keys.gamepad_right_shoulder_up = 'gamepad right shoulder up'

functions:
 bind(original_key, alternative_key)
 unbind(key)
 rebind(to_key, from_key)
 input(key)
 get_combined_key(key)

example:

from ursina import * from ursina import Ursina, input_handler app = Ursina(borderless=False) input_handler.bind('z', 'w') # 'z'-key will now be registered as 'w'-key input_handler.bind('left mouse down', 'attack') # 'left mouse down'-key will now send 'attack'to input functions input_handler.bind('gamepad b', 'attack') # 'gamepad b'-key will now be registered as 'attack'-key def input(key): print('got key:', key) if key == 'attack': destroy(Entity(model='cube', color=color.blue), delay=.2) app.run()


raycast

ursina/raycast


functions:
 raycast(origin, direction:Vec3=(0,0,1), distance=9999, traverse_target:Entity=scene, ignore:list=None, debug=False, color=color.white)

example:

from ursina import * from ursina import Ursina, Entity, held_keys, time, duplicate, camera, EditorCamera app = Ursina() ''' Casts a ray from *origin*, in *direction*, with length *distance* and returns a HitInfo containing information about what it hit. This ray will only hit entities with a collider. Use optional *traverse_target* to only be able to hit a specific entity and its children/descendants. Use optional *ignore* list to ignore certain entities. Setting debug to True will draw the line on screen. Example where we only move if a wall is not hit: ''' class Player(Entity): def update(self): self.direction = Vec3( self.forward * (held_keys['w'] - held_keys['s']) + self.right * (held_keys['d'] - held_keys['a']) ).normalized() # get the direction we're trying to walk in. origin = self.world_position + (self.up*.5) # the ray should start slightly up from the ground so we can walk up slopes or walk over small objects. hit_info = raycast(origin , self.direction, ignore=(self,), distance=.5, debug=False) if not hit_info.hit: self.position += self.direction * 5 * time.dt else: print(hit_info.entity) Player(model='cube', origin_y=-.5, color=color.orange) wall_left = Entity(model='cube', collider='box', scale_y=3, origin_y=-.5, color=color.azure, x=-4) wall_right = duplicate(wall_left, x=4) camera.y = 2 app.run()


terraincast

ursina/terraincast


functions:
 terraincast(world_position, terrain_entity, height_values=None, return_normals=False) uses x and z to return y on terrain.

example:

app = Ursina() terrain_entity = Entity(model=Terrain('heightmap_1', skip=8), scale=(40, 5, 20), texture='heightmap_1') player = Entity(model='sphere', color=color.azure, scale=.2, origin_y=-.5) hv = terrain_entity.model.height_values def update(): direction = Vec3(held_keys['d'] - held_keys['a'], 0, held_keys['w'] - held_keys['s']).normalized() player.position += direction * time.dt * 4 y = terraincast(player.world_position, terrain_entity, hv) if y is not None: player.y = y EditorCamera() from ursina.shaders import ssao_shader camera.shader = ssao_shader Sky() app.run()


boxcast

ursina/boxcast


functions:
 boxcast(origin, direction=(0,0,1), distance=9999, thickness=(1,1), traverse_target=scene, ignore:list=None, debug=False) similar to raycast, but with width and height

example:

from ursina import Ursina, held_keys, camera, duplicate, raycast, time, EditorCamera app = Ursina() ''' Casts a ray from *origin*, in *direction*, with length *distance* and returns a HitInfo containing information about what it hit. This ray will only hit entities with a collider. Use optional *traverse_target* to only be able to hit a specific entity and its children/descendants. Use optional *ignore* list to ignore certain entities. Setting debug to True will draw the line on screen. Example where we only move if a wall is not hit: ''' class Player(Entity): def update(self): self.direction = Vec3( self.forward * (held_keys['w'] - held_keys['s']) + self.right * (held_keys['d'] - held_keys['a']) ).normalized() # get the direction we're trying to walk in. origin = self.world_position + (self.up*.5) # the ray should start slightly up from the ground so we can walk up slopes or walk over small objects. hit_info = raycast(origin , self.direction, ignore=(self,), distance=.5, debug=False) if not hit_info.hit: self.position += self.direction * 5 * time.dt Player(model='cube', origin_y=-.5, color=color.orange) wall_left = Entity(model='cube', collider='box', scale_y=3, origin_y=-.5, color=color.azure, x=-4) wall_right = duplicate(wall_left, x=4) camera.y = 2 app.run()


Collider

ursina/collider

Collider(entity, shape)

.collision_node = CollisionNode('CollisionNode')
.shape = shape
.node_path = entity.attachNewNode(self.collision_node)

properties:
.visible

functions:
 remove()

example:

from ursina import * from ursina import Ursina, Entity, Pipe, Circle, Button, scene, EditorCamera, color app = Ursina() e = Button(parent=scene, model='sphere', x=2) e.collider = 'box' # add BoxCollider based on entity's bounds. e.collider = 'sphere' # add SphereCollider based on entity's bounds. e.collider = 'capsule' # add CapsuleCollider based on entity's bounds. e.collider = 'mesh' # add MeshCollider matching the entity's model. e.collider = 'file_name' # load a model and us it as MeshCollider. e.collider = e.model # copy target model/Mesh and use it as MeshCollider. e.collider = BoxCollider(e, center=Vec3(0,0,0), size=Vec3(1,1,1)) # add BoxCollider at custom positions and size. e.collider = SphereCollider(e, center=Vec3(0,0,0), radius=.75) # add SphereCollider at custom positions and size. e.collider = CapsuleCollider(e, center=Vec3(0,0,0), height=3, radius=.75) # add CapsuleCollider at custom positions and size. e.collider = MeshCollider(e, mesh=e.model, center=Vec3(0,0,0)) # add MeshCollider with custom shape and center. m = Pipe(base_shape=Circle(6), thicknesses=(1, .5)) e = Button(parent=scene, model='cube', collider='mesh', color=color.red, highlight_color=color.yellow) sphere = Button(parent=scene, model='icosphere', collider='mesh', color=color.red, highlight_color=color.yellow, x=4) EditorCamera() def input(key): if key == 'c': e.collider = None app.run()


BoxCollider(Collider)

ursina/collider

BoxCollider(entity, center=(0,0,0), size=(1,1,1))

.center = center
.size = size

example:

from ursina import * from ursina import Ursina, Entity, Pipe, Circle, Button, scene, EditorCamera, color app = Ursina() e = Button(parent=scene, model='sphere', x=2) e.collider = 'box' # add BoxCollider based on entity's bounds. e.collider = 'sphere' # add SphereCollider based on entity's bounds. e.collider = 'capsule' # add CapsuleCollider based on entity's bounds. e.collider = 'mesh' # add MeshCollider matching the entity's model. e.collider = 'file_name' # load a model and us it as MeshCollider. e.collider = e.model # copy target model/Mesh and use it as MeshCollider. e.collider = BoxCollider(e, center=Vec3(0,0,0), size=Vec3(1,1,1)) # add BoxCollider at custom positions and size. e.collider = SphereCollider(e, center=Vec3(0,0,0), radius=.75) # add SphereCollider at custom positions and size. e.collider = CapsuleCollider(e, center=Vec3(0,0,0), height=3, radius=.75) # add CapsuleCollider at custom positions and size. e.collider = MeshCollider(e, mesh=e.model, center=Vec3(0,0,0)) # add MeshCollider with custom shape and center. m = Pipe(base_shape=Circle(6), thicknesses=(1, .5)) e = Button(parent=scene, model='cube', collider='mesh', color=color.red, highlight_color=color.yellow) sphere = Button(parent=scene, model='icosphere', collider='mesh', color=color.red, highlight_color=color.yellow, x=4) EditorCamera() def input(key): if key == 'c': e.collider = None app.run()


SphereCollider(Collider)

ursina/collider

SphereCollider(entity, center=(0,0,0), radius=.5)

.center = center
.radius = radius

example:

from ursina import * from ursina import Ursina, Entity, Pipe, Circle, Button, scene, EditorCamera, color app = Ursina() e = Button(parent=scene, model='sphere', x=2) e.collider = 'box' # add BoxCollider based on entity's bounds. e.collider = 'sphere' # add SphereCollider based on entity's bounds. e.collider = 'capsule' # add CapsuleCollider based on entity's bounds. e.collider = 'mesh' # add MeshCollider matching the entity's model. e.collider = 'file_name' # load a model and us it as MeshCollider. e.collider = e.model # copy target model/Mesh and use it as MeshCollider. e.collider = BoxCollider(e, center=Vec3(0,0,0), size=Vec3(1,1,1)) # add BoxCollider at custom positions and size. e.collider = SphereCollider(e, center=Vec3(0,0,0), radius=.75) # add SphereCollider at custom positions and size. e.collider = CapsuleCollider(e, center=Vec3(0,0,0), height=3, radius=.75) # add CapsuleCollider at custom positions and size. e.collider = MeshCollider(e, mesh=e.model, center=Vec3(0,0,0)) # add MeshCollider with custom shape and center. m = Pipe(base_shape=Circle(6), thicknesses=(1, .5)) e = Button(parent=scene, model='cube', collider='mesh', color=color.red, highlight_color=color.yellow) sphere = Button(parent=scene, model='icosphere', collider='mesh', color=color.red, highlight_color=color.yellow, x=4) EditorCamera() def input(key): if key == 'c': e.collider = None app.run()


MeshCollider(Collider)

ursina/collider

MeshCollider(entity, mesh=None, center=(0,0,0))

.center = center
.collision_polygons = []

functions:
 remove()

example:

from ursina import * from ursina import Ursina, Entity, Pipe, Circle, Button, scene, EditorCamera, color app = Ursina() e = Button(parent=scene, model='sphere', x=2) e.collider = 'box' # add BoxCollider based on entity's bounds. e.collider = 'sphere' # add SphereCollider based on entity's bounds. e.collider = 'capsule' # add CapsuleCollider based on entity's bounds. e.collider = 'mesh' # add MeshCollider matching the entity's model. e.collider = 'file_name' # load a model and us it as MeshCollider. e.collider = e.model # copy target model/Mesh and use it as MeshCollider. e.collider = BoxCollider(e, center=Vec3(0,0,0), size=Vec3(1,1,1)) # add BoxCollider at custom positions and size. e.collider = SphereCollider(e, center=Vec3(0,0,0), radius=.75) # add SphereCollider at custom positions and size. e.collider = CapsuleCollider(e, center=Vec3(0,0,0), height=3, radius=.75) # add CapsuleCollider at custom positions and size. e.collider = MeshCollider(e, mesh=e.model, center=Vec3(0,0,0)) # add MeshCollider with custom shape and center. m = Pipe(base_shape=Circle(6), thicknesses=(1, .5)) e = Button(parent=scene, model='cube', collider='mesh', color=color.red, highlight_color=color.yellow) sphere = Button(parent=scene, model='icosphere', collider='mesh', color=color.red, highlight_color=color.yellow, x=4) EditorCamera() def input(key): if key == 'c': e.collider = None app.run()


Sky(Entity)

ursina/prefabs/sky

Sky(**kwargs)

Sky.instances = []

functions:
 update()
 input(key)


EditorCamera(Entity)

ursina/prefabs/editor_camera

EditorCamera(**kwargs)

.rotation_speed = 200
.pan_speed = Vec2(5, 5)
.move_speed = 10
.target_fov = camera.fov
.zoom_speed = 1.25
.zoom_smoothing = 8
.rotate_around_mouse_hit = False
.ignore_scroll_on_ui = True
.smoothing_helper = Entity(add_to_scene_entities=False)
.rotation_smoothing = 0
.look_at = self.smoothing_helper.look_at
.look_at_2d = self.smoothing_helper.look_at_2d
.rotate_key = 'right mouse'
.start_position = self.position
.perspective_fov = camera.fov
.orthographic_fov = camera.fov
.on_destroy = self.on_disable
.shortcuts = {'toggle_orthographic':'shift+p', 'focus':'shift+f', 'reset_center':'alt+f'}

functions:
 on_enable()
 on_disable()
 on_destroy()
 input(key)
 update()

example:

from ursina import Ursina, Sky, load_model, color, Text, window, Button app = Ursina(vsync=False, use_ingame_console=True) ''' Simple camera for debugging. Hold right click and move the mouse to rotate around point. ''' sky = Sky() e = Entity(model=load_model('cube', use_deepcopy=True), color=color.white, collider='box') e.model.colorize() ground = Entity(model='plane', scale=32, texture='white_cube', texture_scale=(32,32), collider='box') box = Entity(model='cube', collider='box', texture='white_cube', scale=(10,2,2), position=(2,1,5), color=color.light_gray) b = Button(position=window.top_left, scale=.05) ec = EditorCamera(ignore_scroll_on_ui=True) rotation_info = Text(position=window.top_left) def update(): rotation_info.text = str(int(ec.rotation_y)) + '\n' + str(int(ec.rotation_x)) app.run()


Tilemap(GridEditor)

ursina/prefabs/tilemap

Tilemap(tilemap='', tileset='', tileset_size=(8,8), **kwargs)

.grid = [[self.tilemap.get_pixel(x,y) for y in range(self.tilemap.height)] for x in range(self.tilemap.width)]
.tileset = tileset
.tileset_size = tileset_size
.model = Mesh()
.texture = tileset
.colliders = list()
.auto_render = False
.outline = Entity(parent=self, model=Quad(segments=0, mode='line', thickness=1), color=color.cyan, z=.01, origin=(-.5,-.5), enabled=self.edit_mode)
.uv_dict = { '11111111' : [(4,1), (5,1), (6,1), (7,1)], fill
.single_block_coordinates = [(4,0), (5,0), (6,0), (7,0)]
.variation_chance = [0,0,0,0,1,1,1,2,2,3]
.uv_margin = .002

functions:
 update()
 draw_temp(position)
 input(key)
 render()
 save()

example:

app = Ursina() EditorCamera() tilemap = Tilemap('tilemap_test_level', tileset='test_tileset', tileset_size=(8,4), parent=scene) tilemap.canvas.texture = 'tilemap_test_level' camera.orthographic = True camera.position = tilemap.tilemap.size / 2 camera.fov = tilemap.tilemap.height Text('press tab to toggle edit mode', origin=(.5,0), position=(-.55,.4)) app.run()


FirstPersonController(Entity)

ursina/prefabs/first_person_controller

FirstPersonController(**kwargs)

.cursor = Entity(parent=camera.ui, model='quad', color=color.pink, scale=.008, rotation_z=45)
.speed = 5
.height = 2
.camera_pivot = Entity(parent=self, y=self.height)
.mouse_sensitivity = Vec2(40, 40)
.gravity = 1
.grounded = False
.jump_height = 2
.jump_up_duration = .5
.fall_after = .35 will interrupt jump up
.jumping = False
.air_time = 0
.traverse_target = scene by default, it will collide with everything. change this to change the raycasts' traverse targets.
.ignore_list = [self, ]
.on_destroy = self.on_disable

functions:
 update()
 input(key)
 jump()
 start_fall()
 land()
 on_enable()
 on_disable()

example:

from ursina.prefabs.first_person_controller import FirstPersonController window.vsync = False app = Ursina() ground = Entity(model='plane', scale=(100,1,100), color=color.yellow.tint(-.2), texture='white_cube', texture_scale=(100,100), collider='box') e = Entity(model='cube', scale=(1,5,10), x=2, y=.01, rotation_y=45, collider='box', texture='white_cube') e.texture_scale = (e.scale_z, e.scale_y) e = Entity(model='cube', scale=(1,5,10), x=-2, y=.01, collider='box', texture='white_cube') e.texture_scale = (e.scale_z, e.scale_y) player = FirstPersonController(y=2, origin_y=-.5) player.gun = None gun = Button(parent=scene, model='cube', color=color.blue, origin_y=-.5, position=(3,0,3), collider='box', scale=(.2,.2,1)) def get_gun(): gun.parent = camera gun.position = Vec3(.5,0,.5) player.gun = gun gun.on_click = get_gun gun_2 = duplicate(gun, z=7, x=8) slope = Entity(model='cube', collider='box', position=(0,0,8), scale=6, rotation=(45,0,0), texture='brick', texture_scale=(8,8)) slope = Entity(model='cube', collider='box', position=(5,0,10), scale=6, rotation=(80,0,0), texture='brick', texture_scale=(8,8)) hookshot_target = Button(parent=scene, model='cube', color=color.brown, position=(4,5,5)) hookshot_target.on_click = Func(player.animate_position, hookshot_target.position, duration=.5, curve=curve.linear) def input(key): if key == 'left mouse down' and player.gun: gun.blink(color.orange) bullet = Entity(parent=gun, model='cube', scale=.1, color=color.black) bullet.world_parent = scene bullet.animate_position(bullet.position+(bullet.forward*50), curve=curve.linear, duration=1) destroy(bullet, delay=1) app.run()


PlatformerController2d(Entity)

ursina/prefabs/platformer_controller_2d

PlatformerController2d(**kwargs)

.model = 'cube'
.origin_y = -.5
.scale_y = 2
.color = color.orange
.collider = 'box'
.animator = Animator({'idle' : None, 'walk' : None, 'jump' : None})
.walk_speed = 8
.walking = False
.velocity = 0 the walk direction is stored here. -1 for left and 1 for right.
.jump_height = 4
.jump_duration = .5
.jumping = False
.max_jumps = 1
.jumps_left = self.max_jumps
.gravity = 1
.grounded = True
.air_time = 0 this increase while we're falling and used when calculating the distance we fall so we fall faster and faster instead of linearly.
.traverse_target = scene by default, it will collide with everything except itself. you can change this to change the boxcast traverse target.
.ignore_list = [self, ]
.gravity = 0
.min_x = -99999
.max_x = 99999

functions:
 update()
 input(key)
 jump()
 start_fall()
 land()

example:

app = Ursina() camera.orthographic = True camera.fov = 10 ground = Entity(model='cube', color=color.white33, origin_y=.5, scale=(20, 1, 1), collider='box', y=-1) wall = Entity(model='cube', color=color.azure, origin=(-.5,.5), scale=(5,10), x=10, y=.5, collider='box') wall_2 = Entity(model='cube', color=color.white33, origin=(-.5,.5), scale=(5,10), x=10, y=0, collider='box') ceiling = Entity(model='cube', color=color.white33, origin_y=-.5, scale=(1, 1, 1), y=1, collider='box') ceiling = Entity(model='cube', color=color.white33, origin_y=-.5, scale=(5, 5, 1), y=2, collider='box') ground = Entity(model='cube', color=color.white33, origin_y=.5, scale=(20, 3, 1), collider='box', y=-1, rotation_z=45, x=-5) def input(key): if key == 'c': wall.collision = not wall.collision print(wall.collision) player_controller = PlatformerController2d(scale_y=2, jump_height=4, x=3, y=20, max_jumps=2) ec = EditorCamera() ec.add_script(SmoothFollow(target=player_controller, offset=[0,1,0], speed=4)) app.run()


Conversation(Entity)

ursina/prefabs/conversation

Conversation(variables_object=None, **kwargs)

.question = Button(parent=self, text_origin=(-.5,0), scale=(1,.1), model=Quad(radius=.5,aspect=1/.1), text='Question')
.more_indicator = Entity(parent=self.question, model=Circle(3), position=(.45,-.4,-1), rotation_z=180, color=color.azure, world_scale=.5, z=-1, enabled=False)
.spacing = 4 * .02
.wordwrap = 65
.button_model = Quad(radius=.5, aspect=1/.075)
.variables_object = variables_object
.answer_0 = Button(parent=self, text='answer_0', y=self.question.y-self.spacing-.025, scale=(1,.075), text_origin=(-.5,0), model=copy(self.button_model))
.answer_1 = Button(parent=self, text='answer_1', y=self.answer_0.y-self.spacing, scale=(1,.075), text_origin=(-.5,0), model=copy(self.button_model))
.answer_2 = Button(parent=self, text='answer_2', y=self.answer_1.y-self.spacing, scale=(1,.075), text_origin=(-.5,0), model=copy(self.button_model))
.buttons = (self.answer_0, self.answer_1, self.answer_2)
.question_appear_sequence = None
.button_appear_sequence = None
.started = False

functions:
 ask(node, question_part=0)
 on_click(node=child)
 input(key)
 next()
 start_conversation(conversation)
 parse_conversation(convo)

example:

app = Ursina() variables = Empty( evil=0, chaos=0, bar_mission_solved=False, ) conversation = Conversation(variables_object=variables) convo = dedent(''' I'm looking for my sister. Can you help me find her, please? I haven't seen her in days! Who know what could've happened!? I'm worried. Will you help me? * Yes, of course. This can be a dangerous city. Oh no! Do you think something happened to her? What should I do?! * She's probably fine. She can handle herself. You're right. I'm still worried though. * Don't worry, I'll look for her. * Maybe. (stats.chaos += 1) Help me look for her, please! *runs off* * I'm sorry, but I don't have time right now. (evil += 1) A true friend wouldn't say that. * I know where she is! (if bar_mission_solved) Really? Where? * I saw her on a ship by the docks, it looked like they were ready to set off. Thank you! *runs off* ''') conversation.start_conversation(convo) def input(key): if key == 'space': print(variables.evil) Sprite('shore', z=1) app.run()


Button(Entity)

ursina/prefabs/button

Button(text='', parent=camera.ui, model=Default, radius=.1, origin=(0,0), text_origin=(0,0), text_size=1, color=Default, collider='box', highlight_scale=1, pressed_scale=1, disabled=False, **kwargs)

.origin = origin
.color = color
.highlight_color = self.color.tint(.2)
.pressed_color = self.color.tint(-.2)
.highlight_scale = highlight_scale multiplier
.pressed_scale = pressed_scale multiplier
.highlight_sound = None
.pressed_sound = None
.collider = collider
.disabled = disabled
.text_entity = None
.text_origin = text_origin

properties:
.text
.text_origin
.text_color
.icon
.icon_world_scale
.text_size
.origin

functions:
 input(key)
 on_mouse_enter()
 on_mouse_exit()
 fit_to_text(radius=.1, padding=Vec2(Text.size*1.5, Text.size))

example:

from ursina import * app = Ursina() Button.default_color = color.red b = Button(model='quad', scale=.05, x=-.5, color=color.lime, text='text scale\ntest', text_size=.5, text_color=color.black) b.text_size = .5 b.on_click = Sequence(Wait(.5), Func(print, 'aaaaaa'), ) b = Button(parent=camera.ui, text='hello world!', scale=.25) Button.default_color = color.blue b = Button(text='hello world!', icon='sword', scale=.25, text_origin=(-.5,0), x=.5) b.on_click = application.quit # assign a function to the button. b.tooltip = Tooltip('exit') par = Entity(parent=camera.ui, scale=.2, y=-.2) b = Button(parent=par, text='test', scale_x=1, origin=(-.5,.5)) b.text ='new text' print(b.text_entity) Button(text='sound', scale=.2, position=(-.25,-.2), color=color.pink, highlight_sound='blip_1', pressed_sound=Audio('coin_1', autoplay=False)) Text('Text size\nreference', x=.15) def input(key): if key == 'd': scene.clear() if key == 'space': b.text = 'updated text' app.run()


Draggable(Button)

ursina/prefabs/draggable

Draggable(**kwargs)

.require_key = None
.dragging = False
.delta_drag = 0
.start_pos = self.world_position
.start_offset = (0,0,0)
.step = (0,0,0)
.plane_direction = (0,0,1)
.lock = Vec3(0,0,0) set to 1 to lock movement on any of x, y and z axes
.min_x, self.min_y, self.min_z = -inf, -inf, -inf
.max_x, self.max_y, self.max_z = inf, inf, inf

properties:
.step

functions:
 input(key)
 start_dragging()
 stop_dragging()
 update()

example:

app = Ursina() Entity(model='plane', scale=8, texture='white_cube', texture_scale=(8,8)) draggable_button = Draggable(scale=.1, text='drag me', position=(-.5, 0)) world_space_draggable = Draggable(parent=scene, model='cube', color=color.azure, plane_direction=(0,1,0), lock=(1,0,0)) EditorCamera(rotation=(30,10,0)) world_space_draggable.drop = Func(print, 'dropped cube') app.run()


Tooltip(Text)

ursina/prefabs/tooltip

Tooltip(text='', wordwrap=40, background_color=color.black66, **kwargs)


functions:
 update()

example:

app = Ursina() tooltip_test = Tooltip( '<scale:1.5><pink>' + 'Rainstorm' + '<scale:1> \n \n' + '''Summon a <blue>rain storm <default>to deal 5 <blue>water damage <default>to <red>everyone, <default>including <orange>yourself. <default> Lasts for 4 rounds.'''.replace('\n', ' '), background_color=color.violet, font='VeraMono.ttf', wordwrap=50, ) tooltip_test.enabled = True app.run()


Slider(Entity)

ursina/prefabs/slider

Slider(min=0, max=1, default=None, height=Text.size, text='', dynamic=False, radius=Text.size/2, bar_color=color.black66, **kwargs)

.parent = camera.ui
.vertical = False
.min = min
.max = max
.default = default
.step = 0 for example, setting .step to 1, would make the slider snap to the closest integer.
.height = height
.on_value_changed = None set this to a function you want to be called when the slider changes
.setattr = None set this to (object, 'attrname') to set that value when the slider changes
.label = Text(parent=self, origin=(0.5, 0), x=-0.025, text=text)
.bg = Entity(parent=self, model=Quad(scale=(.525, height), radius=radius, segments=3), origin_x=-0.25, collider='box', color=bar_color)
.knob = Draggable(parent=self, min_x=0, max_x=.5, min_y=0, max_y=.5, step=self.step, model=Quad(radius=Text.size/2, scale=(Text.size, height)), collider='box', color=color.light_gray, text='0', text_origin=(0, -.55), z=-.1)
.value = self.default
.dynamic = dynamic if set to True, will call on_value_changed() while dragging. if set to False, will only call on_value_changed() after dragging.

properties:
.value
.step

functions:
 bg_click()
 drop()
 update()
 slide()

example:

app = Ursina() box = Entity(model='cube', origin_y=-.5, scale=1, color=color.orange) def scale_box(): box.scale_y = slider.value print(thin_slider.value) slider = Slider(0, 20, default=10, height=Text.size*3, y=-.4, step=1, on_value_changed=scale_box, vertical=True) thin_slider = ThinSlider(text='height', dynamic=True, on_value_changed=scale_box) thin_slider.label.origin = (0,0) thin_slider.label.position = (.25, -.1) app.run()


ThinSlider(Slider)

ursina/prefabs/slider

ThinSlider(*args, **kwargs)


example:

app = Ursina() box = Entity(model='cube', origin_y=-.5, scale=1, color=color.orange) def scale_box(): box.scale_y = slider.value print(thin_slider.value) slider = Slider(0, 20, default=10, height=Text.size*3, y=-.4, step=1, on_value_changed=scale_box, vertical=True) thin_slider = ThinSlider(text='height', dynamic=True, on_value_changed=scale_box) thin_slider.label.origin = (0,0) thin_slider.label.position = (.25, -.1) app.run()


TextField(Entity)

ursina/prefabs/text_field

TextField(max_lines=64, line_height=1.1, character_limit=None, **kwargs)

.font = 'VeraMono.ttf'
.line_height = line_height
.max_lines = max_lines
.character_limit = character_limit
.scroll_parent = Entity(parent=self)
.text_entity = Text(parent=self.scroll_parent, start_tag='☾', end_tag='☽', font=self.font, text='', line_height=self.line_height, origin=(-.5, .5))
.line_numbers = Text(parent=self.scroll_parent, font=self.font, line_height=line_height, text='0', origin=(.5,.5), x=-.04, color=color.gray, enabled=False)
.character_width = Text.get_width('a', font=self.font)
.cursor_parent = Entity(parent=self.scroll_parent, scale=(self.character_width, -1*Text.size*self.line_height))
.cursor = Entity(name='text_field_cursor', parent=self.cursor_parent, model='cube', color=color.cyan, origin=(-.5, -.5), scale=(.1, 1, 0), enabled=False)
.bg = Entity(name='text_field_bg', parent=self, model='quad', double_sided=True, color=color.dark_gray, origin=(-.5,.5), z=0.005, scale=(120, Text.size*self.max_lines*self.line_height), collider='box', visible=True)
.selection = [Vec2(0,0), Vec2(0,0)]
.selection_parent = Entity(name='text_field_selection_parent', parent=self.cursor_parent, scale=(1,1,0))
.register_mouse_input = False
.world_space_mouse = False
.triple_click_delay = 0.3
.scroll = 0
.scroll_amount = 2
.active = True
.highlight_color = color.hsv(120,1,1,.1)
.text = ''
.delimiters = ' .,!?;:(){}[]<>\'\"@#$%^&*+=-\\|/`~'
.replacements = dict()
.on_undo = []
.on_redo = []
.on_value_changed = None
.shortcuts = { 'newline': ('enter', 'enter hold'), 'erase': ('backspace', 'backspace hold'), 'erase_word': ('ctrl+backspace', 'ctrl+backspace hold'), 'delete_line': ('ctrl+shift+k',), 'duplicate_line': ('ctrl+shift+d',), 'undo': ('ctrl+z', 'ctrl+z hold'), 'redo': ('ctrl+y', 'ctrl+y hold', 'ctrl+shift+z', 'ctrl+shift+z hold'), 'indent': ('tab',), 'dedent': ('shift+tab',), 'move_line_down': ('ctrl+down arrow', 'ctrl+down arrow hold'), 'move_line_up': ('ctrl+up arrow', 'ctrl+up arrow hold'), 'scroll_up': ('scroll up',), 'scroll_down': ('scroll down',), 'cut': ('ctrl+x',), 'copy': ('ctrl+c',), 'paste': ('ctrl+v',), 'select_all': ('ctrl+a',), 'select_word': ('double click',), 'select_line': ('triple click',), 'scroll_to_bottom': ('shift+alt+e',), 'move_operations' : { 'move_left': ('left arrow', 'left arrow hold', 'shift+left arrow', 'shift+left arrow hold'), 'move_right': ('right arrow', 'right arrow hold', 'shift+right arrow', 'shift+right arrow hold'), 'move_up': ('up arrow', 'up arrow hold', 'shift+up arrow', 'shift+up arrow hold'), 'move_down': ('down arrow', 'down arrow hold', 'shift+down arrow', 'shift+down arrow hold'), 'move_to_end_of_word' : ('ctrl+right arrow', 'ctrl+right arrow hold', 'ctrl+shift+right arrow', 'ctrl+shift+right arrow hold'), 'move_to_start_of_word' : ('ctrl+left arrow', 'ctrl+left arrow hold', 'ctrl+shift+left arrow', 'ctrl+shift+left arrow hold'), },
.middle_click_scroller = Entity(parent=self, start_y=None, input=middle_click_input, update=middle_click_update, t=0, update_rate=.05)

properties:
.active

functions:
 middle_click_input(key)
 middle_click_update()
 add_text(s, move_cursor=True, rerender=True)
 move_line(line_index, delta, move_cursor=True)
 erase(rerender=True)
 delete_selected()
 get_selected()
 get_mouse_position_unclamped()
 get_mouse_position()
 set_scroll(value, render=True)
 input(key)
 move_to_start_of_word()
 move_to_end_of_word()
 scroll_to_bottom(blank_lines_at_bottom=0)
 text_input(key)
 render()
 update()
 select_all()
 draw_selection()

example:

from ursina import Ursina, window, Button app = Ursina(vsync=60) window.color = color.hsv(0, 0, .1) Button.default_color = color._20 window.color = color._25 te = TextField(max_lines=30, scale=1, register_mouse_input = True, text='1234') from textwrap import dedent te.text = dedent(''' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sapien tellus, venenatis sit amet ante et, malesuada porta risus. Etiam et mi luctus, viverra urna at, maximus eros. Sed dictum faucibus purus, nec rutrum ipsum condimentum in. Mauris iaculis arcu nec justo rutrum euismod. Suspendisse dolor tortor, congue id erat sit amet, sollicitudin facilisis velit. Aliquam sapien tellus, venenatis sit amet ante et, malesuada porta risus. Etiam et mi luctus, viverra urna at, maximus eros. Sed dictum faucibus purus, nec rutrum ipsum condimentum in. Mauris iaculis arcu nec justo rutrum euismod. Suspendisse dolor tortor, congue id erat sit amet, sollicitudin facilisis velit. '''*30 )[1:] te.render() def input(key): if key == '3': te.input('scroll down') app.run()


Cursor(Entity)

ursina/prefabs/cursor

Cursor(**kwargs)

.parent = camera.ui
.texture = 'cursor'
.model = 'quad'
.color = color.light_gray
.render_queue = 1

functions:
 update()

example:

from ursina import Ursina, Button, scene, Panel, Mesh app = Ursina() Button('button').fit_to_text() camera.orthographic = True camera.fov = 100 cursor = Cursor(model=Mesh(vertices=[(-.5,0,0),(.5,0,0),(0,-.5,0),(0,.5,0)], triangles=[(0,1),(2,3)], mode='line', thickness=2), scale=.02) mouse.visible = False app.run()


InputField(Button)

ursina/prefabs/input_field

InputField(default_value='', label='', max_lines=1, character_limit=24, text='', active=False, **kwargs)

.default_value = default_value
.limit_content_to = None
.hide_content = False if set to True, will display content as '*'. can also be set to character instead of True.
.next_field = None
.submit_on = [] for example: self.submit_on
.on_submit = None function to be called when you press self.submit_on.
.on_value_changed = None
.text_field = TextField(world_parent=self, x=-.45, y=.25, z=-.1, max_lines=max_lines, character_limit=character_limit, text=text, register_mouse_input=True)
.active = active

properties:
.text
.text_color
.active

functions:
 render()
 input(key)

example:

app = Ursina() gradient = Entity(model='quad', texture='vertical_gradient', parent=camera.ui, scale=(camera.aspect_ratio,1), color=color.hsv(240,.6,.1,.75)) username_field = InputField(y=-.12, limit_content_to='0123456789', default_value='11', active=True) username_field.text = '0929468098' password_field = InputField(y=-.18, hide_content=True) username_field.next_field = password_field def submit(): print('ursername:', username_field.text) print('password:', password_field.text) Button(text='Login', scale=.1, color=color.cyan.tint(-.4), y=-.26, on_click=submit).fit_to_text() username_field.on_value_changed = submit app.run()


ContentTypes

ursina/prefabs/input_field

ContentTypes.int = '0123456789'
ContentTypes.float = int + '.,'
ContentTypes.int_math = int + '+-*/'
ContentTypes.math = float + '+-*/'

example:

app = Ursina() gradient = Entity(model='quad', texture='vertical_gradient', parent=camera.ui, scale=(camera.aspect_ratio,1), color=color.hsv(240,.6,.1,.75)) username_field = InputField(y=-.12, limit_content_to='0123456789', default_value='11', active=True) username_field.text = '0929468098' password_field = InputField(y=-.18, hide_content=True) username_field.next_field = password_field def submit(): print('ursername:', username_field.text) print('password:', password_field.text) Button(text='Login', scale=.1, color=color.cyan.tint(-.4), y=-.26, on_click=submit).fit_to_text() username_field.on_value_changed = submit app.run()


ButtonList(Entity)

ursina/prefabs/button_list

ButtonList(button_dict, button_height=1.1, width=.5, popup=False, color=Button.default_color, highlight_color=color.white33, selected_color=color.azure, font=Text.default_font, clear_selected_on_enable=True, **kwargs)

.clear_selected_on_enable = clear_selected_on_enable
.button_height = button_height
.width = width
.text_entity = Text(parent=self, font=font, origin=(-.5,.5), text='empty', world_scale=20, z=-.1, x=.01, y=-(button_height*.25*Text.size), line_height=button_height)
.bg = Entity(parent=self, model='quad', origin=(-.5,.5), scale=width, color=color, collider='box')
.highlight = Entity(parent=self.bg, model='quad', color=highlight_color, scale=(1,self.button_height), origin=(-.5,.5), z=-.01, add_to_scene_entities=False)
.selection_marker = Entity(parent=self.bg, model='quad', color=selected_color, scale=(1,self.button_height), origin=(-.5,.5), z=-.02, enabled=False, add_to_scene_entities=False)
.button_dict = button_dict
.popup = popup

properties:
.button_dict
.selected

functions:
 input(key)
 update()
 on_disable()
 on_enable()

example:

from ursina import Ursina, Func app = Ursina() default = Func(print, 'not yet implemented') def test(a=1, b=2): print('------:', a, b) button_dict = {} for i in range(6, 20): button_dict[f'button {i}'] = Func(print, i) bl = ButtonList(button_dict, font='VeraMono.ttf', button_height=1.5, popup=0, clear_selected_on_enable=False) def input(key): if key == 'space': bl.button_dict = { 'one' : None, 'two' : default, 'tree' : Func(test, 3, 4), 'four' : Func(test, b=3, a=4), } if key == 'o': bl.enabled = True bl.selected = 'button 7' bl.button_dict = {} app.run()


ButtonGroup(Entity)

ursina/prefabs/button_group

ButtonGroup(options, default='', min_selection=1, max_selection=1, origin=(-.5,.5,0), spacing=(0.025,0,0), label='', **kwargs)

.deselected_color = Button.default_color
.selected_color = ButtonGroup.default_selected_color
.min_selection = min_selection
.max_selection = max(min_selection, max_selection)
.origin = origin
.spacing = spacing
.buttons = []
.selected = []
.options = options
.parent = camera.ui
.scale = Text.size * 2

properties:
.options
.value
.label

functions:
 layout()
 input(key)
 select(b)
 on_value_changed()

example:

from ursina import * app = Ursina() center = Entity(parent=camera.ui, model='circle', scale=.005, color=color.red, z=-1) gender_selection = ButtonGroup(('man', 'woman', 'other'), origin=(-.5,0), label='choose gender:') def on_value_changed(): print('set gender:', gender_selection.value) gender_selection.on_value_changed = on_value_changed window.color = color._32


WindowPanel(Draggable)

ursina/prefabs/window_panel

WindowPanel(title='', content=[], **kwargs)

.content = content
.popup = False
.panel = Entity(parent=self, model='quad', origin=(0,.5), z=.1, color=self.color.tint(.1), collider='box')

functions:
 layout()

example:

''' WindowPanel is an easy way to create UI. It will automatically layout the content. ''' from ursina import Ursina, ButtonGroup app = Ursina() wp = WindowPanel( title='Custom Window', content=( Text('Name:'), InputField(name='name_field'), Button(text='Submit', color=color.azure), Slider(), Slider(), ButtonGroup(('test', 'eslk', 'skffk')) ), popup=True ) wp.y = wp.panel.scale_y / 2 * wp.scale_y # center the window panel wp.layout() def input(key): if key == 'space': wp.enabled = True app.run()


Space

ursina/prefabs/window_panel

Space(height=1)

.height = height

example:

''' WindowPanel is an easy way to create UI. It will automatically layout the content. ''' from ursina import Ursina, ButtonGroup app = Ursina() wp = WindowPanel( title='Custom Window', content=( Text('Name:'), InputField(name='name_field'), Button(text='Submit', color=color.azure), Slider(), Slider(), ButtonGroup(('test', 'eslk', 'skffk')) ), popup=True ) wp.y = wp.panel.scale_y / 2 * wp.scale_y # center the window panel wp.layout() def input(key): if key == 'space': wp.enabled = True app.run()


FileBrowser(Entity)

ursina/prefabs/file_browser

FileBrowser(file_button_class=FileButton, selection_limit=1, start_path=None, file_types:list=None, **kwargs)

.file_types = file_types if file_types else ['.*', ]

properties:
.scroll
.path
.selection

functions:
 input(key)
 on_enable()
 close()
 folder_up()
 open(path=None)

example:

app = Ursina() fb = FileBrowser(file_types=('.*'), enabled=False) def on_submit(paths): print('--------', paths) for p in paths: print('---', p) fb.on_submit = on_submit def input(key): if key == 'tab': fb.enabled = not fb.enabled app.run()


FileButton(Button)

ursina/prefabs/file_browser

FileButton(load_menu, path, **kwargs)

.load_menu = load_menu
.path = path
.original_color = self.color
.selected = False

properties:
.selected

functions:
 on_click()
 on_double_click()

example:

app = Ursina() fb = FileBrowser(file_types=('.*'), enabled=False) def on_submit(paths): print('--------', paths) for p in paths: print('---', p) fb.on_submit = on_submit def input(key): if key == 'tab': fb.enabled = not fb.enabled app.run()


FileBrowserSave(FileBrowser)

ursina/prefabs/file_browser_save

FileBrowserSave(**kwargs)

.save_button = self.open_button
.file_name_field = InputField(parent=self, scale_x=.75, scale_y=self.save_button.scale_y, y=self.save_button.y)
.file_type = '' to save as
.last_saved_file = None gets set when you save a file
.overwrite_prompt = WindowPanel( content=( Text('Overwrite?'), Button('Yes', color=color.azure, on_click=self._save), Button('Cancel') ), z=-1, popup=True, enabled=False)

properties:
.file_type

functions:
 on_enable()
 on_disable()
 on_submit(path) implement .on_submit to handle saving

example:

from ursina import * from ursina.prefabs.file_browser_save import FileBrowserSave app = Ursina() wp = FileBrowserSave(file_type = '.*') import json save_data = {'level': 4, 'name':'Link'} wp.data = json.dumps(save_data) wp.enabled = False def input(key): if key == 'tab': wp.enabled = not wp.enabled app.run()




RadialMenu(Entity)

ursina/prefabs/radial_menu

RadialMenu(buttons=list(), **kwargs)

.parent = camera.ui
.buttons = buttons
.open_at_cursor = True
.open_duration = .1
.bg = Panel(parent=self, model='quad', z=99, scale=999, collider='box', color=color.hsv(0,0,0,.1), enabled=False)
.z = -99
.scale = .075

functions:
 on_enable()
 input(key)

example:

app = Ursina() rm = RadialMenu( buttons = ( RadialMenuButton(text='1'), RadialMenuButton(text='2'), RadialMenuButton(text='3'), RadialMenuButton(text='4'), RadialMenuButton(text='5', scale=.5), RadialMenuButton(text='6', color=color.red), ), enabled = False ) RadialMenuButton(text='6', color=color.red,x =-.5, scale=.06), def enable_radial_menu(): rm.enabled = True cube = Button(parent=scene, model='cube', color=color.orange, highlight_color=color.azure, on_click=enable_radial_menu) EditorCamera() app.run()


RadialMenuButton(Button)

ursina/prefabs/radial_menu

RadialMenuButton(**kwargs)


example:

app = Ursina() rm = RadialMenu( buttons = ( RadialMenuButton(text='1'), RadialMenuButton(text='2'), RadialMenuButton(text='3'), RadialMenuButton(text='4'), RadialMenuButton(text='5', scale=.5), RadialMenuButton(text='6', color=color.red), ), enabled = False ) RadialMenuButton(text='6', color=color.red,x =-.5, scale=.06), def enable_radial_menu(): rm.enabled = True cube = Button(parent=scene, model='cube', color=color.orange, highlight_color=color.azure, on_click=enable_radial_menu) EditorCamera() app.run()


HealthBar(Button)

ursina/prefabs/health_bar

HealthBar(max_value=100, value=Default, roundness=.25, bar_color=color.red.tint(-.2), highlight_color=color.black66, animation_duration=.1, show_text=True, show_lines=False, text_size=.7, scale=(.5,.025), origin=(-.5,.5), name='health_bar', **kwargs)

.bar = Entity(parent=self, model=Quad(radius=roundness), origin=origin, z=-.005, color=bar_color, highlight_color=highlight_color, ignore=True)
.lines = Entity(parent=self.bar, y=-1, color=color.black33, ignore=True, enabled=show_lines, z=-.05)
.max_value = max_value
.clamp = True
.roundness = roundness
.animation_duration = animation_duration
.show_lines = show_lines
.show_text = show_text
.value = self.max_value if value == Default else value

properties:
.value
.show_text
.show_lines
.bar_color

example:

app = Ursina() health_bar_1 = HealthBar(bar_color=color.lime.tint(-.25), roundness=.5, max_value=100, value=50, scale=(.5,.1)) print(health_bar_1.text_entity.enabled, health_bar_1.text_entity.text) def input(key): if key == '+' or key == '+ hold': health_bar_1.value += 10 if key == '-' or key == '- hold': health_bar_1.value -= 10 print('ow') app.run()


ColorPicker(Entity)

ursina/prefabs/color_picker

ColorPicker(dynamic=True, **kwargs)

.bg = Entity(parent=self, z=.01, model=Quad(aspect=.5/.2), scale=[.5,.225], origin=[0,.5], color=color.black66)
.h_slider = Slider(parent=self, max=360, step=1, dynamic=dynamic, on_value_changed=self._calculate_color)
.s_slider = Slider(parent=self, max=100, step=1, dynamic=dynamic, on_value_changed=self._calculate_color)
.v_slider = Slider(parent=self, max=100, step=1, dynamic=dynamic, on_value_changed=self._calculate_color)
.a_slider = Slider(parent=self, max=100, default=100, step=1, dynamic=dynamic, on_value_changed=self._calculate_color)
.on_value_changed = None assign a function here
.preview = Button(parent=self, scale=(.5*.84,.05), origin=[0,.5], y=slider.y-.02, color=color.white)

example:

from ursina import Ursina app = Ursina() ColorPicker() app.run()


HotReloader(Entity)

ursina/prefabs/hot_reloader

HotReloader(path=__file__, **kwargs)

.path = path
.path = Path(self.path)
.hotreload = False toggle with f9
.hotkeys = { 'ctrl+r' : self.reload_code, 'f5' : self.reload_code, 'f6' : self.reload_textures, 'f7' : self.reload_models, 'f8' : self.reload_shaders, 'f9' : self.toggle_hotreloading, }
.hotreload_window_settings = dict(size=(window.size[0]/2,window.size[1]/2), always_on_top=True, position=(window.fullscreen_size[0]-window.size[0]/22, 0))

functions:
 input(key)
 update()
 get_source_code()
 toggle_hotreloading()
 reload_code(reset_camera=True)
 reload_textures()
 reload_models()
 reload_shaders()

example:

from ursina import * app = Ursina() ''' By default you can press F5 to reload the starting script, F6 to reimport textures and F7 to reload models. '''


GridEditor(Entity)

ursina/prefabs/grid_editor

GridEditor(size=(32,32), palette=(' ', '#', '|', 'o'), canvas_color=color.white, edit_mode=True, **kwargs)

.w, self.h = int(size[0]), int(size[1])
.canvas = Entity(parent=self, model='quad', origin=(-.5,-.5), shader=unlit_shader, scale=(self.w/self.h, 1), color=canvas_color)
.canvas_collider = Entity(parent=self.canvas, model='wireframe_quad', origin=self.canvas.origin, color=color.blue, scale=2, position=(-.5,-.5), collider='box', visible=False)
.brush_size = 1
.auto_render = True
.cursor = Entity(parent=self.canvas, model=Quad(segments=0, mode='line', thickness=2), origin=(-.5,-.5), scale=(1/self.w, 1/self.h), color=color.hsv(120,1,1,.5), z=-.2, shader=unlit_shader)
.selected_char = palette[1]
.palette = palette
.start_pos = None
.prev_draw = None
.lock_axis = None
.outline = Entity(parent=self.canvas, model=Quad(segments=0, mode='line', thickness=2), color=color.cyan, z=.01, origin=(-.5,-.5))
.rect_selection = [Vec2(0,0), Vec2(0,0)]
.selection_renderer = Entity(parent=self.canvas, model=Mesh(mode='line', thickness=2), color=color.lime, alpha=.5, z=-.01, origin=(-.5,-.5), scale=(1/self.w,1/self.h))
.rect_tool = Entity(parent=self.canvas, model=Quad(0, mode='line', thickness=2), color=color.lime, z=-.01, origin=(-.5,-.5), start=Vec2(0,0), end=Vec2(0,0))
.selection_matrix = [[0 for y in range(self.h)] for x in range(self.w)]
.temp_paste_layer = Entity(parent=self.cursor, model='quad', origin=(-.5,-.5), z=-.02, enabled=False)
.is_in_paste_mode = False
.undo_stack = []
.undo_index = 0
.help_icon = Button(parent=self.canvas, scale=.025, model='circle', origin=(-.5,-.5), position=(-.0,1.005,-1), text='?', target_scale=.025)
.edit_mode = edit_mode

properties:
.palette
.edit_mode

functions:
 update()
 get_cursor_position()
 draw(x, y)
 input(key)
 record_undo()
 floodfill(matrix, x, y, first=True)
 copy()
 enter_paste_mode()
 exit_paste_mode(discard=False)
 clear_selection()
 render_selection()

example:

app = Ursina(borderless=False) ''' pixel editor example, it's basically a drawing tool. can be useful for level editors and such here we create a new texture, but can also give it an existing texture to modify. ''' from PIL import Image t = Texture(Image.new(mode='RGBA', size=(32,32), color=(0,0,0,1))) from ursina.prefabs.grid_editor import PixelEditor editor = PixelEditor(parent=scene, texture=load_texture('brick'), scale=10) camera.orthographic = True camera.fov = 15 EditorCamera(rotation_speed=0) from ursina.prefabs.grid_editor import ASCIIEditor ASCIIEditor(x=0, scale=.1) app.run()


PixelEditor(GridEditor)

ursina/prefabs/grid_editor

PixelEditor(texture, palette=(color.black, color.white, color.light_gray, color.gray, color.red, color.orange, color.yellow, color.lime, color.green, color.turquoise, color.cyan, color.azure, color.blue, color.violet, color.magenta, color.pink), **kwargs)


properties:
.texture

functions:
 set_texture(texture, render=True, clear_undo_stack=True)
 draw(x, y)
 render()
 save()

example:

app = Ursina(borderless=False) ''' pixel editor example, it's basically a drawing tool. can be useful for level editors and such here we create a new texture, but can also give it an existing texture to modify. ''' from PIL import Image t = Texture(Image.new(mode='RGBA', size=(32,32), color=(0,0,0,1))) from ursina.prefabs.grid_editor import PixelEditor editor = PixelEditor(parent=scene, texture=load_texture('brick'), scale=10) camera.orthographic = True camera.fov = 15 EditorCamera(rotation_speed=0) from ursina.prefabs.grid_editor import ASCIIEditor ASCIIEditor(x=0, scale=.1) app.run()


ASCIIEditor(GridEditor)

ursina/prefabs/grid_editor

ASCIIEditor(size=(61,28), palette=(' ', '#', '|', 'A', '/', '\\', 'o', '_', '-', 'i', 'M', '.'), font='VeraMono.ttf', canvas_color=color.black, line_height=1.1, **kwargs)

.text_entity = Text(parent=self.parent, text=text, x=-.0, y=.5, line_height=line_height, font=font)
.scale = (self.text_entity.width, self.text_entity.height)

functions:
 render()
 input(key)

example:

app = Ursina(borderless=False) ''' pixel editor example, it's basically a drawing tool. can be useful for level editors and such here we create a new texture, but can also give it an existing texture to modify. ''' from PIL import Image t = Texture(Image.new(mode='RGBA', size=(32,32), color=(0,0,0,1))) from ursina.prefabs.grid_editor import PixelEditor editor = PixelEditor(parent=scene, texture=load_texture('brick'), scale=10) camera.orthographic = True camera.fov = 15 EditorCamera(rotation_speed=0) from ursina.prefabs.grid_editor import ASCIIEditor ASCIIEditor(x=0, scale=.1) app.run()


grid_layout

ursina/scripts/grid_layout


functions:
 grid_layout(l, max_x=8, max_y=8, spacing=(0,0,0), origin=(-.5,.5,0), offset=(0,0,0))

example:

app = Ursina() center = Entity(model='quad', scale=.1, color=color.red) p = Entity() for i in range(4*5): b = Button(parent=p, model='quad', scale=Vec2(.2,.1), text=str(i), color=color.tint(color.random_color(),-.6)) b.text_entity.scale=1 t = time.time() grid_layout(p.children, max_x=7, max_y=10, origin=(0, .5), spacing=(.15, 0)) center = Entity(parent=camera.ui, model=Circle(), scale=.005, color=color.lime) EditorCamera() print(time.time() - t)


duplicate

ursina/duplicate


functions:
 duplicate(entity, copy_children=True, *args, **kwargs): # use a for loop instead of duplicate() use a for loop instead of duplicate() if you can.

example:

from ursina import * from ursina import Ursina, Button, scene, EditorCamera app = Ursina() e = Button(parent=scene, scale=1, text='yolo') e2 = duplicate(e, x=1.25) EditorCamera() app.run()


SmoothFollow

ursina/scripts/smooth_follow

SmoothFollow(target=None, offset=(0,0,0), speed=8, rotation_speed=0, rotation_offset=(0,0,0))

.target = target
.offset = offset
.speed = speed
.rotation_speed = rotation_speed
.rotation_offset = rotation_offset

functions:
 update()

example:

app = Ursina() player = Entity(model='cube', color=color.orange) def update(): player.x += held_keys['d'] * .1 player.x -= held_keys['a'] * .1 e = Entity(model='cube') sf = e.add_script(SmoothFollow(target=player, offset=(0,2,0))) def input(key): global sf if key == '1' and sf in e.scripts: e.scripts.remove(sf) EditorCamera() app.run()


Scrollable

ursina/scripts/scrollable

Scrollable(**kwargs)

.max = inf
.min = -inf
.scroll_speed = .05
.scroll_smoothing = 16
.axis = 'y'
.target_value = None

functions:
 update()
 input(key)

example:

''' This will make target entity move up or down when you hover the entity/its children while scrolling the scroll wheel. ''' app = Ursina() p = Button(model='quad', scale=(.4, .8), collider='box') for i in range(8): Button(parent=p , scale_y=.05, text=f'giopwjoigjwr{i}', origin_y=.5, y=.5-(i*.05)) p.add_script(Scrollable()) app.run()


NoclipMode

ursina/scripts/noclip_mode

NoclipMode(speed=10, require_key='shift')

.speed = speed
.require_key = require_key
.ignore_paused = True

functions:
 input(key)
 update()

example:

app = Ursina() player = Entity(model='cube', color=color.orange) Entity(model='plane', scale=10) EditorCamera() player.add_script(NoclipMode2d()) app.run()


NoclipMode2d

ursina/scripts/noclip_mode

NoclipMode2d(speed=10, require_key='shift')

.speed = speed
.require_key = require_key
.ignore_paused = True

functions:
 input(key)
 update()

example:

app = Ursina() player = Entity(model='cube', color=color.orange) Entity(model='plane', scale=10) EditorCamera() player.add_script(NoclipMode2d()) app.run()


build

ursina/build

.project_folder = Path.cwd()
.project_name = project_folder.stem
.build_folder = Path(project_folder / f'build_{platform.system()}')
.build_folder.mkdir(exist_ok=True)
.ignore_folders = []
.ignore_filetypes = []
.compressed_textures = []
.compressed_textures_folder = Path(project_folder/'textures_compressed')
.python_dest = Path(build_folder / 'python')
.python_dlls_dest = Path(build_folder / 'python/DLLs')
.python_lib_dest = Path(build_folder / 'python/Lib')
.src_dest = Path(build_folder / 'src')
.build_engine = True
.build_game = True
.entry_point = 'main.py'
.start_time = time.time()

functions:
 copytree(src, dst, symlinks=False, ignore_patterns=[], ignore_filetypes=[])


models

quad
wireframe_cube
plane
circle
diamond
wireframe_quad
sphere
cube
icosphere
cube_uv_top
arrow
sky_dome


textures

noise
grass
vignette
arrow_right
test_tileset
tilemap_test_level
shore
file_icon
sky_sunset
radial_gradient
circle
perlin_noise
brick
grass_tintable
circle_outlined
ursina_logo
arrow_down
cog
vertical_gradient
white_cube
horizontal_gradient
folder
rainbow
heightmap_1
sky_default


unlit_shader

ursina/shaders/unlit_shader

default_input
'texture_scale' : Vec2(1,1),
'texture_offset' : Vec2(0.0, 0.0),

example:

from ursina import * from ursina.prefabs.primitives import * app = Ursina() shader = unlit_shader ground = GrayPlane(scale=10, y=-2, texture='shore', shader=shader, texture_scale=(10,10)) ground.set_shader_input('texture_scale', Vec2(2, 1)) EditorCamera() app.run()


lit_with_shadows_shader

ursina/shaders/lit_with_shadows_shader

default_input
'texture_scale': Vec2(1,1),
'texture_offset': Vec2(0,0),
'shadow_color' : Color(0, .5, 1, .25),
'shadow_blur': .005,
'shadow_samples': 4

example:

from ursina import * app = Ursina() shader = lit_with_shadows_shader a = Entity(model='cube', shader=shader, y=1, color=color.light_gray) Entity(model='sphere', texture='shore', y=2, x=1, shader=shader) Entity(model='plane', scale=16, texture='grass', shader=lit_with_shadows_shader) from ursina.lights import DirectionalLight sun = DirectionalLight(shadow_map_resolution=(2048,2048)) sun.look_at(Vec3(-1,-1,-10)) scene.fog_density = (1, 50) Sky(color=color.light_gray) EditorCamera() def update(): a.x += (held_keys['d'] - held_keys['a']) * time.dt * 5 a.y += (held_keys['e'] - held_keys['q']) * time.dt * 5 a.z += (held_keys['w'] - held_keys['s']) * time.dt * 5 def input(key): if key == 'r': if sun.color == color.white: sun.color = color.red else: sun.color = color.white app.run()


matcap_shader

ursina/shaders/matcap_shader


example:

from ursina import * from ursina.prefabs.primitives import * app = Ursina() window.color=color.black shader = matcap_shader a = WhiteCube(shader=shader, texture='shore') b = WhiteSphere(shader=shader, rotation_y=180, x=3, texture='shore') GrayPlane(scale=10, y=-2, texture='shore') Sky(color=color.light_gray) EditorCamera() def update(): b.rotation_z += 1 b.rotation_y += 1 b.rotation_x += 1 print('-----------------', repr(a.shader)) app.run()


colored_lights_shader

ursina/shaders/colored_lights_shader

default_input
'top_color': color.hsv(220, .12, .82),
'bottom_color': color.hsv(285, .13, .47),
'left_color': color.hsv(217, .3, .68),
'right_color': color.hsv(0, .25, .93),
'front_color': color.hsv(231, .08, .69),
'back_color': color.hsv(240, .05, .76),

example:

from ursina import * from ursina.prefabs.primitives import * app = Ursina() window.color=color.black shader = colored_lights_shader Entity(model='cube', color=color.white, shader=colored_lights_shader) e = Entity(model='cube', x=1.2, shader=colored_lights_shader, color=color.white) e.set_shader_input('top_color', hsv(0,1,1)) e.set_shader_input('bottom_color', hsv(0,0,0)) e.set_shader_input('left_color', hsv(0,0,0)) e.set_shader_input('right_color', hsv(0,0,0)) e.set_shader_input('front_color', hsv(0,0,0)) e.set_shader_input('back_color', hsv(0,0,0)) GrayPlane(scale=10, y=-2, texture='shore') Sky(color=color.light_gray) EditorCamera(rotate_around_mouse_hit=False) EditorCamera() app.run()


fresnel_shader

ursina/shaders/fresnel_shader

default_input
'texture_scale' : Vec2(1,1),
'texture_offset' : Vec2(0.0, 0.0),
'fresnel_color' : color.light_gray,
'fresnel_texture' : Func(load_texture, 'white_cube'),

example:

from ursina import * app = Ursina() b = Entity(model='sphere', color=color.black, shader=fresnel_shader) ground = Entity(model='plane', color=color.gray, shader=fresnel_shader, y=-1, scale=64, texture='grass', texture_scale=Vec2(32,32)) ground.set_shader_input('fresnel_color', color.gray) ground.set_shader_input('fresnel_texture', load_texture('white_cube')) EditorCamera() for i in range(16): e = Entity(model='cube', origin_y=-.5, scale=2, texture='brick', texture_scale=(1,2), x=random.uniform(-8,8), z=random.uniform(-8,8) + 8, scale_y = random.uniform(2,3), color=color.hsv(0, 0, random.uniform(.9, 1)), shader=fresnel_shader, ) e.set_shader_input('fresnel_texture', load_texture('brick')) def update(): for e in scene.entities: if hasattr(e, 'shader') and e.shader == fresnel_shader: e.set_shader_input('camera_world_position', camera.world_position) app.run()


projector_shader

ursina/shaders/projector_shader


example:

from ursina import * app = Ursina() Entity.default_shader = projector_shader editor_camera = EditorCamera(rotation_x=30,) light = Entity(model='sphere', unlit=True) ground = Entity(model='plane', collider='box', scale=64, texture='grass', texture_scale=(4,4)) random.seed(0) for i in range(16): Entity(model='cube', origin_y=-.5, scale=2, texture='brick', texture_scale=(1,2), x=random.uniform(-8,8), z=random.uniform(-8,8) + 8, collider='box', scale_y = random.uniform(2,3), color=color.hsv(0, 0, random.uniform(.9, 1)) ) scene.fog_density = (10, 200) projector_texture = load_texture('vignette', application.internal_textures_folder) projector_shader.default_input['projector_texture'] = projector_texture def update(): light.x += (held_keys['d'] - held_keys['a']) * time.dt * 3 light.z += (held_keys['w'] - held_keys['s']) * time.dt * 3 for e in scene.entities: if hasattr(e,'shader') and e.shader == projector_shader: e.set_shader_input('projector_uv_offset', light.world_position.xz * projector_shader.default_input['projector_uv_scale']) app.run()


texture_blend_shader

ursina/shaders/texture_blend_shader


example:

from ursina import * Texture.default_filtering = 'bilinear' app = Ursina(vsync=False) e = Entity(model='plane', shader=texture_blend_shader, texture='shore') e.set_shader_input('red_texture', load_texture('dirt')) e.set_shader_input('green_texture', load_texture('grass_tintable.tif')) e.set_shader_input('green_tint', color.hex('#6f6d24')) e.set_shader_input('blue_texture', load_texture('cobblestone.tif')) blend_map = load_texture('texture_blend_map_example') e.set_shader_input('blend_map', blend_map) e.scale_x = blend_map.width / blend_map.height e.scale *= 200 EditorCamera(rotation_x=30) def input(key): if key == 'space': if e.shader: e.shader = None else: e.shader = texture_blend_shader if key == 'left mouse up': blend_map.apply() e.collider = 'mesh' def update(): if mouse.left and mouse.hovered_entity == e: x, _, y = mouse.point + Vec3(.5) print(x, y) blend_map.set_pixel(int(x*blend_map.width), int(y*blend_map.height), color.green) blend_map.apply() app.run()


instancing_shader

ursina/shaders/instancing_shader


example:

from ursina import Ursina, window, Entity, EditorCamera, Vec3, color, application, time, Cone import random window.vsync = False app = Ursina() instances = [] Entity(model='plane', texture='grass', scale=128) application.asset_folder = application.asset_folder.parent.parent p = Entity(model=Cone(5), y=1, texture='brick') p.model.uvs = [(v[0],v[1]) for v in p.model.vertices] p.model.generate() p.shader = instancing_shader p.setInstanceCount(256) for z in range(16): for x in range(16): e = Entity(add_to_scene_entities=False, position=Vec3(x, 0, z), color=color.lime, rotation_y=random.random()*360) instances.append(e) print(e.quaternion, Quat()) p.set_shader_input('position_offsets', [e.position*4 for e in instances]) p.set_shader_input('rotation_offsets', [e.quaternion for e in instances]) p.set_shader_input('scale_multipliers',[e.scale*random.uniform(.9,2) for e in instances]) p.set_shader_input('colors', p.model.colors) print(len(p.model.vertices) * len(instances)) EditorCamera() app.run()


triplanar_shader

ursina/shaders/triplanar_shader

default_input
'texture_scale' : Vec2(1,1),
'side_texture' : 'brick',
'side_texture_scale' : Vec2(1,1),

example:

from ursina import * from ursina.prefabs.primitives import * app = Ursina() window.color=color.black shader = triplanar_shader a = Draggable(parent=scene, model='cube', shader=shader, texture=load_texture('brick'), plane_direction=Vec3(0,1,0)) t = load_texture('brick')._texture print('------', type(t)) a.set_shader_input('side_texture', load_texture('brick')) b = AzureSphere(shader=shader, rotation_y=180, x=3, texture='grass') b.texture.filtering = False GrayPlane(scale=10, y=-2, texture='shore') b.set_shader_input('side_texture', load_texture('brick')) Sky(color=color.light_gray) EditorCamera() def set_side_texture_scale(): value = side_texture_scale_slider.value b.set_shader_input('side_texture_scale', Vec2(value, value)) a.set_shader_input('side_texture_scale', Vec2(value, value)) side_texture_scale_slider = Slider(text='side_texture_scale', min=0, max=10, default=1, dynamic=True, on_value_changed=set_side_texture_scale) def update(): b.rotation_y += 1 b.rotation_x += 1 app.run()


normals_shader

ursina/shaders/normals_shader


example:

from ursina import * from ursina.prefabs.primitives import * app = Ursina() window.color=color.black shader = normals_shader a = WhiteCube(shader=shader) b = AzureSphere(rotation_y=180, x=3) b.shader = shader GrayPlane(scale=10, y=-2, texture='shore') Sky(color=color.light_gray) EditorCamera() def update(): b.rotation_z += 1 b.rotation_y += 1 b.rotation_x += 1 app.run()


transition_shader

ursina/shaders/transition_shader


example:

from ursina import * app = Ursina() window.color = color._16 Texture.default_filtering = 'bilinear' e = Entity(model='quad', shader=transition_shader, scale=5, cutoff=0, texture='sword_slash', color=color.azure ) mask = load_texture('sword_slash') e.set_shader_input('mask_texture', mask) EditorCamera() min_cutoff_slider = Slider(0, 1, dynamic=True, y=-.4) def on_value_changed(): e.set_shader_input('min_cutoff', min_cutoff_slider.value) min_cutoff_slider.on_value_changed = on_value_changed max_cutoff_slider = Slider(0, 1, default=1, dynamic=True, y=-.45) def on_value_changed(): e.set_shader_input('max_cutoff', max_cutoff_slider.value) max_cutoff_slider.on_value_changed = on_value_changed def input(key): if key == 'space': e.cutoff = 0 e.animate('cutoff', 1, duration=.1, curve=curve.linear, delay=.05) app.run()


fxaa

ursina/shaders/screenspace_shaders/fxaa

default_input
'window_size': Vec2(1280,720),

example:

app = Ursina() window.color=color.black Entity(model='plane', scale=10, y=-2, texture='shore') EditorCamera() Entity(model='quad', color=color.red, double_sided=True) Entity(model='quad', color=color.green, z=-.001, scale=.5, texture='circle') camera.shader = fxaa_shader camera.clip_plane_far=100 Sky() def input(key): if key == 'space': if not camera.shader: camera.shader = fxaa_shader else: camera.shader = None app.run()


ssao

ursina/shaders/screenspace_shaders/ssao


example:

from ursina import * app = Ursina() e = Entity(model='sphere', color=color.orange) e = Entity(model='cube', y=-1) e = Entity(model='plane', scale=100, y=-1) camera.shader = ssao_shader EditorCamera() def input(key): if key == 'space': if camera.shader: camera.shader = None else: camera.shader = ssao_shader random.seed(2) for i in range(20): e = Entity(model='cube', position=Vec3(random.random(),random.random(),random.random())*3, rotation=Vec3(random.random(),random.random(),random.random())*360) app.run()


camera_outline_shader

ursina/shaders/screenspace_shaders/camera_outline_shader


example:

from ursina import * app = Ursina() Entity(model='cube', texture='white_cube', color=color.red) Entity(model='cube', texture='white_cube', color=color.white, x=1.1) Entity(model='sphere', texture='white_cube', color=color.gray, y=1.1) camera.shader = empty_shader print(camera.shader) t = 0 frame = 0 def update(): global t, frame t += time.dt frame += 1 EditorCamera() app.run()


pixelation_shader

ursina/shaders/screenspace_shaders/pixelation_shader


example:

from ursina import * app = Ursina() e = Entity(model='sphere', color=color.orange) e = Entity(model='cube', y=-1) camera.shader = pixelation_shader EditorCamera() app.run()


camera_contrast

ursina/shaders/screenspace_shaders/camera_contrast

default_input
'contrast': 1,

example:

from ursina import * app = Ursina() e = Entity(model='sphere') e = Entity(model='cube', y=-1) camera.shader = camera_contrast_shader camera.set_shader_input('contrast', 1) slider = ThinSlider(max=2, dynamic=True, position=(-.25, -.45)) def adjust_contrast(): camera.set_shader_input("contrast", slider.value) slider.on_value_changed = adjust_contrast EditorCamera() app.run()


camera_vertical_blur

ursina/shaders/screenspace_shaders/camera_vertical_blur

default_input
=dict(
blur_size = .1

example:

from ursina import * app = Ursina() window.color = color._16 e = Entity(model='sphere', color=color.orange) e = Entity(model='cube', y=-1) camera.shader = camera_vertical_blur_shader slider = ThinSlider(max=.1, dynamic=True, position=(-.25, -.45)) def set_blur(): print(slider.value) camera.set_shader_input("blur_size", slider.value) slider.on_value_changed = set_blur EditorCamera() app.run()


camera_grayscale

ursina/shaders/screenspace_shaders/camera_grayscale


example:

from ursina import * app = Ursina() e = Entity(model='sphere', color=color.orange) e = Entity(model='cube', y=-1) camera.shader = camera_grayscale_shader EditorCamera() def input(key): if key == 'space': if camera.shader: camera.shader = None else: camera.shader = camera_grayscale_shader app.run()