블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2811)
Unity3D (867)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (234)
협업 (61)
3DS Max (3)
Game (12)
Utility (140)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

이펙트 작업을 위해서... 이런것들이 필요 합니다.^^

 

회사를 옮길때 마다 부탁을 해야 하는 겨우가 생기더군요.^^

그렇게 중요한 내용은 아니지만 작업 할때 가끔 필요하다라고 생각이 드는 경우가 있어서...

나중에 프로그래머님들게 부탁 좀 할려고 정리좀 해봅니다.^^

 

간혹 지원을 하지 않는 엔진이 있어서...^^ 

 

 

------------------ Tip ------------------

오른손 좌표계: OpenGL 사용.

 

왼손 좌표계: Direct 3D 사용.

 

[축:axis]

-월드 축: 항상 고정이 되어 있는 축. 변화지 않는 축 입니다.

             (지구의 남과 북이 변화지 않는것 처럼, X, Y, Z,절대 절대 변화지 않는 축)

 

-로컬 축: 움직임에 따라, 축이 바라 보는 방향이 변화는 축

             ( 오브젝트 생성시 가지고 있던 축. 움직임에 따라 항상  축은 유지하되, 바라 보는 방향은

                변한다.)

-----------------------------------------

 

[ 이펙트 작업에 필요한 기능 ]

 

1) 캐릭터에 이펙트 작업시 링크 기능 지원.

-아래 이미지 처럼 각각의 Biped와 Bone, Dummy, 특정네임(프로그래머가 설정해준 네임), 등등... 이펙트가 필요로 하는 모든 네임에 링크가 가능 해야 한다.

 

-빨강점은 이펙트와 링크가 되면 위치하는 지점.

 

-캐릭터의 이펙트 작업시.

 *Biped와 Bone, Dummy, center, 특정네임에 로컬 축, 월드 축을 지원.

 *Biped와 Bone, Dummy, center, 특정네임에 링크 방식과 비 링크 방식 지원.

  (비 링크 방식일때는 워치또는 회전 값만을 사용 할뿐 Biped와 Bone, Dummy, center

   특정네임에 움직임에 반응 하지 않는다.)

*버프 계열 이펙트 작업시 머리에 생성 되는 이펙트 지원.

 (머리에서의 일정 높이를 항상 유지 하며, 캐릭터의 이동시 같이 움직인다. 단 캐릭터의 회전

  값을 인식 해서는 안된다.)

 

 

2) 메쉬 오브젝트가 지원.

-맥스에서 작업한 메쉬 오브젝트의 move, rotate, scale, UVmap 애님, opasity 등을 지원 해야 한다.

 

-씨퀀스 및 16분할 맵 소스 지원.

 

-2-sided 지원.

 

 

 3) 다양한 쉐이더 모드 / 레이어 모드 지원.

-add, multiply, alpha인식, overlay, colorkey.. 등등 다양한 레이어 모드 지원.

(포토샾의 레이어 기능을 참고)

 

-맥스에서의 기본적인 meterrial 과 글로우 효과, 고스트 효과, 카멜레온 효과, 굴절 효과 같은 특수한 쉐이더 효과들이 지원 되야 한다.

(아래 이미지는 쉐이더 효과를 합성툴에서 만들어 본 이미지)

 

4) 기본 빌보드 지원

-기본 적으로 이펙트 툴에 파티클, 빌보드 방식이 포함 되어 있지만, 모든 엔진이 그런 것이 아님으로 필요시 프로그래머에게 요청을 해야 한다.

 

-빌보드는 (단독1~5정도)으로 사용 할때는 메쉬와 비슷 하지만, 여러개(10개 이상)를 사용 하며, 파티클과 비슷한 개념으로 생각 해야 한다.

(파티클 하나 하나를 보면 빌보드와 비슷 하다고 보면 된다. 간다하게 맥스에서 파티클에 맵을 한번 해보면 알수 있다.)

 

-기본 빌보드는 맥스 Plane[정 사각형 판]이라고 보시면 되고, 기본 빌보드는 항상 카메라만을 주시 하면서 정면만을 보여준다.

 

-기본 빌보드의 갯수 증가 기능 및 위치 랜덤 생성 기능.

(파티클의 기능에 누가 되지 않는 만큰의 갯수 약 5~8개 정도이며, 생성시에는

  위치가 랜덤하게 발생 해야 한다.)

 

-2-sided 지원.

 

-빌보드 종류.

 *기본적인 빌보드.(항상 카메라만 본다)

 *방향을 바꿀수 있는 빌보드.(원하는 방향을 설정 할수 있다.)

 *박스 형태의 빌보드.(위/아래는 면이 없다.)

 *원통형의 빌보드.(위/아래는 면이 없으며, 면을 수를 조절이 가능 해야 한다.)

 *한쪽 축이 고정된 빌보드이며, 카메라만 항상 바라 본다.

  ( 기본 빌보드에 1개의 축을 고정 해준다.)

 *기타... 엔진에서 지원되는 빌보드.

 

