mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[Update] Epsilon 15.3.1
This commit is contained in:
@@ -177,6 +177,9 @@ void Turtle::setVisible(bool visible) {
|
||||
|
||||
void Turtle::write(const char * string) {
|
||||
// We erase the turtle to redraw it on top of the text
|
||||
if (isOutOfBounds()) {
|
||||
return;
|
||||
}
|
||||
erase();
|
||||
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
@@ -195,6 +198,10 @@ void Turtle::viewDidDisappear() {
|
||||
m_drawn = false;
|
||||
}
|
||||
|
||||
bool Turtle::isOutOfBounds() const {
|
||||
return absF(x()) > k_maxPosition || absF(y()) > k_maxPosition;
|
||||
};
|
||||
|
||||
// Private functions
|
||||
|
||||
void Turtle::setHeadingPrivate(mp_float_t angle) {
|
||||
@@ -255,6 +262,7 @@ bool Turtle::hasDotBuffers() {
|
||||
}
|
||||
|
||||
KDRect Turtle::iconRect() const {
|
||||
assert(!isOutOfBounds());
|
||||
KDPoint iconOffset = KDPoint(-k_iconSize/2, -k_iconSize/2);
|
||||
return KDRect(position().translatedBy(iconOffset), k_iconSize, k_iconSize);
|
||||
}
|
||||
@@ -262,7 +270,7 @@ KDRect Turtle::iconRect() const {
|
||||
bool Turtle::draw(bool force) {
|
||||
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
|
||||
|
||||
if ((m_speed > 0 || force) && m_visible && !m_drawn && hasUnderneathPixelBuffer()) {
|
||||
if ((m_speed > 0 || force) && m_visible && !m_drawn && hasUnderneathPixelBuffer() && !isOutOfBounds()) {
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
|
||||
// Get the pixels underneath the turtle
|
||||
@@ -344,7 +352,7 @@ bool Turtle::dot(mp_float_t x, mp_float_t y) {
|
||||
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
|
||||
|
||||
// Draw the dot if the pen is down
|
||||
if (m_penDown && hasDotBuffers()) {
|
||||
if (m_penDown && hasDotBuffers() && !isOutOfBounds()) {
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
KDRect rect(
|
||||
position(x, y).translatedBy(KDPoint(-m_penSize/2, -m_penSize/2)),
|
||||
@@ -369,6 +377,7 @@ bool Turtle::dot(mp_float_t x, mp_float_t y) {
|
||||
void Turtle::drawPaw(PawType type, PawPosition pos) {
|
||||
assert(!m_drawn);
|
||||
assert(m_underneathPixelBuffer != nullptr);
|
||||
assert(!isOutOfBounds());
|
||||
KDCoordinate pawOffset = 5;
|
||||
constexpr float crawlOffset = 0.6f;
|
||||
constexpr float angles[] = {M_PI_4, 3*M_PI_4, -3*M_PI_4, -M_PI_4};
|
||||
@@ -391,7 +400,7 @@ void Turtle::drawPaw(PawType type, PawPosition pos) {
|
||||
}
|
||||
|
||||
void Turtle::erase() {
|
||||
if (!m_drawn || m_underneathPixelBuffer == nullptr) {
|
||||
if (!m_drawn || m_underneathPixelBuffer == nullptr || isOutOfBounds()) {
|
||||
return;
|
||||
}
|
||||
KDContext * ctx = KDIonContext::sharedContext();
|
||||
|
||||
@@ -82,6 +82,13 @@ public:
|
||||
|
||||
void viewDidDisappear();
|
||||
|
||||
/* isOutOfBounds returns true if nothing should be drawn at current position.
|
||||
* We avoid drawing at extreme position (far from screen bounds) to prevent
|
||||
* coordinate overflows. However, this solution makes the turtle go faster
|
||||
* when out of bound, and can prevent text that would have been visible to be
|
||||
* drawn. We use very large bounds to temper these effects. */
|
||||
bool isOutOfBounds() const;
|
||||
|
||||
private:
|
||||
static constexpr mp_float_t k_headingScale = M_PI / 180;
|
||||
/* The Y axis is oriented upwards in Turtle and downwards in Kandinsky, so we
|
||||
@@ -94,6 +101,7 @@ private:
|
||||
static constexpr KDColor k_defaultColor = KDColorBlack;
|
||||
static constexpr uint8_t k_defaultPenSize = 1;
|
||||
static constexpr const KDFont * k_font = KDFont::LargeFont;
|
||||
static constexpr mp_float_t k_maxPosition = KDCOORDINATE_MAX * 0.75f;
|
||||
|
||||
enum class PawType : uint8_t {
|
||||
FrontRight = 0,
|
||||
|
||||
@@ -164,15 +164,16 @@ void MicroPython::init(void * heapStart, void * heapEnd) {
|
||||
static mp_obj_t pystack[1024];
|
||||
mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]);
|
||||
#endif
|
||||
|
||||
volatile int stackTop;
|
||||
void * stackTopAddress = (void *)(&stackTop);
|
||||
/* We delimit the stack part that will be used by Python. The stackTop is the
|
||||
* address of the first object that can be allocated on Python stack. This
|
||||
* boundaries are used:
|
||||
* - by gc_collect to determine where to collect roots of the objects that
|
||||
* must be kept on the heap
|
||||
* - to check if the maximal recursion depth has been reached. */
|
||||
* - to check if the maximal recursion depth has been reached.
|
||||
* Current stack pointer could go backward after initialization. A stack start
|
||||
* pointer defined in main is therefore used. */
|
||||
void * stackTopAddress = Ion::stackStart();
|
||||
|
||||
#if MP_PORT_USE_STACK_SYMBOLS
|
||||
mp_stack_set_top(stackTopAddress);
|
||||
size_t stackLimitInBytes = (char *)stackTopAddress - (char *)&_stack_end;
|
||||
@@ -218,7 +219,7 @@ void MicroPython::collectRootsAtAddress(char * address, int byteLength) {
|
||||
alignedByteLength += reinterpret_cast<uintptr_t>(address) & bitMaskOnes;
|
||||
|
||||
assert(alignedAddress % ((uintptr_t)sizeof(uintptr_t)) == 0);
|
||||
gc_collect_root((void **)alignedAddress, byteLength / sizeof(uintptr_t));
|
||||
gc_collect_root((void **)alignedAddress, alignedByteLength / sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
|
||||
@@ -243,7 +244,8 @@ KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
|
||||
NamedColor("pink", Palette::Pink),
|
||||
NamedColor("orange", Palette::Orange),
|
||||
NamedColor("purple", Palette::Purple),
|
||||
NamedColor("grey", Palette::GreyDark),
|
||||
NamedColor("gray", Palette::GrayDark),
|
||||
NamedColor("grey", Palette::GrayDark),
|
||||
NamedColor("cyan", Palette::Cyan),
|
||||
NamedColor("magenta", Palette::Magenta)
|
||||
};
|
||||
@@ -262,12 +264,12 @@ KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
|
||||
return KDColor::RGB24(colorInt);
|
||||
}
|
||||
|
||||
mp_float_t greyLevel = mp_obj_float_get(mp_parse_num_decimal(color, strlen(color), false, false, NULL));
|
||||
if (greyLevel >= 0.0 && greyLevel <= 1.0) {
|
||||
uint8_t color = maxColorIntensity * (float) greyLevel;
|
||||
mp_float_t grayLevel = mp_obj_float_get(mp_parse_num_decimal(color, strlen(color), false, false, NULL));
|
||||
if (grayLevel >= 0.0 && grayLevel <= 1.0) {
|
||||
uint8_t color = maxColorIntensity * (float) grayLevel;
|
||||
return KDColor::RGB888(color, color, color);
|
||||
}
|
||||
mp_raise_ValueError("Grey levels are between 0.0 and 1.0");
|
||||
mp_raise_ValueError("Gray levels are between 0.0 and 1.0");
|
||||
} else if(mp_obj_is_int(input)) {
|
||||
mp_raise_TypeError("Int are not colors");
|
||||
//See https://github.com/numworks/epsilon/issues/1533#issuecomment-618443492
|
||||
|
||||
Reference in New Issue
Block a user