Skip to content

Commit f3cd422

Browse files
committed
added texture mixer object
1 parent ab9187e commit f3cd422

File tree

2 files changed

+460
-0
lines changed

2 files changed

+460
-0
lines changed

src/objects/video/VideoMixer.cpp

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
/*==============================================================================
2+
3+
ofxVisualProgramming: A visual programming patching environment for OF
4+
5+
Copyright (c) 2021 Emanuele Mazza aka n3m3da <[email protected]>
6+
7+
ofxVisualProgramming is distributed under the MIT License.
8+
This gives everyone the freedoms to use ofxVisualProgramming in any context:
9+
commercial or non-commercial, public or private, open or closed source.
10+
11+
Permission is hereby granted, free of charge, to any person obtaining a
12+
copy of this software and associated documentation files (the "Software"),
13+
to deal in the Software without restriction, including without limitation
14+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
15+
and/or sell copies of the Software, and to permit persons to whom the
16+
Software is furnished to do so, subject to the following conditions:
17+
18+
The above copyright notice and this permission notice shall be included
19+
in all copies or substantial portions of the Software.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27+
DEALINGS IN THE SOFTWARE.
28+
29+
See https://github.com/d3cod3/ofxVisualProgramming for documentation
30+
31+
==============================================================================*/
32+
33+
#ifndef OFXVP_BUILD_WITH_MINIMAL_OBJECTS
34+
35+
#include "VideoMixer.h"
36+
37+
//--------------------------------------------------------------
38+
VideoMixer::VideoMixer() : PatchObject("texture mixer"){
39+
40+
this->numInlets = 6;
41+
this->numOutlets = 1;
42+
43+
_inletParams[0] = new ofTexture(); // tex1
44+
_inletParams[1] = new ofTexture(); // tex2
45+
_inletParams[2] = new ofTexture(); // tex3
46+
_inletParams[3] = new ofTexture(); // tex4
47+
_inletParams[4] = new ofTexture(); // tex5
48+
_inletParams[5] = new ofTexture(); // tex6
49+
50+
_outletParams[0] = new ofTexture(); // texture output
51+
52+
this->initInletsState();
53+
54+
posX = posY = drawW = drawH = 0.0f;
55+
56+
dataInlets = 6;
57+
58+
needReset = false;
59+
loaded = false;
60+
61+
kuro = new ofImage();
62+
mixFbo = new ofFbo();
63+
64+
canvasWidth = STANDARD_TEXTURE_WIDTH;
65+
canvasHeight = STANDARD_TEXTURE_HEIGHT;
66+
temp_width = STANDARD_TEXTURE_WIDTH;
67+
temp_height = STANDARD_TEXTURE_HEIGHT;
68+
69+
this->setIsResizable(true);
70+
this->setIsTextureObj(true);
71+
72+
prevW = this->width;
73+
prevH = this->height;
74+
75+
}
76+
77+
//--------------------------------------------------------------
78+
void VideoMixer::newObject(){
79+
PatchObject::setName( this->objectName );
80+
81+
this->addInlet(VP_LINK_TEXTURE,"t1");
82+
this->addInlet(VP_LINK_TEXTURE,"t2");
83+
this->addInlet(VP_LINK_TEXTURE,"t3");
84+
this->addInlet(VP_LINK_TEXTURE,"t4");
85+
this->addInlet(VP_LINK_TEXTURE,"t5");
86+
this->addInlet(VP_LINK_TEXTURE,"t6");
87+
88+
this->addOutlet(VP_LINK_TEXTURE,"output");
89+
90+
this->setCustomVar(static_cast<float>(dataInlets),"NUM_INLETS");
91+
92+
this->setCustomVar(static_cast<float>(prevW),"WIDTH");
93+
this->setCustomVar(static_cast<float>(prevH),"HEIGHT");
94+
this->setCustomVar(static_cast<float>(canvasWidth),"CANVAS_WIDTH");
95+
this->setCustomVar(static_cast<float>(canvasHeight),"CANVAS_HEIGHT");
96+
97+
alphas.assign(32,255);
98+
for(int i=0;i<32;i++){
99+
this->setCustomVar(alphas.at(i),"T"+ofToString(i)+"_alpha");
100+
}
101+
}
102+
103+
//--------------------------------------------------------------
104+
void VideoMixer::setupObjectContent(shared_ptr<ofAppGLFWWindow> &mainWindow){
105+
// load kuro
106+
kuro->load("images/kuro.jpg");
107+
108+
texData.width = kuro->getWidth();
109+
texData.height = kuro->getHeight();
110+
texData.textureTarget = GL_TEXTURE_2D;
111+
texData.bFlipTexture = true;
112+
113+
kuroTex = new ofTexture();
114+
kuroTex->clear();
115+
kuroTex->allocate(texData);
116+
kuroTex->loadData(kuro->getPixels());
117+
118+
mixFbo->allocate(canvasWidth, canvasHeight, GL_RGBA);
119+
mixFbo->begin();
120+
glColor4f(0.0f,0.0f,0.0f,1.0f);
121+
ofDrawRectangle(0,0,canvasWidth, canvasHeight);
122+
mixFbo->end();
123+
124+
}
125+
126+
//--------------------------------------------------------------
127+
void VideoMixer::updateObjectContent(map<int,shared_ptr<PatchObject>> &patchObjects){
128+
129+
// mix texture inlets with alpha
130+
if(mixFbo->isAllocated()){
131+
*static_cast<ofTexture *>(_outletParams[0]) = mixFbo->getTexture();
132+
}else{
133+
*static_cast<ofTexture *>(_outletParams[0]) = *kuroTex;
134+
}
135+
136+
137+
if(needReset){
138+
needReset = false;
139+
resetInletsSettings();
140+
}
141+
142+
if(!loaded){
143+
loaded = true;
144+
canvasWidth = this->getCustomVar("CANVAS_WIDTH");
145+
canvasHeight = this->getCustomVar("CANVAS_HEIGHT");
146+
prevW = this->getCustomVar("WIDTH");
147+
prevH = this->getCustomVar("HEIGHT");
148+
this->width = prevW;
149+
this->height = prevH;
150+
151+
for(int i=0;i<32;i++){
152+
alphas.at(i) = this->getCustomVar("T"+ofToString(i)+"_alpha");
153+
}
154+
155+
initInlets();
156+
}
157+
}
158+
159+
//--------------------------------------------------------------
160+
void VideoMixer::drawObjectContent(ofTrueTypeFont *font, shared_ptr<ofBaseGLRenderer>& glRenderer){
161+
ofSetColor(255);
162+
163+
mixFbo->begin();
164+
165+
ofSetColor(0,0,0);
166+
ofDrawRectangle(0,0,canvasWidth,canvasHeight);
167+
168+
for(int i=0;i<dataInlets;i++){
169+
if(this->inletsConnected[i]){
170+
ofSetColor(255,255,255,alphas.at(i));
171+
static_cast<ofTexture *>(_inletParams[i])->draw(0,0,canvasWidth,canvasHeight);
172+
}
173+
}
174+
175+
mixFbo->end();
176+
177+
// DRAW
178+
ofSetColor(255);
179+
if(static_cast<ofTexture *>(_outletParams[0])->isAllocated()){
180+
// draw node texture preview with OF
181+
if(scaledObjW*canvasZoom > 90.0f && this->width > 120 && this->height > 70){
182+
drawNodeOFTexture(*static_cast<ofTexture *>(_outletParams[0]), posX, posY, drawW, drawH, objOriginX, objOriginY, scaledObjW, scaledObjH, canvasZoom, this->scaleFactor);
183+
}
184+
}else{
185+
// background
186+
if(scaledObjW*canvasZoom > 90.0f){
187+
ofSetColor(34,34,34);
188+
ofDrawRectangle(objOriginX - (IMGUI_EX_NODE_PINS_WIDTH_NORMAL*this->scaleFactor/canvasZoom), objOriginY-(IMGUI_EX_NODE_HEADER_HEIGHT*this->scaleFactor/canvasZoom),scaledObjW + (IMGUI_EX_NODE_PINS_WIDTH_NORMAL*this->scaleFactor/canvasZoom),scaledObjH + (((IMGUI_EX_NODE_HEADER_HEIGHT+IMGUI_EX_NODE_FOOTER_HEIGHT)*this->scaleFactor)/canvasZoom) );
189+
}
190+
}
191+
192+
}
193+
194+
//--------------------------------------------------------------
195+
void VideoMixer::drawObjectNodeGui( ImGuiEx::NodeCanvas& _nodeCanvas ){
196+
197+
// CONFIG GUI inside Menu
198+
if(_nodeCanvas.BeginNodeMenu()){
199+
200+
ImGui::Separator();
201+
ImGui::Separator();
202+
ImGui::Separator();
203+
204+
if (ImGui::BeginMenu("CONFIG"))
205+
{
206+
207+
drawObjectNodeConfig(); this->configMenuWidth = ImGui::GetWindowWidth();
208+
209+
ImGui::EndMenu();
210+
}
211+
212+
_nodeCanvas.EndNodeMenu();
213+
}
214+
215+
// Visualize (Object main view)
216+
if( _nodeCanvas.BeginNodeContent(ImGuiExNodeView_Visualise) ){
217+
218+
// get imgui node translated/scaled position/dimension for drawing textures in OF
219+
objOriginX = (ImGui::GetWindowPos().x + ((IMGUI_EX_NODE_PINS_WIDTH_NORMAL - 1)*this->scaleFactor) - _nodeCanvas.GetCanvasTranslation().x)/_nodeCanvas.GetCanvasScale();
220+
objOriginY = (ImGui::GetWindowPos().y - _nodeCanvas.GetCanvasTranslation().y)/_nodeCanvas.GetCanvasScale();
221+
scaledObjW = this->width - (IMGUI_EX_NODE_PINS_WIDTH_NORMAL*this->scaleFactor/_nodeCanvas.GetCanvasScale());
222+
scaledObjH = this->height - ((IMGUI_EX_NODE_HEADER_HEIGHT+IMGUI_EX_NODE_FOOTER_HEIGHT)*this->scaleFactor/_nodeCanvas.GetCanvasScale());
223+
224+
// save object dimensions (for resizable ones)
225+
if(this->width != prevW){
226+
prevW = this->width;
227+
this->setCustomVar(static_cast<float>(prevW),"WIDTH");
228+
}
229+
if(this->height != prevH){
230+
prevH = this->height;
231+
this->setCustomVar(static_cast<float>(prevH),"HEIGHT");
232+
}
233+
234+
_nodeCanvas.EndNodeContent();
235+
}
236+
237+
// get imgui canvas zoom
238+
canvasZoom = _nodeCanvas.GetCanvasScale();
239+
240+
}
241+
242+
//--------------------------------------------------------------
243+
void VideoMixer::drawObjectNodeConfig(){
244+
ImGui::Spacing();
245+
if(ImGui::InputInt("Texture Inlets",&dataInlets)){
246+
if(dataInlets > MAX_INLETS){
247+
dataInlets = MAX_INLETS;
248+
}
249+
}
250+
ImGui::SameLine(); ImGuiEx::HelpMarker("You can set 32 inlets max.");
251+
ImGui::Spacing();
252+
if(ImGui::Button("APPLY",ImVec2(224*scaleFactor,26*scaleFactor))){
253+
this->setCustomVar(static_cast<float>(dataInlets),"NUM_INLETS");
254+
needReset = true;
255+
}
256+
ImGui::Spacing();
257+
if(ImGui::InputInt("Width",&temp_width)){
258+
if(temp_width > OUTPUT_TEX_MAX_WIDTH){
259+
temp_width = OUTPUT_TEX_MAX_WIDTH;
260+
}
261+
}
262+
ImGui::SameLine(); ImGuiEx::HelpMarker("You can set the texture resolution WxH (limited for now at max. 4800x4800)");
263+
264+
if(ImGui::InputInt("Height",&temp_height)){
265+
if(temp_height > OUTPUT_TEX_MAX_HEIGHT){
266+
temp_height = OUTPUT_TEX_MAX_HEIGHT;
267+
}
268+
}
269+
ImGui::Spacing();
270+
if(ImGui::Button("APPLY",ImVec2(224*scaleFactor,26*scaleFactor))){
271+
needReset = true;
272+
}
273+
ImGui::Spacing();
274+
ImGui::Spacing();
275+
276+
ImGui::PushItemWidth(130*this->scaleFactor);
277+
for(int i=0;i<dataInlets;i++){
278+
string tempstr = "T"+ofToString(i)+" alpha";
279+
if(ImGui::SliderFloat(tempstr.c_str(),&alphas.at(i), 0.0f, 255.0f)){
280+
this->setCustomVar(alphas.at(i),"T"+ofToString(i)+"_alpha");
281+
}
282+
}
283+
ImGui::PopItemWidth();
284+
285+
ImGui::Spacing();
286+
287+
ImGuiEx::ObjectInfo(
288+
"Receives up to 32 textures, and mix them using alpha.",
289+
"https://mosaic.d3cod3.org/reference.php?r=texture-mixer", scaleFactor);
290+
}
291+
292+
//--------------------------------------------------------------
293+
void VideoMixer::removeObjectContent(bool removeFileFromData){
294+
295+
}
296+
297+
//--------------------------------------------------------------
298+
void VideoMixer::initInlets(){
299+
dataInlets = this->getCustomVar("NUM_INLETS");
300+
301+
this->numInlets = dataInlets;
302+
303+
resetInletsSettings();
304+
}
305+
306+
//--------------------------------------------------------------
307+
void VideoMixer::resetInletsSettings(){
308+
309+
vector<bool> tempInletsConn;
310+
for(int i=0;i<this->numInlets;i++){
311+
if(this->inletsConnected[i]){
312+
tempInletsConn.push_back(true);
313+
}else{
314+
tempInletsConn.push_back(false);
315+
}
316+
}
317+
318+
this->numInlets = dataInlets;
319+
320+
for(int i=0;i<this->numInlets;i++){
321+
_inletParams[i] = new ofTexture();
322+
}
323+
324+
this->inletsType.clear();
325+
this->inletsNames.clear();
326+
327+
for(int i=0;i<this->numInlets;i++){
328+
this->addInlet(VP_LINK_TEXTURE,"t"+ofToString(i));
329+
}
330+
331+
this->inletsConnected.clear();
332+
for(int i=0;i<this->numInlets;i++){
333+
if(i<static_cast<int>(tempInletsConn.size())){
334+
if(tempInletsConn.at(i)){
335+
this->inletsConnected.push_back(true);
336+
}else{
337+
this->inletsConnected.push_back(false);
338+
}
339+
}else{
340+
this->inletsConnected.push_back(false);
341+
}
342+
}
343+
344+
if(canvasWidth != temp_width || canvasHeight != temp_height){
345+
canvasWidth = temp_width;
346+
canvasHeight = temp_height;
347+
348+
ofLog(OF_LOG_NOTICE,"Changing texture dimensions to: %ix%i",canvasWidth,canvasHeight);
349+
350+
this->setCustomVar(static_cast<float>(canvasWidth),"CANVAS_WIDTH");
351+
this->setCustomVar(static_cast<float>(canvasHeight),"CANVAS_HEIGHT");
352+
353+
mixFbo = new ofFbo();
354+
mixFbo->allocate(canvasWidth, canvasHeight, GL_RGBA);
355+
mixFbo->begin();
356+
glColor4f(0.0f,0.0f,0.0f,1.0f);
357+
ofDrawRectangle(0,0,canvasWidth, canvasHeight);
358+
mixFbo->end();
359+
360+
_outletParams[0] = new ofTexture();
361+
static_cast<ofTexture *>(_outletParams[0])->allocate(canvasWidth,canvasHeight,GL_RGB);
362+
363+
}
364+
365+
ofNotifyEvent(this->resetEvent, this->nId);
366+
367+
this->saveConfig(false);
368+
369+
}
370+
371+
OBJECT_REGISTER( VideoMixer, "texture mixer", OFXVP_OBJECT_CAT_TEXTURE)
372+
373+
#endif

0 commit comments

Comments
 (0)