[$this, 'render_block']
]);
}
public function enqueue_admin_assets($hook) {
$screen = get_current_screen();
if ($screen->base === 'media' && isset($_GET['item'])
|| !(($hook !== 'upload.php' && strpos($hook, 'post.php') === false))) {
wp_enqueue_script('active-contour-class', plugin_dir_url(__FILE__) . 'assets/class.Contour.js', [], $this->version, true);
wp_enqueue_script('active-contour-primitives-class', plugin_dir_url(__FILE__) . 'assets/class.Primitives.js', [], $this->version, true);
wp_enqueue_script('active-contour-collection-class', plugin_dir_url(__FILE__) . 'assets/class.ContourCollection.js', [], $this->version, true);
wp_enqueue_script('active-contour-calc-class', plugin_dir_url(__FILE__) . 'assets/class.ContourCalc.js', [], $this->version, true);
wp_enqueue_script('active-contour-editor-class', plugin_dir_url(__FILE__) . 'assets/class.ContourEditor.js', ['jquery', 'wp-i18n' ], $this->version, true);
wp_enqueue_script('active-contour-editor', plugin_dir_url(__FILE__) . 'assets/editor.js', ['jquery'], $this->version, true);
wp_enqueue_style('active-contour-style', plugin_dir_url(__FILE__) . 'assets/editor.css', [], $this->version);
}
}
public function enqueue_front_assets() {
wp_enqueue_script('active-contour-front', plugin_dir_url(__FILE__) . 'assets/front.js', [], $this->version, true);
wp_enqueue_style('active-contour-front-style', plugin_dir_url(__FILE__) . 'assets/front.css', [], $this->version);
}
public function add_metabox() {
add_meta_box(
'active-contour-meta',
esc_html(__('Active Contour', 'active-contour')),
[$this, 'metabox_html'],
'attachment',
'normal', 'high'
);
}
public function attachment_fields_to_edit($form_fields, $post) {
$data = get_post_meta($post->ID, '_active_contours', true);
$form_fields['active_contour_json'] = [
'label' => 'Контуры',
'input' => 'textarea',
'value' => $data,
'extra_rows' => [
'nonce' => wp_nonce_field(
'active_contour_update_' . $post->ID, // Action.
'active_contour_update', // Nonce name.
true, // Output referer?
false // Echo?
),
],
];
return $form_fields;
}
public function save_attachment_data($data) {
if (isset($_POST['id'],
$_POST['changes'],
$_POST['changes']['active_contour_json'],
$_POST['changes']['active_contour_update_nonce'])) {
$nonce = wp_unslash($_POST['changes']['active_contour_update_nonce']);
$id = intval($_POST['id']);
if (wp_verify_nonce($nonce, 'active_contour_update_' . $id)) {
$newValue = wp_unslash($_POST['changes']['active_contour_json']);
if (json_decode($newValue) !== null) {
update_post_meta($id, '_active_contours', $newValue);
}
}
}
}
public function metabox_html($post) {
// textarea has been inserted as a fields_to_edit
echo '
';
echo 'If you use GPT (or another AI with vision capabilities), you can try generating a contour of points using a prompt like the following:';
echo '
Based on this image, return a JSON object with the following structure:
{
"title": "Object name",
"tags": ["tag1", "tag2", "..."],
"dots": [{ "x": ..., "y": ... }, ...]
}
The dots array should contain normalized coordinates (values from 0 to 1) outlining the shape of the specified object.
Dots must form a closed shape. Do not round coordinates, leave precison as is.
Also include a meaningful title and relevant tags describing the object.
Repeat this format for each of the following objects: ENTER YOUR OBJECTS LIST.
';
echo 'You can then input the resulting objects one by one using the form below — they will be added to the contour list for further editing.
';
echo '
';
echo '
' . esc_html(__('Export', 'active-contour')) . ' ';
}
public function shortcode($atts) {
$atts = shortcode_atts([
'id' => 0,
'size' => 'full',
'cid' => '',
'group' => '', // * - any group
'tags' => '',
'align' => 'left'
], $atts);
$id = intval($atts['id']);
$meta = wp_get_attachment_metadata($id);
if (empty($meta['sizes'][$atts['size']])) {
$atts['size'] = 'full';
}
if (!in_array($atts['align'], ['left', 'right', 'center', 'full'])) {
$atts['align'] = 'left';
}
$img_url = wp_get_attachment_image_url($id, $atts['size']);
if (!$img_url) return '-- айди не верен --';
$data = get_post_meta($id, '_active_contours', true);
if (!$data) {
$data = '[]';
}
if (!empty($atts['cid']) && preg_match_all('/(\d+)/', $atts['cid'], $m)) {
$id_filter = $m[1];
} else {
$id_filter = [];
}
if (!empty($atts['tags'])) {
$tags = preg_split('/\s*,\s*/', $atts['tags']);
} else {
$tags = [];
}
$group = trim($atts['group']);
$json = json_decode($data);
$contours = [];
$isEmptyConditions = empty($id_filter) && empty($tags) && empty($group);
if ($json !== null && !$isEmptyConditions) {
// group pre-validation
$all_groups = [];
if ($json !== null && !$isEmptyConditions) {
foreach($json as $contour) {
if (property_exists($contour, 'group')) {
$all_groups[$contour->group] = 1;
}
}
}
if (!isset($all_groups[$group]) && $group !== '*') {
$group = '';
}
foreach($json as $contour) {
if (!empty($id_filter) && !in_array($contour->id, $id_filter)) {
continue;
}
if (!empty($tags) && count(array_intersect($contour->tags, $tags)) == 0) {
continue;
}
if (!empty($group)) {
if ($group !== '*'
&& (!property_exists($contour, 'group') || $contour->group != $group)) continue;
}
$point_string = implode(' ', array_map(function($p) {
return $p->x . ',' . $p->y;
}, $contour->dots));
$classes = [
'animation-' . (empty($contour->animation) ? 'default' : esc_attr($contour->animation)),
'effect-' . (empty($contour->hoverEffect) ? 'default' : esc_attr($contour->hoverEffect)),
];
$polygon = 'url)
. '" target="_blank"') . '>'
. '
' . htmlentities($contour->title) . '';
$contours[] = $polygon;
}
}
$alignClass = $atts['align'] ? 'active-contour-aligmnent-' . $atts['align'] : '';
ob_start();
?>
shortcode($attrs);
}
public function api() {
register_rest_route('active-contour/v1', '/render',
[
'methods' => 'GET',
'callback' => function($request) {
$id = intval($request['id']);
$cid = sanitize_text_field($request['cid']);
$group = sanitize_text_field($request['group']);
$tags = sanitize_text_field($request['tags']);
$size = sanitize_text_field($request['size']);
$align = sanitize_text_field($request['align']);
return ['html' => do_shortcode("[active_contour id=\"{$id}\" cid=\"{$cid}\" size=\"{$size}\" group=\"{$group}\" tags=\"{$tags}\" align=\"{$align}\"]")];
},
'permission_callback' => function () {
return is_user_logged_in() && current_user_can('edit_posts');
}
]);
register_rest_route('active-contour/v1', '/data',
[
'methods' => 'GET',
'callback' => function($request) {
$id = intval($request['id']);
$meta = wp_get_attachment_metadata($id);
if ($meta) {
$data = get_post_meta($id, '_active_contours', true);
return ['json' => $data, 'sizes' => $meta];
} else {
return ['json' => '[]', 'sizes' => []];
}
},
'permission_callback' => function () {
return is_user_logged_in() && current_user_can('edit_posts');
}
]);
}
}