mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-07 08:49:06 +00:00
Long click to move; Boosty page on click before redirect
This commit is contained in:
@@ -8,11 +8,19 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ImageSpan;
|
||||||
|
import android.text.style.ReplacementSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@@ -30,6 +38,7 @@ import androidx.activity.EdgeToEdge;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
@@ -94,9 +103,11 @@ import ru.ytkab0bp.slicebeam.view.BeamSwitch;
|
|||||||
import ru.ytkab0bp.slicebeam.view.BoostySubsView;
|
import ru.ytkab0bp.slicebeam.view.BoostySubsView;
|
||||||
import ru.ytkab0bp.slicebeam.view.FadeRecyclerView;
|
import ru.ytkab0bp.slicebeam.view.FadeRecyclerView;
|
||||||
import ru.ytkab0bp.slicebeam.view.MiniColorView;
|
import ru.ytkab0bp.slicebeam.view.MiniColorView;
|
||||||
|
import ru.ytkab0bp.slicebeam.view.TextColorImageSpan;
|
||||||
|
|
||||||
public class SetupActivity extends AppCompatActivity {
|
public class SetupActivity extends AppCompatActivity {
|
||||||
public final static String EXTRA_ABOUT = "about";
|
public final static String EXTRA_ABOUT = "about";
|
||||||
|
public final static String EXTRA_BOOSTY_ONLY = "boosty_only";
|
||||||
|
|
||||||
private final static String TAG = "SetupActivity";
|
private final static String TAG = "SetupActivity";
|
||||||
|
|
||||||
@@ -137,6 +148,7 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
private Map<ProfilesRepo, List<Slic3rConfigWrapper>> profilesMap = new HashMap<>();
|
private Map<ProfilesRepo, List<Slic3rConfigWrapper>> profilesMap = new HashMap<>();
|
||||||
private boolean isProfilesLoaded;
|
private boolean isProfilesLoaded;
|
||||||
private boolean about;
|
private boolean about;
|
||||||
|
private boolean boostyOnly;
|
||||||
|
|
||||||
private List<ConfigObject> enabledPrinters = new ArrayList<>();
|
private List<ConfigObject> enabledPrinters = new ArrayList<>();
|
||||||
|
|
||||||
@@ -153,8 +165,9 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
SliceBeam.EVENT_BUS.registerListener(this);
|
SliceBeam.EVENT_BUS.registerListener(this);
|
||||||
|
|
||||||
about = getIntent().getBooleanExtra(EXTRA_ABOUT, false);
|
about = getIntent().getBooleanExtra(EXTRA_ABOUT, false);
|
||||||
|
boostyOnly = getIntent().getBooleanExtra(EXTRA_BOOSTY_ONLY, false);
|
||||||
|
|
||||||
if (!about) {
|
if (!about && !boostyOnly) {
|
||||||
new BeamAlertDialogBuilder(this)
|
new BeamAlertDialogBuilder(this)
|
||||||
.setTitle(R.string.IntroEarlyAccess)
|
.setTitle(R.string.IntroEarlyAccess)
|
||||||
.setMessage(R.string.IntroEarlyAccessMessage)
|
.setMessage(R.string.IntroEarlyAccessMessage)
|
||||||
@@ -166,7 +179,7 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
adapter = new SimpleRecyclerAdapter() {
|
adapter = new SimpleRecyclerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return about ? 1 : limitRepoFragmentCount ? REPOS_INDEX + 1 : limitProfileFragmentCount ? PROFILES_INDEX + 1 : super.getItemCount();
|
return about || boostyOnly ? 1 : limitRepoFragmentCount ? REPOS_INDEX + 1 : limitProfileFragmentCount ? PROFILES_INDEX + 1 : super.getItemCount();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
setItems();
|
setItems();
|
||||||
@@ -197,13 +210,15 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||||
if (position == 0) {
|
if (position == 0 && !boostyOnly) {
|
||||||
backgroundProgress = positionOffset;
|
backgroundProgress = positionOffset;
|
||||||
} else {
|
} else {
|
||||||
backgroundProgress = 1f;
|
backgroundProgress = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position == BOOSTY_INDEX) {
|
if (boostyOnly) {
|
||||||
|
boostyProgress = 1f;
|
||||||
|
} else if (position == BOOSTY_INDEX) {
|
||||||
boostyProgress = 1f - positionOffset;
|
boostyProgress = 1f - positionOffset;
|
||||||
} else if (position == BOOSTY_INDEX - 1) {
|
} else if (position == BOOSTY_INDEX - 1) {
|
||||||
boostyProgress = positionOffset;
|
boostyProgress = positionOffset;
|
||||||
@@ -462,7 +477,9 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setItems() {
|
private void setItems() {
|
||||||
if (about) {
|
if (boostyOnly) {
|
||||||
|
adapter.setItems(Collections.singletonList(new BoostyItem()));
|
||||||
|
} else if (about) {
|
||||||
adapter.setItems(Collections.singletonList(new AboutItem()));
|
adapter.setItems(Collections.singletonList(new AboutItem()));
|
||||||
} else {
|
} else {
|
||||||
List<SimpleRecyclerItem> items = new ArrayList<>(Arrays.asList(
|
List<SimpleRecyclerItem> items = new ArrayList<>(Arrays.asList(
|
||||||
@@ -1008,25 +1025,42 @@ public class SetupActivity extends AppCompatActivity {
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
TextView subscribeButton = new TextView(ctx);
|
TextView subscribeButton = new TextView(ctx);
|
||||||
subscribeButton.setText(R.string.IntroBoostySupport);
|
SpannableStringBuilder sb = SpannableStringBuilder.valueOf(ctx.getString(R.string.IntroBoostySupport)).append(" ");
|
||||||
|
Drawable dr = ContextCompat.getDrawable(ctx, R.drawable.external_link_outline_24);
|
||||||
|
int size = ViewUtils.dp(16);
|
||||||
|
dr.setBounds(0, 0, size, size);
|
||||||
|
sb.append("d", new TextColorImageSpan(dr, ViewUtils.dp(2f)), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
subscribeButton.setText(sb);
|
||||||
subscribeButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
subscribeButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
subscribeButton.setTextColor(ThemesRepo.getColor(R.attr.boostyColorTop));
|
subscribeButton.setTextColor(Color.WHITE);
|
||||||
subscribeButton.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
|
subscribeButton.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
|
||||||
subscribeButton.setGravity(Gravity.CENTER);
|
subscribeButton.setGravity(Gravity.CENTER);
|
||||||
subscribeButton.setPadding(ViewUtils.dp(12), ViewUtils.dp(8), ViewUtils.dp(12), ViewUtils.dp(8));
|
subscribeButton.setPadding(ViewUtils.dp(12), ViewUtils.dp(8), ViewUtils.dp(12), ViewUtils.dp(8));
|
||||||
|
subscribeButton.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), 16));
|
||||||
subscribeButton.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://boosty.to/ytkab0bp"))));
|
subscribeButton.setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://boosty.to/ytkab0bp"))));
|
||||||
ll.addView(subscribeButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {{
|
ll.addView(subscribeButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(52)) {{
|
||||||
bottomMargin = ViewUtils.dp(12);
|
leftMargin = rightMargin = ViewUtils.dp(16);
|
||||||
|
bottomMargin = ViewUtils.dp(8);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
TextView buttonView = new TextView(ctx);
|
TextView buttonView = new TextView(ctx);
|
||||||
buttonView.setText(R.string.IntroNext);
|
if (boostyOnly) {
|
||||||
|
buttonView.setText(android.R.string.ok);
|
||||||
|
} else {
|
||||||
|
buttonView.setText(R.string.IntroNext);
|
||||||
|
}
|
||||||
buttonView.setTextColor(ThemesRepo.getColor(R.attr.textColorOnAccent));
|
buttonView.setTextColor(ThemesRepo.getColor(R.attr.textColorOnAccent));
|
||||||
buttonView.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
|
buttonView.setTypeface(ViewUtils.getTypeface(ViewUtils.ROBOTO_MEDIUM));
|
||||||
buttonView.setGravity(Gravity.CENTER);
|
buttonView.setGravity(Gravity.CENTER);
|
||||||
buttonView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
buttonView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
buttonView.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), ThemesRepo.getColor(R.attr.boostyColorTop), 16));
|
buttonView.setBackground(ViewUtils.createRipple(ThemesRepo.getColor(android.R.attr.colorControlHighlight), ThemesRepo.getColor(R.attr.boostyColorTop), 16));
|
||||||
buttonView.setOnClickListener(v-> scrollToNext());
|
buttonView.setOnClickListener(v-> {
|
||||||
|
if (boostyOnly) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scrollToNext();
|
||||||
|
});
|
||||||
ll.addView(buttonView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(52)) {{
|
ll.addView(buttonView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewUtils.dp(52)) {{
|
||||||
leftMargin = rightMargin = ViewUtils.dp(16);
|
leftMargin = rightMargin = ViewUtils.dp(16);
|
||||||
bottomMargin = ViewUtils.dp(16);
|
bottomMargin = ViewUtils.dp(16);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import ru.ytkab0bp.slicebeam.SliceBeam;
|
|||||||
import ru.ytkab0bp.slicebeam.components.BeamAlertDialogBuilder;
|
import ru.ytkab0bp.slicebeam.components.BeamAlertDialogBuilder;
|
||||||
import ru.ytkab0bp.slicebeam.components.UnfoldMenu;
|
import ru.ytkab0bp.slicebeam.components.UnfoldMenu;
|
||||||
import ru.ytkab0bp.slicebeam.events.FlattenModeResetEvent;
|
import ru.ytkab0bp.slicebeam.events.FlattenModeResetEvent;
|
||||||
|
import ru.ytkab0bp.slicebeam.events.LongClickTranslationEvent;
|
||||||
import ru.ytkab0bp.slicebeam.events.NeedSnackbarEvent;
|
import ru.ytkab0bp.slicebeam.events.NeedSnackbarEvent;
|
||||||
import ru.ytkab0bp.slicebeam.events.ObjectsListChangedEvent;
|
import ru.ytkab0bp.slicebeam.events.ObjectsListChangedEvent;
|
||||||
import ru.ytkab0bp.slicebeam.events.SelectedObjectChangedEvent;
|
import ru.ytkab0bp.slicebeam.events.SelectedObjectChangedEvent;
|
||||||
@@ -139,7 +140,7 @@ public class OrientationMenu extends ListBedMenu {
|
|||||||
private Vec3d tempVec = new Vec3d();
|
private Vec3d tempVec = new Vec3d();
|
||||||
private int startedScrollObject;
|
private int startedScrollObject;
|
||||||
|
|
||||||
private void translateVisual(Double x, Double y, Double z) {
|
public void translateVisual(Double x, Double y, Double z) {
|
||||||
int j = fragment.getGlView().getRenderer().getSelectedObject();
|
int j = fragment.getGlView().getRenderer().getSelectedObject();
|
||||||
if (j == -1) return;
|
if (j == -1) return;
|
||||||
startedScrollObject = j;
|
startedScrollObject = j;
|
||||||
@@ -395,6 +396,24 @@ public class OrientationMenu extends ListBedMenu {
|
|||||||
startedScrollObject = -1;
|
startedScrollObject = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(runOnMainThread = true)
|
||||||
|
public void onLongClickTranslation(LongClickTranslationEvent e) {
|
||||||
|
if (e.visual) {
|
||||||
|
int j = fragment.getGlView().getRenderer().getSelectedObject();
|
||||||
|
if (j == -1) return;
|
||||||
|
|
||||||
|
Model model = fragment.getGlView().getRenderer().getModel();
|
||||||
|
model.getTranslation(j, tempVec);
|
||||||
|
|
||||||
|
xTitle.setText(formatTrackTitle(R.string.MenuOrientationPositionXValue, tempVec.x + e.x));
|
||||||
|
yTitle.setText(formatTrackTitle(R.string.MenuOrientationPositionYValue, tempVec.y + e.y));
|
||||||
|
xTrack.setCurrentPosition((int) (tempVec.x + e.x));
|
||||||
|
yTrack.setCurrentPosition((int) (tempVec.y + e.y));
|
||||||
|
} else {
|
||||||
|
setSelectionValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(runOnMainThread = true)
|
@EventHandler(runOnMainThread = true)
|
||||||
public void onSelectedObjectChanged(SelectedObjectChangedEvent e) {
|
public void onSelectedObjectChanged(SelectedObjectChangedEvent e) {
|
||||||
stopScroll();
|
stopScroll();
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package ru.ytkab0bp.slicebeam.events;
|
||||||
|
|
||||||
|
import ru.ytkab0bp.eventbus.Event;
|
||||||
|
|
||||||
|
@Event
|
||||||
|
public class LongClickTranslationEvent {
|
||||||
|
public final double x;
|
||||||
|
public final double y;
|
||||||
|
public final boolean visual;
|
||||||
|
|
||||||
|
public LongClickTranslationEvent(double x, double y, boolean visual) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.visual = visual;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -144,7 +144,7 @@ public class SettingsFragment extends ProfileListFragment {
|
|||||||
}),
|
}),
|
||||||
BeamServerData.isBoostyAvailable() ? new OptionElement(R.drawable.boosty, getContext().getString(R.string.SettingsBoosty)).setColor(R.attr.boostyColorTop, true).setOnClick(() -> {
|
BeamServerData.isBoostyAvailable() ? new OptionElement(R.drawable.boosty, getContext().getString(R.string.SettingsBoosty)).setColor(R.attr.boostyColorTop, true).setOnClick(() -> {
|
||||||
Activity act = (Activity) getContext();
|
Activity act = (Activity) getContext();
|
||||||
act.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://boosty.to/ytkab0bp")));
|
act.startActivity(new Intent(act, SetupActivity.class).putExtra(SetupActivity.EXTRA_BOOSTY_ONLY, true));
|
||||||
}) : null,
|
}) : null,
|
||||||
new OptionElement(R.drawable.k3d_logo_new_14, getContext().getString(R.string.SettingsK3D)).setColor(R.attr.k3dColor, true).setOnClick(() -> {
|
new OptionElement(R.drawable.k3d_logo_new_14, getContext().getString(R.string.SettingsK3D)).setColor(R.attr.k3dColor, true).setOnClick(() -> {
|
||||||
Activity act = (Activity) getContext();
|
Activity act = (Activity) getContext();
|
||||||
|
|||||||
@@ -107,6 +107,18 @@ public class MobileNavigationDelegate extends DelegateSlotImpl {
|
|||||||
return root = fl;
|
return root = fl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onBackPressed() {
|
||||||
|
if (super.onBackPressed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (currentSlot != 0) {
|
||||||
|
switchSlot(0, () -> navigationView.setSelectedItemId(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FrameLayout getOverlayView() {
|
public FrameLayout getOverlayView() {
|
||||||
return root;
|
return root;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class Camera {
|
|||||||
this.zoom = zoom;
|
this.zoom = zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(float x, float y) {
|
public Vec3d calcScreenMovement(float x, float y) {
|
||||||
x /= zoom;
|
x /= zoom;
|
||||||
y /= zoom;
|
y /= zoom;
|
||||||
|
|
||||||
@@ -61,8 +61,10 @@ public class Camera {
|
|||||||
screenX.multiply(x);
|
screenX.multiply(x);
|
||||||
screenY.multiply(y);
|
screenY.multiply(y);
|
||||||
|
|
||||||
Vec3d move = new Vec3d(screenX).add(screenY);
|
return new Vec3d(screenX).add(screenY);
|
||||||
|
}
|
||||||
|
public void move(float x, float y) {
|
||||||
|
Vec3d move = calcScreenMovement(x, y);
|
||||||
position.add(move);
|
position.add(move);
|
||||||
origin.add(move);
|
origin.add(move);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,9 +374,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onClick(float x, float y) {
|
public int raycastObjectIndex(float x, float y) {
|
||||||
if (model == null || isViewerEnabled) return false;
|
if (model == null) return -1;
|
||||||
|
|
||||||
double minDistance = Double.MAX_VALUE;
|
double minDistance = Double.MAX_VALUE;
|
||||||
int j = -1;
|
int j = -1;
|
||||||
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
for (int i = 0, c = model.getObjectsCount(); i < c; i++) {
|
||||||
@@ -394,6 +393,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onClick(float x, float y) {
|
||||||
|
if (model == null || isViewerEnabled) return false;
|
||||||
|
|
||||||
|
int j = raycastObjectIndex(x, y);
|
||||||
|
|
||||||
if (isInFlattenMode && (j == selectedObject || j == -1)) {
|
if (isInFlattenMode && (j == selectedObject || j == -1)) {
|
||||||
int minPlane = -1;
|
int minPlane = -1;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class Bed3D {
|
|||||||
|
|
||||||
private void configure(String path) {
|
private void configure(String path) {
|
||||||
Native.bed_configure(pointer, path);
|
Native.bed_configure(pointer, path);
|
||||||
|
Native.bed_init_triangles_mesh(pointer, triangles.pointer);
|
||||||
boundingVolume = Native.bed_get_bounding_volume(pointer);
|
boundingVolume = Native.bed_get_bounding_volume(pointer);
|
||||||
|
|
||||||
min = max = null;
|
min = max = null;
|
||||||
@@ -78,6 +79,10 @@ public class Bed3D {
|
|||||||
return boundingVolume != null;
|
return boundingVolume != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GLModel.MeshRaycaster getRaycaster() {
|
||||||
|
return triangles.getRaycaster();
|
||||||
|
}
|
||||||
|
|
||||||
public void render(boolean bottom, double[] viewModelMatrix, double[] projectionMatrix, float invZoom) {
|
public void render(boolean bottom, double[] viewModelMatrix, double[] projectionMatrix, float invZoom) {
|
||||||
assertTrue(viewModelMatrix.length == 16);
|
assertTrue(viewModelMatrix.length == 16);
|
||||||
assertTrue(projectionMatrix.length == 16);
|
assertTrue(projectionMatrix.length == 16);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class Native {
|
|||||||
static native int bed_get_bounding_volume_max_size(long ptr);
|
static native int bed_get_bounding_volume_max_size(long ptr);
|
||||||
static native double[] bed_get_bounding_volume(long ptr);
|
static native double[] bed_get_bounding_volume(long ptr);
|
||||||
static native void bed_configure(long ptr, String configPath);
|
static native void bed_configure(long ptr, String configPath);
|
||||||
|
static native void bed_init_triangles_mesh(long ptr, long triangles);
|
||||||
static native boolean bed_arrange(long ptr, long modelPtr);
|
static native boolean bed_arrange(long ptr, long modelPtr);
|
||||||
static native void bed_release(long ptr);
|
static native void bed_release(long ptr);
|
||||||
|
|
||||||
|
|||||||
@@ -17,17 +17,23 @@ import android.opengl.GLSurfaceView;
|
|||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ru.ytkab0bp.slicebeam.R;
|
import ru.ytkab0bp.slicebeam.R;
|
||||||
|
import ru.ytkab0bp.slicebeam.SliceBeam;
|
||||||
|
import ru.ytkab0bp.slicebeam.events.LongClickTranslationEvent;
|
||||||
import ru.ytkab0bp.slicebeam.render.GLRenderer;
|
import ru.ytkab0bp.slicebeam.render.GLRenderer;
|
||||||
|
import ru.ytkab0bp.slicebeam.slic3r.GLModel;
|
||||||
import ru.ytkab0bp.slicebeam.theme.IThemeView;
|
import ru.ytkab0bp.slicebeam.theme.IThemeView;
|
||||||
import ru.ytkab0bp.slicebeam.theme.ThemesRepo;
|
import ru.ytkab0bp.slicebeam.theme.ThemesRepo;
|
||||||
import ru.ytkab0bp.slicebeam.utils.Prefs;
|
import ru.ytkab0bp.slicebeam.utils.Prefs;
|
||||||
|
import ru.ytkab0bp.slicebeam.utils.Vec3d;
|
||||||
import ru.ytkab0bp.slicebeam.utils.ViewUtils;
|
import ru.ytkab0bp.slicebeam.utils.ViewUtils;
|
||||||
|
|
||||||
public class GLView extends GLSurfaceView implements IThemeView {
|
public class GLView extends GLSurfaceView implements IThemeView {
|
||||||
@@ -40,9 +46,26 @@ public class GLView extends GLSurfaceView implements IThemeView {
|
|||||||
private boolean fromTwoPointers;
|
private boolean fromTwoPointers;
|
||||||
private boolean onePointerGesture;
|
private boolean onePointerGesture;
|
||||||
private boolean twoPointerGesture;
|
private boolean twoPointerGesture;
|
||||||
|
private boolean longClickGesture;
|
||||||
private boolean isScaling;
|
private boolean isScaling;
|
||||||
|
|
||||||
|
private Vec3d tempVec = new Vec3d();
|
||||||
|
private Vec3d longClickOffset = new Vec3d();
|
||||||
|
private Vec3d longClickTranslation = new Vec3d();
|
||||||
|
private ArrayList<GLModel.HitResult> longClickHitResults = new ArrayList<>();
|
||||||
private long lastActionTime = System.currentTimeMillis();
|
private long lastActionTime = System.currentTimeMillis();
|
||||||
|
private Runnable longClick = () -> {
|
||||||
|
getRenderer().getBed().getRaycaster().raycast(getRenderer(), longClickHitResults, lastX, lastY);
|
||||||
|
if (!longClickHitResults.isEmpty()) {
|
||||||
|
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
|
longClickGesture = true;
|
||||||
|
|
||||||
|
GLModel.HitResult result = longClickHitResults.get(0);
|
||||||
|
getRenderer().getModel().getTranslation(getRenderer().getSelectedObject(), tempVec);
|
||||||
|
longClickOffset.x = result.position.x - tempVec.x;
|
||||||
|
longClickOffset.y = result.position.y - tempVec.y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private Path path = new Path();
|
private Path path = new Path();
|
||||||
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
@@ -249,21 +272,43 @@ public class GLView extends GLSurfaceView implements IThemeView {
|
|||||||
int action = e.getActionMasked();
|
int action = e.getActionMasked();
|
||||||
|
|
||||||
if (e.getPointerCount() > 2) {
|
if (e.getPointerCount() > 2) {
|
||||||
|
removeCallbacks(longClick);
|
||||||
|
longClickGesture = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {
|
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
if (e.getPointerCount() == 2) {
|
if (e.getPointerCount() == 2) {
|
||||||
|
removeCallbacks(longClick);
|
||||||
|
longClickGesture = false;
|
||||||
calcStartFocus(e);
|
calcStartFocus(e);
|
||||||
fromTwoPointers = true;
|
fromTwoPointers = true;
|
||||||
} else {
|
} else {
|
||||||
lastX = e.getX();
|
lastX = e.getX();
|
||||||
lastY = e.getY();
|
lastY = e.getY();
|
||||||
|
|
||||||
|
int j = renderer.raycastObjectIndex(lastX, lastY);
|
||||||
|
if (j == renderer.getSelectedObject() && j != -1) {
|
||||||
|
postDelayed(longClick, 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_CANCEL) {
|
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||||
|
removeCallbacks(longClick);
|
||||||
|
if (longClickGesture) {
|
||||||
|
queueEvent(()->{
|
||||||
|
int j = getRenderer().getSelectedObject();
|
||||||
|
getRenderer().getModel().getTranslation(j, tempVec);
|
||||||
|
getRenderer().setSelectionTranslation(0, 0, 0);
|
||||||
|
getRenderer().getModel().translate(j, longClickTranslation.x, longClickTranslation.y, 0);
|
||||||
|
getRenderer().invalidateGlModel(j);
|
||||||
|
requestRender();
|
||||||
|
SliceBeam.EVENT_BUS.fireEvent(new LongClickTranslationEvent(longClickTranslation.x, longClickTranslation.y, false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
longClickGesture = false;
|
||||||
if (fromTwoPointers) {
|
if (fromTwoPointers) {
|
||||||
if (e.getPointerCount() == 1) {
|
if (e.getPointerCount() == 1) {
|
||||||
fromTwoPointers = false;
|
fromTwoPointers = false;
|
||||||
@@ -286,7 +331,7 @@ public class GLView extends GLSurfaceView implements IThemeView {
|
|||||||
onePointerGesture = false;
|
onePointerGesture = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rotate with inertia
|
// TODO: Rotate with inertia?
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_MOVE) {
|
if (action == MotionEvent.ACTION_MOVE) {
|
||||||
@@ -347,18 +392,35 @@ public class GLView extends GLSurfaceView implements IThemeView {
|
|||||||
if (Math.sqrt(distanceX * distanceX + distanceY * distanceY) >= touchSlop) {
|
if (Math.sqrt(distanceX * distanceX + distanceY * distanceY) >= touchSlop) {
|
||||||
onePointerGesture = true;
|
onePointerGesture = true;
|
||||||
startingGesture = true;
|
startingGesture = true;
|
||||||
|
removeCallbacks(longClick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onePointerGesture) {
|
if (onePointerGesture) {
|
||||||
if (!startingGesture) {
|
if (!startingGesture) {
|
||||||
int mode = Prefs.getCameraControlMode();
|
if (longClickGesture) {
|
||||||
if (mode == Prefs.CAMERA_CONTROL_MODE_ROTATE_MOVE) {
|
Vec3d move = getRenderer().getCamera().calcScreenMovement(distanceX / touchSlop * 4.5f, distanceY / touchSlop * 4.5f);
|
||||||
renderer.getCamera().rotateAround(distanceX / touchSlop * Prefs.getCameraSensitivity(), distanceY / touchSlop * Prefs.getCameraSensitivity());
|
|
||||||
|
getRenderer().getModel().getTranslation(getRenderer().getSelectedObject(), tempVec);
|
||||||
|
getRenderer().getBed().getRaycaster().raycast(getRenderer(), longClickHitResults, e.getX(), e.getY());
|
||||||
|
if (!longClickHitResults.isEmpty()) {
|
||||||
|
GLModel.HitResult result = longClickHitResults.get(0);
|
||||||
|
longClickTranslation.x = result.position.x - tempVec.x - longClickOffset.x;
|
||||||
|
longClickTranslation.y = result.position.y - tempVec.y - longClickOffset.y;
|
||||||
|
getRenderer().setSelectionTranslation(longClickTranslation.x, longClickTranslation.y, 0);
|
||||||
|
SliceBeam.EVENT_BUS.fireEvent(new LongClickTranslationEvent(longClickTranslation.x, longClickTranslation.y, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
requestRender();
|
||||||
} else {
|
} else {
|
||||||
renderer.getCamera().move(distanceX / touchSlop * Prefs.getCameraSensitivity(), distanceY / touchSlop * Prefs.getCameraSensitivity());
|
int mode = Prefs.getCameraControlMode();
|
||||||
|
if (mode == Prefs.CAMERA_CONTROL_MODE_ROTATE_MOVE) {
|
||||||
|
renderer.getCamera().rotateAround(distanceX / touchSlop * Prefs.getCameraSensitivity(), distanceY / touchSlop * Prefs.getCameraSensitivity());
|
||||||
|
} else {
|
||||||
|
renderer.getCamera().move(distanceX / touchSlop * Prefs.getCameraSensitivity(), distanceY / touchSlop * Prefs.getCameraSensitivity());
|
||||||
|
}
|
||||||
|
requestRender();
|
||||||
}
|
}
|
||||||
requestRender();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastX = e.getX();
|
lastX = e.getX();
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ public class SnackbarsLayout extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void show(Snackbar snackbar) {
|
public void show(Snackbar snackbar) {
|
||||||
|
if (snackbar.tag != null) {
|
||||||
|
dismiss(snackbar.tag);
|
||||||
|
}
|
||||||
|
|
||||||
SnackbarView v = new SnackbarView(getContext()).bind(snackbar);
|
SnackbarView v = new SnackbarView(getContext()).bind(snackbar);
|
||||||
addView(v);
|
addView(v);
|
||||||
applyTransforms();
|
applyTransforms();
|
||||||
|
|||||||
@@ -1401,6 +1401,19 @@ extern "C" {
|
|||||||
bed_util_init_contourlines(ref->contour, ref->contourlines);
|
bed_util_init_contourlines(ref->contour, ref->contourlines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_ru_ytkab0bp_slicebeam_slic3r_Native_bed_1init_1triangles_1mesh(JNIEnv* env, jclass, jlong ptr, jlong triangles_ptr) {
|
||||||
|
auto ref = reinterpret_cast<BedRef*>(ptr);
|
||||||
|
auto tRef = reinterpret_cast<GLModelRef*>(triangles_ptr);
|
||||||
|
|
||||||
|
auto contour = ref->contour;
|
||||||
|
BoundingBox bb = get_extents(contour);
|
||||||
|
Point center = bb.center();
|
||||||
|
float scaleFactor = 4;
|
||||||
|
contour.scale(scaleFactor);
|
||||||
|
contour.translate(-center.x() * scaleFactor * 0.5f, -center.y() * scaleFactor * 0.5f);
|
||||||
|
bed_util_init_triangles_its(contour, &tRef->mesh.its);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_ru_ytkab0bp_slicebeam_slic3r_Native_bed_1arrange(JNIEnv* env, jclass, jlong ptr, jlong model) {
|
JNIEXPORT jboolean JNICALL Java_ru_ytkab0bp_slicebeam_slic3r_Native_bed_1arrange(JNIEnv* env, jclass, jlong ptr, jlong model) {
|
||||||
BedRef* ref = (BedRef*) (intptr_t) ptr;
|
BedRef* ref = (BedRef*) (intptr_t) ptr;
|
||||||
ModelRef* mRef = (ModelRef*) (intptr_t) model;
|
ModelRef* mRef = (ModelRef*) (intptr_t) model;
|
||||||
|
|||||||
@@ -56,6 +56,22 @@ void bed_util_init_gridlines(ExPolygon& contour, GLModel* glGridlines) {
|
|||||||
glGridlines->init_from(std::move(init_data));
|
glGridlines->init_from(std::move(init_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bed_util_init_triangles_its(ExPolygon& contour, indexed_triangle_set* its) {
|
||||||
|
if (contour.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto triangles = triangulate_expolygon_3d(contour, 0);
|
||||||
|
its->vertices.reserve(triangles.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < triangles.size(); i += 3) {
|
||||||
|
its->vertices.emplace_back(triangles[i].cast<float>());
|
||||||
|
its->vertices.emplace_back(triangles[i + 1].cast<float>());
|
||||||
|
its->vertices.emplace_back(triangles[i + 2].cast<float>());
|
||||||
|
|
||||||
|
its->indices.emplace_back(i, i + 1, i + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void bed_util_init_triangles(ExPolygon& contour, GLModel* glTriangles) {
|
void bed_util_init_triangles(ExPolygon& contour, GLModel* glTriangles) {
|
||||||
if (glTriangles->is_initialized())
|
if (glTriangles->is_initialized())
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user