designer2 import sequences

This commit is contained in:
nakst 2021-10-01 21:53:34 +01:00
parent 9dfe4f0a8b
commit 91e674a7f3
5 changed files with 469 additions and 156 deletions

View File

@ -740,7 +740,6 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
instance->title, instance->titleBytes, instance->iconID);
} else if (message->type == ES_MSG_ANIMATE) {
message->animate.complete = ReorderItemAnimate(tab, message->animate.deltaMs, "windowTabEntranceDuration");
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) {
EsElementSetDisabled(band->GetChild(0), true);
@ -847,6 +846,13 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
EsMenuShow(menu);
} else if (message->type == ES_MSG_MOUSE_MIDDLE_UP && ((element->state & UI_STATE_HOVERED) || (tab->closeButton->state & UI_STATE_HOVERED))) {
if (EsButtonGetCheck(tab->closeButton) == ES_CHECK_CHECKED) {
// The tab contains a modified document, so it will probably popup a dialog after it receives the close request.
// Therefore, we should switch to that tab.
tab->BringToFront();
WindowTabActivate(tab);
}
WindowTabClose(tab);
} else if (message->type == ES_MSG_REORDER_ITEM_TEST) {
} else {

Binary file not shown.

Binary file not shown.

View File

@ -1664,7 +1664,6 @@ enum ObjectType {
OBJ_VAR_COLOR = 0x40,
OBJ_VAR_INT,
OBJ_VAR_TEXT_STYLE,
OBJ_VAR_ICON_STYLE,
OBJ_VAR_CONTOUR_STYLE,
OBJ_PAINT_OVERWRITE = 0x60,
@ -1724,7 +1723,7 @@ void ObjectAddObjectProperty(Object2 *object, const char *cName, uint64_t value)
arrput(object->properties, property);
}
uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *idAllocator) {
uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *idAllocator, Layer *layer) {
char cPropertyName[PROPERTY_NAME_SIZE];
if (!paint->tag) {
@ -1768,6 +1767,67 @@ uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *
*x += 100;
arrput(*objects, object);
if (layer) {
for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) {
Sequence *s = layer->sequences[i];
assert(arrlenu(s->keyframes) == 1);
Keyframe *keyframe = s->keyframes[0];
uint32_t stateBits = 0;
if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED;
if (s->flagChecked) stateBits |= THEME_STATE_CHECKED;
if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE;
if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON;
if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM;
if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED;
if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER;
if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT;
if (s->flagSelected) stateBits |= THEME_STATE_SELECTED;
Object2 override = { .type = object.type, .id = ++(*idAllocator) };
ObjectAddIntegerProperty(&override, "_graphX", *x);
ObjectAddIntegerProperty(&override, "_graphY", y);
ObjectAddIntegerProperty(&override, "_graphW", 80);
ObjectAddIntegerProperty(&override, "_graphH", 60);
ObjectAddObjectProperty(&override, "_parent", object.id);
ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState);
ObjectAddIntegerProperty(&override, "_stateBits", stateBits);
ObjectAddIntegerProperty(&override, "_duration", s->duration);
bool addObject = false;
for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) {
Property *property = &keyframe->properties[i];
if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8
&& property->path[2] == 0 && property->path[3] == 2 && property->path[4] == 2) {
assert(property->path[5] == 2 && property->path[7] == 0);
RfGrowableBuffer state = { 0 };
state.s.op = RF_OP_LOAD;
state.s.access = RfReadGrowableBuffer;
state.data = property->data;
RfItem item = GradientStop_Type.fields[GradientStop_color].item;
uint32_t value; item.type->op(&state.s, &item, &value);
char cPropertyName[PROPERTY_NAME_SIZE];
snprintf(cPropertyName, sizeof(cPropertyName), "stops_%d_color", property->path[6]);
ObjectAddObjectProperty(&override, cPropertyName, ColorLookupPointer(value)->object2ID);
addObject = true;
} else {
continue;
}
}
if (addObject) {
arrput(*objects, override);
object.id = override.id;
*x += 100;
} else {
arrfree(override.properties);
}
}
}
return object.id;
} else if (paint->tag == Paint_radialGradient + 1) {
Object2 object = { .type = OBJ_PAINT_RADIAL_GRADIENT, .id = ++(*idAllocator) };
@ -1805,6 +1865,63 @@ uint64_t ExportPaint2(Paint *paint, int *x, int y, Object2 **objects, uint64_t *
ObjectAddObjectProperty(&object, "color", ColorLookupPointer(paint->overwrite.color)->object2ID);
*x += 100;
arrput(*objects, object);
if (layer) {
for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) {
Sequence *s = layer->sequences[i];
assert(arrlenu(s->keyframes) == 1);
Keyframe *keyframe = s->keyframes[0];
uint32_t stateBits = 0;
if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED;
if (s->flagChecked) stateBits |= THEME_STATE_CHECKED;
if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE;
if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON;
if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM;
if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED;
if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER;
if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT;
if (s->flagSelected) stateBits |= THEME_STATE_SELECTED;
Object2 override = { .type = object.type, .id = ++(*idAllocator) };
ObjectAddIntegerProperty(&override, "_graphX", *x);
ObjectAddIntegerProperty(&override, "_graphY", y);
ObjectAddIntegerProperty(&override, "_graphW", 80);
ObjectAddIntegerProperty(&override, "_graphH", 60);
ObjectAddObjectProperty(&override, "_parent", object.id);
ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState);
ObjectAddIntegerProperty(&override, "_stateBits", stateBits);
ObjectAddIntegerProperty(&override, "_duration", s->duration);
bool addObject = false;
for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) {
Property *property = &keyframe->properties[i];
if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8
&& property->path[2] == 0 && property->path[3] == 2 && property->path[4] == 3) {
assert(property->path[5] == 0);
RfGrowableBuffer state = { 0 };
state.s.op = RF_OP_LOAD;
state.s.access = RfReadGrowableBuffer;
state.data = property->data;
RfItem item = PaintOverwrite_Type.fields[PaintOverwrite_color].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(&override, "color", ColorLookupPointer(value)->object2ID);
addObject = true;
} else {
continue;
}
}
if (addObject) {
arrput(*objects, override);
object.id = override.id;
*x += 100;
}
}
}
return object.id;
} else {
assert(false);
@ -1837,10 +1954,137 @@ uint64_t ExportFillMode2(PathFillMode *fill, int *x, int y, Object2 **objects, u
}
}
void ExportProperty2(Layer *layer, Property *property, Object2 *override) {
bool unhandled = false;
RfGrowableBuffer state = { 0 };
state.s.op = RF_OP_LOAD;
state.s.access = RfReadGrowableBuffer;
state.data = property->data;
if (property->path[0] == (uint32_t) -2 && property->path[1] == 8 && property->path[2] == 0) {
if (layer->base.tag == LayerBase_box + 1) {
if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_l) {
RfItem item = Rectangle8_Type.fields[Rectangle8_l].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "borders0", value);
} else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_r) {
RfItem item = Rectangle8_Type.fields[Rectangle8_r].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "borders1", value);
} else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_t) {
RfItem item = Rectangle8_Type.fields[Rectangle8_t].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "borders2", value);
} else if (property->path[3] == LayerBox_borders && property->path[4] == Rectangle8_b) {
RfItem item = Rectangle8_Type.fields[Rectangle8_b].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "borders3", value);
} else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_tl) {
RfItem item = Corners8_Type.fields[Corners8_tl].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "corners0", value);
} else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_tr) {
RfItem item = Corners8_Type.fields[Corners8_tr].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "corners1", value);
} else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_bl) {
RfItem item = Corners8_Type.fields[Corners8_bl].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "corners2", value);
} else if (property->path[3] == LayerBox_corners && property->path[4] == Corners8_br) {
RfItem item = Corners8_Type.fields[Corners8_br].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "corners3", value);
} else if (property->path[3] == LayerBox_mainPaint && property->path[4] == Paint_solid && property->path[5] == PaintSolid_color) {
RfItem item = PaintSolid_Type.fields[PaintSolid_color].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(override, "mainPaint", ColorLookupPointer(value)->object2ID);
} else if (property->path[3] == LayerBox_borderPaint && property->path[4] == Paint_solid && property->path[5] == PaintSolid_color) {
RfItem item = PaintSolid_Type.fields[PaintSolid_color].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(override, "borderPaint", ColorLookupPointer(value)->object2ID);
} else if (property->path[3] == LayerBox_mainPaint && property->path[4] == Paint_overwrite && property->path[5] == PaintOverwrite_color) {
fprintf(stderr, "\t>>\n");
} else {
unhandled = true;
}
} else if (layer->base.tag == LayerBase_metrics + 1) {
if (property->path[3] == LayerMetrics_textSize || property->path[3] == LayerMetrics_selectedText) {
// Ignore.
} else if (property->path[3] == LayerMetrics_textColor) {
RfItem item = LayerMetrics_Type.fields[LayerMetrics_textColor].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(override, "textColor", ColorLookupPointer(value)->object2ID);
} else if (property->path[3] == LayerMetrics_iconColor) {
RfItem item = LayerMetrics_Type.fields[LayerMetrics_iconColor].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(override, "iconColor", ColorLookupPointer(value)->object2ID);
} else {
unhandled = true;
}
} else if (layer->base.tag == LayerBase_path + 1) {
if (property->path[3] == LayerPath_alpha) {
RfItem item = LayerPath_Type.fields[LayerPath_alpha].item;
int16_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "alpha", value);
} else if (property->path[3] == LayerPath_fills && property->path[4] == 0 && property->path[5] == PathFill_paint
&& property->path[6] == Paint_solid && property->path[7] == PaintSolid_color) {
RfItem item = PaintSolid_Type.fields[PaintSolid_color].item;
uint32_t value; item.type->op(&state.s, &item, &value);
ObjectAddObjectProperty(override, "fills_0_paint", ColorLookupPointer(value)->object2ID);
ObjectAddIntegerProperty(override, "fills_count", 1);
} else {
unhandled = true;
}
} else {
unhandled = true;
}
} else if (property->path[0] == (uint32_t) -2 && property->path[1] == 5) {
if (layer->base.tag == LayerBase_box + 1) {
if (property->path[2] == Rectangle8_l) {
RfItem item = Rectangle8_Type.fields[Rectangle8_l].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "offset0", value - layer->offset.l);
} else if (property->path[2] == Rectangle8_r) {
RfItem item = Rectangle8_Type.fields[Rectangle8_r].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "offset1", value - layer->offset.r);
} else if (property->path[2] == Rectangle8_t) {
RfItem item = Rectangle8_Type.fields[Rectangle8_t].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "offset2", value - layer->offset.t);
} else if (property->path[2] == Rectangle8_b) {
RfItem item = Rectangle8_Type.fields[Rectangle8_b].item;
int8_t value; item.type->op(&state.s, &item, &value);
ObjectAddIntegerProperty(override, "offset3", value - layer->offset.b);
}
} else {
unhandled = true;
}
} else {
unhandled = true;
}
assert(!unhandled);
#if 0
if (unhandled) {
fprintf(stderr, "\tunhandled on %s: ", LayerBase_Type.fields[layer->base.tag - 1].cName);
for (uintptr_t i = 0; property->path[i] != RF_PATH_TERMINATOR; i++) {
fprintf(stderr, "%d, ", property->path[i]);
}
fprintf(stderr, "\n");
}
#endif
}
void ActionExportDesigner2(void *cp) {
// TODO Exporting sequences.
// TODO Inherited text styles.
// TODO Merging identical layers and styles.
// TODO Auto-name override layers.
Object2 *objects = NULL;
uint64_t objectIDAllocator = 0;
@ -1896,12 +2140,12 @@ void ActionExportDesigner2(void *cp) {
Style *style = styleSet.styles[i];
Object2 layerGroup = { .type = OBJ_LAYER_GROUP, .id = ++objectIDAllocator };
Object2 metrics = { 0 }, textStyle = { 0 }, iconStyle = { 0 };
Object2 metrics = { 0 }, textStyle = { 0 };
int32_t layerCount = 0;
for (uintptr_t i = 0; i < arrlenu(style->layers); i++) {
Layer *layer = LayerLookup(style->layers[i]);
bool addToLayerGroup = false, addToObjects = false;
bool addToLayerGroup = false;
Object2 object = { 0 };
if (layer->base.tag == LayerBase_box + 1) {
@ -1919,16 +2163,14 @@ void ActionExportDesigner2(void *cp) {
ObjectAddIntegerProperty(&object, "autoCorners", box->autoCorners);
ObjectAddIntegerProperty(&object, "autoBorders", box->autoBorders);
ObjectAddIntegerProperty(&object, "shadowHiding", box->shadowHiding);
ObjectAddObjectProperty(&object, "mainPaint", ExportPaint2(&box->mainPaint, &x, y, &objects, &objectIDAllocator));
ObjectAddObjectProperty(&object, "borderPaint", ExportPaint2(&box->borderPaint, &x, y, &objects, &objectIDAllocator));
ObjectAddObjectProperty(&object, "mainPaint", ExportPaint2(&box->mainPaint, &x, y, &objects, &objectIDAllocator, layer));
ObjectAddObjectProperty(&object, "borderPaint", ExportPaint2(&box->borderPaint, &x, y, &objects, &objectIDAllocator, NULL));
addToLayerGroup = true;
addToObjects = true;
} else if (layer->base.tag == LayerBase_text + 1) {
object.type = OBJ_LAYER_TEXT, object.id = ++objectIDAllocator;
ObjectAddObjectProperty(&object, "color", ColorLookupPointer(layer->base.text.color)->object2ID);
ObjectAddIntegerProperty(&object, "blur", layer->base.text.blur);
addToLayerGroup = true;
addToObjects = true;
} else if (layer->base.tag == LayerBase_path + 1) {
object.type = OBJ_LAYER_PATH, object.id = ++objectIDAllocator;
LayerPath *path = &layer->base.path;
@ -1955,72 +2197,138 @@ void ActionExportDesigner2(void *cp) {
for (uintptr_t i = 0; i < arrlenu(path->fills); i++) {
sprintf(cPropertyName, "fills_%d_paint", (int) i);
ObjectAddObjectProperty(&object, cPropertyName, ExportPaint2(&path->fills[i].paint, &x, y, &objects, &objectIDAllocator));
ObjectAddObjectProperty(&object, cPropertyName, ExportPaint2(&path->fills[i].paint, &x, y, &objects, &objectIDAllocator, NULL));
sprintf(cPropertyName, "fills_%d_mode", (int) i);
ObjectAddObjectProperty(&object, cPropertyName, ExportFillMode2(&path->fills[i].mode, &x, y, &objects, &objectIDAllocator));
}
addToLayerGroup = true;
addToObjects = true;
} else {
object.type = OBJ_LAYER_METRICS, object.id = ++objectIDAllocator;
} else if (layer->base.tag == LayerBase_metrics + 1) {
LayerMetrics *m = &layer->base.metrics;
ObjectAddIntegerProperty(&object, "clipEnabled", m->clipEnabled);
ObjectAddIntegerProperty(&object, "wrapText", m->wrapText);
ObjectAddIntegerProperty(&object, "ellipsis", m->ellipsis);
ObjectAddIntegerProperty(&object, "insets0", m->insets.l);
ObjectAddIntegerProperty(&object, "insets1", m->insets.r);
ObjectAddIntegerProperty(&object, "insets2", m->insets.t);
ObjectAddIntegerProperty(&object, "insets3", m->insets.b);
ObjectAddIntegerProperty(&object, "clipInsets0", m->clipInsets.l);
ObjectAddIntegerProperty(&object, "clipInsets1", m->clipInsets.r);
ObjectAddIntegerProperty(&object, "clipInsets2", m->clipInsets.t);
ObjectAddIntegerProperty(&object, "clipInsets3", m->clipInsets.b);
ObjectAddIntegerProperty(&object, "preferredWidth", m->preferredSize.width);
ObjectAddIntegerProperty(&object, "preferredHeight", m->preferredSize.height);
ObjectAddIntegerProperty(&object, "minimumWidth", m->minimumSize.width);
ObjectAddIntegerProperty(&object, "minimumHeight", m->minimumSize.height);
ObjectAddIntegerProperty(&object, "maximumWidth", m->maximumSize.width);
ObjectAddIntegerProperty(&object, "maximumHeight", m->maximumSize.height);
ObjectAddIntegerProperty(&object, "gapMajor", m->gaps.major);
ObjectAddIntegerProperty(&object, "gapMinor", m->gaps.minor);
ObjectAddIntegerProperty(&object, "gapWrap", m->gaps.wrap);
ObjectAddIntegerProperty(&object, "cursor", m->cursor);
ObjectAddIntegerProperty(&object, "horizontalTextAlign", m->textHorizontalAlign + 1);
ObjectAddIntegerProperty(&object, "verticalTextAlign", m->textVerticalAlign + 1);
assert(!m->globalOffset.l && !m->globalOffset.r && !m->globalOffset.t && !m->globalOffset.b);
addToObjects = true;
metrics = object;
textStyle.type = OBJ_VAR_TEXT_STYLE, textStyle.id = ++objectIDAllocator;
ObjectAddIntegerProperty(&textStyle, "_graphX", x);
ObjectAddIntegerProperty(&textStyle, "_graphY", y);
ObjectAddIntegerProperty(&textStyle, "_graphW", 80);
ObjectAddIntegerProperty(&textStyle, "_graphH", 60);
ObjectAddObjectProperty(&textStyle, "textColor", ColorLookupPointer(m->textColor)->object2ID);
ObjectAddObjectProperty(&textStyle, "selectedBackground", ColorLookupPointer(m->selectedBackground)->object2ID);
ObjectAddObjectProperty(&textStyle, "selectedText", ColorLookupPointer(m->selectedText)->object2ID);
ObjectAddIntegerProperty(&textStyle, "textSize", m->textSize);
ObjectAddIntegerProperty(&textStyle, "fontWeight", m->fontWeight);
ObjectAddIntegerProperty(&textStyle, "isItalic", m->italic);
ObjectAddIntegerProperty(&textStyle, "fontFamily", m->fontFamily == FONT_FAMILY_MONO ? 0xFFFD : 0xFFFF);
arrput(objects, textStyle);
object.type = OBJ_VAR_TEXT_STYLE, object.id = ++objectIDAllocator;
ObjectAddObjectProperty(&object, "textColor", ColorLookupPointer(m->textColor)->object2ID);
ObjectAddObjectProperty(&object, "selectedBackground", ColorLookupPointer(m->selectedBackground)->object2ID);
ObjectAddObjectProperty(&object, "selectedText", ColorLookupPointer(m->selectedText)->object2ID);
ObjectAddIntegerProperty(&object, "textSize", m->textSize);
ObjectAddIntegerProperty(&object, "fontWeight", m->fontWeight);
ObjectAddIntegerProperty(&object, "isItalic", m->italic);
ObjectAddIntegerProperty(&object, "fontFamily", m->fontFamily == FONT_FAMILY_MONO ? 0xFFFD : 0xFFFF);
ObjectAddIntegerProperty(&object, "iconSize", m->iconSize);
ObjectAddObjectProperty(&object, "iconColor", ColorLookupPointer(m->iconColor)->object2ID);
textStyle = object;
metrics.type = OBJ_LAYER_METRICS, metrics.id = ++objectIDAllocator;
ObjectAddIntegerProperty(&metrics, "clipEnabled", m->clipEnabled);
ObjectAddIntegerProperty(&metrics, "wrapText", m->wrapText);
ObjectAddIntegerProperty(&metrics, "ellipsis", m->ellipsis);
ObjectAddIntegerProperty(&metrics, "insets0", m->insets.l);
ObjectAddIntegerProperty(&metrics, "insets1", m->insets.r);
ObjectAddIntegerProperty(&metrics, "insets2", m->insets.t);
ObjectAddIntegerProperty(&metrics, "insets3", m->insets.b);
ObjectAddIntegerProperty(&metrics, "clipInsets0", m->clipInsets.l);
ObjectAddIntegerProperty(&metrics, "clipInsets1", m->clipInsets.r);
ObjectAddIntegerProperty(&metrics, "clipInsets2", m->clipInsets.t);
ObjectAddIntegerProperty(&metrics, "clipInsets3", m->clipInsets.b);
ObjectAddIntegerProperty(&metrics, "preferredWidth", m->preferredSize.width);
ObjectAddIntegerProperty(&metrics, "preferredHeight", m->preferredSize.height);
ObjectAddIntegerProperty(&metrics, "minimumWidth", m->minimumSize.width);
ObjectAddIntegerProperty(&metrics, "minimumHeight", m->minimumSize.height);
ObjectAddIntegerProperty(&metrics, "maximumWidth", m->maximumSize.width);
ObjectAddIntegerProperty(&metrics, "maximumHeight", m->maximumSize.height);
ObjectAddIntegerProperty(&metrics, "gapMajor", m->gaps.major);
ObjectAddIntegerProperty(&metrics, "gapMinor", m->gaps.minor);
ObjectAddIntegerProperty(&metrics, "gapWrap", m->gaps.wrap);
ObjectAddIntegerProperty(&metrics, "cursor", m->cursor);
ObjectAddIntegerProperty(&metrics, "horizontalTextAlign", m->textHorizontalAlign + 1);
ObjectAddIntegerProperty(&metrics, "verticalTextAlign", m->textVerticalAlign + 1);
ObjectAddIntegerProperty(&metrics, "_graphX", x);
ObjectAddIntegerProperty(&metrics, "_graphY", y);
ObjectAddIntegerProperty(&metrics, "_graphW", 80);
ObjectAddIntegerProperty(&metrics, "_graphH", 60);
arrput(objects, metrics);
x += 100;
} else {
assert(false);
}
ObjectAddIntegerProperty(&object, "_graphX", x);
ObjectAddIntegerProperty(&object, "_graphY", y);
ObjectAddIntegerProperty(&object, "_graphW", 80);
ObjectAddIntegerProperty(&object, "_graphH", 60);
arrput(objects, object);
x += 100;
iconStyle.type = OBJ_VAR_ICON_STYLE, iconStyle.id = ++objectIDAllocator;
ObjectAddIntegerProperty(&iconStyle, "_graphX", x);
ObjectAddIntegerProperty(&iconStyle, "_graphY", y);
ObjectAddIntegerProperty(&iconStyle, "_graphW", 80);
ObjectAddIntegerProperty(&iconStyle, "_graphH", 60);
ObjectAddIntegerProperty(&iconStyle, "iconSize", m->iconSize);
ObjectAddObjectProperty(&iconStyle, "iconColor", ColorLookupPointer(m->iconColor)->object2ID);
arrput(objects, iconStyle);
uint64_t previousOverrideID = object.id;
for (uintptr_t i = 0; i < arrlenu(layer->sequences); i++) {
Sequence *s = layer->sequences[i];
assert(arrlenu(s->keyframes) == 1);
Keyframe *keyframe = s->keyframes[0];
char buffer[256];
snprintf(buffer, sizeof(buffer), "%s%s%s%s%s%s%s%s%s%s",
((StringOption *) PrimaryState_Type.fields[s->primaryState].item.options)->string,
s->flagFocused ? " (focused)" : "",
s->flagChecked ? " (checked)" : "",
s->flagIndeterminate ? " (indeterminate)" : "",
s->flagDefault ? " (default)" : "",
s->flagItemFocus ? " (list item focus)" : "",
s->flagListFocus ? " (list focus)" : "",
s->flagBeforeEnter ? " (before enter)" : "",
s->flagAfterExit ? " (after exit)" : "",
s->flagSelected ? " (selected)" : "");
fprintf(stderr, "%.*s:%.*s:%s:%d\n", (int) style->name.byteCount, (char *) style->name.buffer,
(int) layer->name.byteCount, (char *) layer->name.buffer, buffer, s->duration);
uint32_t stateBits = 0;
if (s->flagFocused) stateBits |= THEME_STATE_FOCUSED;
if (s->flagChecked) stateBits |= THEME_STATE_CHECKED;
if (s->flagIndeterminate) stateBits |= THEME_STATE_INDETERMINATE;
if (s->flagDefault) stateBits |= THEME_STATE_DEFAULT_BUTTON;
if (s->flagItemFocus) stateBits |= THEME_STATE_FOCUSED_ITEM;
if (s->flagListFocus) stateBits |= THEME_STATE_LIST_FOCUSED;
if (s->flagBeforeEnter) stateBits |= THEME_STATE_BEFORE_ENTER;
if (s->flagAfterExit) stateBits |= THEME_STATE_AFTER_EXIT;
if (s->flagSelected) stateBits |= THEME_STATE_SELECTED;
Object2 override = { .type = object.type, .id = ++objectIDAllocator };
ObjectAddIntegerProperty(&override, "_graphX", x);
ObjectAddIntegerProperty(&override, "_graphY", y);
ObjectAddIntegerProperty(&override, "_graphW", 80);
ObjectAddIntegerProperty(&override, "_graphH", 60);
ObjectAddObjectProperty(&override, "_parent", previousOverrideID);
ObjectAddIntegerProperty(&override, "_primaryState", s->primaryState);
ObjectAddIntegerProperty(&override, "_stateBits", stateBits);
ObjectAddIntegerProperty(&override, "_duration", s->duration);
bool addObject = false;
for (uintptr_t i = 0; i < arrlenu(keyframe->properties); i++) {
Property *property = &keyframe->properties[i];
if (layer->base.tag == LayerBase_box + 1 && property->path[0] == (uint32_t) -2 && property->path[1] == 8 && property->path[2] == 0
&& property->path[3] == 2 && (property->path[4] == 2 || property->path[4] == 3)) {
continue;
}
ExportProperty2(layer, property, &override);
addObject = true;
}
if (addObject) {
arrput(objects, override);
previousOverrideID = override.id;
x += 100;
} else {
arrfree(override.properties);
}
}
if (addToLayerGroup) {
sprintf(cPropertyName, "layers_%d_layer", layerCount);
ObjectAddObjectProperty(&layerGroup, cPropertyName, object.id);
ObjectAddObjectProperty(&layerGroup, cPropertyName, previousOverrideID);
sprintf(cPropertyName, "layers_%d_offset0", layerCount);
ObjectAddIntegerProperty(&layerGroup, cPropertyName, layer->offset.l);
sprintf(cPropertyName, "layers_%d_offset1", layerCount);
@ -2041,15 +2349,6 @@ void ActionExportDesigner2(void *cp) {
ObjectAddIntegerProperty(&layerGroup, cPropertyName, layer->mode);
layerCount++;
}
if (addToObjects) {
ObjectAddIntegerProperty(&object, "_graphX", x);
ObjectAddIntegerProperty(&object, "_graphY", y);
ObjectAddIntegerProperty(&object, "_graphW", 80);
ObjectAddIntegerProperty(&object, "_graphH", 60);
arrput(objects, object);
x += 100;
}
}
{
@ -2074,7 +2373,6 @@ void ActionExportDesigner2(void *cp) {
ObjectAddObjectProperty(&object, "appearance", layerGroup.id);
ObjectAddObjectProperty(&object, "metrics", metrics.id);
ObjectAddObjectProperty(&object, "textStyle", textStyle.id);
ObjectAddObjectProperty(&object, "iconStyle", iconStyle.id);
arrput(objects, object);
x += 100;
}

View File

@ -16,12 +16,13 @@
// x86_64-w64-mingw32-gcc -O3 -o bin/designer2.exe -D UI_WINDOWS util/designer2.cpp -DUNICODE -lgdi32 -luser32 -lkernel32 -Wl,--subsystem,windows -fno-exceptions -fno-rtti
// TODO Needed to replace the old designer:
// Import and reorganize old theming data.
// Import old theming data.
// Export.
// Prototyping display: previewing state transitions.
// TODO Additional features:
// Scrollbars?
// In a conditional layer, properties from conditional linked objects (such as a gradient paint) should show if their conditions match.
// Scrollbars on the canvas?
// Icons for different object types (especially color overwrite objects).
// Fix moving/resizing objects when zoomed in.
// Path layers: dashed contours.
@ -35,6 +36,9 @@
// Get text rendering on non-Essence platforms.
// Proper bezier path editor.
// Path boolean operations.
// Timeline editor for applying a given state change, with rows for possibly many different layers.
// TODO Reorganize old theming data!
//////////////////////////////////////////////////////////////
@ -271,7 +275,6 @@ enum ObjectType : uint8_t {
OBJ_VAR_COLOR = 0x40,
OBJ_VAR_INT,
OBJ_VAR_TEXT_STYLE,
OBJ_VAR_ICON_STYLE,
OBJ_VAR_CONTOUR_STYLE,
OBJ_PAINT_OVERWRITE = 0x60,
@ -409,11 +412,11 @@ bool ObjectMatchesPreviewState(Object *object) {
&& ((stateBits & canvas->previewStateBits) == stateBits);
}
Property *PropertyFindOrInherit(bool first, Object *object, const char *cName, uint8_t type = 0) {
Property *PropertyFindOrInherit(Object *object, const char *cName, uint8_t type = 0) {
uintptr_t depth = 0;
while (object && (depth++ < 100)) {
if (first || !ObjectIsConditional(object) || (canvas->previewStateActive && ObjectMatchesPreviewState(object))) {
if (!ObjectIsConditional(object) || (canvas->previewStateActive && ObjectMatchesPreviewState(object))) {
// Return the value if the object has this property.
Property *property = PropertyFind(object, cName);
if (property) return type && property->type != type ? nullptr : property;
@ -424,24 +427,23 @@ Property *PropertyFindOrInherit(bool first, Object *object, const char *cName, u
// Go to the inheritance parent object.
Property *property = PropertyFind(object, "_parent", PROP_OBJECT);
object = ObjectFind(property ? property->object : 0);
first = false;
}
return nullptr;
}
int32_t PropertyFindOrInheritReadInt32(bool first, Object *object, const char *cName, int32_t defaultValue = 0) {
Property *property = PropertyFindOrInherit(first, object, cName, PROP_INT);
int32_t PropertyFindOrInheritReadInt32(Object *object, const char *cName, int32_t defaultValue = 0) {
Property *property = PropertyFindOrInherit(object, cName, PROP_INT);
return property ? property->integer : defaultValue;
}
float PropertyFindOrInheritReadFloat(bool first, Object *object, const char *cName, float defaultValue = 0) {
Property *property = PropertyFindOrInherit(first, object, cName, PROP_FLOAT);
float PropertyFindOrInheritReadFloat(Object *object, const char *cName, float defaultValue = 0) {
Property *property = PropertyFindOrInherit(object, cName, PROP_FLOAT);
return property ? property->floating : defaultValue;
}
Object *PropertyFindOrInheritReadObject(bool first, Object *object, const char *cName) {
Property *property = PropertyFindOrInherit(first, object, cName, PROP_OBJECT);
Object *PropertyFindOrInheritReadObject(Object *object, const char *cName) {
Property *property = PropertyFindOrInherit(object, cName, PROP_OBJECT);
return property ? ObjectFind(property->object) : nullptr;
}
@ -1372,7 +1374,7 @@ void InspectorPopulate() {
UIButtonCreate(0, UI_BUTTON_SMALL, "Rename", -1)->invoke = InspectorRenameObject;
UIParentPop();
bool inheritWithAnimation = object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_VAR_ICON_STYLE
bool inheritWithAnimation = object->type == OBJ_VAR_TEXT_STYLE
|| object->type == OBJ_LAYER_BOX || object->type == OBJ_LAYER_TEXT || object->type == OBJ_LAYER_PATH
|| object->type == OBJ_PAINT_OVERWRITE || object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT
|| object->type == OBJ_VAR_CONTOUR_STYLE;
@ -1421,7 +1423,6 @@ void InspectorPopulate() {
InspectorAddLink(object, "Appearance:", "appearance");
InspectorAddLink(object, "Metrics:", "metrics");
InspectorAddLink(object, "Text style:", "textStyle");
InspectorAddLink(object, "Icon style:", "iconStyle");
InspectorAddBooleanToggle(object, "Public style", "isPublic");
} else if (object->type == OBJ_VAR_COLOR) {
InspectorBind(&UIColorPickerCreate(&UIPanelCreate(0, 0)->e, UI_COLOR_PICKER_HAS_OPACITY)->e, object->id, "color", INSPECTOR_COLOR_PICKER);
@ -1504,7 +1505,7 @@ void InspectorPopulate() {
InspectorAddRadioSwitch(object, "Monospaced", "fontFamily", ES_FONT_MONOSPACED);
InspectorBind(&UIButtonCreate(0, UI_BUTTON_SMALL, "X", 1)->e, object->id, "fontFamily", INSPECTOR_REMOVE_BUTTON);
UIParentPop();
} else if (object->type == OBJ_VAR_ICON_STYLE) {
InspectorAddLink(object, "Icon color:", "iconColor");
InspectorAddInteger(object, "Icon size:", "iconSize");
} else if (object->type == OBJ_VAR_CONTOUR_STYLE) {
@ -1833,14 +1834,11 @@ uint32_t GraphGetColorFromProperty(Property *property) {
void ExportGradientStopArray(Object *object, EsBuffer *data, size_t stopCount) {
for (uintptr_t i = 0; i < stopCount; i++) {
char cPropertyName[PROPERTY_NAME_SIZE];
sprintf(cPropertyName, "stops_%d_color", (int32_t) i);
Property *color = PropertyFind(object, cPropertyName, PROP_OBJECT);
sprintf(cPropertyName, "stops_%d_position", (int32_t) i);
Property *position = PropertyFind(object, cPropertyName, PROP_OBJECT);
ThemeGradientStop stop = {};
stop.color = GraphGetColor(ObjectFind(color ? color->object : 0));
stop.position = GraphGetIntegerFromProperty(position);
sprintf(cPropertyName, "stops_%d_color", (int32_t) i);
stop.color = GraphGetColor(PropertyFindOrInheritReadObject(object, cPropertyName));
sprintf(cPropertyName, "stops_%d_position", (int32_t) i);
stop.position = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, cPropertyName, PROP_INT));
EsBufferWrite(data, &stop, sizeof(stop));
}
}
@ -1859,18 +1857,18 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) {
return THEME_PAINT_SOLID;
} else if (object->type == OBJ_PAINT_OVERWRITE) {
ExportPaint(PropertyFindOrInheritReadObject(false, object, "color"), data, depth + 1);
ExportPaint(PropertyFindOrInheritReadObject(object, "color"), data, depth + 1);
return THEME_PAINT_OVERWRITE;
} else if (object->type == OBJ_PAINT_LINEAR_GRADIENT) {
if (data) {
ThemePaintLinearGradient paint = {};
paint.transform[0] = PropertyFindOrInheritReadFloat(false, object, "transformX");
paint.transform[1] = PropertyFindOrInheritReadFloat(false, object, "transformY");
paint.transform[2] = PropertyFindOrInheritReadFloat(false, object, "transformStart");
paint.stopCount = PropertyFindOrInheritReadInt32(false, object, "stops_count");
paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(false, object, "useGammaInterpolation");
paint.useSystemColor = !!PropertyFindOrInheritReadInt32(false, object, "useSystemColor");
paint.repeatMode = PropertyFindOrInheritReadInt32(false, object, "repeatMode");
paint.transform[0] = PropertyFindOrInheritReadFloat(object, "transformX");
paint.transform[1] = PropertyFindOrInheritReadFloat(object, "transformY");
paint.transform[2] = PropertyFindOrInheritReadFloat(object, "transformStart");
paint.stopCount = PropertyFindOrInheritReadInt32(object, "stops_count");
paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(object, "useGammaInterpolation");
paint.useSystemColor = !!PropertyFindOrInheritReadInt32(object, "useSystemColor");
paint.repeatMode = PropertyFindOrInheritReadInt32(object, "repeatMode");
EsBufferWrite(data, &paint, sizeof(paint));
ExportGradientStopArray(object, data, paint.stopCount);
}
@ -1879,15 +1877,15 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) {
} else if (object->type == OBJ_PAINT_RADIAL_GRADIENT) {
if (data) {
ThemePaintRadialGradient paint = {};
paint.transform[0] = PropertyFindOrInheritReadFloat(false, object, "transform0");
paint.transform[1] = PropertyFindOrInheritReadFloat(false, object, "transform1");
paint.transform[2] = PropertyFindOrInheritReadFloat(false, object, "transform2");
paint.transform[3] = PropertyFindOrInheritReadFloat(false, object, "transform3");
paint.transform[4] = PropertyFindOrInheritReadFloat(false, object, "transform4");
paint.transform[5] = PropertyFindOrInheritReadFloat(false, object, "transform5");
paint.stopCount = PropertyFindOrInheritReadInt32(false, object, "stops_count");
paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(false, object, "useGammaInterpolation");
paint.repeatMode = PropertyFindOrInheritReadInt32(false, object, "repeatMode");
paint.transform[0] = PropertyFindOrInheritReadFloat(object, "transform0");
paint.transform[1] = PropertyFindOrInheritReadFloat(object, "transform1");
paint.transform[2] = PropertyFindOrInheritReadFloat(object, "transform2");
paint.transform[3] = PropertyFindOrInheritReadFloat(object, "transform3");
paint.transform[4] = PropertyFindOrInheritReadFloat(object, "transform4");
paint.transform[5] = PropertyFindOrInheritReadFloat(object, "transform5");
paint.stopCount = PropertyFindOrInheritReadInt32(object, "stops_count");
paint.useGammaInterpolation = !!PropertyFindOrInheritReadInt32(object, "useGammaInterpolation");
paint.repeatMode = PropertyFindOrInheritReadInt32(object, "repeatMode");
EsBufferWrite(data, &paint, sizeof(paint));
ExportGradientStopArray(object, data, paint.stopCount);
}
@ -1898,37 +1896,37 @@ int8_t ExportPaint(Object *object, EsBuffer *data, int depth = 0) {
}
}
void ExportLayerBox(bool first, Object *object, EsBuffer *data) {
Property *mainPaint = PropertyFindOrInherit(first, object, "mainPaint", PROP_OBJECT);
Property *borderPaint = PropertyFindOrInherit(first, object, "borderPaint", PROP_OBJECT);
void ExportLayerBox(Object *object, EsBuffer *data) {
Property *mainPaint = PropertyFindOrInherit(object, "mainPaint", PROP_OBJECT);
Property *borderPaint = PropertyFindOrInherit(object, "borderPaint", PROP_OBJECT);
ThemeLayerBox box = {};
box.mainPaintType = ExportPaint(ObjectFind(mainPaint ? mainPaint->object : 0), nullptr);
box.borderPaintType = ExportPaint(ObjectFind(borderPaint ? borderPaint->object : 0), nullptr);
box.borders.l = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders0"));
box.borders.r = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders1"));
box.borders.t = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders2"));
box.borders.b = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "borders3"));
box.corners.tl = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners0"));
box.corners.tr = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners1"));
box.corners.bl = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners2"));
box.corners.br = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "corners3"));
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "isBlurred" ))) box.flags |= THEME_LAYER_BOX_IS_BLURRED;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "autoCorners" ))) box.flags |= THEME_LAYER_BOX_AUTO_CORNERS;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "autoBorders" ))) box.flags |= THEME_LAYER_BOX_AUTO_BORDERS;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "shadowHiding"))) box.flags |= THEME_LAYER_BOX_SHADOW_HIDING;
box.borders.l = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders0"));
box.borders.r = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders1"));
box.borders.t = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders2"));
box.borders.b = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "borders3"));
box.corners.tl = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners0"));
box.corners.tr = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners1"));
box.corners.bl = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners2"));
box.corners.br = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "corners3"));
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "isBlurred" ))) box.flags |= THEME_LAYER_BOX_IS_BLURRED;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "autoCorners" ))) box.flags |= THEME_LAYER_BOX_AUTO_CORNERS;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "autoBorders" ))) box.flags |= THEME_LAYER_BOX_AUTO_BORDERS;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "shadowHiding"))) box.flags |= THEME_LAYER_BOX_SHADOW_HIDING;
EsBufferWrite(data, &box, sizeof(box));
ExportPaint(ObjectFind(mainPaint ? mainPaint->object : 0), data);
ExportPaint(ObjectFind(borderPaint ? borderPaint->object : 0), data);
}
void ExportLayerPath(bool first, Object *object, EsBuffer *data) {
Property *pointCount = PropertyFindOrInherit(false, object, "points_count", PROP_INT);
Property *fillCount = PropertyFindOrInherit(false, object, "fills_count", PROP_INT);
void ExportLayerPath(Object *object, EsBuffer *data) {
Property *pointCount = PropertyFindOrInherit(object, "points_count", PROP_INT);
Property *fillCount = PropertyFindOrInherit(object, "fills_count", PROP_INT);
ThemeLayerPath path = {};
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "pathFillEvenOdd"))) path.flags |= THEME_LAYER_PATH_FILL_EVEN_ODD;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "pathClosed"))) path.flags |= THEME_LAYER_PATH_CLOSED;
path.alpha = GraphGetIntegerFromProperty(PropertyFindOrInherit(first, object, "alpha"));
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "pathFillEvenOdd"))) path.flags |= THEME_LAYER_PATH_FILL_EVEN_ODD;
if (GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "pathClosed"))) path.flags |= THEME_LAYER_PATH_CLOSED;
path.alpha = GraphGetIntegerFromProperty(PropertyFindOrInherit(object, "alpha"));
path.pointCount = pointCount ? pointCount->integer : 0;
path.fillCount = fillCount ? fillCount->integer : 0;
EsBufferWrite(data, &path, sizeof(path));
@ -1939,7 +1937,7 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) {
Property *property;
#define LAYER_PATH_WRITE_POINT(x) \
sprintf(cPropertyName, "points_%d_" #x, (int32_t) i); \
property = PropertyFindOrInherit(first, object, cPropertyName, PROP_FLOAT); \
property = PropertyFindOrInherit(object, cPropertyName, PROP_FLOAT); \
EsBufferWrite(data, property ? &property->floating : &zero, sizeof(float));
LAYER_PATH_WRITE_POINT(x0);
LAYER_PATH_WRITE_POINT(y0);
@ -1954,11 +1952,11 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) {
ThemeLayerPathFill fill = {};
sprintf(cPropertyName, "fills_%d_paint", (int32_t) i);
Object *paint = PropertyFindOrInheritReadObject(first, object, cPropertyName);
Object *paint = PropertyFindOrInheritReadObject(object, cPropertyName);
fill.paintAndFillType |= ExportPaint(paint, nullptr);
sprintf(cPropertyName, "fills_%d_mode", (int32_t) i);
Object *mode = PropertyFindOrInheritReadObject(first, object, cPropertyName);
Object *mode = PropertyFindOrInheritReadObject(object, cPropertyName);
// TODO Dashed contours.
@ -1973,12 +1971,12 @@ void ExportLayerPath(bool first, Object *object, EsBuffer *data) {
if (mode && mode->type == OBJ_VAR_CONTOUR_STYLE) {
ThemeLayerPathFillContour contour = {};
contour.miterLimit = PropertyFindOrInheritReadFloat(first, mode, "miterLimit");
contour.internalWidth = PropertyFindOrInheritReadInt32(first, mode, "internalWidth");
contour.externalWidth = PropertyFindOrInheritReadInt32(first, mode, "externalWidth");
contour.mode = PropertyFindOrInheritReadInt32(first, mode, "joinMode")
| (PropertyFindOrInheritReadInt32(first, mode, "capMode") << 2)
| (PropertyFindOrInheritReadInt32(first, mode, "integerWidthsOnly") ? 0x80 : 0);
contour.miterLimit = PropertyFindOrInheritReadFloat(mode, "miterLimit");
contour.internalWidth = PropertyFindOrInheritReadInt32(mode, "internalWidth");
contour.externalWidth = PropertyFindOrInheritReadInt32(mode, "externalWidth");
contour.mode = PropertyFindOrInheritReadInt32(mode, "joinMode")
| (PropertyFindOrInheritReadInt32(mode, "capMode") << 2)
| (PropertyFindOrInheritReadInt32(mode, "integerWidthsOnly") ? 0x80 : 0);
EsBufferWrite(data, &contour, sizeof(contour));
}
}
@ -2077,16 +2075,16 @@ void CanvasDrawLayer(Object *object, UIRectangle bounds, UIPainter *painter, int
}
if (object->type == OBJ_LAYER_BOX) {
bounds.l += PropertyFindOrInheritReadInt32(depth == 0, object, "offset0") * canvas->zoom;
bounds.r += PropertyFindOrInheritReadInt32(depth == 0, object, "offset1") * canvas->zoom;
bounds.t += PropertyFindOrInheritReadInt32(depth == 0, object, "offset2") * canvas->zoom;
bounds.b += PropertyFindOrInheritReadInt32(depth == 0, object, "offset3") * canvas->zoom;
bounds.l += PropertyFindOrInheritReadInt32(object, "offset0") * canvas->zoom;
bounds.r += PropertyFindOrInheritReadInt32(object, "offset1") * canvas->zoom;
bounds.t += PropertyFindOrInheritReadInt32(object, "offset2") * canvas->zoom;
bounds.b += PropertyFindOrInheritReadInt32(object, "offset3") * canvas->zoom;
uint8_t buffer[4096];
EsBuffer data = { .out = buffer, .bytes = sizeof(buffer) };
ThemeLayer layer = { .position = { .r = 100, .b = 100 }, .type = THEME_LAYER_BOX };
EsBufferWrite(&data, &layer, sizeof(layer));
ExportLayerBox(depth == 0, object, &data);
ExportLayerBox(object, &data);
CanvasDrawLayerFromData(painter, bounds, data);
} else if (object->type == OBJ_LAYER_TEXT) {
#ifdef OS_ESSENCE
@ -2115,7 +2113,7 @@ void CanvasDrawLayer(Object *object, UIRectangle bounds, UIPainter *painter, int
EsBuffer data = { .out = buffer, .bytes = sizeof(buffer) };
ThemeLayer layer = { .position = { .r = 100, .b = 100 }, .type = THEME_LAYER_PATH };
EsBufferWrite(&data, &layer, sizeof(layer));
ExportLayerPath(depth == 0, object, &data);
ExportLayerPath(object, &data);
CanvasDrawLayerFromData(painter, bounds, data);
} else if (object->type == OBJ_LAYER_GROUP) {
int32_t layerCount = PropertyReadInt32(object, "layers_count");
@ -2178,20 +2176,19 @@ void CanvasDrawStyle(Object *object, UIRectangle bounds, UIPainter *painter, int
textStyle.size = GraphGetIntegerFromProperty(PropertyFindOrInherit(false, object, "textSize")) * canvas->zoom;
textStyle.color = GraphGetColorFromProperty(PropertyFindOrInherit(false, object, "textColor"));
EsDrawTextSimple((_EsPainter *) &themePainter, ui.instance->window, bounds, "Sample", -1, textStyle, ES_TEXT_H_CENTER | ES_TEXT_V_CENTER);
} else if (object->type == OBJ_VAR_ICON_STYLE) {
#if 0
EsDrawStandardIcon((_EsPainter *) &themePainter, ES_ICON_GO_NEXT_SYMBOLIC,
GraphGetIntegerFromProperty(PropertyFindOrInherit(false, object, "iconSize")), bounds,
GraphGetColorFromProperty(PropertyFindOrInherit(false, object, "iconColor")));
#endif
}
#endif
if (object->type == OBJ_STYLE) {
Property *appearance = PropertyFindOrInherit(false, object, "appearance");
Property *textStyle = PropertyFindOrInherit(false, object, "textStyle");
Property *iconStyle = PropertyFindOrInherit(false, object, "iconStyle");
Property *appearance = PropertyFindOrInherit(object, "appearance");
Property *textStyle = PropertyFindOrInherit(object, "textStyle");
if (appearance) CanvasDrawLayer(ObjectFind(appearance->object), bounds, painter, depth + 1);
if (textStyle) CanvasDrawStyle(ObjectFind(textStyle->object), bounds, painter, depth + 1);
else if (iconStyle) CanvasDrawStyle(ObjectFind(iconStyle->object), bounds, painter, depth + 1);
}
}
@ -2268,6 +2265,7 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) {
UIRectangle selectionIntersection = UIRectangleIntersection(bounds, selectionBounds);
bool isSelected = (object->flags & OBJECT_IS_SELECTED) == (inspectorPickData == nullptr)
|| (canvas->selecting && UI_RECT_VALID(selectionIntersection));
bool isConditional = ObjectIsConditional(object);
if (!canvas->showPrototype) {
if (isSelected) {
@ -2281,7 +2279,7 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) {
UIDrawBlock(painter, UI_RECT_4(bounds.l + 1, bounds.r + 1, bounds.b, bounds.b + 1), 0xFF404040);
UIDrawBlock(painter, UI_RECT_4(bounds.r, bounds.r + 1, bounds.t + 1, bounds.b + 1), 0xFF404040);
if (ObjectIsConditional(object)) {
if (isConditional) {
UIRectangle indicator = UI_RECT_4(bounds.l - ui.glyphWidth, bounds.l, bounds.t, bounds.t + ui.glyphHeight);
UIDrawBlock(painter, indicator, 0xFFFFFF00);
UIDrawString(painter, indicator, "?", -1, 0xFF000000, UI_ALIGN_CENTER, nullptr);
@ -2297,6 +2295,12 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) {
buffer, -1, 0xFF000000, UI_ALIGN_CENTER, nullptr);
}
if (isConditional) {
canvas->previewStateActive = true;
canvas->previewPrimaryState = PropertyReadInt32(object, "_primaryState");
canvas->previewStateBits = PropertyReadInt32(object, "_stateBits");
}
if (object->type == OBJ_VAR_INT || object->type == OBJ_MOD_MULTIPLY) {
int32_t value = GraphGetInteger(object);
char buffer[32];
@ -2315,17 +2319,23 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) {
snprintf(buffer, sizeof(buffer), "%.8X", color);
UIRectangle area = UI_RECT_4(bounds.l, bounds.r, bounds.t, bounds.t + UIMeasureStringHeight());
UIDrawString(painter, area, buffer, -1, isLight ? 0xFF000000 : 0xFFFFFFFF, UI_ALIGN_CENTER, nullptr);
} else if (object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_VAR_ICON_STYLE || object->type == OBJ_STYLE) {
} else if (object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_STYLE) {
CanvasDrawStyle(object, bounds, painter);
} else if (object->type == OBJ_INSTANCE) {
Property *style = PropertyFind(object, "style", PROP_OBJECT);
canvas->previewStateActive = object->id == selectedObjectID;
CanvasDrawStyle(ObjectFind(style ? style->object : 0), bounds, painter);
canvas->previewStateActive = false;
} else {
// TODO Preview for the metrics layer. Show the preferred size, insets and gaps?
// TODO Preview for OBJ_VAR_CONTOUR_STYLE.
}
canvas->previewStateActive = false;
if (!canvas->showPrototype) {
canvas->previewPrimaryState = THEME_PRIMARY_STATE_IDLE;
canvas->previewStateBits = 0;
}
}
if (canvas->showArrows && !canvas->showPrototype) {
@ -2615,7 +2625,6 @@ void ObjectAddCommand(void *) {
UIMenuAddItem(menu, 0, "Color variable", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_COLOR);
UIMenuAddItem(menu, 0, "Integer variable", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_INT);
UIMenuAddItem(menu, 0, "Text style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_TEXT_STYLE);
UIMenuAddItem(menu, 0, "Icon style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_ICON_STYLE);
UIMenuAddItem(menu, 0, "Contour style", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_VAR_CONTOUR_STYLE);
UIMenuAddItem(menu, 0, "Metrics", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_LAYER_METRICS);
UIMenuAddItem(menu, 0, "Overwrite paint", -1, ObjectAddCommandInternal, (void *) (uintptr_t) OBJ_PAINT_OVERWRITE);