-빌보드 지원 기능

 *move, rotate, scale, opasity 기능 지원.

 *씨퀀스 및 16분할 맵 소스 지원.

 *loop 기능 지원

 *Biped와 Bone, Dummy, center, 특정네임에 로컬 축, 월드 축을 지원.

 *Biped와 Bone, Dummy, center, 특정네임에 링크 방식과 비 링크 방식 지원.

  (비 링크 방식일때는 워치또는 회전 값만을 사용 할뿐 Biped와 Bone, Dummy, center

   특정네임에 움직임에 반응 하지 않는다.)

 

5) 트레일 효과 지원.

 -검의 잔상 기능.

  (맥스에서고스트 트레일 효과와 비슷 기능.)

 

-잔상의 왜곡 효과.

 (굴절 현상)

 

5) 파티클 툴의 부수적인 기능 지원.

-기본적으로 particleIllusion정도의 툴.

 

- Biped와 Bone, Dummy, center, 특정네임에 로컬 축, 월드 축을 지원.

 

-Biped와 Bone, Dummy, center, 특정네임에 링크 방식과 비 링크 방식 지원.

  (비 링크 방식일때는 워치또는 회전 값만을 사용 할뿐 Biped와 Bone, Dummy, center

   특정네임에 움직임에 반응 하지 않는다.)

 

-파티클을 모으는 방식 지원.

 (보통은 퍼지는 기능은 되지만, 기를 모을때 사용할수 있는 기능은 지원 안 하는 경우가 많다.)

 

-링크된 파티클과 파티클 사이에 보간 기능 지원.

 (Bip01 R Thigh와 Bip01 R Calf 사이에 파티클 링크시, 링크된 위치에서만 파티클이 발생 하기

  때문에, 링크된 사이에는 파티클이 발생 할수 있게 해준다.)

 

-파티클의 트레일 발생 지원.

 (귀무자의 기를 빨라 드리는 효과를 참고 하면 된다.)

 

-파티클 타이밍 조절 지원.

(1프레임에 100개의 파티클을 전부 불출 또는 10프레임 있다가 100프레임을 전주 분출 등등..)

 

-파티클 발생 방식.

 *움직임에 영향을 받지 않는 방식.

   (별이 반짝이는 것처럼, 처음 생성 위치에서 발생 하면 아무런 영향을 받지 않으며, 파티클의

    꼬리가 생기지 않는다.)

 *움직임에 영향을 받는 방식

   (대표적으로 파티클의 꼬리가 발생 한다.)

 

6) 데칼 기능 지원.

-마법진과 또는 바닥 이펙트 처리에 사용 되는 방식.

(바닥의 왜곡면과 상관 없이, 발생 하는 기능. 간혹 왜곡이 아주 심한 경우에는

 이펙트 모양이 늘러지게 보이는 경우가 있다.)

 

==========================================================================================

아래의내용들은 이펙트 작업시 필요 하다라고 느끼거나, 있어으면 하는 것들을 적어 본 것입니다.

 그렇다고, 꼭! 이 기능이 이었야 작업을 잘 할수 있는 것은 더더욱 아닙니다.

부족함에 약간의 도움을 주기 위해서 라는것을 알아 주시길....^^

==========================================================================================

반응형

'Gamebryo > Effect' 카테고리의 다른 글

강의자료 - 파티클 예제  (0) 2011.03.22
Setup about Effect Dumy…  (0) 2011.03.21
파티클 컨트롤 해보기  (0) 2011.02.24
이펙트 출력  (0) 2011.02.08
검광, 검기 잔상 효과에 대하여...  (1) 2011.01.21
Posted by blueasa
, |

Delta3D API Documentation

Link / 2011. 1. 25. 01:49
반응형
Posted by blueasa
, |
반응형

'Utility > Doxygen' 카테고리의 다른 글

[삽질] KingsTools 함수등 정보가 안보일 때..  (0) 2012.06.12
자주쓰는 DoxyGen 주석  (0) 2011.06.17
Posted by blueasa
, |

Gamebryo 관련 사이트

Link / 2011. 1. 21. 01:32

출처: http://stnzone.com/gboard/blog/?id=1003 -> 자존심님의 블로그

 

 

 

http://www.gamebryo101.com/

 

호오... 상당히 폐쇄적인 겜브리오 국내 커뮤니티에 비하면 여기 어떤 곳일지??

 

일단 링크!!!



출처 : http://jedikim72.blog.me/10038718610

반응형
Posted by blueasa
, |
반응형
Posted by blueasa
, |

게임코디에서 글을 읽다가 검기 이펙트 구현에 대한 글을 보았다.

지피지에서 검광으로 검색해서 찾은 쓰레드에서 얻은 정보들~!

 

 

지피지의 관련 쓰레드

http://www.gpgstudy.com/forum/viewtopic.php?t=18848&highlight=%B0%CB%B1%A4

 

 

