1 /*$
2  Copyright (C) 2013-2020 Azel.
3 
4  This file is part of AzPainter.
5 
6  AzPainter is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  AzPainter is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 $*/
19 
20 /*********************************************
21  * [dock] レイヤで使うウィジェット
22  *
23  * パラメータ部分、アルファマスク選択
24  *********************************************/
25 
26 #include "mDef.h"
27 #include "mContainerDef.h"
28 #include "mWidget.h"
29 #include "mContainer.h"
30 #include "mComboBox.h"
31 #include "mPixbuf.h"
32 #include "mSysCol.h"
33 #include "mEvent.h"
34 #include "mMenu.h"
35 #include "mTrans.h"
36 
37 #include "defDraw.h"
38 #include "defBlendMode.h"
39 
40 #include "ValueBar.h"
41 #include "SelMaterial.h"
42 #include "LayerItem.h"
43 
44 #include "draw_main.h"
45 #include "draw_layer.h"
46 #include "Docks_external.h"
47 
48 #include "trgroup.h"
49 
50 #include "img_layer_amask.h"
51 
52 
53 //---------------------
54 
55 enum
56 {
57 	WID_BAR_OPACITY = 100,
58 	WID_CB_BLENDMODE,
59 	WID_AMASK,
60 	WID_SEL_TEXTURE
61 };
62 
63 enum
64 {
65 	TRID_AMASK_TOP = 100
66 };
67 
68 //---------------------
69 
70 
71 /************************************
72  * アルファマスク選択
73  ************************************/
74 
75 
76 typedef struct
77 {
78 	mWidget wg;
79 	int curno;
80 }_alphamask;
81 
82 
83 /** メニュー */
84 
_amask_run_menu(mWidget * wg)85 static int _amask_run_menu(mWidget *wg)
86 {
87 	mMenu *menu;
88 	mMenuItemInfo *pi;
89 	int no;
90 	mBox box;
91 
92 	menu = mMenuNew();
93 
94 	M_TR_G(TRGROUP_DOCK_LAYER);
95 
96 	mMenuAddTrTexts(menu, TRID_AMASK_TOP, 4);
97 	mMenuSetCheck(menu, TRID_AMASK_TOP + APP_DRAW->curlayer->alphamask, 1);
98 
99 	mWidgetGetRootBox(wg, &box);
100 
101 	pi = mMenuPopup(menu, NULL, box.x, box.y + box.h, 0);
102 
103 	no = (pi)? pi->id - TRID_AMASK_TOP: -1;
104 
105 	mMenuDestroy(menu);
106 
107 	return no;
108 }
109 
110 /** イベント */
111 
_amask_event_handle(mWidget * wg,mEvent * ev)112 static int _amask_event_handle(mWidget *wg,mEvent *ev)
113 {
114 	int amask;
115 
116 	if(ev->type == MEVENT_POINTER
117 		&& (ev->pt.type == MEVENT_POINTER_TYPE_PRESS
118 			|| ev->pt.type == MEVENT_POINTER_TYPE_DBLCLK))
119 	{
120 		if(ev->pt.btt == M_BTT_RIGHT
121 			|| (ev->pt.btt == M_BTT_LEFT && (ev->pt.state & M_MODS_CTRL)))
122 			//右クリック or Ctrl+左 => OFF
123 			amask = 0;
124 		else if(ev->pt.btt == M_BTT_LEFT && (ev->pt.state & M_MODS_SHIFT))
125 			//Shift+左 => アルファマスクON/OFF
126 			amask = (APP_DRAW->curlayer->alphamask == 1)? 0: 1;
127 		else if(ev->pt.btt == M_BTT_LEFT)
128 			//左クリック => メニュー
129 			amask = _amask_run_menu(wg);
130 		else
131 			amask = -1;
132 
133 		//選択変更
134 
135 		if(amask != -1)
136 		{
137 			APP_DRAW->curlayer->alphamask = amask;
138 
139 			((_alphamask *)wg)->curno = amask;
140 
141 			mWidgetUpdate(wg);
142 		}
143 	}
144 
145 	return 1;
146 }
147 
148 /** 描画 */
149 
_amask_draw_handle(mWidget * wg,mPixbuf * pixbuf)150 static void _amask_draw_handle(mWidget *wg,mPixbuf *pixbuf)
151 {
152 	if(wg->fState & MWIDGET_STATE_ENABLED)
153 	{
154 		//有効
155 		mPixbufBltFromGray(pixbuf, 0, 0, g_img_layer_amask,
156 			((_alphamask *)wg)->curno * 16, 0, 16, 16, 16 * 4);
157 	}
158 	else
159 	{
160 		//無効
161 		mPixbufBox(pixbuf, 0, 0, 16, 16, MSYSCOL(FRAME_LIGHT));
162 		mPixbufFillBox(pixbuf, 1, 1, 14, 14, MSYSCOL(FACE));
163 	}
164 }
165 
166 /** 作成 */
167 
_alphamask_new(mWidget * parent)168 static _alphamask *_alphamask_new(mWidget *parent)
169 {
170 	_alphamask *p;
171 
172 	p = (_alphamask *)mWidgetNew(sizeof(_alphamask), parent);
173 	if(!p) return NULL;
174 
175 	p->wg.id = WID_AMASK;
176 	p->wg.hintW = p->wg.hintH = 16;
177 	p->wg.fLayout = MLF_MIDDLE;
178 	p->wg.fEventFilter |= MWIDGET_EVENTFILTER_POINTER;
179 	p->wg.draw = _amask_draw_handle;
180 	p->wg.event = _amask_event_handle;
181 
182 	return p;
183 }
184 
185 
186 /**************************************
187  * パラメータ部分のコンテナ
188  **************************************/
189 
190 
191 typedef struct
192 {
193 	mWidget wg;
194 	mContainerData ct;
195 
196 	SelMaterial *selmat;
197 	ValueBar *bar_opacity;
198 	mComboBox *cb_blend;
199 	_alphamask *amask;
200 }_paramct;
201 
202 
203 
204 /** イベント */
205 
_paramct_event_handle(mWidget * wg,mEvent * ev)206 static int _paramct_event_handle(mWidget *wg,mEvent *ev)
207 {
208 	if(ev->type == MEVENT_NOTIFY)
209 	{
210 		switch(ev->notify.id)
211 		{
212 			//不透明度
213 			case WID_BAR_OPACITY:
214 				if(ev->notify.param2)
215 				{
216 					APP_DRAW->curlayer->opacity = (int)(ev->notify.param1 * 128.0 / 100.0 + 0.5);
217 
218 					drawUpdate_rect_imgcanvas_canvasview_inLayerHave(APP_DRAW, NULL);
219 					DockLayer_update_curlayer(FALSE);
220 				}
221 				break;
222 			//合成モード
223 			case WID_CB_BLENDMODE:
224 				if(ev->notify.type == MCOMBOBOX_N_CHANGESEL)
225 				{
226 					APP_DRAW->curlayer->blendmode = ev->notify.param2;
227 
228 					DockLayer_update_curlayer(FALSE);
229 					drawUpdate_rect_imgcanvas_canvasview_inLayerHave(APP_DRAW, NULL);
230 				}
231 				break;
232 			//テクスチャ
233 			case WID_SEL_TEXTURE:
234 				drawLayer_setTexture(APP_DRAW, (const char *)ev->notify.param1);
235 				break;
236 		}
237 	}
238 
239 	return 1;
240 }
241 
242 /** 作成 */
243 
DockLayer_parameter_new(mWidget * parent)244 mWidget *DockLayer_parameter_new(mWidget *parent)
245 {
246 	_paramct *p;
247 	mWidget *ct;
248 
249 	//作成
250 
251 	p = (_paramct *)mContainerNew(sizeof(_paramct), parent);
252 	if(!p) return NULL;
253 
254 	mContainerSetPadding_b4(M_CONTAINER(p), M_MAKE_DW4(3,5,3,5));
255 
256 	p->wg.fLayout = MLF_EXPAND_W;
257 	p->wg.notifyTarget = MWIDGET_NOTIFYTARGET_SELF;
258 	p->wg.event = _paramct_event_handle;
259 	p->ct.sepW = 5;
260 
261 	//[合成モード + アルファマスク]
262 
263 	ct = mContainerCreate(M_WIDGET(p), MCONTAINER_TYPE_HORZ, 0, 6, MLF_EXPAND_W);
264 
265 	//合成モード
266 
267 	p->cb_blend = mComboBoxCreate(ct, WID_CB_BLENDMODE, 0, MLF_EXPAND_W, 0);
268 
269 	M_TR_G(TRGROUP_BLENDMODE);
270 	mComboBoxAddTrItems(p->cb_blend, BLENDMODE_NUM, 0, 0);
271 
272 	//アルファマスク
273 
274 	p->amask = _alphamask_new(ct);
275 
276 	//[濃度]
277 
278 	p->bar_opacity = ValueBar_new(M_WIDGET(p), WID_BAR_OPACITY, MLF_EXPAND_W,
279 		0, 0, 100, 100);
280 
281 	//[テクスチャ]
282 
283 	p->selmat = SelMaterial_new(M_WIDGET(p), WID_SEL_TEXTURE, SELMATERIAL_TYPE_TEXTURE);
284 
285 	return (mWidget *)p;
286 }
287 
288 /** カレントレイヤの値をセット */
289 
DockLayer_parameter_setValue(mWidget * wg)290 void DockLayer_parameter_setValue(mWidget *wg)
291 {
292 	_paramct *p = (_paramct *)wg;
293 	LayerItem *pi = APP_DRAW->curlayer;
294 	mBool bNormal;
295 
296 	//初期作成時は除く
297 	if(!pi) return;
298 
299 	bNormal = LAYERITEM_IS_IMAGE(pi);
300 
301 	//不透明度
302 
303 	ValueBar_setPos(p->bar_opacity, (int)(pi->opacity * 100 / 128.0 + 0.5));
304 
305 	//合成モード
306 
307 	mComboBoxSetSel_index(p->cb_blend, pi->blendmode);
308 	mWidgetEnable(M_WIDGET(p->cb_blend), bNormal);
309 
310 	//Aマスク
311 
312 	p->amask->curno = pi->alphamask;
313 
314 	mWidgetEnable(M_WIDGET(p->amask), bNormal);
315 	mWidgetUpdate(M_WIDGET(p->amask));
316 
317 	//テクスチャ
318 
319 	SelMaterial_setName(p->selmat, pi->texture_path);
320 	mWidgetEnable(M_WIDGET(p->selmat), bNormal);
321 }
322