diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/PersonaltyBean.java b/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/PersonaltyBean.java new file mode 100644 index 00000000..8cdc1528 --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/PersonaltyBean.java @@ -0,0 +1,13 @@ +package com.qxcm.moduleutil.bean; + +import lombok.Data; +/** + *@author qx + *@data 2025/6/7 + *@description: 装扮类型表 + */ +@Data +public class PersonaltyBean { + private String id; + private String name; +} diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/SvgaModel.java b/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/SvgaModel.java new file mode 100644 index 00000000..68a84119 --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/bean/SvgaModel.java @@ -0,0 +1,39 @@ +package com.qxcm.moduleutil.bean; + +/** + *@author qx + *@data 2025/6/7 + *@description: + */ +public class SvgaModel { + public static final int TYPE_GIFT = 0; + public static final int TYPE_JUE = 1; + public static final int TYPE_JUE_AND_APPROACH = 2; + public static final int TYPE_APPROACH = 3; + public String url; + public int type; + public String approachUrl; + public String userName; + public String nobilityName; + + public SvgaModel() { + } + + public SvgaModel(String url) { + this.type=TYPE_GIFT; + this.url = url; + } + + public SvgaModel(String url, int type) { + this.url = url; + this.type = type; + } + + public SvgaModel(String url, int type, String approachUrl, String userName, String nobilityName) { + this.url = url; + this.type = type; + this.approachUrl = approachUrl; + this.userName = userName; + this.nobilityName=nobilityName; + } +} diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/AvatarFrameView.java b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/AvatarFrameView.java new file mode 100644 index 00000000..7728796c --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/AvatarFrameView.java @@ -0,0 +1,296 @@ +package com.qxcm.moduleutil.widget; + +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.net.Uri; +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Surface; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; + +import com.blankj.utilcode.util.PathUtils; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.ui.PlayerView; +import com.liulishuo.okdownload.DownloadTask; +import com.liulishuo.okdownload.StatusUtil; +import com.liulishuo.okdownload.core.cause.EndCause; +import com.liulishuo.okdownload.core.cause.ResumeFailedCause; +import com.liulishuo.okdownload.core.listener.DownloadListener1; +import com.liulishuo.okdownload.core.listener.assist.Listener1Assist; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGADynamicEntity; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.qxcm.moduleutil.R; +import com.qxcm.moduleutil.databinding.RoomViewSvgaAnimBinding; +import com.qxcm.moduleutil.utils.Md5Utils; +import com.qxcm.moduleutil.utils.logger.Logger; +import com.tencent.bugly.idasc.crashreport.CrashReport; +import com.tencent.qgame.animplayer.AnimConfig; +import com.tencent.qgame.animplayer.inter.IAnimListener; + +import java.io.File; +import java.net.URL; + + +public class AvatarFrameView extends FrameLayout implements IAnimListener { + + @Override + public void onFailed(int i, @Nullable String s) { + + } + + @Override + public boolean onVideoConfigReady(@NonNull AnimConfig animConfig) { + return true; + } + + @Override + public void onVideoStart() { + + } + + @Override + public void onVideoRender(int i, @Nullable AnimConfig animConfig) { + + } + + @Override + public void onVideoComplete() { + if (mType == 1) { + mBinding.playView.startPlay(mFile); + } + + } + + @Override + public void onVideoDestroy() { + + } + + public enum RenderType {SVGA, MP4} + + private RenderType renderType; + private ExoPlayer exoPlayer; + private PlayerView playerView; + private SVGAImageView svgaSurface; + private GLSurfaceView glSurfaceView; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); + private ChannelSplitRenderer1 renderer; + private int mType;//1:循环播放 2:播放一次停止播放 + private File mFile; + + private RoomViewSvgaAnimBinding mBinding; + + public AvatarFrameView(@NonNull Context context) { + this(context, null); + } + + public AvatarFrameView(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public AvatarFrameView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mBinding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.room_view_svga_anim, this, true); + initViews(); + } + + private void initViews() { + // 初始化 ExoPlayer View + playerView = new PlayerView(getContext()); + playerView.setUseController(false); + playerView.setVisibility(View.GONE); + addView(playerView); + + // 初始化 SVGA View + svgaSurface = new SVGAImageView(getContext()); + svgaSurface.setVisibility(View.GONE); + addView(svgaSurface); + +// // 初始化 GLSurfaceView +// glSurfaceView = new GLSurfaceView(getContext()); +// glSurfaceView.setEGLContextClientVersion(2); +// renderer = new ChannelSplitRenderer1(); +// glSurfaceView.setRenderer(renderer); +// glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); +// glSurfaceView.setVisibility(View.GONE); // 默认隐藏 +// addView(glSurfaceView); + + // 初始化 ExoPlayer + exoPlayer = new ExoPlayer.Builder(getContext()).build(); + playerView.setPlayer(exoPlayer); + + mBinding.playView.setAnimListener(this); + } + + public void setSource(String url, RenderType type, int type2) { + clearPrevious(); + renderType = type; + mType = type2; + switch (type) { + case SVGA: + mBinding.playView.stopPlay(); + mBinding.playView.setVisibility(View.GONE); + loadSVGA(url); + break; + case MP4: +// loadMP4(url); + mBinding.playView.setVisibility(View.VISIBLE); + downloadAndPlayMp4(url); + break; + } + } + + private void downloadAndPlayMp4(String url) { + DownloadTask task = new DownloadTask.Builder(url, PathUtils.getInternalAppCachePath() + , Md5Utils.getStringMD5(url) + ".mp4") + // the minimal interval millisecond for callback progress + .setMinIntervalMillisCallbackProcess(100) + // do re-download even if the task has already been completed in the past. + .setPassIfAlreadyCompleted(false) + .setAutoCallbackToUIThread(true) + .build(); + if (StatusUtil.isCompleted(task)) { + playMp4(task.getFile()); + mFile = task.getFile(); + } else { + task.enqueue(new DownloadListener1() { + @Override + public void taskStart(@NonNull DownloadTask task, @NonNull Listener1Assist.Listener1Model model) { + Logger.e("taskStart", model); + } + + @Override + public void retry(@NonNull DownloadTask task, @NonNull ResumeFailedCause cause) { + Logger.e("retry", cause); + CrashReport.postCatchedException(new RuntimeException("下载文件重试:" + cause == null ? "" : cause.name())); + } + + @Override + public void connected(@NonNull DownloadTask task, int blockCount, long currentOffset, long totalLength) { + Logger.e("connected", blockCount); + } + + @Override + public void progress(@NonNull DownloadTask task, long currentOffset, long totalLength) { + Logger.e("progress", currentOffset); + } + + @Override + public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause, @NonNull Listener1Assist.Listener1Model model) { + Logger.e("taskEnd", model); + playMp4(task.getFile()); + mFile = task.getFile(); + if (cause != null && cause != EndCause.COMPLETED) { +// CrashReport.postCatchedException(new RuntimeException("下载任务结束:" + cause == null ? "" : cause.name() + "_realCause:" + realCause == null ? "" : realCause.getMessage())); + } + } + }); + } + } + + private void playMp4(File file) { + if (file != null) { + mBinding.playView.startPlay(file); + + } else { +// showAnim(); +// playMp4(file); + CrashReport.postCatchedException(new RuntimeException("播放MP4失败:File is null")); + } + } + + private void loadSVGA(String url) { + svgaSurface.setVisibility(View.VISIBLE); + try { + new SVGAParser(getContext()).parse(new URL(url), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity videoItem) { + SVGADrawable drawable = new SVGADrawable(videoItem, new SVGADynamicEntity()); + svgaSurface.setImageDrawable(drawable); + svgaSurface.startAnimation(); + } + + @Override + public void onError() { + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void loadMP4(String url) { + svgaSurface.setVisibility(View.GONE); + playerView.setVisibility(View.GONE); + + glSurfaceView.setVisibility(View.VISIBLE); + glSurfaceView.onResume(); + glSurfaceView.requestRender(); + // 使用 post 确保 GLSurfaceView 已完成 layout + glSurfaceView.post(() -> { + Log.d("@@@", "GLSurfaceView size after layout: " + glSurfaceView.getWidth() + "x" + glSurfaceView.getHeight()); + + glSurfaceView.onResume(); + glSurfaceView.requestRender(); + + renderer.setOnSurfaceTextureReadyListener(surfaceTexture -> { + mainHandler.post(() -> { + Surface surface = new Surface(surfaceTexture); + + MediaItem mediaItem = MediaItem.fromUri(Uri.parse(url)); + exoPlayer.setMediaItem(mediaItem); + exoPlayer.setVideoSurface(surface); + exoPlayer.prepare(); + exoPlayer.play(); + Log.d("@@@", "ExoPlayer state after play: " + exoPlayer.getPlaybackState()); + }); + }); + }); + } + + private void clearPrevious() { + if (exoPlayer != null) { + exoPlayer.stop(); + exoPlayer.clearVideoSurface(); + } + + if (svgaSurface.getDrawable() instanceof SVGADrawable) { + ((SVGADrawable) svgaSurface.getDrawable()).stop(); + } + + if (playerView != null) playerView.setVisibility(View.GONE); + if (svgaSurface != null) svgaSurface.setVisibility(View.GONE); +// if (glSurfaceView != null) glSurfaceView.setVisibility(View.GONE); + mBinding.playView.setVisibility(View.GONE); + } + + public void release() { + if (exoPlayer != null) { + exoPlayer.release(); + } + + if (svgaSurface.getDrawable() instanceof SVGADrawable) { + ((SVGADrawable) svgaSurface.getDrawable()).stop(); + } + + if (glSurfaceView != null) { + glSurfaceView.onPause(); // 必须调用生命周期方法 +// glSurfaceView.requestRender(); + } + } +} diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer.kt b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer.kt new file mode 100644 index 00000000..93596cc1 --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer.kt @@ -0,0 +1,122 @@ +package com.qxcm.moduleutil.widget + + +import android.graphics.SurfaceTexture +import android.opengl.GLES20 +import android.opengl.Matrix + +class ChannelSplitRenderer { + + private val vertexShaderCode = """ + attribute vec4 aPosition; + attribute vec2 aTexCoord; + varying vec2 vTexCoord; + void main() { + gl_Position = aPosition; + vTexCoord = aTexCoord; + } + """ + + private val fragmentShaderCode = """ + precision mediump float; + uniform sampler2D uTexture; + varying vec2 vTexCoord; + void main() { + // 只使用左半部分作为最终颜色 + vec2 leftCoord = vec2(vTexCoord.x * 0.5, vTexCoord.y); + vec4 color = texture2D(uTexture, leftCoord); + + // 设置 alpha 为 1.0 表示完全不透明,或根据需求设为 0.0 表示全透明 + gl_FragColor = vec4(color.rgb, 0.0); // 左通道颜色 + 不透明 + }""" + + private var program = 0 + private var positionHandle = 0 + private var texCoordHandle = 0 + private var textureHandle = 0 + private val projectionMatrix = FloatArray(16) + private val modelMatrix = FloatArray(16) + + fun onSurfaceCreated(surface: SurfaceTexture, width: Int, height: Int) { + // 初始化着色器 + val vertexShader = ShaderUtils.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode) + val fragmentShader = ShaderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode) + + program = GLES20.glCreateProgram().also { + GLES20.glAttachShader(it, vertexShader) + GLES20.glAttachShader(it, fragmentShader) + GLES20.glLinkProgram(it) + } + + positionHandle = GLES20.glGetAttribLocation(program, "aPosition") + texCoordHandle = GLES20.glGetAttribLocation(program, "aTexCoord") + textureHandle = GLES20.glGetUniformLocation(program, "uTexture") + + // 初始化矩阵 + Matrix.setIdentityM(projectionMatrix, 0) + Matrix.setIdentityM(modelMatrix, 0) + + GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f) + GLES20.glEnable(GLES20.GL_BLEND) + GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA) + } + + fun onSurfaceChanged(width: Int, height: Int) { + GLES20.glViewport(0, 0, width, height) + } + + fun onDrawFrame(textureId: Int) { + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) + GLES20.glUseProgram(program) + + // 定义顶点坐标(全屏) + val vertices = floatArrayOf( + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f + ) + + // 修改纹理坐标,只映射左半部分视频内容到左侧屏幕 + val texCoords = floatArrayOf( + 0.0f, 1.0f, // 左下角 + 0.5f, 1.0f, // 右下角(对应视频中间) + 0.0f, 0.0f, // 左上角 + 0.5f, 0.0f // 右上角 + ) + + val vertexBuffer = ShaderUtils.createFloatBuffer(vertices) + val texBuffer = ShaderUtils.createFloatBuffer(texCoords) + + GLES20.glEnableVertexAttribArray(positionHandle) + GLES20.glVertexAttribPointer( + positionHandle, 3, + GLES20.GL_FLOAT, false, + 0, vertexBuffer + ) + + GLES20.glEnableVertexAttribArray(texCoordHandle) + GLES20.glVertexAttribPointer( + texCoordHandle, 2, + GLES20.GL_FLOAT, false, + 0, texBuffer + ) + + // 绑定纹理 + GLES20.glActiveTexture(GLES20.GL_TEXTURE0) + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId) + GLES20.glUniform1i(textureHandle, 0) + + // 绘制 + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4) + + // 清理 + GLES20.glDisableVertexAttribArray(positionHandle) + GLES20.glDisableVertexAttribArray(texCoordHandle) + } + + + fun release() { + GLES20.glDeleteProgram(program) + } +} \ No newline at end of file diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer1.java b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer1.java new file mode 100644 index 00000000..8d8b3c0d --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ChannelSplitRenderer1.java @@ -0,0 +1,200 @@ +package com.qxcm.moduleutil.widget; + +import android.graphics.SurfaceTexture; +import android.opengl.EGL14; +import android.opengl.EGLConfig; +import android.opengl.EGLContext; +import android.opengl.EGLDisplay; +import android.opengl.EGLSurface; +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.opengl.Matrix; +import android.os.Handler; +import android.os.HandlerThread; +import android.util.Log; +import android.view.Surface; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.opengles.GL10; + + +public class ChannelSplitRenderer1 implements GLSurfaceView.Renderer { + + private static final String VERTEX_SHADER = + "uniform mat4 uMVPMatrix;\n" + + "uniform mat4 uSTMatrix;\n" + + "attribute vec4 aPosition;\n" + + "attribute vec4 aTextureCoord;\n" + + "varying vec2 vTextureCoord;\n" + + "void main() {\n" + + " gl_Position = uMVPMatrix * aPosition;\n" + + " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + + "}\n"; + + private static final String FRAGMENT_SHADER = + "#extension GL_OES_EGL_image_external : require\n" + + "precision mediump float;\n" + + "varying vec2 vTextureCoord;\n" + + "uniform samplerExternalOES sTexture;\n" + + "void main() {\n" + + " vec2 uv = vTextureCoord;\n" + + " // 左边部分的 UV 坐标范围 (0.0, 0.1) 到 (0.6, 0.9)\n" + + " if (uv.x >= 0.0 && uv.x <= 0.6 && uv.y >= 0.1 && uv.y <= 0.9) {\n" + + " // 居中显示\n" + + " vec2 newUV = vec2(uv.x * (1.0 / 0.6), uv.y); // 水平方向拉伸\n" + + " gl_FragColor = texture2D(sTexture, newUV);\n" + + " } else {\n" + + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); // 设置为完全透明\n" + + " }\n" + + "}\n"; + + + private int mProgram; + private int maPositionHandle; + private int maTextureHandle; + private int muMVPMatrixHandle; + private int muSTMatrixHandle; + + private float[] mMVPMatrix = new float[16]; + private float[] mSTMatrix = new float[16]; + + private SurfaceTexture surfaceTexture; + private int externalTextureId = -1; + + private final float[] mTriangleVerticesData = { + // X, Y, Z, U, V + -1.0f, -1.0f, 0, 0.f, 0.f, + 1.0f, -1.0f, 0, 1.f, 0.f, + -1.0f, 1.0f, 0, 0.f, 1.f, + 1.0f, 1.0f, 0, 1.f, 1.f, + }; + + private FloatBuffer mTriangleVertices; + + public ChannelSplitRenderer1() { + mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4) + .order(ByteOrder.nativeOrder()).asFloatBuffer(); + mTriangleVertices.put(mTriangleVerticesData).position(0); + Matrix.setIdentityM(mSTMatrix, 0); + } + + public interface OnSurfaceTextureReadyListener { + void onSurfaceTextureReady(SurfaceTexture surfaceTexture); + } + private OnSurfaceTextureReadyListener surfaceTextureReadyListener; + + public void setOnSurfaceTextureReadyListener(OnSurfaceTextureReadyListener listener) { + this.surfaceTextureReadyListener = listener; + } + + @Override + public void onSurfaceCreated(GL10 gl, javax.microedition.khronos.egl.EGLConfig config) { + Log.d("@@@@", "onDrawFrame called"); + GLES20.glDisable(GLES20.GL_DEPTH_TEST); + GLES20.glDisable(GLES20.GL_STENCIL_TEST); + GLES20.glDisable(GLES20.GL_BLEND); + GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 设置透明背景 + + int[] textures = new int[1]; + GLES20.glGenTextures(1, textures, 0); + externalTextureId = textures[0]; + + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, externalTextureId); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); + + surfaceTexture = new SurfaceTexture(externalTextureId); + + mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER); + maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); + maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); + muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); + muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix"); + + if (surfaceTextureReadyListener != null) { + surfaceTextureReadyListener.onSurfaceTextureReady(surfaceTexture); + } + } + + @Override + public void onSurfaceChanged(GL10 gl, int width, int height) { + GLES20.glViewport(0, 0, width, height); + } + + private long lastTimestamp = -1; + @Override + public void onDrawFrame(GL10 gl) { + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + if (surfaceTexture != null) { + surfaceTexture.updateTexImage(); + long timestamp = surfaceTexture.getTimestamp(); + + if (timestamp != lastTimestamp) { + Log.d("@@@", "New frame received, timestamp: " + timestamp); + lastTimestamp = timestamp; + } + + surfaceTexture.getTransformMatrix(mSTMatrix); + } else { + Log.e("@@@", "SurfaceTexture is null in onDrawFrame"); + } + + GLES20.glUseProgram(mProgram); + + Matrix.setIdentityM(mMVPMatrix, 0); + + GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); + GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); + + mTriangleVertices.position(0); + GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 20, mTriangleVertices); + GLES20.glEnableVertexAttribArray(maPositionHandle); + + mTriangleVertices.position(3); + GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 20, mTriangleVertices); + GLES20.glEnableVertexAttribArray(maTextureHandle); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, externalTextureId); + + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + } + + public SurfaceTexture getSurfaceTexture() { + return surfaceTexture; + } + + private int loadShader(int shaderType, String source) { + int shader = GLES20.glCreateShader(shaderType); + GLES20.glShaderSource(shader, source); + GLES20.glCompileShader(shader); + int[] compiled = new int[1]; + GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + return 0; + } + return shader; + } + + private int createProgram(String vertexSource, String fragmentSource) { + int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); + int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); + int program = GLES20.glCreateProgram(); + GLES20.glAttachShader(program, vertexShader); + GLES20.glAttachShader(program, pixelShader); + GLES20.glLinkProgram(program); + int[] linkStatus = new int[1]; + GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); + if (linkStatus[0] != GLES20.GL_TRUE) { + return 0; + } + return program; + } +} diff --git a/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ShaderUtils.java b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ShaderUtils.java new file mode 100644 index 00000000..3e457128 --- /dev/null +++ b/moduleUtil/src/main/java/com/qxcm/moduleutil/widget/ShaderUtils.java @@ -0,0 +1,40 @@ +package com.qxcm.moduleutil.widget; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import android.opengl.GLES20; +import android.util.Log; + +public class ShaderUtils { + + private static final String TAG = "ShaderUtils"; + + // 创建并编译着色器 + public static int loadShader(int type, String shaderCode) { + int shader = GLES20.glCreateShader(type); + GLES20.glShaderSource(shader, shaderCode); + GLES20.glCompileShader(shader); + + int[] compiled = new int[1]; + GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + Log.e(TAG, "Could NOT compile shader: " + GLES20.glGetShaderInfoLog(shader)); + GLES20.glDeleteShader(shader); + return 0; + } + + return shader; + } + + // 创建 FloatBuffer + public static FloatBuffer createFloatBuffer(float[] array) { + ByteBuffer bb = ByteBuffer.allocateDirect(array.length * 4); + bb.order(ByteOrder.nativeOrder()); + FloatBuffer buffer = bb.asFloatBuffer(); + buffer.put(array); + buffer.position(0); + return buffer; + } +} diff --git a/moduleUtil/src/main/res/layout/room_view_svga_anim.xml b/moduleUtil/src/main/res/layout/room_view_svga_anim.xml new file mode 100644 index 00000000..d8366cd3 --- /dev/null +++ b/moduleUtil/src/main/res/layout/room_view_svga_anim.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/moduleUtil/src/main/res/layout/room_view_svga_animation.xml b/moduleUtil/src/main/res/layout/room_view_svga_animation.xml new file mode 100644 index 00000000..321a272b --- /dev/null +++ b/moduleUtil/src/main/res/layout/room_view_svga_animation.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/modulevocal/src/main/java/com/example/modulevocal/conacts/PersonalityConacts.java b/modulevocal/src/main/java/com/example/modulevocal/conacts/PersonalityConacts.java new file mode 100644 index 00000000..c8a23e9d --- /dev/null +++ b/modulevocal/src/main/java/com/example/modulevocal/conacts/PersonalityConacts.java @@ -0,0 +1,19 @@ +package com.example.modulevocal.conacts; + +import android.app.Activity; + +import com.qxcm.moduleutil.activity.IPresenter; +import com.qxcm.moduleutil.activity.IView; +import com.qxcm.moduleutil.bean.PersonaltyBean; + +import java.util.List; + +public class PersonalityConacts { + public interface View extends IView { + void getPersonaltyList(List personaltyBean); + + } + public interface IMePre extends IPresenter { + void getPersonaltyList(); + } +} diff --git a/modulevocal/src/main/java/com/example/modulevocal/presenter/PersonalityPresenter.java b/modulevocal/src/main/java/com/example/modulevocal/presenter/PersonalityPresenter.java new file mode 100644 index 00000000..79a54ea2 --- /dev/null +++ b/modulevocal/src/main/java/com/example/modulevocal/presenter/PersonalityPresenter.java @@ -0,0 +1,33 @@ +package com.example.modulevocal.presenter; + +import android.content.Context; + +import com.example.modulevocal.conacts.PersonalityConacts; +import com.qxcm.moduleutil.bean.PersonaltyBean; +import com.qxcm.moduleutil.http.BaseObserver; +import com.qxcm.moduleutil.presenter.BasePresenter; + +import java.util.List; + +import io.reactivex.disposables.Disposable; + +public class PersonalityPresenter extends BasePresenter implements PersonalityConacts.IMePre{ + public PersonalityPresenter(PersonalityConacts.View view, Context context) { + super(view, context); + } + + @Override + public void getPersonaltyList() { + api.getPersonaltyList(new BaseObserver>() { + @Override + public void onSubscribe(Disposable d) { + addDisposable(d); + } + + @Override + public void onNext(List personaltyBeans) { + MvpRef.get().getPersonaltyList(personaltyBeans); + } + }); + } +}