D3DXVec3CatmullRom 함수를 이용해 Catmull-Rom Splines를 소개하는 사이트

http://www.mvps.org/directx/articles/catmull/#demo

 

 

Catumull-Rom 스플라인을 이용한 Path 보간 데모

http://www.mvps.org/directx/articles/catmull/lightmap.zip

 

 

 

 

 

그나저나,

감버려에서도 검기, 검광 잔상을 보여주는 샘플이 있긴하다.

Eturnum 이란 풀데모를 보면 NPC가 들고 다니는 창의 날에 검기 잔상이 알흠답게 남는다.

나중에 필요할 때 자세히 봐둬야할듯~

 

대충 훑어보니 동적인 TriShape를 검기의 보간된 궤적에 맞춰 생성하고 아래 Swoosh 텍스쳐를 바르는 것 같다.

 

요건 검기가 보이는 순간의 스샷



[출처] 검광, 검기 잔상 효과에 대하여...|작성자 엉클 제다이


출처 :


ㅇㄹㅇㄹ

반응형

'Gamebryo > Effect' 카테고리의 다른 글

강의자료 - 파티클 예제  (0) 2011.03.22
Setup about Effect Dumy…  (0) 2011.03.21
파티클 컨트롤 해보기  (0) 2011.02.24
이펙트 출력  (0) 2011.02.08
이펙트 작업에 필요한 기능  (0) 2011.01.27
Posted by blueasa
, |
        다음 메쏘드를 이용하여 알아내면 됩니다.
       
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
       

        사용법은 아래 소스코드를 보시고 이해 하시면 될것 같네요..

       
        동시 키 눌림
은 아래와같이 OR (|) 연산자를 이용하시면 되는데..
        간혹 Ctrl + C, Ctrl + V, Ctrl + X 등이 캐치 되지 않는 경우가 있습니다.

        그럴경우는 툴박스나, 메뉴바, 컨텍스트메뉴 (마우스 오른쪽메뉴) 에서 해당 숏컷이 등록되어 있는지 확인하시고,
        등록이 되어 있다면, 해당 숏컷에 이벤트를 등록 해 주시면 됩니다.


        메소드를 보시면 제일 마지막에 
       
        return base.ProcessCmdKey(ref msg, keyData);
       

        이런 부분이 있습니다.

        저 부분이 다음 이벤트로 이벤트를 넘겨주는 역할을 하게 되는것이죠..

        즉 ProcessCmdKey 가 받은 이벤트를 오버라이딩하여 우리가 원하는 코드를 넣었으니,
        다시 원래 가야할 길로 보내주는겁니다.

        KeyDown 이나.. 그 전에 어떤 이벤트 핸들러가 있다면 그쪽으로 넘어가겠죠..;;;
        정확한 내용은 찾는데로 업뎃하겠습니다..


        예제 소스를 보시면 쉽게 이해가 되시리라 믿습니다.



        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Down:
                case Keys.Up:
                case Keys.Right:
                case Keys.Left:
                case Keys.Control | Keys.Down:
                case Keys.Control | Keys.Up:
                case Keys.Control | Keys.Right:
                case Keys.Control | Keys.Left:
                    // 방향키, 혹은 컨트롤키 + 방향키가 입력되었을때
                    // 처리, 혹은 다른 메쏘드 호출을 여기에 적어주시면 됩니다.
                    break;

                case Keys.Control | Keys.X:
                    // 잘라내기 (Ctrl + X)
                    // 처리, 혹은 다른 메쏘드 호출을 여기에 적어주시면 됩니다.
                    break;

                case Keys.Control | Keys.C:
                    // 복사하기 (Ctrl + C)
                    // 처리, 혹은 다른 메쏘드 호출을 여기에 적어주시면 됩니다.
                    break;

                case Keys.Control | Keys.V:
                    // 붙여넣기 (Ctrl + V)
                    // 처리, 혹은 다른 메쏘드 호출을 여기에 적어주시면 됩니다.
                    break;

                default:
                    break;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }


반응형

'Programming > C#' 카테고리의 다른 글

DataGridView to XML  (0) 2011.03.23
ToolTip 사용하기  (0) 2011.02.11
[펌] 외부 응용프로그램 실행하기 (Process.Start 메서드) - CMD  (0) 2011.01.13
sendmessage in C#  (1) 2010.12.27
C# SendMessage Keypress  (1) 2010.12.26
Posted by blueasa
, |

#define 과 얼핏 비슷해 보이지만비슷한 유형별의 데이터를 표현하기 위해 반드시 필요한 C++의 필수 타입인 enum 의 몇 가지 재미있고 유용한 팁을 소개합니다.

 

1. namespace 와 결합하기

 

일반적으로 enum 을 이용하여 타입이름을 짓기란 쉬운 일이 아닙니다.

만약 리스트에 필요한 정렬 기준을 enum 으로 표현한다면 아래 정도가 됩니다.

 

enum SORT_LIST

{

           SORT_DATE,                 // 날짜순

