I want to have a zoom effect inside an area in a EditorWindow, something like a zoomable scrollview.
The following snippet deals only with the panning effect but it exemplifies the issue I'm having when the contents inside the zoomable area and the clipping rect can't be handled independently of each other through hSliderValue1 (clipping) and hSliderValue2 (panning).
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ZoomTestWindow : EditorWindow
{
private static float kEditorWindowTabHeight = 20;
private static Matrix4x4 _prevGuiMatrix;
public static float hSliderValue1 = 0;
public static float hSliderValue2 = 0;
Rect[] wr = new Rect[]{
new Rect(0, 0, 100, 100),
new Rect(50, 50, 100, 100),
new Rect(100, 100, 100, 100)
};
[MenuItem("Window/Zoom Test #%w")]
private static void Init()
{
ZoomTestWindow window = EditorWindow.GetWindow<ZoomTestWindow>("Zoom Test", true, new System.Type[] {
typeof(UnityEditor.SceneView),
typeof(EditorWindow).Assembly.GetType("UnityEditor.SceneHierarchyWindow")});
window.Show();
EditorWindow.FocusWindowIfItsOpen<ZoomTestWindow>();
}
public static Rect BeginZoomArea()
{
GUI.EndGroup(); //End the group that Unity began so we're not bound by the EditorWindow
GUI.BeginGroup(new Rect(hSliderValue1, 0, 200, 200));
_prevGuiMatrix = GUI.matrix;
GUI.matrix = Matrix4x4.TRS(new Vector2(hSliderValue2, 0), Quaternion.identity, Vector3.one);;
return new Rect();
}
public static void EndZoomArea()
{
GUI.matrix = _prevGuiMatrix;
GUI.EndGroup();
GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height - (kEditorWindowTabHeight + 3)));
}
public void OnGUI()
{
BeginZoomArea();
BeginWindows();
wr[0] = GUI.Window(0, wr[0], DrawWindow, "hello");
wr[1] = GUI.Window(1, wr[1], DrawWindow, "world");
wr[2] = GUI.Window(2, wr[2], DrawWindow, "!");
EndWindows();
EndZoomArea();
hSliderValue1 = GUI.HorizontalSlider(new Rect(200, 5, 100, 30), hSliderValue1, 0, 100);
hSliderValue2 = GUI.HorizontalSlider(new Rect(200, 25, 100, 30), hSliderValue2, 0, 100);
}
void DrawWindow(int id)
{
GUI.Button(new Rect(0, 30, 100, 50), "Wee!");
GUI.DragWindow();
}
}
Is there a way to do this, maybe by using a scroll view?
Embed the group controlled by hSliderValue1 inside a new group.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ZoomMoveTestWindow: EditorWindow
{
private static float kEditorWindowTabHeight = 20;
private static Matrix4x4 _prevGuiMatrix;
public static float hSliderValue1 = 0;
public static float hSliderValue2 = 0;
Rect[] wr = new Rect[]{
new Rect(0, 0, 100, 100),
new Rect(50, 50, 100, 100),
new Rect(100, 100, 100, 100)
};
[MenuItem("Window/Zoom Test #%w")]
private static void Init()
{
ZoomMoveTestWindow window = EditorWindow.GetWindow<ZoomMoveTestWindow>("Zoom Test", true, new System.Type[] {
typeof(UnityEditor.SceneView),
typeof(EditorWindow).Assembly.GetType("UnityEditor.SceneHierarchyWindow")});
window.Show();
EditorWindow.FocusWindowIfItsOpen<ZoomMoveTestWindow>();
}
public static Rect BeginZoomArea(Rect rect)
{
GUI.BeginGroup(rect);
GUI.BeginGroup(new Rect(hSliderValue1, 0, 200, 200));
_prevGuiMatrix = GUI.matrix;
GUI.matrix = Matrix4x4.TRS(new Vector2(hSliderValue2, 0), Quaternion.identity, Vector3.one);
return new Rect();
}
public static void EndZoomArea()
{
GUI.EndGroup();
GUI.matrix = _prevGuiMatrix;
GUI.EndGroup();
GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height - (kEditorWindowTabHeight + 3)));
}
public void OnGUI()
{
GUI.EndGroup(); //End the group that Unity began so we're not bound by the EditorWindow
BeginZoomArea(new Rect(10,10, 200, 200));
BeginWindows();
wr[0] = GUI.Window(0, wr[0], DrawWindow, "hello");
wr[1] = GUI.Window(1, wr[1], DrawWindow, "world");
wr[2] = GUI.Window(2, wr[2], DrawWindow, "!");
EndWindows();
EndZoomArea();
hSliderValue1 = GUI.HorizontalSlider(new Rect(250, 5, 100, 30), hSliderValue1, 0, 100);
hSliderValue2 = GUI.HorizontalSlider(new Rect(250, 35, 100, 30), hSliderValue2, 0, 100);
}
void DrawWindow(int id)
{
GUI.Button(new Rect(0, 30, 100, 50), "Wee!");
GUI.DragWindow();
}
}
It works but I don't know why. Because the interaction of GUI.matrix and BeginGroup(rect) is unknown.
PS: This post may help you.
Related
I am trying to create a TArray Recoil Pattern for my Gun with 30 different FVector coordinates for each bullet. I went through tultorial videos and read https://docs.unrealengine.com/5.0/en-US/array-containers-in-unreal-engine/ this guide for adding to the array.I tried using Add, Emplace, Innit to no avail. I even set the size to 30 with SetNum, still didn't work i do not understand what my issue is with adding elements to the TArray. I keep getting this crash error : I keep getting this crash error
this is my GunProperties.H
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GunProperties.generated.h"
#define TRACE_WEAPON ECC_GameTraceChannel1
UENUM(BlueprintType)
namespace EWeaponProjectile
{
enum ProjectileType
{
EBullet UMETA(DisplayName = "Bullet"),
ESpread UMETA(DisplayName = "Spread"),
EProjectile UMETA(DisplayName = "Projectile"),
};
}
USTRUCT()
struct FWeaponData
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, Category = Ammo)
int32 MaxAmmo;
UPROPERTY(EditDefaultsOnly, Category = Config)
float TimeBetweenShots;
UPROPERTY(EditDefaultsOnly, Category = Ammo)
int32 ShotCost;
UPROPERTY(EditDefaultsOnly, Category = Config)
float WeaponRange;
UPROPERTY(EditDefaultsOnly, Category = Config)
float WeaponSpread;
UPROPERTY(EditDefaultsOnly, Category = Config)
float recoilResetTimeSeconds;
UPROPERTY(EditDefaultsOnly, Category = Config)
float lastTimeShotForAr;
};
UCLASS()
class PLAYERVSAI_API AGunProperties : public AActor
{
GENERATED_BODY()
public:
// Called when the game starts or when spawned
AGunProperties();
// Called every frame
UFUNCTION()
void Fire(const FVector CameraDir);
UFUNCTION()
void InstantFire(const FVector CameraDir);
virtual void BeginPlay() override;
UPROPERTY(EditDefaultsOnly, Category = Config)
FWeaponData WeaponConfig;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = Config)
TEnumAsByte<EWeaponProjectile::ProjectileType> ProjectileType;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Collision)
UBoxComponent* CollisionComp;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Config)
USkeletalMeshComponent* WeaponMesh;
/*void InterpAiming(float DeltaSeconds);
void InterpRelativeHand(float DeltaSeconds);*/
FTransform RecoilTransform;
FTransform FinalRecoilTransform;
//Handle Vector Recoil , returns New Location
protected:
FHitResult WeaponTrace(const FVector &TraceFrom, const FVector &TraceTo) const;
void HandleARShooting(UCameraComponent* Camera);
void ProcessInstantHit(const FHitResult& Impact, const FVector& Origin, const FVector& ShootDir, int32 RandomSeed, float RadicalSpread);
void ProcessInstantHitForAR(const FHitResult& Impact, const FVector& Origin);
TArray<FVector> RecoilPattern[];
};
This is my GunProperties.cpp
#include "GunProperties.h"
#include "Engine.h"
AGunProperties::AGunProperties()
{
PrimaryActorTick.bCanEverTick = false;
CollisionComp = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionComp"));
RootComponent = CollisionComp;
WeaponMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Gun Mesh"));
WeaponMesh->AttachTo(RootComponent);
}
void AGunProperties::BeginPlay()
{
Super::BeginPlay();
if (ProjectileType == EWeaponProjectile::EBullet)
{
RecoilPattern->SetNum(30);
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.2, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.3, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(-0.5, 0, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, -0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
RecoilPattern->Emplace(FVector(0, 0.3, 0));
}
}
void AGunProperties::Fire( FVector CameraDir)
{
if (ProjectileType == EWeaponProjectile::EBullet)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Black, TEXT("Bullet"));
//InstantFire(CameraDir);
}
if (ProjectileType == EWeaponProjectile::ESpread)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Black, TEXT("Spread"));
for (int32 i = 0; i <= WeaponConfig.WeaponSpread; i++)
{
InstantFire(CameraDir);
}
}
if (ProjectileType == EWeaponProjectile::EProjectile)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Black, TEXT("Projectile"));
}
}
void AGunProperties::InstantFire( FVector CameraDir)
{
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
const float CurrentSpread = WeaponConfig.WeaponSpread;
const float SpreadCone = FMath::DegreesToRadians(WeaponConfig.WeaponSpread );
const FVector StartTrace = WeaponMesh->GetSocketLocation("MF");
const FVector ShootDir = WeaponRandomStream.VRandCone(StartTrace, SpreadCone, SpreadCone);
const FVector EndTrace = StartTrace + ShootDir * WeaponConfig.WeaponRange;
const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread);
}
FHitResult AGunProperties::WeaponTrace(const FVector& TraceFrom, const FVector& TraceTo) const
{
static FName WeaponFireTag = FName(TEXT("WeaponTrace"));
FCollisionQueryParams TraceParams(WeaponFireTag, true);
TraceParams.bReturnPhysicalMaterial = true;
TraceParams.AddIgnoredActor(this);
FHitResult Hit(ForceInit);
GetWorld()->LineTraceSingleByChannel(Hit, TraceFrom, TraceTo, TRACE_WEAPON, TraceParams);
return Hit;
}
void AGunProperties::HandleARShooting(UCameraComponent* Camera)
{
if (GetWorld()->DeltaTimeSeconds - WeaponConfig.lastTimeShotForAr / WeaponConfig.TimeBetweenShots)
{
//We shoot
const FVector StartTrace = WeaponMesh->GetSocketLocation("MF");
const FVector ShootDir = FVector(StartTrace);
const FVector EndTrace = StartTrace * WeaponConfig.WeaponRange;
const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHitForAR(Impact, StartTrace);
WeaponConfig.lastTimeShotForAr = GetWorld()->DeltaTimeSeconds;
}
}
void AGunProperties::ProcessInstantHit(const FHitResult& Impact, const FVector& Origin, const FVector& ShootDir, int32 RandomSeed, float RadicalSpread)
{
const FVector EndTrace = Origin + ShootDir * WeaponConfig.WeaponRange;
const FVector EndPoint = Impact.GetActor() ? Impact.ImpactPoint : EndTrace;
DrawDebugLine(this->GetWorld(), Origin, Impact.TraceEnd, FColor::Black,false, 1000, 10.f);
}
void AGunProperties::ProcessInstantHitForAR(const FHitResult& Impact, const FVector& Origin)
{
const FVector EndTrace = Origin* WeaponConfig.WeaponRange;
const FVector EndPoint = Impact.GetActor() ? Impact.ImpactPoint : EndTrace;
DrawDebugLine(this->GetWorld(), Origin, Impact.TraceEnd, FColor::Black, false, 1000, 10.f);
}
The issues was that i did not add UPROPERTY() above the TArray. Epic does not mention this in the guide that i linked or maybe i missed it somewhere. Give the credits to the people in this post who mentioned it . https://forums.unrealengine.com/t/why-does-the-engine-crash-when-adding-to-an-array/82703/8
I'm the beginner of game coding, and meet some problem...
I would like to make coin stack and then click the coin all the coin would become small and fly to dedicate position, however, the coin position wasn't initialized which causes the Vector3 of coin move up 0.1f every time...
Please help me to solve it!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class createcoin : MonoBehaviour
{ public Transform RightCoinArea;
public Transform LeftCoinArea;
public Sprite sprite1;
List<Vector3> rightcoinpos = new List<Vector3>();
List<Vector3> leftcoinpos = new List<Vector3>();
public Vector3 [] rightpos= new Vector3 [6] ;
public Vector3[] leftpos = new Vector3[6];
// Start is called before the first frame update
void Start()
{
rightcoinpos.Add(rightpos);
leftcoinpos.Add(leftpos);
}
//create coin
public async void coincreate()
{
//coin stack random
for (float i = 0; i <= 0.1f; i += 0.1f)
{
var coin8 = await PoolSystem.Instance.GetGameObject(eBundle.Game, "Flycoin",
rightcoinpos[Random.Range(0, rightcoinpos.Count)] += Vector3.up * i, new Vector3(0.4f, 0.4f, 04f), sFileExtension.Prefab, RightCoinArea);
//to initialize sprite
coin8.GetComponent<SpriteRenderer>().sprite = sprite1;
}
//coin stack random
for (float i = 0; i < 0.2f; i += 0.1f)
{
var coin9 = await PoolSystem.Instance.GetGameObject(eBundle.Game, "Flycoin", leftcoinpos[Random.Range(0, leftcoinpos.Count)] += Vector3.up * i, new Vector3(0.4f, 0.4f, 04f), sFileExtension.Prefab, LeftCoinArea);
//to initialize sprite
coin9.GetComponent<SpriteRenderer>().sprite = sprite1;
}
}
public void Moveout()
{
//gameobject back to the objectpool
if (RightCoinArea.gameObject.transform.localScale == new Vector3(0, 0, 0))
{
PoolSystem.Instance.Recover(RightCoinArea.gameObject);
}
if (LeftCoinArea.gameObject.transform.localScale == new Vector3(0, 0, 0))
{
PoolSystem.Instance.Recover(LeftCoinArea.gameObject);
}
//delete all the position in List
rightcoinpos.Clear();
leftcoinpos.Clear();
//to initialize the position
Vector3 tempos_R = rightpos;
Vector3 tempos_L = leftpos;
rightcoinpos.Add(rightpos);
leftcoinpos.Add(leftpos);
}
public void click()
{
coin_test.GetComponent<SpriteRenderer>().sprite = sprite2_test;
//coin fly to end dedicate pos
DOTween.To(setter: value =>
{
coin_test.position = Parabola(start_test.position, new Vector3(0, 4.5f, 0), 1.5f, value);
}, startValue: 0, endValue: 1, duration: 1.5f)
.SetEase(Ease.Linear);
//change coin scale
transform.DOScale(0.0f, 2.0f).OnComplete(Moveout);
}
//Parabola
public static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t)
{
float Func(float x) => 0.5f * (-height * x * x + height * x);
var mid = Vector3.Lerp(start, end, t);
return new Vector3(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t), mid.z);
}
}
enter image description hereI have 4 sprites. I am placing all 4 sprites in different place on the mobile screen. But it is taking the last added sprite image that is (sprite4.png) all the sprites images(sprite1.png, sprite2.png, sprite3.png and sprite4.png).
In short its displaying all the sprite images same.
The code is given below, please share your experience
// the below code is running without error but displaying same images in all the sprites
package com.example.test1;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.util.FPSLogger;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
/*;
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga
*
* #author Nicolas Gramlich
* #since 15:13:46 - 15.06.2010
*/
public class Puzzle extends GameActivity {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
final Scene scene = new Scene();
// ===========================================================
// Fields
// ===========================================================
private BitmapTextureAtlas mBitmapTextureAtlas;
private ITextureRegion spriteTextureRegion1;
private ITextureRegion spriteTextureRegion2;
private ITextureRegion spriteTextureRegion3;
private ITextureRegion spriteTextureRegion4;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public EngineOptions onCreateEngineOptions() {
// Toast.makeText(this, "Touch & Drag the face!", Toast.LENGTH_LONG).show();
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
#Override
public void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 96, 96, TextureOptions.BILINEAR);
this.spriteTextureRegion1 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite1.png", 0, 0);
this.spriteTextureRegion2 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite2.png", 0, 0);
this.spriteTextureRegion3 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite3.png", 0, 0);
this.spriteTextureRegion4= BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite4.png", 0, 0);
// scene.attachChild(sprite1);
this.mBitmapTextureAtlas.load();
}
#Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
/* set sprite1 positions on screen */
final float sprite1_posX = (40);
final float sprite1_posY = (40);
final Sprite sprite1 = new Sprite(sprite1_posX, sprite1_posY, this.spriteTextureRegion1, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
//sprite1.setScale(3);
scene.attachChild(sprite1);
scene.registerTouchArea(sprite1);
scene.setTouchAreaBindingOnActionDownEnabled(true);
/* set sprite2 positions on screen */
final Sprite sprite2 = new Sprite(sprite1_posX, sprite1_posY + (sprite1.getHeight()*3 + 10), this.spriteTextureRegion2, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
//sprite2.setScale(3);
scene.attachChild(sprite2);
scene.registerTouchArea(sprite2);
scene.setTouchAreaBindingOnActionDownEnabled(true);
/* set sprite3 positions on screen */
final Sprite sprite3 = new Sprite(sprite1_posX, sprite1_posY + (sprite1.getHeight() + 20), this.spriteTextureRegion3, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
// sprite3.setScale(3);
scene.attachChild(sprite3);
scene.registerTouchArea(sprite3);
scene.setTouchAreaBindingOnActionDownEnabled(true);
/* set sprite3 positions on screen */
final Sprite sprite4 = new Sprite(sprite1_posX, sprite1_posY + (sprite1.getHeight() + 30), this.spriteTextureRegion4, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
// sprite4.setScale(3);
scene.attachChild(sprite4);
scene.registerTouchArea(sprite4);
scene.setTouchAreaBindingOnActionDownEnabled(true);
return scene;
}
}
Oh sorry I know what is the problem:
this.spriteTextureRegion1 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite1.png", 0, 0);
this.spriteTextureRegion2 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite2.png", 0, 0);
this.spriteTextureRegion3 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite3.png", 0, 0);
this.spriteTextureRegion4= BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite4.png", 0, 0);
At the end, where you put 0, 0 - you declare where your region should be located on the Texture atlas. Imagine stickers you put on the sheet of paper. You put one, then on this you put another, and third and fourth. This way you can see only the one that is on top. So you have to put your regions in different places of the texture atlas. If all your images are 40x40 it should look like this (also your atlas might be bigger (512x512):
this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 512, 512, TextureOptions.BILINEAR);
this.spriteTextureRegion1 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite1.png", 0, 0);
this.spriteTextureRegion2 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite2.png", 50, 0);
this.spriteTextureRegion3 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite3.png", 0, 50);
this.spriteTextureRegion4= BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "sprite4.png", 50, 50);
In my game, I am using simple textures on quads. I could see Unity GUI allows us to slice the image by setting "image type" option as sliced.
I would like to do the same to my other textures I use in quads.
In simple words, I dont want the edges of my textures to be scaled when the texture itself is scaled.
Thanks.
Looks like you have to generate the mesh yourself, not so hard as it sounds. The mesh has to look like this:
Each textured mesh is defined by vertices (red dots on the picture) and (in this case) each vertex has two parameters:
A Vector3 with position. Only x and y used here, as a quad is flat (so, z = 0).
A Vector2 with the UV, that is how the material is put on the mesh. This are the texture coordinates: u and v.
To configure this mesh, I added parameters:
b - for border - how big is the border of the gameobject (in 3d units)
w, h - for width and height of the gameobject (in 3d units)
m - how big is the margin in the image (in float 0f to 0.5f)
How to do this in Unity3d:
Create an GameObject, add a MeshRenderer with the material you want and an empty MeshFilter.
Add a script that creates a mesh. Look at Unity3d docs for Mesh, first example.
Note that for unity3d you have to create this with triangles, not quads (so for each quad make two triangles).
Chanibal's solutions worked like a charm for me, but since I wasn't an expert in the matter, it wasn't trivial to me to implement this. I will let this code here in case somebody could find it useful.
using UnityEngine;
public class SlicedMesh : MonoBehaviour
{
private float _b = 0.1f;
public float Border
{
get
{
return _b;
}
set
{
_b = value;
CreateSlicedMesh();
}
}
private float _w = 1.0f;
public float Width
{
get
{
return _w;
}
set
{
_w = value;
CreateSlicedMesh();
}
}
private float _h = 1.0f;
public float Height
{
get
{
return _h;
}
set
{
_h = value;
CreateSlicedMesh();
}
}
private float _m = 0.4f;
public float Margin
{
get
{
return _m;
}
set
{
_m = value;
CreateSlicedMesh();
}
}
void Start()
{
CreateSlicedMesh();
}
void CreateSlicedMesh()
{
Mesh mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
mesh.vertices = new Vector3[] {
new Vector3(0, 0, 0), new Vector3(_b, 0, 0), new Vector3(_w-_b, 0, 0), new Vector3(_w, 0, 0),
new Vector3(0, _b, 0), new Vector3(_b, _b, 0), new Vector3(_w-_b, _b, 0), new Vector3(_w, _b, 0),
new Vector3(0, _h-_b, 0), new Vector3(_b, _h-_b, 0), new Vector3(_w-_b, _h-_b, 0), new Vector3(_w, _h-_b, 0),
new Vector3(0, _h, 0), new Vector3(_b, _h, 0), new Vector3(_w-_b, _h, 0), new Vector3(_w, _h, 0)
};
mesh.uv = new Vector2[] {
new Vector2(0, 0), new Vector2(_m, 0), new Vector2(1-_m, 0), new Vector2(1, 0),
new Vector2(0, _m), new Vector2(_m, _m), new Vector2(1-_m, _m), new Vector2(1, _m),
new Vector2(0, 1-_m), new Vector2(_m, 1-_m), new Vector2(1-_m, 1-_m), new Vector2(1, 1-_m),
new Vector2(0, 1), new Vector2(_m, 1), new Vector2(1-_m, 1), new Vector2(1, 1)
};
mesh.triangles = new int[] {
0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
2, 6, 7,
2, 7, 3,
4, 8, 9,
4, 9, 5,
5, 9, 10,
5, 10, 6,
6, 10, 11,
6, 11, 7,
8, 12, 13,
8, 13, 9,
9, 13, 14,
9, 14, 10,
10, 14, 15,
10, 15, 11
};
}
}
Here is another impementation of the same mesh as described above(just add Tile9Mesh script to empty GameObject and it should work
):
using UnityEngine;
namespace Util {
[ExecuteInEditMode]
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class Tile9Mesh : MonoBehaviour {
public float width = 1;
public float height = 1;
[Range(0, 0.5f)]
public float uvLeft = 0.2f;
[Range(0, 0.5f)]
public float uvRight = 0.2f;
[Range(0, 0.5f)]
public float uvTop = 0.2f;
[Range(0, 0.5f)]
public float uvBottom = 0.2f;
public float uvToWorldScaleX = 1;
public float uvToWorldScaleY = 1;
private Mesh mesh;
private Vector3[] vertices;
private Vector2[] uv;
private void Start() {
vertices = new Vector3[16];
uv = new Vector2[16];
mesh = new Mesh {
name = "Tile9Mesh"
};
FillGeometry();
FillMesh();
mesh.triangles = new[] {
0, 1, 12, 0, 12, 11,
1, 2, 13, 1, 13, 12,
2, 3, 4, 2, 4, 13,
13, 4, 5, 13, 5, 14,
14, 5, 6, 14, 6, 7,
15, 14, 7, 15, 7, 8,
10, 15, 8, 10, 8, 9,
11, 12, 15, 11, 15, 10,
12, 13, 14, 12, 14, 15
};
RecalculateMesh();
gameObject.GetComponent<MeshFilter>().mesh = mesh;
}
public void UpdateMesh() {
if (mesh != null) {
FillGeometry();
FillMesh();
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}
private void FillGeometry() {
{
float w = width;
float h = height;
float l = uvLeft * uvToWorldScaleX;
float r = width - uvRight * uvToWorldScaleX;
float t = height - uvTop * uvToWorldScaleY;
float b = uvBottom * uvToWorldScaleY;
vertices[0] = new Vector3(0, 0, 0);
vertices[1] = new Vector3(0, b, 0);
vertices[2] = new Vector3(0, t, 0);
vertices[3] = new Vector3(0, h, 0);
vertices[4] = new Vector3(l, h, 0);
vertices[5] = new Vector3(r, h, 0);
vertices[6] = new Vector3(w, h, 0);
vertices[7] = new Vector3(w, t, 0);
vertices[8] = new Vector3(w, b, 0);
vertices[9] = new Vector3(w, 0, 0);
vertices[10] = new Vector3(r, 0, 0);
vertices[11] = new Vector3(l, 0, 0);
vertices[12] = new Vector3(l, b, 0);
vertices[13] = new Vector3(l, t, 0);
vertices[14] = new Vector3(r, t, 0);
vertices[15] = new Vector3(r, b, 0);
}
{
const float w = 1;
const float h = 1;
float l = uvLeft;
float r = 1 - uvRight;
float t = 1 - uvTop;
float b = uvBottom;
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, b);
uv[2] = new Vector2(0, t);
uv[3] = new Vector2(0, h);
uv[4] = new Vector2(l, h);
uv[5] = new Vector2(r, h);
uv[6] = new Vector2(w, h);
uv[7] = new Vector2(w, t);
uv[8] = new Vector2(w, b);
uv[9] = new Vector2(w, 0);
uv[10] = new Vector2(r, 0);
uv[11] = new Vector2(l, 0);
uv[12] = new Vector2(l, b);
uv[13] = new Vector2(l, t);
uv[14] = new Vector2(r, t);
uv[15] = new Vector2(r, b);
}
}
private void FillMesh() {
mesh.vertices = vertices;
mesh.uv = uv;
}
private void RecalculateMesh() {
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
#if UNITY_EDITOR
private void OnValidate() {
if (mesh != null) {
UpdateMesh();
}
}
#endif
}
}
I want to show a triangle strip when user swap finger on screen. I am not sure how to do it with AndEngine, using particle system or using sprites or using Triangle Strip algo...
I haven't wrote any code because I am struck that what to do. I am uploading an image please share your ideas.
Update
someone has done this in Iphone but unfortunately I am unfamiliar with language syntax please help me in understanding algo of this code https://github.com/hiepnd/CCBlade
**Effect I want **
Complete Android Project Download
http://www.andengine.org/forums/resources/complete-runnable-project/1301
I have done this code but could not get the desired effect...
package org.az.algo.examples;
import javax.microedition.khronos.opengles.GL10;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.particle.ParticleSystem;
import org.anddev.andengine.entity.particle.emitter.RectangleParticleEmitter;
import org.anddev.andengine.entity.particle.initializer.AlphaInitializer;
import org.anddev.andengine.entity.particle.initializer.ColorInitializer;
import org.anddev.andengine.entity.particle.initializer.GravityInitializer;
import org.anddev.andengine.entity.particle.initializer.RotationInitializer;
import org.anddev.andengine.entity.particle.modifier.AlphaModifier;
import org.anddev.andengine.entity.particle.modifier.ColorModifier;
import org.anddev.andengine.entity.particle.modifier.ExpireModifier;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.Toast;
public class ParticleSystemSimpleExample extends BaseExample {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
// ===========================================================
// Fields
// ===========================================================
private Camera mCamera;
private BitmapTextureAtlas mBitmapTextureAtlas;
private TextureRegion mParticleTextureRegion;
private BitmapTextureAtlas mBitmapTextureAtlasStreak;
private TextureRegion mStreadTextureRegion;
private Sprite[] mSprite = new Sprite[20];
private int mIndex = 0;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public Engine onLoadEngine() {
Toast.makeText(this, "Touch the screen to move the particlesystem.", Toast.LENGTH_LONG).show();
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
}
#Override
public void onLoadResources() {
this.mBitmapTextureAtlas = new BitmapTextureAtlas(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mParticleTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "gfx/particle_point.png", 0, 0);
this.mBitmapTextureAtlasStreak = new BitmapTextureAtlas(128, 16, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mStreadTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlasStreak, this, "gfx/streak1.png", 0, 0);
this.mEngine.getTextureManager().loadTextures(this.mBitmapTextureAtlas, this.mBitmapTextureAtlasStreak);
}
#Override
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
// final CircleOutlineParticleEmitter particleEmitter = new CircleOutlineParticleEmitter(CAMERA_WIDTH * 0.5f, CAMERA_HEIGHT * 0.5f + 20, 80);
final RectangleParticleEmitter particleEmitter = new RectangleParticleEmitter(CAMERA_WIDTH * 0.5f, CAMERA_HEIGHT * 0.5f, 5f,5f);
// final PointParticleEmitter particleEmitter = new PointParticleEmitter(10, 10);
final ParticleSystem particleSystem = new ParticleSystem(particleEmitter, 100, 100, 1000, this.mParticleTextureRegion);
particleSystem.setParticlesSpawnEnabled(false);
scene.setOnSceneTouchListener(new IOnSceneTouchListener() {
#Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_MOVE){
particleSystem.setParticlesSpawnEnabled(true);
particleEmitter.setCenter(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
mSprite[getIndex()].setPosition(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
mSprite[getIndex()].setVisible(true);
}else if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP){
particleSystem.setParticlesSpawnEnabled(false);
hideAll();
}else if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
particleSystem.reset();
}
return true;
}
});
particleSystem.addParticleInitializer(new ColorInitializer(1, 0, 0));
particleSystem.addParticleInitializer(new AlphaInitializer(0));
particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
// particleSystem.addParticleInitializer(new VelocityInitializer(-2, 2, -20, -10));
particleSystem.addParticleInitializer(new GravityInitializer());
// particleSystem.addParticleModifier(new ScaleModifier(0.5f, 1.0f, 0, 1.5f));
particleSystem.addParticleModifier(new ColorModifier(1, 1, 0, 0.5f, 0, 0, 0, 3));
particleSystem.addParticleModifier(new ColorModifier(1, 1, 0.5f, 1, 0, 1, 4, 6));
particleSystem.addParticleModifier(new AlphaModifier(0, 1, 0, 0.5f));
particleSystem.addParticleModifier(new AlphaModifier(1, 0, 2.5f, 3.5f));
particleSystem.addParticleModifier(new ExpireModifier(6, 6f));
scene.attachChild(particleSystem);
for(int i = 0; i < mSprite.length; i++){
mSprite[i] = new Sprite(-20, 0, mStreadTextureRegion);
mSprite[i].setVisible(false);
scene.attachChild(mSprite[i]);
}
return scene;
}
#Override
public void onLoadComplete() {
}
private int getIndex(){
if(mIndex >= mSprite.length -1){
mIndex = 0;
}
System.out.println("Index ........ "+mIndex);
return mIndex++;
}
private void hideAll(){
for(int i = 0; i<mSprite.length; i++){
mSprite[i].setVisible(false);
mSprite[i].setPosition(-CAMERA_WIDTH, 0);
}
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
image I used with this code is also attached
Updated
partial effect achieved.. but problem on fast swiping.. all complete projects are uploaded here http://www.andengine.org/forums/post31772.html#p31772
Here is a solution in LibGDX. It uses GL_TRIANGLE_STRIP.
https://github.com/mattdesl/lwjgl-basics/wiki/LibGDX-Finger-Swipe
The final solution uses two triangle strips and a custom texCoord attribute, allowing for us to use a lookup texture to achieve fake (but efficient) anti-aliasing. A more efficient/flexible anti-aliasing would use shaders and a single triangle strip. Use vertex attribute -1.0 for the top and 1.0 for the bottom edge of your swipe, and 1.0 for the tips. Then in the frag shader, use abs() -- so 0.0 means "center" and 1.0 means "edge."
Something like this:
color.a *= smoothstep(0.0, 2./thickness, 1.0-abs(vTexCoord.t));