cleanup render path
This commit is contained in:
parent
26b42a6747
commit
45bc8a8bb4
8
Makefile
8
Makefile
|
@ -77,7 +77,7 @@ endif
|
||||||
|
|
||||||
CXXFLAGS += -std=c++14
|
CXXFLAGS += -std=c++14
|
||||||
|
|
||||||
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DDATE=\"$(DATE)\" -DINFO=\"$(INFO)\" -Wno-narrowing -Wno-int-conversion #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t
|
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DPROSPERON_VER=\"$(SEM)\" -DPROSPERON_COM=\"$(COM)\" -DPROSPERON_DATE=\"$(DATE)\" -DPROSPERON_INFO=\"$(INFO)\" -Wno-narrowing -Wno-int-conversion #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t
|
||||||
CPPFLAGS += -DCONFIG_VERSION=\"2024-02-14\" -DCONFIG_BIGNUM #for quickjs
|
CPPFLAGS += -DCONFIG_VERSION=\"2024-02-14\" -DCONFIG_BIGNUM #for quickjs
|
||||||
|
|
||||||
# ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER
|
# ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER
|
||||||
|
@ -139,7 +139,7 @@ endif
|
||||||
|
|
||||||
# All other sources
|
# All other sources
|
||||||
OBJS != find source -type f -name '*.c' | grep -vE 'test|tool|example|fuzz|main' | grep -vE 'quickjs'
|
OBJS != find source -type f -name '*.c' | grep -vE 'test|tool|example|fuzz|main' | grep -vE 'quickjs'
|
||||||
CPPOBJS != find source -type f -name '*.cpp' | grep -vE 'test|tool|example|fuzz|main|ImCurveEdit|GraphEditor|neo_sequencer|imgui_neo_sequencer'
|
CPPOBJS != find source -type f -name '*.cpp' | grep -vE 'test|tool|example|fuzz|main|GraphEditor|ImCurveEdit'
|
||||||
OBJS += $(CPPOBJS)
|
OBJS += $(CPPOBJS)
|
||||||
OBJS += source/engine/yugine.c
|
OBJS += source/engine/yugine.c
|
||||||
OBJS += $(shell find source/engine -type f -name '*.m')
|
OBJS += $(shell find source/engine -type f -name '*.m')
|
||||||
|
@ -240,8 +240,8 @@ ICNSIZE = 16 32 128 256 512 1024
|
||||||
ICNNAME := $(addsuffix .png, $(ICNSIZE))
|
ICNNAME := $(addsuffix .png, $(ICNSIZE))
|
||||||
ICON = icons/moon.gif
|
ICON = icons/moon.gif
|
||||||
icon.ico: $(ICON)
|
icon.ico: $(ICON)
|
||||||
for i in $(ICNSIZE); do convert $^ -thumbnail $${i}x$${i} $${i}.png; done
|
for i in $(ICNSIZE); do magick $^ -thumbnail $${i}x$${i} $${i}.png; done
|
||||||
convert $(ICNNAME) icon.ico
|
magick $(ICNNAME) icon.ico
|
||||||
rm $(ICNNAME)
|
rm $(ICNNAME)
|
||||||
|
|
||||||
resource.o: resource.rc resource.manifest icon.ico
|
resource.o: resource.rc resource.manifest icon.ico
|
||||||
|
|
|
@ -101,7 +101,27 @@ game.engine_start = function (s) {
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
1, 1, 0], 0),
|
1, 1, 0], 0),
|
||||||
verts: 4,
|
verts: 4,
|
||||||
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
|
uv: os.make_buffer([
|
||||||
|
0, 0,
|
||||||
|
0, 1,
|
||||||
|
1, 0,
|
||||||
|
1, 1], 2),
|
||||||
|
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
||||||
|
count: 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
shape.flipquad = {
|
||||||
|
pos: os.make_buffer([
|
||||||
|
0, 0, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
1, 1, 0], 0),
|
||||||
|
verts: 4,
|
||||||
|
uv: os.make_buffer([
|
||||||
|
0, 1,
|
||||||
|
0, 0,
|
||||||
|
1, 1,
|
||||||
|
1, 0], 2),
|
||||||
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
||||||
count: 6,
|
count: 6,
|
||||||
};
|
};
|
||||||
|
@ -121,7 +141,11 @@ game.engine_start = function (s) {
|
||||||
0.5, -0.5, -0.5,
|
0.5, -0.5, -0.5,
|
||||||
0.5, 0.5, -0.5], 0),
|
0.5, 0.5, -0.5], 0),
|
||||||
verts: 4,
|
verts: 4,
|
||||||
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
|
uv: os.make_buffer([
|
||||||
|
0, 0,
|
||||||
|
0, 1,
|
||||||
|
1, 0,
|
||||||
|
1, 1], 2),
|
||||||
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
||||||
count: 6,
|
count: 6,
|
||||||
};
|
};
|
||||||
|
|
|
@ -111,11 +111,6 @@ var stencilop = {
|
||||||
decr_wrap: 8
|
decr_wrap: 8
|
||||||
};
|
};
|
||||||
|
|
||||||
var depth_map = {
|
|
||||||
off: false,
|
|
||||||
on: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var face_map = {
|
var face_map = {
|
||||||
ccw: 1,
|
ccw: 1,
|
||||||
cw: 2,
|
cw: 2,
|
||||||
|
@ -180,7 +175,6 @@ render.colormask = colormask;
|
||||||
render.primitive_map = primitive_map;
|
render.primitive_map = primitive_map;
|
||||||
render.cull_map = cull_map;
|
render.cull_map = cull_map;
|
||||||
render.stencilop = stencilop;
|
render.stencilop = stencilop;
|
||||||
render.depth_map = depth_map;
|
|
||||||
render.face_map = face_map;
|
render.face_map = face_map;
|
||||||
render.compare = compare;
|
render.compare = compare;
|
||||||
render.blendfactor = blendfactor;
|
render.blendfactor = blendfactor;
|
||||||
|
@ -421,7 +415,7 @@ function create_shader_obj(file) {
|
||||||
return compiled;
|
return compiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_shader(shader) {
|
function make_shader(shader, pipe) {
|
||||||
if (shader_cache[shader]) return shader_cache[shader];
|
if (shader_cache[shader]) return shader_cache[shader];
|
||||||
|
|
||||||
var file = shader;
|
var file = shader;
|
||||||
|
@ -444,7 +438,9 @@ function make_shader(shader) {
|
||||||
|
|
||||||
var shaderobj = json.decode(io.slurp(writejson));
|
var shaderobj = json.decode(io.slurp(writejson));
|
||||||
var obj = shaderobj[os.sys()];
|
var obj = shaderobj[os.sys()];
|
||||||
obj.pipe = render.pipeline(obj, base_pipeline);
|
|
||||||
|
pipe ??= base_pipeline;
|
||||||
|
obj.pipe = render.pipeline(obj, pipe);
|
||||||
shader_cache[file] = obj;
|
shader_cache[file] = obj;
|
||||||
shader_times[file] = io.mod(file);
|
shader_times[file] = io.mod(file);
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -611,7 +607,9 @@ render.init = function () {
|
||||||
textshader = make_shader("shaders/text_base.cg");
|
textshader = make_shader("shaders/text_base.cg");
|
||||||
render.spriteshader = make_shader("shaders/sprite.cg");
|
render.spriteshader = make_shader("shaders/sprite.cg");
|
||||||
spritessboshader = make_shader("shaders/sprite_ssbo.cg");
|
spritessboshader = make_shader("shaders/sprite_ssbo.cg");
|
||||||
render.postshader = make_shader("shaders/simplepost.cg");
|
var postpipe = Object.create(base_pipeline);
|
||||||
|
postpipe.cull = cull_map.none;
|
||||||
|
render.postshader = make_shader("shaders/simplepost.cg", postpipe);
|
||||||
slice9shader = make_shader("shaders/9slice.cg");
|
slice9shader = make_shader("shaders/9slice.cg");
|
||||||
circleshader = make_shader("shaders/circle.cg");
|
circleshader = make_shader("shaders/circle.cg");
|
||||||
polyshader = make_shader("shaders/poly.cg");
|
polyshader = make_shader("shaders/poly.cg");
|
||||||
|
@ -1089,7 +1087,7 @@ prosperon.gizmos = function () {
|
||||||
|
|
||||||
prosperon.make_camera = function () {
|
prosperon.make_camera = function () {
|
||||||
var cam = world.spawn();
|
var cam = world.spawn();
|
||||||
cam.near = 0.1;
|
cam.near = -1;
|
||||||
cam.far = 1000;
|
cam.far = 1000;
|
||||||
cam.ortho = true;
|
cam.ortho = true;
|
||||||
cam.viewport = [0, 0, 1, 1];
|
cam.viewport = [0, 0, 1, 1];
|
||||||
|
@ -1213,7 +1211,6 @@ prosperon.render = function () {
|
||||||
profile.endreport("sprites");
|
profile.endreport("sprites");
|
||||||
profile.report("draws");
|
profile.report("draws");
|
||||||
prosperon.draw();
|
prosperon.draw();
|
||||||
// sgl.draw();
|
|
||||||
profile.endreport("draws");
|
profile.endreport("draws");
|
||||||
profile.endreport("world");
|
profile.endreport("world");
|
||||||
prosperon.hudcam.size = prosperon.camera.size;
|
prosperon.hudcam.size = prosperon.camera.size;
|
||||||
|
@ -1239,8 +1236,9 @@ prosperon.render = function () {
|
||||||
render.viewport(...prosperon.camera.view());
|
render.viewport(...prosperon.camera.view());
|
||||||
render.use_shader(render.postshader);
|
render.use_shader(render.postshader);
|
||||||
prosperon.postvals.diffuse = prosperon.screencolor;
|
prosperon.postvals.diffuse = prosperon.screencolor;
|
||||||
|
|
||||||
render.use_mat(prosperon.postvals);
|
render.use_mat(prosperon.postvals);
|
||||||
render.draw(shape.quad);
|
render.draw(os.backend() === "directx" ? shape.flipquad : shape.quad);
|
||||||
|
|
||||||
profile.endreport("post process");
|
profile.endreport("post process");
|
||||||
|
|
||||||
|
@ -1249,7 +1247,6 @@ prosperon.render = function () {
|
||||||
// Flush & render
|
// Flush & render
|
||||||
prosperon.appcam.transform.pos = [window.size.x / 2, window.size.y / 2, -100];
|
prosperon.appcam.transform.pos = [window.size.x / 2, window.size.y / 2, -100];
|
||||||
prosperon.appcam.size = window.size.slice();
|
prosperon.appcam.size = window.size.slice();
|
||||||
if (os.sys() !== "macos") prosperon.appcam.size.y *= -1;
|
|
||||||
|
|
||||||
render.set_camera(prosperon.appcam);
|
render.set_camera(prosperon.appcam);
|
||||||
render.viewport(...prosperon.appcam.view());
|
render.viewport(...prosperon.appcam.view());
|
||||||
|
|
|
@ -1224,6 +1224,18 @@ HMM_Mat4 HMM_InvOrthographic(HMM_Mat4 OrthoMatrix) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMM_Mat4 HMM_Orthographic_DX(float l, float r, float b, float t, float near, float far)
|
||||||
|
{
|
||||||
|
return HMM_Orthographic_LH_ZO(l,r,b,t,near,far);
|
||||||
|
}
|
||||||
|
|
||||||
|
HMM_Mat4 HMM_Orthographic_GL(float l, float r, float b, float t, float near, float far)
|
||||||
|
{
|
||||||
|
// return HMM_MulM4(HMM_Orthographic_LH_NO(l,r,b,t,near,far), HMM_Scale((HMM_Vec3){1,-1,1}));
|
||||||
|
return HMM_Orthographic_LH_NO(l,r,b,t,near,far);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HMM_Mat4 HMM_Orthographic_Metal(float l, float r, float b, float t, float near, float far)
|
HMM_Mat4 HMM_Orthographic_Metal(float l, float r, float b, float t, float near, float far)
|
||||||
{
|
{
|
||||||
HMM_Mat4 adjust = {0};
|
HMM_Mat4 adjust = {0};
|
||||||
|
|
|
@ -623,6 +623,10 @@ HMM_Mat4 HMM_Perspective_LH_ZO(float FOV, float AspectRatio, float Near, float F
|
||||||
|
|
||||||
HMM_Mat4 HMM_Perspective_Metal(float FOV, float AspectRation, float Near, float Far);
|
HMM_Mat4 HMM_Perspective_Metal(float FOV, float AspectRation, float Near, float Far);
|
||||||
HMM_Mat4 HMM_Orthographic_Metal(float l, float r, float b, float t, float near, float far);
|
HMM_Mat4 HMM_Orthographic_Metal(float l, float r, float b, float t, float near, float far);
|
||||||
|
|
||||||
|
HMM_Mat4 HMM_Orthographic_DX(float l, float r, float b, float t, float near, float far);
|
||||||
|
HMM_Mat4 HMM_Orthographic_GL(float l, float r, float b, float t, float near, float far);
|
||||||
|
|
||||||
HMM_Mat4 HMM_InvPerspective_RH(HMM_Mat4 PerspectiveMatrix);
|
HMM_Mat4 HMM_InvPerspective_RH(HMM_Mat4 PerspectiveMatrix);
|
||||||
HMM_Mat4 HMM_InvPerspective_LH(HMM_Mat4 PerspectiveMatrix);
|
HMM_Mat4 HMM_InvPerspective_LH(HMM_Mat4 PerspectiveMatrix);
|
||||||
HMM_Mat4 HMM_Translate(HMM_Vec3 Translation);
|
HMM_Mat4 HMM_Translate(HMM_Vec3 Translation);
|
||||||
|
|
|
@ -41,7 +41,10 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STB_PERLIN_IMPLEMENTATION
|
#define STB_PERLIN_IMPLEMENTATION
|
||||||
#include "stb_perlin.h"
|
#include "stb_perlin.h"
|
||||||
|
@ -795,16 +798,17 @@ HMM_Mat4 camera2projection(JSValue cam) {
|
||||||
HMM_Vec2 size = js2vec2(js_getpropstr(cam,"size"));
|
HMM_Vec2 size = js2vec2(js_getpropstr(cam,"size"));
|
||||||
|
|
||||||
if (ortho)
|
if (ortho)
|
||||||
|
#ifdef SOKOL_GLCORE
|
||||||
|
return HMM_Orthographic_GL(
|
||||||
|
#elifdef SOKOL_D3D11
|
||||||
|
return HMM_Orthographic_DX(
|
||||||
|
#else
|
||||||
return HMM_Orthographic_Metal(
|
return HMM_Orthographic_Metal(
|
||||||
|
#endif
|
||||||
-size.x/2,
|
-size.x/2,
|
||||||
size.x/2,
|
size.x/2,
|
||||||
#ifdef SOKOL_GLCORE //flipping orthographic Y if opengl
|
|
||||||
size.y/2,
|
|
||||||
-size.y/2,
|
|
||||||
#else
|
|
||||||
-size.y/2,
|
-size.y/2,
|
||||||
size.y/2,
|
size.y/2,
|
||||||
#endif
|
|
||||||
near,
|
near,
|
||||||
far
|
far
|
||||||
);
|
);
|
||||||
|
@ -1369,7 +1373,6 @@ static const JSCFunctionListEntry js_sgl_funcs[] = {
|
||||||
|
|
||||||
JSC_CCALL(gui_scissor,
|
JSC_CCALL(gui_scissor,
|
||||||
sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
|
sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
|
||||||
// sgl_scissor_rectf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
|
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(gui_text,
|
JSC_CCALL(gui_text,
|
||||||
|
@ -2880,6 +2883,18 @@ JSValue js_os_sys(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_backend,
|
||||||
|
#ifdef SOKOL_GLCORE
|
||||||
|
return str2js("opengl");
|
||||||
|
#elifdef SOKOL_WGPU
|
||||||
|
return str2js("wgpu");
|
||||||
|
#elifdef SOKOL_D3D11
|
||||||
|
return str2js("directx");
|
||||||
|
#elifdef SOKOL_METAL
|
||||||
|
return str2js("metal");
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_quit, quit();)
|
JSC_CCALL(os_quit, quit();)
|
||||||
JSC_CCALL(os_exit, exit(js2number(argv[0]));)
|
JSC_CCALL(os_exit, exit(js2number(argv[0]));)
|
||||||
JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
|
JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
|
||||||
|
@ -2960,9 +2975,11 @@ JSC_CCALL(os_mallinfo,
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_rusage,
|
JSC_CCALL(os_rusage,
|
||||||
|
ret = JS_NewObject(js);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
struct rusage jsmem;
|
struct rusage jsmem;
|
||||||
getrusage(RUSAGE_SELF, &jsmem);
|
getrusage(RUSAGE_SELF, &jsmem);
|
||||||
ret = JS_NewObject(js);
|
|
||||||
JSJMEMRET(ru_maxrss);
|
JSJMEMRET(ru_maxrss);
|
||||||
JSJMEMRET(ru_ixrss);
|
JSJMEMRET(ru_ixrss);
|
||||||
JSJMEMRET(ru_idrss);
|
JSJMEMRET(ru_idrss);
|
||||||
|
@ -2977,6 +2994,7 @@ JSC_CCALL(os_rusage,
|
||||||
JSJMEMRET(ru_nsignals);
|
JSJMEMRET(ru_nsignals);
|
||||||
JSJMEMRET(ru_nvcsw);
|
JSJMEMRET(ru_nvcsw);
|
||||||
JSJMEMRET(ru_nivcsw);
|
JSJMEMRET(ru_nivcsw);
|
||||||
|
#endif
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_mem,
|
JSC_CCALL(os_mem,
|
||||||
|
@ -3527,6 +3545,7 @@ JSC_CCALL(os_turbulence,
|
||||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, turbulence, 4),
|
MIST_FUNC_DEF(os, turbulence, 4),
|
||||||
MIST_FUNC_DEF(os, fbm, 4),
|
MIST_FUNC_DEF(os, fbm, 4),
|
||||||
|
MIST_FUNC_DEF(os, backend, 0),
|
||||||
MIST_FUNC_DEF(os, ridge, 5),
|
MIST_FUNC_DEF(os, ridge, 5),
|
||||||
MIST_FUNC_DEF(os, perlin, 3),
|
MIST_FUNC_DEF(os, perlin, 3),
|
||||||
MIST_FUNC_DEF(os, rectpack, 3),
|
MIST_FUNC_DEF(os, rectpack, 3),
|
||||||
|
@ -3633,9 +3652,9 @@ void ffi_load() {
|
||||||
|
|
||||||
QJSGLOBALCLASS(poly2d);
|
QJSGLOBALCLASS(poly2d);
|
||||||
|
|
||||||
JS_SetPropertyStr(js, prosperon, "version", str2js(VER));
|
JS_SetPropertyStr(js, prosperon, "version", str2js(PROSPERON_VER));
|
||||||
JS_SetPropertyStr(js, prosperon, "revision", str2js(COM));
|
JS_SetPropertyStr(js, prosperon, "revision", str2js(PROSPERON_COM));
|
||||||
JS_SetPropertyStr(js, prosperon, "date", str2js(DATE));
|
JS_SetPropertyStr(js, prosperon, "date", str2js(PROSPERON_DATE));
|
||||||
JS_SetPropertyStr(js, globalThis, "window", window2js(&mainwin));
|
JS_SetPropertyStr(js, globalThis, "window", window2js(&mainwin));
|
||||||
JS_SetPropertyStr(js, globalThis, "texture", JS_DupValue(js,texture_proto));
|
JS_SetPropertyStr(js, globalThis, "texture", JS_DupValue(js,texture_proto));
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,8 @@ struct texture *texture_from_file(const char *path) {
|
||||||
|
|
||||||
struct texture *tex = calloc(1, sizeof(*tex));
|
struct texture *tex = calloc(1, sizeof(*tex));
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(1);
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
char *ext = strrchr(path, '.');
|
char *ext = strrchr(path, '.');
|
||||||
|
|
695
source/engine/thirdparty/imgui/ImSequencer.cpp
vendored
695
source/engine/thirdparty/imgui/ImSequencer.cpp
vendored
|
@ -1,695 +0,0 @@
|
||||||
// https://github.com/CedricGuillemet/ImGuizmo
|
|
||||||
// v 1.89 WIP
|
|
||||||
//
|
|
||||||
// The MIT License(MIT)
|
|
||||||
//
|
|
||||||
// Copyright(c) 2021 Cedric Guillemet
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files(the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions :
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
//
|
|
||||||
#include "ImSequencer.h"
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_internal.h"
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace ImSequencer
|
|
||||||
{
|
|
||||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
|
||||||
static ImVec2 operator+(const ImVec2& a, const ImVec2& b) {
|
|
||||||
return ImVec2(a.x + b.x, a.y + b.y);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
static bool SequencerAddDelButton(ImDrawList* draw_list, ImVec2 pos, bool add = true)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImRect btnRect(pos, ImVec2(pos.x + 16, pos.y + 16));
|
|
||||||
bool overBtn = btnRect.Contains(io.MousePos);
|
|
||||||
bool containedClick = overBtn && btnRect.Contains(io.MouseClickedPos[0]);
|
|
||||||
bool clickedBtn = containedClick && io.MouseReleased[0];
|
|
||||||
int btnColor = overBtn ? 0xAAEAFFAA : 0x77A3B2AA;
|
|
||||||
if (containedClick && io.MouseDownDuration[0] > 0)
|
|
||||||
btnRect.Expand(2.0f);
|
|
||||||
|
|
||||||
float midy = pos.y + 16 / 2 - 0.5f;
|
|
||||||
float midx = pos.x + 16 / 2 - 0.5f;
|
|
||||||
draw_list->AddRect(btnRect.Min, btnRect.Max, btnColor, 4);
|
|
||||||
draw_list->AddLine(ImVec2(btnRect.Min.x + 3, midy), ImVec2(btnRect.Max.x - 3, midy), btnColor, 2);
|
|
||||||
if (add)
|
|
||||||
draw_list->AddLine(ImVec2(midx, btnRect.Min.y + 3), ImVec2(midx, btnRect.Max.y - 3), btnColor, 2);
|
|
||||||
return clickedBtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions)
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
int cx = (int)(io.MousePos.x);
|
|
||||||
int cy = (int)(io.MousePos.y);
|
|
||||||
static float framePixelWidth = 10.f;
|
|
||||||
static float framePixelWidthTarget = 10.f;
|
|
||||||
int legendWidth = 200;
|
|
||||||
|
|
||||||
static int movingEntry = -1;
|
|
||||||
static int movingPos = -1;
|
|
||||||
static int movingPart = -1;
|
|
||||||
int delEntry = -1;
|
|
||||||
int dupEntry = -1;
|
|
||||||
int ItemHeight = 20;
|
|
||||||
|
|
||||||
bool popupOpened = false;
|
|
||||||
int sequenceCount = sequence->GetItemCount();
|
|
||||||
if (!sequenceCount)
|
|
||||||
return false;
|
|
||||||
ImGui::BeginGroup();
|
|
||||||
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
|
||||||
ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
|
|
||||||
ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
|
|
||||||
int firstFrameUsed = firstFrame ? *firstFrame : 0;
|
|
||||||
|
|
||||||
|
|
||||||
int controlHeight = sequenceCount * ItemHeight;
|
|
||||||
for (int i = 0; i < sequenceCount; i++)
|
|
||||||
controlHeight += int(sequence->GetCustomHeight(i));
|
|
||||||
int frameCount = ImMax(sequence->GetFrameMax() - sequence->GetFrameMin(), 1);
|
|
||||||
|
|
||||||
static bool MovingScrollBar = false;
|
|
||||||
static bool MovingCurrentFrame = false;
|
|
||||||
struct CustomDraw
|
|
||||||
{
|
|
||||||
int index;
|
|
||||||
ImRect customRect;
|
|
||||||
ImRect legendRect;
|
|
||||||
ImRect clippingRect;
|
|
||||||
ImRect legendClippingRect;
|
|
||||||
};
|
|
||||||
ImVector<CustomDraw> customDraws;
|
|
||||||
ImVector<CustomDraw> compactCustomDraws;
|
|
||||||
// zoom in/out
|
|
||||||
const int visibleFrameCount = (int)floorf((canvas_size.x - legendWidth) / framePixelWidth);
|
|
||||||
const float barWidthRatio = ImMin(visibleFrameCount / (float)frameCount, 1.f);
|
|
||||||
const float barWidthInPixels = barWidthRatio * (canvas_size.x - legendWidth);
|
|
||||||
|
|
||||||
ImRect regionRect(canvas_pos, canvas_pos + canvas_size);
|
|
||||||
|
|
||||||
static bool panningView = false;
|
|
||||||
static ImVec2 panningViewSource;
|
|
||||||
static int panningViewFrame;
|
|
||||||
if (ImGui::IsWindowFocused() && io.KeyAlt && io.MouseDown[2])
|
|
||||||
{
|
|
||||||
if (!panningView)
|
|
||||||
{
|
|
||||||
panningViewSource = io.MousePos;
|
|
||||||
panningView = true;
|
|
||||||
panningViewFrame = *firstFrame;
|
|
||||||
}
|
|
||||||
*firstFrame = panningViewFrame - int((io.MousePos.x - panningViewSource.x) / framePixelWidth);
|
|
||||||
*firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), sequence->GetFrameMax() - visibleFrameCount);
|
|
||||||
}
|
|
||||||
if (panningView && !io.MouseDown[2])
|
|
||||||
{
|
|
||||||
panningView = false;
|
|
||||||
}
|
|
||||||
framePixelWidthTarget = ImClamp(framePixelWidthTarget, 0.1f, 50.f);
|
|
||||||
|
|
||||||
framePixelWidth = ImLerp(framePixelWidth, framePixelWidthTarget, 0.33f);
|
|
||||||
|
|
||||||
frameCount = sequence->GetFrameMax() - sequence->GetFrameMin();
|
|
||||||
if (visibleFrameCount >= frameCount && firstFrame)
|
|
||||||
*firstFrame = sequence->GetFrameMin();
|
|
||||||
|
|
||||||
|
|
||||||
// --
|
|
||||||
if (expanded && !*expanded)
|
|
||||||
{
|
|
||||||
ImGui::InvisibleButton("canvas", ImVec2(canvas_size.x - canvas_pos.x, (float)ItemHeight));
|
|
||||||
draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);
|
|
||||||
char tmps[512];
|
|
||||||
ImFormatString(tmps, IM_ARRAYSIZE(tmps), sequence->GetCollapseFmt(), frameCount, sequenceCount);
|
|
||||||
draw_list->AddText(ImVec2(canvas_pos.x + 26, canvas_pos.y + 2), 0xFFFFFFFF, tmps);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool hasScrollBar(true);
|
|
||||||
/*
|
|
||||||
int framesPixelWidth = int(frameCount * framePixelWidth);
|
|
||||||
if ((framesPixelWidth + legendWidth) >= canvas_size.x)
|
|
||||||
{
|
|
||||||
hasScrollBar = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// test scroll area
|
|
||||||
ImVec2 headerSize(canvas_size.x, (float)ItemHeight);
|
|
||||||
ImVec2 scrollBarSize(canvas_size.x, 14.f);
|
|
||||||
ImGui::InvisibleButton("topBar", headerSize);
|
|
||||||
draw_list->AddRectFilled(canvas_pos, canvas_pos + headerSize, 0xFFFF0000, 0);
|
|
||||||
ImVec2 childFramePos = ImGui::GetCursorScreenPos();
|
|
||||||
ImVec2 childFrameSize(canvas_size.x, canvas_size.y - 8.f - headerSize.y - (hasScrollBar ? scrollBarSize.y : 0));
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
|
|
||||||
ImGui::BeginChildFrame(889, childFrameSize);
|
|
||||||
sequence->focused = ImGui::IsWindowFocused();
|
|
||||||
ImGui::InvisibleButton("contentBar", ImVec2(canvas_size.x, float(controlHeight)));
|
|
||||||
const ImVec2 contentMin = ImGui::GetItemRectMin();
|
|
||||||
const ImVec2 contentMax = ImGui::GetItemRectMax();
|
|
||||||
const ImRect contentRect(contentMin, contentMax);
|
|
||||||
const float contentHeight = contentMax.y - contentMin.y;
|
|
||||||
|
|
||||||
// full background
|
|
||||||
draw_list->AddRectFilled(canvas_pos, canvas_pos + canvas_size, 0xFF242424, 0);
|
|
||||||
|
|
||||||
// current frame top
|
|
||||||
ImRect topRect(ImVec2(canvas_pos.x + legendWidth, canvas_pos.y), ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + ItemHeight));
|
|
||||||
|
|
||||||
if (!MovingCurrentFrame && !MovingScrollBar && movingEntry == -1 && sequenceOptions & SEQUENCER_CHANGE_FRAME && currentFrame && *currentFrame >= 0 && topRect.Contains(io.MousePos) && io.MouseDown[0])
|
|
||||||
{
|
|
||||||
MovingCurrentFrame = true;
|
|
||||||
}
|
|
||||||
if (MovingCurrentFrame)
|
|
||||||
{
|
|
||||||
if (frameCount)
|
|
||||||
{
|
|
||||||
*currentFrame = (int)((io.MousePos.x - topRect.Min.x) / framePixelWidth) + firstFrameUsed;
|
|
||||||
if (*currentFrame < sequence->GetFrameMin())
|
|
||||||
*currentFrame = sequence->GetFrameMin();
|
|
||||||
if (*currentFrame >= sequence->GetFrameMax())
|
|
||||||
*currentFrame = sequence->GetFrameMax();
|
|
||||||
}
|
|
||||||
if (!io.MouseDown[0])
|
|
||||||
MovingCurrentFrame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//header
|
|
||||||
draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);
|
|
||||||
if (sequenceOptions & SEQUENCER_ADD)
|
|
||||||
{
|
|
||||||
if (SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + legendWidth - ItemHeight, canvas_pos.y + 2), true))
|
|
||||||
ImGui::OpenPopup("addEntry");
|
|
||||||
|
|
||||||
if (ImGui::BeginPopup("addEntry"))
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sequence->GetItemTypeCount(); i++)
|
|
||||||
if (ImGui::Selectable(sequence->GetItemTypeName(i)))
|
|
||||||
{
|
|
||||||
sequence->Add(i);
|
|
||||||
*selectedEntry = sequence->GetItemCount() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndPopup();
|
|
||||||
popupOpened = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//header frame number and lines
|
|
||||||
int modFrameCount = 10;
|
|
||||||
int frameStep = 1;
|
|
||||||
while ((modFrameCount * framePixelWidth) < 150)
|
|
||||||
{
|
|
||||||
modFrameCount *= 2;
|
|
||||||
frameStep *= 2;
|
|
||||||
};
|
|
||||||
int halfModFrameCount = modFrameCount / 2;
|
|
||||||
|
|
||||||
auto drawLine = [&](int i, int regionHeight) {
|
|
||||||
bool baseIndex = ((i % modFrameCount) == 0) || (i == sequence->GetFrameMax() || i == sequence->GetFrameMin());
|
|
||||||
bool halfIndex = (i % halfModFrameCount) == 0;
|
|
||||||
int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);
|
|
||||||
int tiretStart = baseIndex ? 4 : (halfIndex ? 10 : 14);
|
|
||||||
int tiretEnd = baseIndex ? regionHeight : ItemHeight;
|
|
||||||
|
|
||||||
if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))
|
|
||||||
{
|
|
||||||
draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);
|
|
||||||
|
|
||||||
draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)ItemHeight), ImVec2((float)px, canvas_pos.y + (float)regionHeight - 1), 0x30606060, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseIndex && px > (canvas_pos.x + legendWidth))
|
|
||||||
{
|
|
||||||
char tmps[512];
|
|
||||||
ImFormatString(tmps, IM_ARRAYSIZE(tmps), "%d", i);
|
|
||||||
draw_list->AddText(ImVec2((float)px + 3.f, canvas_pos.y), 0xFFBBBBBB, tmps);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
auto drawLineContent = [&](int i, int /*regionHeight*/) {
|
|
||||||
int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);
|
|
||||||
int tiretStart = int(contentMin.y);
|
|
||||||
int tiretEnd = int(contentMax.y);
|
|
||||||
|
|
||||||
if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))
|
|
||||||
{
|
|
||||||
//draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);
|
|
||||||
|
|
||||||
draw_list->AddLine(ImVec2(float(px), float(tiretStart)), ImVec2(float(px), float(tiretEnd)), 0x30606060, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)
|
|
||||||
{
|
|
||||||
drawLine(i, ItemHeight);
|
|
||||||
}
|
|
||||||
drawLine(sequence->GetFrameMin(), ItemHeight);
|
|
||||||
drawLine(sequence->GetFrameMax(), ItemHeight);
|
|
||||||
/*
|
|
||||||
draw_list->AddLine(canvas_pos, ImVec2(canvas_pos.x, canvas_pos.y + controlHeight), 0xFF000000, 1);
|
|
||||||
draw_list->AddLine(ImVec2(canvas_pos.x, canvas_pos.y + ItemHeight), ImVec2(canvas_size.x, canvas_pos.y + ItemHeight), 0xFF000000, 1);
|
|
||||||
*/
|
|
||||||
// clip content
|
|
||||||
|
|
||||||
draw_list->PushClipRect(childFramePos, childFramePos + childFrameSize, true);
|
|
||||||
|
|
||||||
// draw item names in the legend rect on the left
|
|
||||||
size_t customHeight = 0;
|
|
||||||
for (int i = 0; i < sequenceCount; i++)
|
|
||||||
{
|
|
||||||
int type;
|
|
||||||
sequence->Get(i, NULL, NULL, &type, NULL);
|
|
||||||
ImVec2 tpos(contentMin.x + 3, contentMin.y + i * ItemHeight + 2 + customHeight);
|
|
||||||
draw_list->AddText(tpos, 0xFFFFFFFF, sequence->GetItemLabel(i));
|
|
||||||
|
|
||||||
if (sequenceOptions & SEQUENCER_DEL)
|
|
||||||
{
|
|
||||||
if (SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight + 2 - 10, tpos.y + 2), false))
|
|
||||||
delEntry = i;
|
|
||||||
|
|
||||||
if (SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight - ItemHeight + 2 - 10, tpos.y + 2), true))
|
|
||||||
dupEntry = i;
|
|
||||||
}
|
|
||||||
customHeight += sequence->GetCustomHeight(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// slots background
|
|
||||||
customHeight = 0;
|
|
||||||
for (int i = 0; i < sequenceCount; i++)
|
|
||||||
{
|
|
||||||
unsigned int col = (i & 1) ? 0xFF3A3636 : 0xFF413D3D;
|
|
||||||
|
|
||||||
size_t localCustomHeight = sequence->GetCustomHeight(i);
|
|
||||||
ImVec2 pos = ImVec2(contentMin.x + legendWidth, contentMin.y + ItemHeight * i + 1 + customHeight);
|
|
||||||
ImVec2 sz = ImVec2(canvas_size.x + canvas_pos.x, pos.y + ItemHeight - 1 + localCustomHeight);
|
|
||||||
if (!popupOpened && cy >= pos.y && cy < pos.y + (ItemHeight + localCustomHeight) && movingEntry == -1 && cx>contentMin.x && cx < contentMin.x + canvas_size.x)
|
|
||||||
{
|
|
||||||
col += 0x80201008;
|
|
||||||
pos.x -= legendWidth;
|
|
||||||
}
|
|
||||||
draw_list->AddRectFilled(pos, sz, col, 0);
|
|
||||||
customHeight += localCustomHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_list->PushClipRect(childFramePos + ImVec2(float(legendWidth), 0.f), childFramePos + childFrameSize, true);
|
|
||||||
|
|
||||||
// vertical frame lines in content area
|
|
||||||
for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)
|
|
||||||
{
|
|
||||||
drawLineContent(i, int(contentHeight));
|
|
||||||
}
|
|
||||||
drawLineContent(sequence->GetFrameMin(), int(contentHeight));
|
|
||||||
drawLineContent(sequence->GetFrameMax(), int(contentHeight));
|
|
||||||
|
|
||||||
// selection
|
|
||||||
bool selected = selectedEntry && (*selectedEntry >= 0);
|
|
||||||
if (selected)
|
|
||||||
{
|
|
||||||
customHeight = 0;
|
|
||||||
for (int i = 0; i < *selectedEntry; i++)
|
|
||||||
customHeight += sequence->GetCustomHeight(i);
|
|
||||||
draw_list->AddRectFilled(ImVec2(contentMin.x, contentMin.y + ItemHeight * *selectedEntry + customHeight), ImVec2(contentMin.x + canvas_size.x, contentMin.y + ItemHeight * (*selectedEntry + 1) + customHeight), 0x801080FF, 1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// slots
|
|
||||||
customHeight = 0;
|
|
||||||
for (int i = 0; i < sequenceCount; i++)
|
|
||||||
{
|
|
||||||
int* start, * end;
|
|
||||||
unsigned int color;
|
|
||||||
sequence->Get(i, &start, &end, NULL, &color);
|
|
||||||
size_t localCustomHeight = sequence->GetCustomHeight(i);
|
|
||||||
|
|
||||||
ImVec2 pos = ImVec2(contentMin.x + legendWidth - firstFrameUsed * framePixelWidth, contentMin.y + ItemHeight * i + 1 + customHeight);
|
|
||||||
ImVec2 slotP1(pos.x + *start * framePixelWidth, pos.y + 2);
|
|
||||||
ImVec2 slotP2(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2);
|
|
||||||
ImVec2 slotP3(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2 + localCustomHeight);
|
|
||||||
unsigned int slotColor = color | 0xFF000000;
|
|
||||||
unsigned int slotColorHalf = (color & 0xFFFFFF) | 0x40000000;
|
|
||||||
|
|
||||||
if (slotP1.x <= (canvas_size.x + contentMin.x) && slotP2.x >= (contentMin.x + legendWidth))
|
|
||||||
{
|
|
||||||
draw_list->AddRectFilled(slotP1, slotP3, slotColorHalf, 2);
|
|
||||||
draw_list->AddRectFilled(slotP1, slotP2, slotColor, 2);
|
|
||||||
}
|
|
||||||
if (ImRect(slotP1, slotP2).Contains(io.MousePos) && io.MouseDoubleClicked[0])
|
|
||||||
{
|
|
||||||
sequence->DoubleClick(i);
|
|
||||||
}
|
|
||||||
// Ensure grabbable handles
|
|
||||||
const float max_handle_width = slotP2.x - slotP1.x / 3.0f;
|
|
||||||
const float min_handle_width = ImMin(10.0f, max_handle_width);
|
|
||||||
const float handle_width = ImClamp(framePixelWidth / 2.0f, min_handle_width, max_handle_width);
|
|
||||||
ImRect rects[3] = { ImRect(slotP1, ImVec2(slotP1.x + handle_width, slotP2.y))
|
|
||||||
, ImRect(ImVec2(slotP2.x - handle_width, slotP1.y), slotP2)
|
|
||||||
, ImRect(slotP1, slotP2) };
|
|
||||||
|
|
||||||
const unsigned int quadColor[] = { 0xFFFFFFFF, 0xFFFFFFFF, slotColor + (selected ? 0 : 0x202020) };
|
|
||||||
if (movingEntry == -1 && (sequenceOptions & SEQUENCER_EDIT_STARTEND))// TODOFOCUS && backgroundRect.Contains(io.MousePos))
|
|
||||||
{
|
|
||||||
for (int j = 2; j >= 0; j--)
|
|
||||||
{
|
|
||||||
ImRect& rc = rects[j];
|
|
||||||
if (!rc.Contains(io.MousePos))
|
|
||||||
continue;
|
|
||||||
draw_list->AddRectFilled(rc.Min, rc.Max, quadColor[j], 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
ImRect& rc = rects[j];
|
|
||||||
if (!rc.Contains(io.MousePos))
|
|
||||||
continue;
|
|
||||||
if (!ImRect(childFramePos, childFramePos + childFrameSize).Contains(io.MousePos))
|
|
||||||
continue;
|
|
||||||
if (ImGui::IsMouseClicked(0) && !MovingScrollBar && !MovingCurrentFrame)
|
|
||||||
{
|
|
||||||
movingEntry = i;
|
|
||||||
movingPos = cx;
|
|
||||||
movingPart = j + 1;
|
|
||||||
sequence->BeginEdit(movingEntry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom draw
|
|
||||||
if (localCustomHeight > 0)
|
|
||||||
{
|
|
||||||
ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + 1 + customHeight);
|
|
||||||
ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(ItemHeight)),
|
|
||||||
rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(localCustomHeight + ItemHeight)));
|
|
||||||
ImRect clippingRect(rp + ImVec2(float(legendWidth), float(ItemHeight)), rp + ImVec2(canvas_size.x, float(localCustomHeight + ItemHeight)));
|
|
||||||
|
|
||||||
ImRect legendRect(rp + ImVec2(0.f, float(ItemHeight)), rp + ImVec2(float(legendWidth), float(localCustomHeight)));
|
|
||||||
ImRect legendClippingRect(canvas_pos + ImVec2(0.f, float(ItemHeight)), canvas_pos + ImVec2(float(legendWidth), float(localCustomHeight + ItemHeight)));
|
|
||||||
customDraws.push_back({ i, customRect, legendRect, clippingRect, legendClippingRect });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + customHeight);
|
|
||||||
ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(0.f)),
|
|
||||||
rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(ItemHeight)));
|
|
||||||
ImRect clippingRect(rp + ImVec2(float(legendWidth), float(0.f)), rp + ImVec2(canvas_size.x, float(ItemHeight)));
|
|
||||||
|
|
||||||
compactCustomDraws.push_back({ i, customRect, ImRect(), clippingRect, ImRect() });
|
|
||||||
}
|
|
||||||
customHeight += localCustomHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// moving
|
|
||||||
if (/*backgroundRect.Contains(io.MousePos) && */movingEntry >= 0)
|
|
||||||
{
|
|
||||||
#if IMGUI_VERSION_NUM >= 18723
|
|
||||||
ImGui::SetNextFrameWantCaptureMouse(true);
|
|
||||||
#else
|
|
||||||
ImGui::CaptureMouseFromApp();
|
|
||||||
#endif
|
|
||||||
int diffFrame = int((cx - movingPos) / framePixelWidth);
|
|
||||||
if (std::abs(diffFrame) > 0)
|
|
||||||
{
|
|
||||||
int* start, * end;
|
|
||||||
sequence->Get(movingEntry, &start, &end, NULL, NULL);
|
|
||||||
if (selectedEntry)
|
|
||||||
*selectedEntry = movingEntry;
|
|
||||||
int& l = *start;
|
|
||||||
int& r = *end;
|
|
||||||
if (movingPart & 1)
|
|
||||||
l += diffFrame;
|
|
||||||
if (movingPart & 2)
|
|
||||||
r += diffFrame;
|
|
||||||
if (l < 0)
|
|
||||||
{
|
|
||||||
if (movingPart & 2)
|
|
||||||
r -= l;
|
|
||||||
l = 0;
|
|
||||||
}
|
|
||||||
if (movingPart & 1 && l > r)
|
|
||||||
l = r;
|
|
||||||
if (movingPart & 2 && r < l)
|
|
||||||
r = l;
|
|
||||||
movingPos += int(diffFrame * framePixelWidth);
|
|
||||||
}
|
|
||||||
if (!io.MouseDown[0])
|
|
||||||
{
|
|
||||||
// single select
|
|
||||||
if (!diffFrame && movingPart && selectedEntry)
|
|
||||||
{
|
|
||||||
*selectedEntry = movingEntry;
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
movingEntry = -1;
|
|
||||||
sequence->EndEdit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cursor
|
|
||||||
if (currentFrame && firstFrame && *currentFrame >= *firstFrame && *currentFrame <= sequence->GetFrameMax())
|
|
||||||
{
|
|
||||||
static const float cursorWidth = 8.f;
|
|
||||||
float cursorOffset = contentMin.x + legendWidth + (*currentFrame - firstFrameUsed) * framePixelWidth + framePixelWidth / 2 - cursorWidth * 0.5f;
|
|
||||||
draw_list->AddLine(ImVec2(cursorOffset, canvas_pos.y), ImVec2(cursorOffset, contentMax.y), 0xA02A2AFF, cursorWidth);
|
|
||||||
char tmps[512];
|
|
||||||
ImFormatString(tmps, IM_ARRAYSIZE(tmps), "%d", *currentFrame);
|
|
||||||
draw_list->AddText(ImVec2(cursorOffset + 10, canvas_pos.y + 2), 0xFF2A2AFF, tmps);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_list->PopClipRect();
|
|
||||||
draw_list->PopClipRect();
|
|
||||||
|
|
||||||
for (auto& customDraw : customDraws)
|
|
||||||
sequence->CustomDraw(customDraw.index, draw_list, customDraw.customRect, customDraw.legendRect, customDraw.clippingRect, customDraw.legendClippingRect);
|
|
||||||
for (auto& customDraw : compactCustomDraws)
|
|
||||||
sequence->CustomDrawCompact(customDraw.index, draw_list, customDraw.customRect, customDraw.clippingRect);
|
|
||||||
|
|
||||||
// copy paste
|
|
||||||
if (sequenceOptions & SEQUENCER_COPYPASTE)
|
|
||||||
{
|
|
||||||
ImRect rectCopy(ImVec2(contentMin.x + 100, canvas_pos.y + 2)
|
|
||||||
, ImVec2(contentMin.x + 100 + 30, canvas_pos.y + ItemHeight - 2));
|
|
||||||
bool inRectCopy = rectCopy.Contains(io.MousePos);
|
|
||||||
unsigned int copyColor = inRectCopy ? 0xFF1080FF : 0xFF000000;
|
|
||||||
draw_list->AddText(rectCopy.Min, copyColor, "Copy");
|
|
||||||
|
|
||||||
ImRect rectPaste(ImVec2(contentMin.x + 140, canvas_pos.y + 2)
|
|
||||||
, ImVec2(contentMin.x + 140 + 30, canvas_pos.y + ItemHeight - 2));
|
|
||||||
bool inRectPaste = rectPaste.Contains(io.MousePos);
|
|
||||||
unsigned int pasteColor = inRectPaste ? 0xFF1080FF : 0xFF000000;
|
|
||||||
draw_list->AddText(rectPaste.Min, pasteColor, "Paste");
|
|
||||||
|
|
||||||
if (inRectCopy && io.MouseReleased[0])
|
|
||||||
{
|
|
||||||
sequence->Copy();
|
|
||||||
}
|
|
||||||
if (inRectPaste && io.MouseReleased[0])
|
|
||||||
{
|
|
||||||
sequence->Paste();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
ImGui::EndChildFrame();
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
if (hasScrollBar)
|
|
||||||
{
|
|
||||||
ImGui::InvisibleButton("scrollBar", scrollBarSize);
|
|
||||||
ImVec2 scrollBarMin = ImGui::GetItemRectMin();
|
|
||||||
ImVec2 scrollBarMax = ImGui::GetItemRectMax();
|
|
||||||
|
|
||||||
// ratio = number of frames visible in control / number to total frames
|
|
||||||
|
|
||||||
float startFrameOffset = ((float)(firstFrameUsed - sequence->GetFrameMin()) / (float)frameCount) * (canvas_size.x - legendWidth);
|
|
||||||
ImVec2 scrollBarA(scrollBarMin.x + legendWidth, scrollBarMin.y - 2);
|
|
||||||
ImVec2 scrollBarB(scrollBarMin.x + canvas_size.x, scrollBarMax.y - 1);
|
|
||||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF222222, 0);
|
|
||||||
|
|
||||||
ImRect scrollBarRect(scrollBarA, scrollBarB);
|
|
||||||
bool inScrollBar = scrollBarRect.Contains(io.MousePos);
|
|
||||||
|
|
||||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF101010, 8);
|
|
||||||
|
|
||||||
|
|
||||||
ImVec2 scrollBarC(scrollBarMin.x + legendWidth + startFrameOffset, scrollBarMin.y);
|
|
||||||
ImVec2 scrollBarD(scrollBarMin.x + legendWidth + barWidthInPixels + startFrameOffset, scrollBarMax.y - 2);
|
|
||||||
draw_list->AddRectFilled(scrollBarC, scrollBarD, (inScrollBar || MovingScrollBar) ? 0xFF606060 : 0xFF505050, 6);
|
|
||||||
|
|
||||||
ImRect barHandleLeft(scrollBarC, ImVec2(scrollBarC.x + 14, scrollBarD.y));
|
|
||||||
ImRect barHandleRight(ImVec2(scrollBarD.x - 14, scrollBarC.y), scrollBarD);
|
|
||||||
|
|
||||||
bool onLeft = barHandleLeft.Contains(io.MousePos);
|
|
||||||
bool onRight = barHandleRight.Contains(io.MousePos);
|
|
||||||
|
|
||||||
static bool sizingRBar = false;
|
|
||||||
static bool sizingLBar = false;
|
|
||||||
|
|
||||||
draw_list->AddRectFilled(barHandleLeft.Min, barHandleLeft.Max, (onLeft || sizingLBar) ? 0xFFAAAAAA : 0xFF666666, 6);
|
|
||||||
draw_list->AddRectFilled(barHandleRight.Min, barHandleRight.Max, (onRight || sizingRBar) ? 0xFFAAAAAA : 0xFF666666, 6);
|
|
||||||
|
|
||||||
ImRect scrollBarThumb(scrollBarC, scrollBarD);
|
|
||||||
static const float MinBarWidth = 44.f;
|
|
||||||
if (sizingRBar)
|
|
||||||
{
|
|
||||||
if (!io.MouseDown[0])
|
|
||||||
{
|
|
||||||
sizingRBar = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float barNewWidth = ImMax(barWidthInPixels + io.MouseDelta.x, MinBarWidth);
|
|
||||||
float barRatio = barNewWidth / barWidthInPixels;
|
|
||||||
framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;
|
|
||||||
int newVisibleFrameCount = int((canvas_size.x - legendWidth) / framePixelWidthTarget);
|
|
||||||
int lastFrame = *firstFrame + newVisibleFrameCount;
|
|
||||||
if (lastFrame > sequence->GetFrameMax())
|
|
||||||
{
|
|
||||||
framePixelWidthTarget = framePixelWidth = (canvas_size.x - legendWidth) / float(sequence->GetFrameMax() - *firstFrame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sizingLBar)
|
|
||||||
{
|
|
||||||
if (!io.MouseDown[0])
|
|
||||||
{
|
|
||||||
sizingLBar = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fabsf(io.MouseDelta.x) > FLT_EPSILON)
|
|
||||||
{
|
|
||||||
float barNewWidth = ImMax(barWidthInPixels - io.MouseDelta.x, MinBarWidth);
|
|
||||||
float barRatio = barNewWidth / barWidthInPixels;
|
|
||||||
float previousFramePixelWidthTarget = framePixelWidthTarget;
|
|
||||||
framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;
|
|
||||||
int newVisibleFrameCount = int(visibleFrameCount / barRatio);
|
|
||||||
int newFirstFrame = *firstFrame + newVisibleFrameCount - visibleFrameCount;
|
|
||||||
newFirstFrame = ImClamp(newFirstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));
|
|
||||||
if (newFirstFrame == *firstFrame)
|
|
||||||
{
|
|
||||||
framePixelWidth = framePixelWidthTarget = previousFramePixelWidthTarget;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*firstFrame = newFirstFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MovingScrollBar)
|
|
||||||
{
|
|
||||||
if (!io.MouseDown[0])
|
|
||||||
{
|
|
||||||
MovingScrollBar = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float framesPerPixelInBar = barWidthInPixels / (float)visibleFrameCount;
|
|
||||||
*firstFrame = int((io.MousePos.x - panningViewSource.x) / framesPerPixelInBar) - panningViewFrame;
|
|
||||||
*firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (scrollBarThumb.Contains(io.MousePos) && ImGui::IsMouseClicked(0) && firstFrame && !MovingCurrentFrame && movingEntry == -1)
|
|
||||||
{
|
|
||||||
MovingScrollBar = true;
|
|
||||||
panningViewSource = io.MousePos;
|
|
||||||
panningViewFrame = -*firstFrame;
|
|
||||||
}
|
|
||||||
if (!sizingRBar && onRight && ImGui::IsMouseClicked(0))
|
|
||||||
sizingRBar = true;
|
|
||||||
if (!sizingLBar && onLeft && ImGui::IsMouseClicked(0))
|
|
||||||
sizingLBar = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndGroup();
|
|
||||||
|
|
||||||
if (regionRect.Contains(io.MousePos))
|
|
||||||
{
|
|
||||||
bool overCustomDraw = false;
|
|
||||||
for (auto& custom : customDraws)
|
|
||||||
{
|
|
||||||
if (custom.customRect.Contains(io.MousePos))
|
|
||||||
{
|
|
||||||
overCustomDraw = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (overCustomDraw)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
frameOverCursor = *firstFrame + (int)(visibleFrameCount * ((io.MousePos.x - (float)legendWidth - canvas_pos.x) / (canvas_size.x - legendWidth)));
|
|
||||||
//frameOverCursor = max(min(*firstFrame - visibleFrameCount / 2, frameCount - visibleFrameCount), 0);
|
|
||||||
|
|
||||||
/**firstFrame -= frameOverCursor;
|
|
||||||
*firstFrame *= framePixelWidthTarget / framePixelWidth;
|
|
||||||
*firstFrame += frameOverCursor;*/
|
|
||||||
if (io.MouseWheel < -FLT_EPSILON)
|
|
||||||
{
|
|
||||||
*firstFrame -= frameOverCursor;
|
|
||||||
*firstFrame = int(*firstFrame * 1.1f);
|
|
||||||
framePixelWidthTarget *= 0.9f;
|
|
||||||
*firstFrame += frameOverCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (io.MouseWheel > FLT_EPSILON)
|
|
||||||
{
|
|
||||||
*firstFrame -= frameOverCursor;
|
|
||||||
*firstFrame = int(*firstFrame * 0.9f);
|
|
||||||
framePixelWidthTarget *= 1.1f;
|
|
||||||
*firstFrame += frameOverCursor;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expanded)
|
|
||||||
{
|
|
||||||
if (SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + 2, canvas_pos.y + 2), !*expanded))
|
|
||||||
*expanded = !*expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delEntry != -1)
|
|
||||||
{
|
|
||||||
sequence->Del(delEntry);
|
|
||||||
if (selectedEntry && (*selectedEntry == delEntry || *selectedEntry >= sequence->GetItemCount()))
|
|
||||||
*selectedEntry = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dupEntry != -1)
|
|
||||||
{
|
|
||||||
sequence->Duplicate(dupEntry);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
79
source/engine/thirdparty/imgui/ImSequencer.h
vendored
79
source/engine/thirdparty/imgui/ImSequencer.h
vendored
|
@ -1,79 +0,0 @@
|
||||||
// https://github.com/CedricGuillemet/ImGuizmo
|
|
||||||
// v 1.89 WIP
|
|
||||||
//
|
|
||||||
// The MIT License(MIT)
|
|
||||||
//
|
|
||||||
// Copyright(c) 2021 Cedric Guillemet
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files(the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions :
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
|
||||||
// copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
|
||||||
//
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
struct ImDrawList;
|
|
||||||
struct ImRect;
|
|
||||||
namespace ImSequencer
|
|
||||||
{
|
|
||||||
enum SEQUENCER_OPTIONS
|
|
||||||
{
|
|
||||||
SEQUENCER_EDIT_NONE = 0,
|
|
||||||
SEQUENCER_EDIT_STARTEND = 1 << 1,
|
|
||||||
SEQUENCER_CHANGE_FRAME = 1 << 3,
|
|
||||||
SEQUENCER_ADD = 1 << 4,
|
|
||||||
SEQUENCER_DEL = 1 << 5,
|
|
||||||
SEQUENCER_COPYPASTE = 1 << 6,
|
|
||||||
SEQUENCER_EDIT_ALL = SEQUENCER_EDIT_STARTEND | SEQUENCER_CHANGE_FRAME
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SequenceInterface
|
|
||||||
{
|
|
||||||
bool focused = false;
|
|
||||||
virtual int GetFrameMin() const = 0;
|
|
||||||
virtual int GetFrameMax() const = 0;
|
|
||||||
virtual int GetItemCount() const = 0;
|
|
||||||
|
|
||||||
virtual void BeginEdit(int /*index*/) {}
|
|
||||||
virtual void EndEdit() {}
|
|
||||||
virtual int GetItemTypeCount() const { return 0; }
|
|
||||||
virtual const char* GetItemTypeName(int /*typeIndex*/) const { return ""; }
|
|
||||||
virtual const char* GetItemLabel(int /*index*/) const { return ""; }
|
|
||||||
virtual const char* GetCollapseFmt() const { return "%d Frames / %d entries"; }
|
|
||||||
|
|
||||||
virtual void Get(int index, int** start, int** end, int* type, unsigned int* color) = 0;
|
|
||||||
virtual void Add(int /*type*/) {}
|
|
||||||
virtual void Del(int /*index*/) {}
|
|
||||||
virtual void Duplicate(int /*index*/) {}
|
|
||||||
|
|
||||||
virtual void Copy() {}
|
|
||||||
virtual void Paste() {}
|
|
||||||
|
|
||||||
virtual size_t GetCustomHeight(int /*index*/) { return 0; }
|
|
||||||
virtual void DoubleClick(int /*index*/) {}
|
|
||||||
virtual void CustomDraw(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*legendRect*/, const ImRect& /*clippingRect*/, const ImRect& /*legendClippingRect*/) {}
|
|
||||||
virtual void CustomDrawCompact(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*clippingRect*/) {}
|
|
||||||
|
|
||||||
virtual ~SequenceInterface() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// return true if selection is made
|
|
||||||
bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Matty on 2022-01-28.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
||||||
|
|
||||||
#include "imgui_neo_internal.h"
|
|
||||||
#include "imgui_internal.h"
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace ImGui {
|
|
||||||
void RenderNeoSequencerBackground(const ImVec4 &color, const ImVec2 & cursor, const ImVec2 &size, ImDrawList * drawList, float sequencerRounding) {
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
const ImRect area = {cursor, cursor + size};
|
|
||||||
|
|
||||||
drawList->AddRectFilled(area.Min, area.Max, ColorConvertFloat4ToU32(color), sequencerRounding);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderNeoSequencerTopBarBackground(const ImVec4 &color, const ImVec2 &cursor, const ImVec2 &size,
|
|
||||||
ImDrawList *drawList, float sequencerRounding) {
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
const ImRect barArea = {cursor, cursor + size};
|
|
||||||
|
|
||||||
drawList->AddRectFilled(barArea.Min, barArea.Max, ColorConvertFloat4ToU32(color), sequencerRounding);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RenderNeoSequencerTopBarOverlay(float zoom, float valuesWidth,uint32_t startFrame, uint32_t endFrame, uint32_t offsetFrame, const ImVec2 &cursor, const ImVec2 &size,
|
|
||||||
ImDrawList *drawList, bool drawFrameLines,
|
|
||||||
bool drawFrameText, float maxPixelsPerTick) {
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
const auto & style = GetStyle();
|
|
||||||
|
|
||||||
const ImRect barArea = {cursor + ImVec2{style.FramePadding.x + valuesWidth,style.FramePadding.y}, cursor + size };
|
|
||||||
|
|
||||||
const uint32_t viewEnd = endFrame + offsetFrame;
|
|
||||||
const uint32_t viewStart = startFrame + offsetFrame;
|
|
||||||
|
|
||||||
if(drawFrameLines) {
|
|
||||||
const auto count = (int32_t)((float)((viewEnd + 1) - viewStart) / zoom);
|
|
||||||
|
|
||||||
int32_t counter = 0;
|
|
||||||
uint32_t primaryFrames = pow(10, counter++);
|
|
||||||
uint32_t secondaryFrames = pow(10, counter);
|
|
||||||
|
|
||||||
float perFrameWidth = GetPerFrameWidth(size.x, valuesWidth, endFrame, startFrame, zoom);
|
|
||||||
|
|
||||||
if(perFrameWidth <= 0.0f) return;
|
|
||||||
|
|
||||||
while (perFrameWidth < maxPixelsPerTick)
|
|
||||||
{
|
|
||||||
primaryFrames = pow(10, counter++);
|
|
||||||
secondaryFrames = pow(10, counter);
|
|
||||||
|
|
||||||
perFrameWidth *= (float)primaryFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(primaryFrames == 0 || secondaryFrames == 0) {
|
|
||||||
primaryFrames = 1;
|
|
||||||
secondaryFrames = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int32_t i = 0; i < count; i++) {
|
|
||||||
|
|
||||||
const auto primaryFrame = ((viewStart + i) % primaryFrames == 0);
|
|
||||||
const auto secondaryFrame = ((viewStart + i) % secondaryFrames == 0);
|
|
||||||
|
|
||||||
if(!primaryFrame && !secondaryFrame) continue;
|
|
||||||
|
|
||||||
const auto lineHeight = secondaryFrame ? barArea.GetSize().y : barArea.GetSize().y / 2.0f;
|
|
||||||
|
|
||||||
const ImVec2 p1 = {barArea.Min.x + (float)i * (perFrameWidth / (float)primaryFrames), barArea.Max.y};
|
|
||||||
const ImVec2 p2 = {barArea.Min.x + (float)i * (perFrameWidth / (float)primaryFrames), barArea.Max.y - lineHeight};
|
|
||||||
|
|
||||||
drawList->AddLine(p1,p2, IM_COL32_WHITE, 1.0f);
|
|
||||||
|
|
||||||
if(drawFrameText && secondaryFrame) {
|
|
||||||
char text[10];
|
|
||||||
const auto printRes = snprintf(text, sizeof(text), "%i", viewStart + i);
|
|
||||||
if(printRes > 0) {
|
|
||||||
drawList->AddText(NULL, 0, {p1.x + 2.0f, barArea.Min.y }, IM_COL32_WHITE,text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderNeoTimelineLabel(const char * label,const ImVec2 & cursor,const ImVec2 & size, const ImVec4& color,bool isGroup, bool isOpen, ImDrawList *drawList)
|
|
||||||
{
|
|
||||||
const auto& imStyle = GetStyle();
|
|
||||||
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
auto c = cursor;
|
|
||||||
|
|
||||||
if(isGroup) {
|
|
||||||
RenderArrow(drawList,c,IM_COL32_WHITE,isOpen ? ImGuiDir_Down : ImGuiDir_Right);
|
|
||||||
c.x += size.y + imStyle.ItemSpacing.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawList->AddText(c,ColorConvertFloat4ToU32(color),label, FindRenderedTextEnd(label));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderNeoTimelinesBorder(const ImVec4 &color, const ImVec2 &cursor, const ImVec2 &size, ImDrawList *drawList,
|
|
||||||
float rounding, float borderSize)
|
|
||||||
{
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
drawList->AddRect(cursor,cursor + size,ColorConvertFloat4ToU32(color),rounding, 0, borderSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderNeoTimelane(bool selected,const ImVec2 & cursor, const ImVec2& size, const ImVec4& highlightColor, ImDrawList *drawList) {
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
if(selected) {
|
|
||||||
const ImRect area = {cursor, cursor + size};
|
|
||||||
drawList->AddRectFilled(area.Min, area.Max, ColorConvertFloat4ToU32(highlightColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetPerFrameWidth(float totalSizeX, float valuesWidth, uint32_t endFrame, uint32_t startFrame, float zoom) {
|
|
||||||
const auto& imStyle = GetStyle();
|
|
||||||
|
|
||||||
const auto size = totalSizeX - valuesWidth - imStyle.FramePadding.x;
|
|
||||||
|
|
||||||
auto count = (endFrame + 1) - startFrame;
|
|
||||||
|
|
||||||
return ((size / (float)count) * zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Vec2Pair {
|
|
||||||
ImVec2 a;
|
|
||||||
ImVec2 b;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Vec2Pair getCurrentFrameLine(const ImRect & pointerBB, float timelineHeight) {
|
|
||||||
const auto center = ImVec2{pointerBB.Min.x, pointerBB.Max.y} + ImVec2{pointerBB.GetSize().x / 2.0f, 0};
|
|
||||||
|
|
||||||
return Vec2Pair{ center, center + ImVec2{0, timelineHeight} };
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderNeoSequencerCurrentFrame(const ImVec4 &color, const ImVec4 &topColor, const ImRect &pointerBB,
|
|
||||||
float timelineHeight, float lineWidth, ImDrawList *drawList) {
|
|
||||||
if(!drawList) drawList = ImGui::GetWindowDrawList();
|
|
||||||
|
|
||||||
const auto pair = getCurrentFrameLine(pointerBB, timelineHeight);
|
|
||||||
|
|
||||||
drawList->AddLine(pair.a, pair.b, ColorConvertFloat4ToU32(color), lineWidth);
|
|
||||||
|
|
||||||
drawList->PopClipRect();
|
|
||||||
|
|
||||||
{ //Top pointer has custom shape, we have to create it
|
|
||||||
const auto size = pointerBB.GetSize();
|
|
||||||
ImVec2 pts[5];
|
|
||||||
pts[0] = pointerBB.Min;
|
|
||||||
pts[1] = pointerBB.Min + ImVec2{size.x, 0};
|
|
||||||
pts[2] = pointerBB.Min + ImVec2{size.x, size.y * 0.85f};
|
|
||||||
pts[3] = pointerBB.Min + ImVec2{size.x / 2, size.y};
|
|
||||||
pts[4] = pointerBB.Min + ImVec2{0, size.y * 0.85f};
|
|
||||||
|
|
||||||
drawList->AddConvexPolyFilled(pts, sizeof(pts) / sizeof(*pts), ColorConvertFloat4ToU32(topColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Matty on 2022-01-28.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef IMGUI_NEO_INTERNAL_H
|
|
||||||
#define IMGUI_NEO_INTERNAL_H
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_internal.h"
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace ImGui {
|
|
||||||
IMGUI_API void RenderNeoSequencerBackground(const ImVec4& color, const ImVec2 & cursor, const ImVec2& size, ImDrawList * drawList = nullptr, float sequencerRounding = 0.0f);
|
|
||||||
IMGUI_API void RenderNeoSequencerTopBarBackground(const ImVec4& color, const ImVec2 & cursor, const ImVec2& size, ImDrawList * drawList = nullptr, float sequencerRounding = 0.0f);
|
|
||||||
IMGUI_API void RenderNeoSequencerTopBarOverlay(float zoom, float valuesWidth,uint32_t startFrame, uint32_t endFrame, uint32_t offsetFrame, const ImVec2 &cursor, const ImVec2& size, ImDrawList * drawList = nullptr, bool drawFrameLines = true, bool drawFrameText = true, float maxPixelsPerTick = -1.0f);
|
|
||||||
IMGUI_API void RenderNeoTimelineLabel(const char * label,const ImVec2 & cursor,const ImVec2 & size, const ImVec4& color,bool isGroup = false, bool isOpen = false, ImDrawList *drawList = nullptr );
|
|
||||||
IMGUI_API void RenderNeoTimelane(bool selected,const ImVec2 & cursor, const ImVec2& size, const ImVec4& highlightColor, ImDrawList *drawList = nullptr);
|
|
||||||
IMGUI_API void RenderNeoTimelinesBorder(const ImVec4& color, const ImVec2 & cursor, const ImVec2& size, ImDrawList * drawList = nullptr, float rounding = 0.0f, float borderSize = 1.0f);
|
|
||||||
IMGUI_API void RenderNeoSequencerCurrentFrame(const ImVec4& color,const ImVec4 & topColor,const ImRect & pointerBB ,float timelineHeight, float lineWidth = 1.0f, ImDrawList * drawList = nullptr);
|
|
||||||
|
|
||||||
IMGUI_API float GetPerFrameWidth(float totalSizeX, float valuesWidth, uint32_t endFrame, uint32_t startFrame, float zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //IMGUI_NEO_INTERNAL_H
|
|
1376
source/engine/thirdparty/imgui/imgui_neo_sequencer.cpp
vendored
1376
source/engine/thirdparty/imgui/imgui_neo_sequencer.cpp
vendored
File diff suppressed because it is too large
Load diff
156
source/engine/thirdparty/imgui/imgui_neo_sequencer.h
vendored
156
source/engine/thirdparty/imgui/imgui_neo_sequencer.h
vendored
|
@ -1,156 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Matty on 2022-01-28.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef IMGUI_NEO_SEQUENCER_H
|
|
||||||
#define IMGUI_NEO_SEQUENCER_H
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
typedef int ImGuiNeoSequencerFlags;
|
|
||||||
typedef int ImGuiNeoSequencerCol;
|
|
||||||
typedef int ImGuiNeoTimelineFlags;
|
|
||||||
typedef int ImGuiNeoTimelineIsSelectedFlags;
|
|
||||||
|
|
||||||
// Flags for ImGui::BeginNeoSequencer()
|
|
||||||
enum ImGuiNeoSequencerFlags_
|
|
||||||
{
|
|
||||||
ImGuiNeoSequencerFlags_None = 0 ,
|
|
||||||
ImGuiNeoSequencerFlags_AllowLengthChanging = 1 << 0, // Allows changing length of sequence
|
|
||||||
ImGuiNeoSequencerFlags_EnableSelection = 1 << 1, // Enables selection of keyframes
|
|
||||||
ImGuiNeoSequencerFlags_HideZoom = 1 << 2, // Disables zoom bar
|
|
||||||
//ImGuiNeoSequencerFlags_PH = 1 << 3, // PLACEHOLDER
|
|
||||||
ImGuiNeoSequencerFlags_AlwaysShowHeader = 1 << 4, // Enables overlay header, keeping it visible when scrolling
|
|
||||||
|
|
||||||
// Selection options, only work with enable selection flag
|
|
||||||
ImGuiNeoSequencerFlags_Selection_EnableDragging = 1 << 5,
|
|
||||||
ImGuiNeoSequencerFlags_Selection_EnableDeletion = 1 << 6,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Flags for ImGui::BeginNeoTimeline()
|
|
||||||
enum ImGuiNeoTimelineFlags_
|
|
||||||
{
|
|
||||||
ImGuiNeoTimelineFlags_None = 0 ,
|
|
||||||
ImGuiNeoTimelineFlags_AllowFrameChanging = 1 << 0,
|
|
||||||
ImGuiNeoTimelineFlags_Group = 1 << 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Flags for ImGui::IsNeoTimelineSelected()
|
|
||||||
enum ImGuiNeoTimelineIsSelectedFlags_
|
|
||||||
{
|
|
||||||
ImGuiNeoTimelineIsSelectedFlags_None = 0 ,
|
|
||||||
ImGuiNeoTimelineIsSelectedFlags_NewlySelected = 1 << 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ImGuiNeoSequencerCol_
|
|
||||||
{
|
|
||||||
ImGuiNeoSequencerCol_Bg,
|
|
||||||
ImGuiNeoSequencerCol_TopBarBg,
|
|
||||||
ImGuiNeoSequencerCol_SelectedTimeline,
|
|
||||||
ImGuiNeoSequencerCol_TimelineBorder,
|
|
||||||
ImGuiNeoSequencerCol_TimelinesBg,
|
|
||||||
ImGuiNeoSequencerCol_FramePointer,
|
|
||||||
ImGuiNeoSequencerCol_FramePointerHovered,
|
|
||||||
ImGuiNeoSequencerCol_FramePointerPressed,
|
|
||||||
ImGuiNeoSequencerCol_Keyframe,
|
|
||||||
ImGuiNeoSequencerCol_KeyframeHovered,
|
|
||||||
ImGuiNeoSequencerCol_KeyframePressed,
|
|
||||||
ImGuiNeoSequencerCol_KeyframeSelected,
|
|
||||||
ImGuiNeoSequencerCol_FramePointerLine,
|
|
||||||
|
|
||||||
ImGuiNeoSequencerCol_ZoomBarBg,
|
|
||||||
ImGuiNeoSequencerCol_ZoomBarSlider,
|
|
||||||
ImGuiNeoSequencerCol_ZoomBarSliderHovered,
|
|
||||||
ImGuiNeoSequencerCol_ZoomBarSliderEnds,
|
|
||||||
ImGuiNeoSequencerCol_ZoomBarSliderEndsHovered,
|
|
||||||
|
|
||||||
ImGuiNeoSequencerCol_SelectionBorder,
|
|
||||||
ImGuiNeoSequencerCol_Selection,
|
|
||||||
|
|
||||||
ImGuiNeoSequencerCol_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ImGuiNeoSequencerStyle {
|
|
||||||
float SequencerRounding = 2.5f; // Corner rounding around whole sequencer
|
|
||||||
float TopBarHeight = 0.0f; // Value <= 0.0f = Height is calculated by FontSize + FramePadding.y * 2.0f
|
|
||||||
bool TopBarShowFrameLines = true; // Show line for every frame in top bar
|
|
||||||
bool TopBarShowFrameTexts = true; // Show frame number every 10th frame
|
|
||||||
ImVec2 ItemSpacing = {4.0f,0.5f};
|
|
||||||
float DepthItemSpacing = 10.0f; // Amount of text offset per depth level in timeline values
|
|
||||||
float TopBarSpacing = 3.0f; // Space between top bar and timeline
|
|
||||||
float TimelineBorderSize = 1.0f;
|
|
||||||
float CurrentFramePointerSize = 7.0f; // Size of pointing arrow above current frame line
|
|
||||||
float CurrentFrameLineWidth = 1.0f; // Width of line showing current frame over timeline
|
|
||||||
float ZoomHeightScale = 1.0f; // Scale of Zoom bar, base height is font size
|
|
||||||
float CollidedKeyframeOffset = 3.5f; // Offset on which colliding keyframes are rendered
|
|
||||||
|
|
||||||
float MaxSizePerTick = 4.0f; // Maximum amount of pixels per tick on timeline (if less pixels is present, ticks are not rendered)
|
|
||||||
|
|
||||||
ImVec4 Colors[ImGuiNeoSequencerCol_COUNT];
|
|
||||||
|
|
||||||
ImGuiKey ModRemoveKey = ImGuiMod_Ctrl; // Key mod which when held removes selected keyframes from present selection
|
|
||||||
ImGuiKey ModAddKey = ImGuiMod_Shift; // Key mod which when held adds selected keyframes to present selection
|
|
||||||
|
|
||||||
ImGuiNeoSequencerStyle();
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ImGui {
|
|
||||||
typedef int32_t FrameIndexType;
|
|
||||||
|
|
||||||
IMGUI_API const ImVec4& GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol idx);
|
|
||||||
IMGUI_API ImGuiNeoSequencerStyle& GetNeoSequencerStyle();
|
|
||||||
|
|
||||||
IMGUI_API void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, ImU32 col);
|
|
||||||
IMGUI_API void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, const ImVec4& col);
|
|
||||||
IMGUI_API void PopNeoSequencerStyleColor(int count = 1);
|
|
||||||
|
|
||||||
IMGUI_API bool BeginNeoSequencer(const char* id, FrameIndexType * frame, FrameIndexType * startFrame, FrameIndexType * endFrame,const ImVec2& size = ImVec2(0, 0),ImGuiNeoSequencerFlags flags = ImGuiNeoSequencerFlags_None);
|
|
||||||
IMGUI_API void EndNeoSequencer(); //Call only when BeginNeoSequencer() returns true!!
|
|
||||||
|
|
||||||
IMGUI_API bool BeginNeoGroup(const char* label, bool* open = nullptr);
|
|
||||||
IMGUI_API void EndNeoGroup();
|
|
||||||
|
|
||||||
IMGUI_API bool BeginNeoTimeline(const char* label,FrameIndexType ** keyframes, uint32_t keyframeCount, bool * open = nullptr, ImGuiNeoTimelineFlags flags = ImGuiNeoTimelineFlags_None);
|
|
||||||
IMGUI_API void EndNeoTimeLine(); //Call only when BeginNeoTimeline() returns true!!
|
|
||||||
|
|
||||||
// Fully customizable timeline with per key callback
|
|
||||||
IMGUI_API bool BeginNeoTimelineEx(const char* label, bool * open = nullptr, ImGuiNeoTimelineFlags flags = ImGuiNeoTimelineFlags_None);
|
|
||||||
IMGUI_API void NeoKeyframe(int32_t* value);
|
|
||||||
|
|
||||||
IMGUI_API bool IsNeoKeyframeHovered();
|
|
||||||
IMGUI_API bool IsNeoKeyframeSelected();
|
|
||||||
IMGUI_API bool IsNeoKeyframeRightClicked();
|
|
||||||
|
|
||||||
|
|
||||||
// Selection API
|
|
||||||
// DON'T delete keyframes while dragging, internal buffer will get corrupted
|
|
||||||
// Order for deletion is generally:
|
|
||||||
// CanDelete? -> DataSize? -> GetData() -> Delete your data -> ClearSelection()
|
|
||||||
IMGUI_API void NeoClearSelection(); // Clears selection
|
|
||||||
IMGUI_API bool NeoIsSelecting(); // Are we currently selecting?
|
|
||||||
IMGUI_API bool NeoHasSelection(); // Is anything selected?
|
|
||||||
IMGUI_API bool NeoIsDraggingSelection(); // Are we dragging selection?
|
|
||||||
IMGUI_API bool NeoCanDeleteSelection(); // Can selection deletion be done?
|
|
||||||
IMGUI_API bool IsNeoKeyframeSelectionRightClicked(); // Is selection rightclicked?
|
|
||||||
|
|
||||||
// Call only in BeginNeoTimeline / EndNeoTimeLine scope, returns selection per timeline and size per timeline
|
|
||||||
IMGUI_API uint32_t GetNeoKeyframeSelectionSize();
|
|
||||||
IMGUI_API void GetNeoKeyframeSelection(FrameIndexType * selection);
|
|
||||||
|
|
||||||
|
|
||||||
// Sets currently selected timeline inside BeginNeoSequencer scope
|
|
||||||
IMGUI_API void SetSelectedTimeline(const char* timelineLabel);
|
|
||||||
|
|
||||||
IMGUI_API bool IsNeoTimelineSelected(ImGuiNeoTimelineIsSelectedFlags flags = ImGuiNeoTimelineIsSelectedFlags_None);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
// C++ helper
|
|
||||||
// IMGUI_API bool BeginNeoTimeline(const char* label,std::vector<int32_t> & keyframes ,bool * open = nullptr, ImGuiNeoTimelineFlags flags = ImGuiNeoTimelineFlags_None);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif //IMGUI_NEO_SEQUENCER_H
|
|
Loading…
Reference in a new issue