           SORT_NAME,                // 이름

           SORT_CONTENT, // 내용

           S0RT_ETC,                    // 기타

};        

 

bool SortSomeData(SORT_LIST SortList)

{

           switch (SortList)

           {

           case SORT_DATE:

                     break;

           case S0RT_NAME:

                     break;

           // ....

           }

}

 

 

하지만이러한 enum 표현 방식은

  •  SORT_DATE 라는 이름은 너무 흔합니다.  프로그램이 조금만 커져도 이러한 이름들이 다른 곳에서도 필요하게 되어 이름 충돌을 피하기 힘들어 집니다.  이름 충돌을 피하기 위해서는 SORT_LIST를 변경해도 아무런 소용이 없고 SORT_DATE 를 완전히 다른 이름으로 지어야만 합니다.
  • enum 의 타입이름인 SORT_LIST와 실제 값인 SORT_DATE 를 서로 연관 짓기가 힘듭니다. switch 문 내에서도 타입이름(SORT_LIST)은 사용되지 않아서 SORT_DATE만 보고 이 값이 SORT_LIST 의 한 유형인지 구분 짓기 힘듭니다
  • enum 값에 항상 들어 있는 SORT 라는 prefix 도 부담스럽습니다. SORT_XXX 식으로 이름을 짓다 보니타입핑하기도 힘들구요

 

평소 이런 문제에 대해서 알고는 있었지만 그 해결책을 고민만 하던 차에 아주 좋은 해결책을 발견했습니다바로 아래 글에서요. (늘 해결책은 제가 아닌 책이나 다른 글에서 구합니다.)

 

Stupid C++ Tricks #2: Better Enums

 

이 글에서 제안하는 방식은 enum  namespace과 결합하여 가독성을 증가 시키고이름충돌도 최소화시키는 방식입니다. 위에 든 예를 namespace 식으로 표현하면 다음과 같습니다.

 

namespace SortList

{

           enum Enum

           {

                     BytDate, // 다가올날기준

                     ByName,                     // 이름

                     ByContent,        // 내용

                     Etc,

           };        

}

 

bool SortSomeData(SortList::Enum SortList)

{

           switch (SortList)

           {

           case SortList::ByDate:

                     break;

           case SortList::ByName:

                     break;

           // ....

           }

}

 

namespace 와 결합함으로써, enum 의 각 항목에는 항상 SortList 라는 namespace가 따라 붙게 되어 가독성이 증가함을 알 수 있습니다SORT_DATE  보다는 SortList::ByDate 가 읽기 쉽고요즘 웬만한 IDE 에서는 namespace SortList::만 입력하면 자동으로 이하 소속되는 타입이름들이 나열되기 때문에 미스타이핑 할 가능성도 줄여주네요.


사용자 삽입 이미지


게다가 namespace 를 사용하기 때문에 다른 모듈과 이름이 충돌할 가능성도 줄어들었습니다.

이름 충돌이 없기 때문에 아래와 같이 NameEdit 라는 enum 값을 여러 namespace 에 걸쳐 사용하면서 각각의 의미에 맞는 값들을 줄 수가 있게 됩니다.

 

namespace ControlWidth

{

           enum Enum

           {

                     NameEdit = 20,

                     AddressCombo = 60,

                     OkBtn = 30;

                     // ....

           };

};

 

namespace ControlID

{

           enum Enum

           {

                     NameEdit = 100,

                     AddressCombo = 101,

                     OkBtn = 102;

                     // ....

           };

}

 

이와 같이 enum 을 표시하는 방식은 실제 꽤 유용하게 써 먹을 수 있어서 지금 새로 만들고 있는 프로젝트에서도 재작성하는 코드에서 enum 타입을 위 방식으로 변경하고 있는 중입니다.

괜찮은 방법 아닌가요 ? ^^;

 

 

2.  enum 에 문자열 결합하기


2번째 팁은 숫자로만 되어 있는 enum 을 문자열로 치환하는 팁입니다.

C++ 에서 enum 을 정수형으로만 치환가능하기 때문에 사용자가 읽을 수 있는 텍스트로 변경하기 위해서는 enum 값에 1:1 매칭되는 텍스트가 필요한 경우가 많습니다.

이를 해결하는 방법으로 아래 포스팅에서는 enum  #define 매크로를 이용해서 문자열을 매칭시키는 방법을 소개합니다.

 

Enums, Macros, Unicode and Token-Pasting

 

Visual C++ Team Blog 에 소개된 이 방법은 숫자로이뤄진 enum 값과

 

enum Animal { dog, cat, fish, bird };

 

문자로이뤄진char값을매칭시키는방안에대한내용입니다.

 

wchar_t* AnimalDiscription[] = { L"dog", L"cat", L"fish", L"bird" };

 

이를 위해 animal.inc 파일에 아래 라인들을 추가하고

 

MYENUM(dog)

MYENUM(cat)

MYENUM(fish)

MYENUM(bird)

 

