You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Camera app: cleanup, add animations
This commit is contained in:
@@ -849,7 +849,6 @@ class CameraSettingsActivity(Activity):
|
||||
|
||||
def create_advanced_tab(self, tab, prefs):
|
||||
"""Create Advanced settings tab."""
|
||||
#tab.set_scrollbar_mode(lv.SCROLLBAR_MODE.AUTO)
|
||||
tab.set_flex_flow(lv.FLEX_FLOW.COLUMN)
|
||||
tab.set_style_pad_all(1, 0)
|
||||
|
||||
@@ -860,27 +859,23 @@ class CameraSettingsActivity(Activity):
|
||||
|
||||
# Manual Exposure Value (dependent)
|
||||
aec_value = prefs.get_int("aec_value", 300)
|
||||
me_slider, label, cont = self.create_slider(tab, "Manual Exposure", 0, 1200, aec_value, "aec_value")
|
||||
me_slider, label, me_cont = self.create_slider(tab, "Manual Exposure", 0, 1200, aec_value, "aec_value")
|
||||
self.ui_controls["aec_value"] = me_slider
|
||||
|
||||
# Auto Exposure Level (dependent)
|
||||
ae_level = prefs.get_int("ae_level", 0)
|
||||
ae_slider, label, cont = self.create_slider(tab, "Auto Exposure Level", -2, 2, ae_level, "ae_level")
|
||||
ae_slider, label, ae_cont = self.create_slider(tab, "Auto Exposure Level", -2, 2, ae_level, "ae_level")
|
||||
self.ui_controls["ae_level"] = ae_slider
|
||||
|
||||
# Add dependency handler
|
||||
def exposure_ctrl_changed(e=None):
|
||||
is_auto = aec_checkbox.get_state() & lv.STATE.CHECKED
|
||||
if is_auto:
|
||||
me_slider.add_state(lv.STATE.DISABLED)
|
||||
me_slider.set_style_opa(128, 0)
|
||||
ae_slider.remove_state(lv.STATE.DISABLED)
|
||||
ae_slider.set_style_opa(255, 0)
|
||||
mpos.ui.anim.smooth_hide(me_cont, duration=1000)
|
||||
mpos.ui.anim.smooth_show(ae_cont, delay=1000)
|
||||
else:
|
||||
me_slider.remove_state(lv.STATE.DISABLED)
|
||||
me_slider.set_style_opa(255, 0)
|
||||
ae_slider.add_state(lv.STATE.DISABLED)
|
||||
ae_slider.set_style_opa(128, 0)
|
||||
mpos.ui.anim.smooth_hide(ae_cont, duration=1000)
|
||||
mpos.ui.anim.smooth_show(me_cont, delay=1000)
|
||||
|
||||
aec_checkbox.add_event_cb(exposure_ctrl_changed, lv.EVENT.VALUE_CHANGED, None)
|
||||
exposure_ctrl_changed()
|
||||
@@ -897,24 +892,19 @@ class CameraSettingsActivity(Activity):
|
||||
|
||||
# Manual Gain Value (dependent)
|
||||
agc_gain = prefs.get_int("agc_gain", 0)
|
||||
slider, label, cont = self.create_slider(tab, "Manual Gain", 0, 30, agc_gain, "agc_gain")
|
||||
slider, label, agc_cont = self.create_slider(tab, "Manual Gain", 0, 30, agc_gain, "agc_gain")
|
||||
self.ui_controls["agc_gain"] = slider
|
||||
|
||||
if gain_ctrl:
|
||||
slider.add_state(lv.STATE.DISABLED)
|
||||
slider.set_style_opa(128, 0)
|
||||
|
||||
def gain_ctrl_changed(e):
|
||||
def gain_ctrl_changed(e=None):
|
||||
is_auto = agc_checkbox.get_state() & lv.STATE.CHECKED
|
||||
gain_slider = self.ui_controls["agc_gain"]
|
||||
if is_auto:
|
||||
gain_slider.add_state(lv.STATE.DISABLED)
|
||||
gain_slider.set_style_opa(128, 0)
|
||||
mpos.ui.anim.smooth_hide(agc_cont, duration=1000)
|
||||
else:
|
||||
gain_slider.remove_state(lv.STATE.DISABLED)
|
||||
gain_slider.set_style_opa(255, 0)
|
||||
mpos.ui.anim.smooth_show(agc_cont, duration=1000)
|
||||
|
||||
agc_checkbox.add_event_cb(gain_ctrl_changed, lv.EVENT.VALUE_CHANGED, None)
|
||||
gain_ctrl_changed()
|
||||
|
||||
# Gain Ceiling
|
||||
gainceiling_options = [
|
||||
@@ -935,21 +925,17 @@ class CameraSettingsActivity(Activity):
|
||||
("Auto", 0), ("Sunny", 1), ("Cloudy", 2), ("Office", 3), ("Home", 4)
|
||||
]
|
||||
wb_mode = prefs.get_int("wb_mode", 0)
|
||||
dropdown, cont = self.create_dropdown(tab, "WB Mode:", wb_mode_options, wb_mode, "wb_mode")
|
||||
self.ui_controls["wb_mode"] = dropdown
|
||||
wb_dropdown, wb_cont = self.create_dropdown(tab, "WB Mode:", wb_mode_options, wb_mode, "wb_mode")
|
||||
self.ui_controls["wb_mode"] = wb_dropdown
|
||||
|
||||
if whitebal:
|
||||
dropdown.add_state(lv.STATE.DISABLED)
|
||||
|
||||
def whitebal_changed(e):
|
||||
def whitebal_changed(e=None):
|
||||
is_auto = wbcheckbox.get_state() & lv.STATE.CHECKED
|
||||
wb_dropdown = self.ui_controls["wb_mode"]
|
||||
if is_auto:
|
||||
wb_dropdown.add_state(lv.STATE.DISABLED)
|
||||
mpos.ui.anim.smooth_hide(wb_cont, duration=1000)
|
||||
else:
|
||||
wb_dropdown.remove_state(lv.STATE.DISABLED)
|
||||
|
||||
mpos.ui.anim.smooth_show(wb_cont, duration=1000)
|
||||
wbcheckbox.add_event_cb(whitebal_changed, lv.EVENT.VALUE_CHANGED, None)
|
||||
whitebal_changed()
|
||||
|
||||
# AWB Gain
|
||||
awb_gain = prefs.get_bool("awb_gain", True)
|
||||
@@ -974,36 +960,16 @@ class CameraSettingsActivity(Activity):
|
||||
tab.set_flex_flow(lv.FLEX_FLOW.COLUMN)
|
||||
tab.set_style_pad_all(1, 0)
|
||||
|
||||
# Note: Sensor detection isn't performed right now
|
||||
# For now, show sharpness/denoise with note
|
||||
supports_sharpness = True # Assume yes
|
||||
|
||||
# Sharpness
|
||||
sharpness = prefs.get_int("sharpness", 0)
|
||||
slider, label, cont = self.create_slider(tab, "Sharpness", -3, 3, sharpness, "sharpness")
|
||||
self.ui_controls["sharpness"] = slider
|
||||
|
||||
if not supports_sharpness:
|
||||
slider.add_state(lv.STATE.DISABLED)
|
||||
slider.set_style_opa(128, 0)
|
||||
note = lv.label(cont)
|
||||
note.set_text("(Not available on this sensor)")
|
||||
note.set_style_text_color(lv.color_hex(0x808080), 0)
|
||||
note.align(lv.ALIGN.TOP_RIGHT, 0, 0)
|
||||
|
||||
# Denoise
|
||||
denoise = prefs.get_int("denoise", 0)
|
||||
slider, label, cont = self.create_slider(tab, "Denoise", 0, 8, denoise, "denoise")
|
||||
self.ui_controls["denoise"] = slider
|
||||
|
||||
if not supports_sharpness:
|
||||
slider.add_state(lv.STATE.DISABLED)
|
||||
slider.set_style_opa(128, 0)
|
||||
note = lv.label(cont)
|
||||
note.set_text("(Not available on this sensor)")
|
||||
note.set_style_text_color(lv.color_hex(0x808080), 0)
|
||||
note.align(lv.ALIGN.TOP_RIGHT, 0, 0)
|
||||
|
||||
# JPEG Quality
|
||||
# Disabled because JPEG is not used right now
|
||||
#quality = prefs.get_int("quality", 85)
|
||||
|
||||
@@ -41,19 +41,18 @@ class WidgetAnimator:
|
||||
# show_widget and hide_widget could have a (lambda) callback that sets the final state (eg: drawer_open) at the end
|
||||
@staticmethod
|
||||
def show_widget(widget, anim_type="fade", duration=500, delay=0):
|
||||
"""Show a widget with an animation (fade or slide)."""
|
||||
|
||||
lv.anim_delete(widget, None) # stop all ongoing animations to prevent visual glitches
|
||||
widget.remove_flag(lv.obj.FLAG.HIDDEN) # Clear HIDDEN flag to make widget visible for animation
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_delay(delay)
|
||||
anim.set_duration(duration)
|
||||
# Clear HIDDEN flag to make widget visible for animation:
|
||||
anim.set_start_cb(lambda *args: safe_widget_access(lambda: widget.remove_flag(lv.obj.FLAG.HIDDEN)))
|
||||
|
||||
if anim_type == "fade":
|
||||
# Create fade-in animation (opacity from 0 to 255)
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(0, 255)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_style_opa(value, 0)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Ensure opacity is reset after animation
|
||||
@@ -63,50 +62,38 @@ class WidgetAnimator:
|
||||
# Create slide-down animation (y from -height to original y)
|
||||
original_y = widget.get_y()
|
||||
height = widget.get_height()
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(original_y - height, original_y)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Reset y position after animation
|
||||
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: widget.set_y(original_y)))
|
||||
elif anim_type == "slide_up":
|
||||
else: # "slide_up":
|
||||
# Create slide-up animation (y from +height to original y)
|
||||
# Seems to cause scroll bars to be added somehow if done to a keyboard at the bottom of the screen...
|
||||
original_y = widget.get_y()
|
||||
height = widget.get_height()
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(original_y + height, original_y)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Reset y position after animation
|
||||
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: widget.set_y(original_y)))
|
||||
|
||||
# Store and start animation
|
||||
#self.animations[widget] = anim
|
||||
anim.start()
|
||||
return anim
|
||||
|
||||
@staticmethod
|
||||
def hide_widget(widget, anim_type="fade", duration=500, delay=0, hide=True):
|
||||
lv.anim_delete(widget, None) # stop all ongoing animations to prevent visual glitches
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
|
||||
"""Hide a widget with an animation (fade or slide)."""
|
||||
if anim_type == "fade":
|
||||
# Create fade-out animation (opacity from 255 to 0)
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(255, 0)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_style_opa(value, 0)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Set HIDDEN flag after animation
|
||||
@@ -116,34 +103,22 @@ class WidgetAnimator:
|
||||
# Seems to cause scroll bars to be added somehow if done to a keyboard at the bottom of the screen...
|
||||
original_y = widget.get_y()
|
||||
height = widget.get_height()
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(original_y, original_y + height)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Set HIDDEN flag after animation
|
||||
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: WidgetAnimator.hide_complete_cb(widget, original_y, hide)))
|
||||
elif anim_type == "slide_up":
|
||||
else: # "slide_up":
|
||||
print("hide with slide_up")
|
||||
# Create slide-up animation (y from original y to -height)
|
||||
original_y = widget.get_y()
|
||||
height = widget.get_height()
|
||||
anim = lv.anim_t()
|
||||
anim.init()
|
||||
anim.set_var(widget)
|
||||
anim.set_values(original_y, original_y - height)
|
||||
anim.set_duration(duration)
|
||||
anim.set_delay(delay)
|
||||
anim.set_custom_exec_cb(lambda anim, value: safe_widget_access(lambda: widget.set_y(value)))
|
||||
anim.set_path_cb(lv.anim_t.path_ease_in_out)
|
||||
# Set HIDDEN flag after animation
|
||||
anim.set_completed_cb(lambda *args: safe_widget_access(lambda: WidgetAnimator.hide_complete_cb(widget, original_y, hide)))
|
||||
|
||||
# Store and start animation
|
||||
#self.animations[widget] = anim
|
||||
anim.start()
|
||||
return anim
|
||||
|
||||
@@ -156,8 +131,8 @@ class WidgetAnimator:
|
||||
widget.set_y(original_y) # in case it shifted slightly due to rounding etc
|
||||
|
||||
|
||||
def smooth_show(widget):
|
||||
return WidgetAnimator.show_widget(widget, anim_type="fade", duration=500, delay=0)
|
||||
def smooth_show(widget, duration=500, delay=0):
|
||||
return WidgetAnimator.show_widget(widget, anim_type="fade", duration=duration, delay=delay)
|
||||
|
||||
def smooth_hide(widget, hide=True):
|
||||
return WidgetAnimator.hide_widget(widget, anim_type="fade", duration=500, delay=0, hide=hide)
|
||||
def smooth_hide(widget, hide=True, duration=500, delay=0):
|
||||
return WidgetAnimator.hide_widget(widget, anim_type="fade", duration=duration, delay=delay, hide=hide)
|
||||
|
||||
Reference in New Issue
Block a user