add jpg library, export as jpg, export animation frames, add pressure support on mac
This commit is contained in:
@@ -61,8 +61,8 @@ public:
|
||||
void update_memory_usage(size_t bytes);
|
||||
void update(float dt);
|
||||
void resize(float w, float h);
|
||||
bool mouse_down(int button, float x, float y);
|
||||
bool mouse_move(float x, float y);
|
||||
bool mouse_down(int button, float x, float y, float pressure);
|
||||
bool mouse_move(float x, float y, float pressure);
|
||||
bool mouse_up(int button, float x, float y);
|
||||
bool mouse_scroll(float x, float y, float delta);
|
||||
bool mouse_cancel(int button);
|
||||
|
||||
@@ -11,20 +11,22 @@ void App::resize(float w, float h)
|
||||
main->update(w , h, zoom);
|
||||
}
|
||||
|
||||
bool App::mouse_down(int button, float x, float y)
|
||||
bool App::mouse_down(int button, float x, float y, float pressure)
|
||||
{
|
||||
MouseEvent e;
|
||||
e.m_type = button ? kEventType::MouseDownR : kEventType::MouseDownL;
|
||||
e.m_pos = { x / zoom, y / zoom };
|
||||
e.m_pressure = pressure;
|
||||
auto ret = layout[main_id]->on_event(&e);
|
||||
layout[main_id]->update();
|
||||
return ret == kEventResult::Consumed;
|
||||
}
|
||||
bool App::mouse_move(float x, float y)
|
||||
bool App::mouse_move(float x, float y, float pressure)
|
||||
{
|
||||
MouseEvent e;
|
||||
e.m_type = kEventType::MouseMove;
|
||||
e.m_pos = { x / zoom, y / zoom };
|
||||
e.m_pressure = pressure;
|
||||
kEventResult ret = kEventResult::Available;
|
||||
if (auto* main = layout[main_id])
|
||||
ret = main->on_event(&e);
|
||||
|
||||
@@ -165,7 +165,7 @@ ui::StrokeSample ui::Stroke::randomize_sample(const glm::vec2& pos, float pressu
|
||||
s.angle = (m_brush.m_tip_angle + rnd_nor() * m_brush.m_jitter_angle) * (float)(M_PI * 2.0);
|
||||
s.pos = pos + (rnd_vec() * m_brush.m_jitter_spread * 100.f);
|
||||
s.size = 100.f * m_brush.m_tip_size * (1.f - rnd_nor() * m_brush.m_jitter_scale);
|
||||
s.flow = m_brush.m_tip_flow * (1.f - rnd_nor() * m_brush.m_jitter_flow);
|
||||
s.flow = m_brush.m_tip_flow * (1.f - rnd_nor() * m_brush.m_jitter_flow) * pressure;
|
||||
return s;
|
||||
}
|
||||
std::vector<ui::StrokeSample> ui::Stroke::compute_samples()
|
||||
|
||||
@@ -599,9 +599,12 @@ void ui::Canvas::export_equirectangular(std::string data_path)
|
||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||
m_latlong.readTextureData(latlong_data.get());
|
||||
static char name[128];
|
||||
sprintf(name, "%s/latlong.png", data_path.c_str());
|
||||
sprintf(name, "%s/latlong.jpg", data_path.c_str());
|
||||
LOG("writing %s", name);
|
||||
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
jpge::params params;
|
||||
params.m_quality = 100;
|
||||
bool saved = jpge::compress_image_to_jpeg_file(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
||||
//int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &cube_id);
|
||||
@@ -626,7 +629,6 @@ void ui::Canvas::export_anim(std::string data_path)
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
glDisable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
RTT m_latlong;
|
||||
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
|
||||
@@ -646,19 +648,58 @@ void ui::Canvas::export_anim(std::string data_path)
|
||||
};
|
||||
for (auto layer_index : m_order)
|
||||
{
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
m_layers[layer_index].m_rtt[i].bindFramebuffer();
|
||||
m_tmp[i].bindFramebuffer();
|
||||
m_tmp[i].clear({ 1, 1, 1, 1 });
|
||||
|
||||
ui::ShaderManager::use(kShader::Checkerboard);
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
m_plane.draw_fill();
|
||||
|
||||
// copy to tmp2 for layer blending
|
||||
glActiveTexture(GL_TEXTURE0); // TODO: maybe remove this line
|
||||
m_tex2[i].bind();
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height);
|
||||
m_tex2[i].unbind();
|
||||
|
||||
m_layers[layer_index].m_rtt[i].bindTexture();
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex2[i].bind();
|
||||
m_sampler.bind(0);
|
||||
m_sampler_bg.bind(1);
|
||||
ShaderManager::use(ui::kShader::StrokeLayer);
|
||||
ShaderManager::u_int(kShaderUniform::TexBG, 1);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, 1);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
m_plane.draw_fill();
|
||||
m_sampler.unbind();
|
||||
m_sampler_bg.unbind();
|
||||
m_tex2[i].unbind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_layers[layer_index].m_rtt[i].unbindTexture();
|
||||
|
||||
// copy result to cubemap
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
m_layers[layer_index].m_rtt[i].unbindFramebuffer();
|
||||
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
|
||||
// m_layers[layer_index].m_rtt[i].bindFramebuffer();
|
||||
// // copy result to cubemap
|
||||
// glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
// glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0);
|
||||
// glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
// m_layers[layer_index].m_rtt[i].unbindFramebuffer();
|
||||
}
|
||||
|
||||
glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight());
|
||||
m_latlong.clear({ 1, 1, 1, 1 });
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_latlong.bindFramebuffer();
|
||||
m_latlong.clear({ 1, 1, 1, 1 });
|
||||
ui::ShaderManager::use(kShader::Equirect);
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
@@ -672,9 +713,12 @@ void ui::Canvas::export_anim(std::string data_path)
|
||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||
m_latlong.readTextureData(latlong_data.get());
|
||||
static char name[128];
|
||||
sprintf(name, "%s/latlong-frame%02d.png", data_path.c_str(), layer_index);
|
||||
sprintf(name, "%s/latlong-frame%02d.jpg", data_path.c_str(), layer_index);
|
||||
LOG("writing %s", name);
|
||||
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
//int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
jpge::params params;
|
||||
params.m_quality = 100;
|
||||
bool saved = jpge::compress_image_to_jpeg_file(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
switch (me->m_type)
|
||||
{
|
||||
case kEventType::MouseDownL:
|
||||
canvas->stroke_start(loc, 1.f, node->m_brush);
|
||||
canvas->stroke_start(loc, me->m_pressure, node->m_brush);
|
||||
m_dragging = true;
|
||||
node->mouse_capture();
|
||||
break;
|
||||
@@ -82,7 +82,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
if (m_dragging)
|
||||
canvas->stroke_update(loc, 1.f);
|
||||
canvas->stroke_update(loc, me->m_pressure);
|
||||
break;
|
||||
case kEventType::MouseCancel:
|
||||
canvas->stroke_cancel();
|
||||
|
||||
@@ -58,6 +58,7 @@ class MouseEvent : public Event
|
||||
public:
|
||||
MouseEvent() { m_cat = kEventCategory::MouseEvent; }
|
||||
glm::vec2 m_pos;
|
||||
float m_pressure;
|
||||
float m_scroll_delta;
|
||||
};
|
||||
|
||||
|
||||
@@ -202,14 +202,14 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
||||
{
|
||||
CGLLockContext([[self openGLContext] CGLContextObj]);
|
||||
auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
App::I.mouse_down(0, mouseLoc.x, App::I.height - mouseLoc.y - 1);
|
||||
App::I.mouse_down(0, mouseLoc.x, App::I.height - mouseLoc.y - 1, theEvent.pressure);
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
CGLLockContext([[self openGLContext] CGLContextObj]);
|
||||
auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
App::I.mouse_down(1, mouseLoc.x, App::I.height - mouseLoc.y - 1);
|
||||
App::I.mouse_down(1, mouseLoc.x, App::I.height - mouseLoc.y - 1, theEvent.pressure);
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
- (void)mouseUp:(NSEvent *)theEvent
|
||||
@@ -230,21 +230,21 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
||||
{
|
||||
CGLLockContext([[self openGLContext] CGLContextObj]);
|
||||
auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1);
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, theEvent.pressure);
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
-(void)mouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
CGLLockContext([[self openGLContext] CGLContextObj]);
|
||||
auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1);
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, theEvent.pressure);
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
CGLLockContext([[self openGLContext] CGLContextObj]);
|
||||
auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1);
|
||||
App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, theEvent.pressure);
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
- (void)scrollWheel:(NSEvent *)theEvent
|
||||
@@ -269,14 +269,6 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
|
||||
auto chars = [theEvent characters];
|
||||
App::I.key_up(convert_key(keyCode));
|
||||
CGLUnlockContext([[self openGLContext] CGLContextObj]);
|
||||
}
|
||||
- (void)tabletPoint:(NSEvent *)theEvent
|
||||
{
|
||||
|
||||
}
|
||||
- (void)tabletProximity:(NSEvent *)theEvent
|
||||
{
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <jpge.h>
|
||||
#include <jpgd.h>
|
||||
#endif
|
||||
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
Reference in New Issue
Block a user