아래와 같이 enum 을 선언합니다.

 

enum Animal {

#define MYENUM(e) _##e,

#include "animal.inc"

#undef MYENUM

};

 

wchar_t* AnimalDescription[] = {

#define MYENUM(e) L"_" L#e,

#include "animal.inc"

#undef MYENUM

};

 

#define 으로 조금 복잡해 보여서 그렇지, enum 값과 wchar_t* 배열의 선언을 MYENUM 매크로 정의를 통해 확장하는 식입니다.  조금 특이한 것은 MYENUM  enum  wchar_t* 배열 속에서 조금씩 다르게 선언하고데이터를 추가한 후( #include "animal.inc") 에는 바로 undefined 시켜버리는 정도네요

 

이 방법 마음에 드시나요?

해당 링크에 달린 댓글들을 보면 많은 분들이 마음에 들지 않나 봅니다.

가장 크게 문제 삼은 내용은 역시 아래 글과 같은 #define 매크로에 대한 조금 헤묵은 논쟁들입니다.

 

Macros is something C++ (especially the Standards Committee) has always tried to avoid. Such use of macros like this will make code unreadable and cause maintainance problems. I think it's not a good idea to play with such thing.

 

개인적으로는 #define 을 활용한 매크로 활용을 좋게 보고 있습니다.

제가 #define을 좋아하는 이유는

  • 코딩량을 줄여 줍니다코딩하는 량이 줄어든다는 것은 그만큼 유지관리할 코드가 줄어 들고미스타이핑에 의한 작은 실수들을 걸러주기 때문입니다.
  • 자주 해야 하지만 귀찮은 작업들 - Get/Set 함수 같은 - 을 쉽게 처리해 줍니다저 같은 경우 클래스 하나를 만들면 대부분은 private 멤버변수들이어서 늘 public 으로 Get/Set 함수를 구현하는 게 고역 중에 고역인데요.  #define 매크로를 활용하면 늘 심플하고 코드 보기도 편하더군요.


Visual C++ 에 있는 _countof 매크로도 정말 없어서는 안될 매크로 중 하나입니다.

 

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

}

 

아무튼논란의 여지가 있긴 하지만이 팁의 주요 목적은 enum Type 으로 추가할 숫자값과문자열 값이 어느 하나만 추가되거나삭제되지 않고 늘 한번에 관리 될 수 있도록 하기 위한 방안 중에 하나라고 봅니다.  유용했다면 쓰면 될 것이고 그렇지 않으면 안 쓰면 되겠죠 :-)

댓글 중에는 하나의 .inc  include 할 필요 없이 하나의 파일에서 모두 해결하는 방안도 있으니 참고하세요

 

#define ANIMALS(FOO) \

FOO(dog) \

FOO(fish) \

FOO(cat)

 

#define DO_DESCRIPTION(e)  L"_" L#e,

#define DO_ENUM(e)  _##e,

 

wchar_t* AnimalDescription[] = {

ANIMALS(DO_DESCRIPTION)

};

 

enum Animal {

ANIMALS(DO_ENUM)

};

 

 

3.  enum 의 처음과 끝을 지정하자

 

1, 2번에 비하면 좀 약한 팁입니다만, enum 을 사용할 때 처음과 끝을 지정하자는 아이디어는 Code Complete 2 책에 p436에 나와있습니다.

아래와 같은 국가명을 열거할 필요가 있을 때처음과 끝에 해당하는 값을 XXX_FIRST 와 XXX_LAST로 지정하는 방법입니다.

 

enum Country

{

           Country_First = 0,

           Country_China = 0,

           Country_England = 1,

           Country_France = 2,

           Country_Germany = 3,

           Country_India = 4,

           Country_Korea = 5,

           Country_Japan = 6,

           Country_Usa = 7,

           Country_Last = 7,

};

 

XXX_FIRST 와 XXX_LAST 가 시작과 끝을 가르키기 때문에 이를 활용하여 열거형의 모든 항목을 조회하여 원하는 일을 할 때 유용합니다.

 

for (Country cty = Country_First; cty <= Country_Last; cty++)

{

           // 원하는로직수행

}

 

추후 새로운 국가 Country_Italy 를 추가한다면 아래와 같이 enum 만 수정하면 enum 을 사용하는 for loop 는 손대지 않아도 되는 장점이 생깁니다.

 

           Country_Usa = 7,

           Country_Italy = 8,

           Country_Last = 8,

}

 

이상 enum 을 활용하는 몇 가지 팁을 알아 봤습니다 혹시 나만의 좋은 팁이 있으시면 같이 공유해 주세요.


출처 : http://eslife.tistory.com/300

반응형
Posted by blueasa
, |

C++ 을 배운지 꽤 오래 되었지만, 아직도 코드 리뷰를 통해 다른 개발자들의 코드를 볼 때면 한숨이 나오는 경우가 많습니다.

