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