이런 경우가 반복되다 보니, 예전에 몇 가지 코딩 규칙 비슷하게 만들어놓은 자료가 있어 포스팅해 봅니다.  자료가 만들다 말아 내용이 중구난방이네요..  앞으로도 계속 내용 보강해 나가겠습니다.

 

    포인트 핸들 및 윈도우 핸들 체크

-       함수로 전달된 포인터 인자나, new 로 생성한 포인터 등 모든 포인터는 사용하기 직전 포인터 검사를 수행

-       가급적 STL 컨테이너를 사용해서 아예 포인터를 사용하지 않는 것이 정신건강에 이롭다. (STL 자체적으로 메모리 생성 및 소멸)

-       메모리 LEAK 을 막기 위해 SMART POINT 와 같은 Wrapper 클래스를 만든다.

-       (윈도우 프로그램의 경우)윈도우 API 호출 직전 항상 윈도우 핸들이 정상인지 IsWindow 와 같은 함수로 검사한다.

 

    DRY(Don't Repeat Your Code)원칙

-       같은 코드를 여기 저기 중복해서 사용하지 말아야 한다. (☞ 실용주의 프로그래머 참고). 중복해서 사용할 경우 코드 량이 늘어날 뿐만 아니라 유지보수 cost 가 같이 늘어 나고, 추후 추가/개선/변경 등의 요구사항으로 인한 모듈 수정 시 여러 소스를 함께 수정해야 한다.

-       동일한 코드를 공용 루틴(함수)으로 개발 – 2~3줄 짜리 복잡한 if 문도 bool 를 리턴 하는 함수로 개발(Refactoring 참고)

 

    클래스간 종속성 최소화

-       대규모 프로젝트에서는 공통모듈이 변경되어도 이를 사용하는 모듈이 문제가 없도록 반드시 공통모듈은 인터페이스 기반(데이터가 없는, virtual 가상함수로만 구성된)으로 구현한다. (The C++ Programming Language 참고)

-       A 클래스 → B 클래스 → C 클래스를 사용할 경우 각 클래스는 자기가 직접 다루는 클래스(A B, B C) 만 알아야 한다. A 클래스는 C 클래스를 직/간접적으로 include 해서는 안되며 C 클래스의 변경으로 인해 A 클래스가 컴파일 되어서는 안 된다. A 클래스가 C 를 직접 접근할 경우가 있다면 B 클래스에 위임함수를 만들어 해결한다. (☞ 실용주의 프로그래머 참고)

-       B 클래스가 A 클래스로 어떤 데이터를 전달할 경우가 있다면(주로 이벤트 발생시 값을 전달하기 위해) A 클래스의 최소 인터페이스만을 B 클래스에 전달하여(COM 의 이벤트 소스 방식) 종속성을 최소화 한다. (Developer’s Workshop To COM and  ATL 3.0 참고)

 

    함수 인자 전달

-       함수의 인자는 최대 7개를 넘지 않아야 한다(Code Complete 2 참고)

-       클래스 인스턴스를 함수 인자로 넘겨서는 안 된다(특히 함수 인자로 CString 을 넘기는 경우가 많음. CString → const CString& CString*, const char* 등으로 수정한다. )

 

    오류조건을 먼저 검사하여 오류 체크로 인해 코드 가독성이 떨어지지 않도록 하자.

-       특정 오류조건이 발생하면 더 이상 함수 수행에 의미 없을 경우, 이러한 오류 조건들은 함수초입단계부터 먼저 확인해서 바로 리턴 한다

-       위와 같이 오류조건이 먼저 확인되면 프로그램 코드에서 if depth 가 줄어 들고 코드 읽기가 수월해 지는 장점이 있다.

Before

After

void CClass::OnTest()

{

 ...

 ...

 if (m_pWndMain)

 { 

  DoSomething1();

 }

 ...

 if (m_pWndMain)

 { 

  DoSomething2();

 }

 

}

void CClass::OnTest()

{

 if (m_pWndMain == NULL)

  return;

 ...

 ...

 DoSomething1();

 ...

 DoSomething2();

 

}

 

    긴 함수 쪼개기 (Refactoring 참고)

-       긴 함수는 작은 여러 개의 함수로 쪼갠다(Refactoring 책에 의하면 2-3줄 짜리 함수로까지 쪼개어서 코드 가독성을 높이도록 하고 있음)

-       작은 함수로 쪼개다 보면, 작은 함수를 재활용하게 될 수 있고

-       긴 함수보다 코드 읽기가 수월해 지며

-       결국 유지보수가 쉬워진다

 

    enum 값 선언 시 _START, _END 를 활용하자( CODE COMPLETE2 참고)

-       enum 으로 선언된 값들을 변수나 for loop 를 이용하여 반복 계산할 경우가 종종 있는데 이 경우 enum 시작과, 끝을 나타내는 값을 enum 선언에 포함하면 유용하게 사용할 수 있다.

-       추후 enum 에 값을 추가해야 할 경우 _END 값을 사용한 배열은 코드 변경없이 크기가 늘어남

-       For 루프 등에 _START, _END 을 사용할 수 있어 유지 보수에 유리

Before

After

enum WEEK_NAME

{

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

};

 

int nWeeks[SATERDAY + 1];

}

enum WEEK_NAME

{

           WEEK_STAR       = 0,

           SUNDAY                     = 0,

           MONDAY                    = 1,

           TUESDAY                    = 2,

           WEDNESDAY     = 3,

           THURSDAY       = 4,

           FRIDAY            = 5,

           SATERDAY        = 6,

           WEEK_END        = 6,

};

 

int nWeeks[WEEK_END + 1];

 

 

    복잡한 제어문을 가진 루틴을 피하자  

-       If 문은 2 depth 이상 들어 갈 경우 refactoring 하라 (CODE COMPLETE2)

     대부분 코드를 제대로 이해하지 못해 복잡한 코드를 작성하고 있다.

     개발자 90% 2 depth 이상 들어가는 if 문장을 이해하지 못한다

-       IF~ELSE IF ~ELSE IF ~ …. ELSE 가 길게 이어질 경우 SWITCH 문으로 바꾼다

-       IF 문이 길게 늘어 질 경우 함수로 분리한다

-       C++ factory 개념으로 상속을 이용한 클래스를 만드는 방법도 활용


반응형
Posted by blueasa
, |

윈도우를 종료
System.Diagnostics.Process.Start("cmd.exe","ShutDown.exe -s -f -t 00");


윈도우를 재부팅

System.Diagnostics.Process.Start("cmd.exe","ShutDown.exe -r -f -t 00");

 

특정 폴더 열기
System.Diagnostics.Process.Start("explorer.exe", "C:\Temp");

특정 사이트 열기
System.Diagnostics.Process.Start("explorer.exe", "http://www.naver.com");

 

도스명령어 실행

System.Diagnostics.Process.Start("cmd.exe","/c dir");

// cmd 옵션에 대해 더 알고싶으면.. c:>help cmd

 

Process.Start 메서드 사용형식
 

using System.Diagnostics;

//System.Diagnostics 네임스페이스는 시스템 프로세스, 이벤트 로그 및 성능 카운터와 상호 작용할 수 있는 클래스를 제공합니다.

 

public bool Start();
//이 Process 구성 요소의 StartInfo 속성으로 지정된 프로세스 리소스를 시작하거나 다시 사용하여 구성 요소에 연결합니다.

 

Process myProcess = new Process();
string myDocumentsPath =   Environment.GetFolderPath(Environment.SpecialFolder.Personal);
myProcess.StartInfo.FileName = myDocumentsPath + "
\MyFile.doc"; 
myProcess.StartInfo.Verb = "Print";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();

 

public static Process Start( ProcessStartInfo startInfo);
// ProcessStartInfo : 파일 이름 및 모든 명령줄 인수를 포함하여 프로세스를 시작하는 데 사용되는 정보
// 시작할 프로세스의 파일 이름 같은 프로세스 시작 정보가 포함된 매개 변수에 의해 지정된 
// 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다

 

ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
startInfo.Arguments = "
www.naver.com";
Process.Start(startInfo);

 

public static Process Start(string fileName);
// fileName : 프로세스에서 실행될 응용 프로그램 파일 이름입니다.

//문서 또는 응용 프로그램 파일 이름을 지정하여 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다

 

Process.Start("IExplore.exe");

 

public static Process Start(string fileName, string arguments); 
// arguments : 프로세스를 시작할 때 전달할 명령줄 인수입니다

//응용 프로그램 이름 및 명령줄 인수 집합을 지정하여 프로세스 리소스를 시작하고 해당 리소스를 새 Process 구성 요소에 연결합니다.

 

Process.Start("IExplore.exe", "C:\myPath\myFile.htm");
Process.Start("IExplore.exe", "C:\myPath\myFile.asp");

 

 

Process 클래스

Process 구성 요소는 컴퓨터에서 실행 중인 프로세스에 대한 액세스를 제공합니다. 간단히 말해 프로세스란 실행 중인 응용 프로그램을 말합니다.

 

Process 구성 요소는 응용 프로그램의 시작, 중지, 제어 및 모니터링을 위한 유용한 도구입니다.
Process 구성 요소를 사용하면 실행 중인 프로세스의 목록을 얻거나 새로운 프로세스를 시작할 수 있습니다. 또한 Process 구성 요소를 사용하여 시스템 프로세스에도 액세스할 수 있습니다. 
Process 구성 요소를 초기화한 후에는 해당 구성 요소를 사용하여 실행 중인 프로세스에 대한 정보를 얻을 수 있으며 그러한 정보에는 스레드 집합, 로드된 모듈(.dll 및 .exe 파일), 프로세스가 사용하고 있는 메모리 양과 같은 성능 정보 등이 포함됩니다.

 

프로세스 구성 요소는 속성 그룹에 대한 정보를 한 번에 가져옵니다. Process 구성 요소가 특정 그룹의 한 멤버에 대한 정보를 가져올 때 해당 그룹의 나머지 속성 값이 캐싱되므로 Refresh 메서드를 호출하지 않는 한 그룹의 다른 멤버에 대한 새로운 정보를 가져오지 않습니다. 따라서 속성 값이 Refresh 메서드를 마지막으로 호출하여 얻은 속성 값과 같을 수 있습니다. 이러한 그룹 명세는 운영 체제에 따라 다릅니다.

 

더 자세한 사항은 Microsoft Visual Studio .NET 2003 도움말에서 Process 클래스를 참고하세요.

 

 

도스명령수행 프로그램 


 

[전체소스]


using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Diagnostics;

using System.IO;

using System.Threading;


namespace mouseEvents

{


    public class Form1 : System.Windows.Forms.Form

    {

        private System.Windows.Forms.TextBox textBox1;

        private System.Windows.Forms.Label label2;

        private System.ComponentModel.IContainer components;

        private System.Windows.Forms.TextBox tbComm;

        private System.Windows.Forms.Button btnExec;



        public Form1()

        {

            InitializeComponent();

        }


        protected override void Dispose( bool disposing )

        {

            if( disposing )

            {

                if (components != null)

                {

                    components.Dispose();

                }

            }

            base.Dispose( disposing );

        }


        #region Windows Form Designer generated code

        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()

        {

            this.label2 = new System.Windows.Forms.Label();

            this.tbComm = new System.Windows.Forms.TextBox();

            this.btnExec = new System.Windows.Forms.Button();

            this.textBox1 = new System.Windows.Forms.TextBox();

            this.SuspendLayout();

            //

            // label2

            //

            this.label2.Location = new System.Drawing.Point(8, 8);

            this.label2.Name = "label2";

            this.label2.Size = new System.Drawing.Size(72, 17);

            this.label2.TabIndex = 5;

            this.label2.Text = "도스명령어:";

            //

            // tbComm

            //

            this.tbComm.Location = new System.Drawing.Point(80, 8);

            this.tbComm.Name = "tbComm";

            this.tbComm.Size = new System.Drawing.Size(355, 21);

            this.tbComm.TabIndex = 6;

            this.tbComm.Text = "";

            //

            // btnExec

            //

            this.btnExec.Location = new System.Drawing.Point(440, 8);

            this.btnExec.Name = "btnExec";

            this.btnExec.Size = new System.Drawing.Size(104, 25);

            this.btnExec.TabIndex = 1;

            this.btnExec.Text = "실행";

            this.btnExec.Click += new System.EventHandler(this.button2_Click);

            //

            // textBox1

            //

            this.textBox1.AcceptsReturn = true;

            this.textBox1.AcceptsTab = true;

            this.textBox1.Location = new System.Drawing.Point(8, 32);

            this.textBox1.Multiline = true;

            this.textBox1.Name = "textBox1";

            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;

            this.textBox1.Size = new System.Drawing.Size(528, 312);

            this.textBox1.TabIndex = 2;

            this.textBox1.Text = "";

            //

            // Form1

            //

            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

            this.ClientSize = new System.Drawing.Size(547, 350);

            this.Controls.Add(this.tbComm);

            this.Controls.Add(this.label2);

            this.Controls.Add(this.textBox1);

            this.Controls.Add(this.btnExec);

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

            this.MaximizeBox = false;

            this.Name = "Form1";

            this.Text = "Process Class";

            this.ResumeLayout(false);


        }

        #endregion


        [STAThread]

        static void Main()

        {

            Application.Run(new Form1());

        }


        private void button2_Click(object sender, System.EventArgs e)

        {

            this.start();

        }


        private void start()

        {


            //Network 변수

            StreamWriter DosWriter;

            StreamReader DosRedaer;

            StreamReader ErrorReader;

           

            //프로세스 생성및 초기화

            Process DosPr = new Process();

           

            ProcessStartInfo psI = new ProcessStartInfo("cmd");

            psI.UseShellExecute = false;

            psI.RedirectStandardInput = true;

            psI.RedirectStandardOutput = true;

            psI.RedirectStandardError = true;

            psI.CreateNoWindow = true;



            //명령 실행

            DosPr.StartInfo = psI;

            DosPr.Start();

            DosWriter = DosPr.StandardInput;

            DosRedaer = DosPr.StandardOutput;

            ErrorReader = DosPr.StandardError;


            DosWriter.AutoFlush = true;


            DosWriter.WriteLine(tbComm.Text);

           

            DosWriter.Close();


            //출력

            textBox1.Text = DosRedaer.ReadToEnd();

            textBox1.Text += ErrorReader.ReadToEnd();


        }

    }

}



  작성자 : HOONS(박경훈)
  이메일 : tajopkh@hanmail.net

출처 : http://www.cyworld.com/nowy/192742


[출처 : http://skql.tistory.com/510]

반응형
Posted by blueasa
, |