개발 환경 설정
보통 Visual Studio는 개발을 위한 IDE로 사용하므로 확장개발을 위한 SDK를 설치하지는 않습니다. 먼저, Visual Studio Installer를 열어 Extension Development Kit을 설치해주었습니다. 사용하는 버전의 Visual Studio의 Modify 버튼을 눌러 설치된 모듈을 변경할 수 있습니다.
새 솔루션 생성
새 솔루션을 생성하고 언어 설정은 C#, 프로젝트 타입은 Extensions 옵션으로 두고 VSIX Project를 선택해 새 프로젝트를 만듭니다. 정상적으로 개발을 위한 모듈을 설치했다면 메뉴에 노출됩니다. 만약 찾기 어렵다면 Search for Templates 검색바에서 VSIX를 찾아보세요. 그래도 찾을 수 없다면, 설치가 정상적으로 완료되지 않은 상태입니다.
프로젝트를 생성하면 AsyncPackage 클래스가 하나 자동으로 생성됩니다.
저는 VSIXProject1이라는 이름으로 프로젝트를 생성했습니다.
원하는 기능을 구현하기 위해서는 이 프로젝트에 새 아이템을 추가해야합니다.
기능 추가
솔루션 탐색기에서 프로젝트에 새 아이템을 추가합니다. 작업 레이아웃에 솔루션 탐색기가 열려있지 않다면, 상단 메뉴아이템의 View(보기) - Solution Explorer(솔루션 탐색기)를 통해 열 수 있습니다. 프로젝트 이름에 우클릭하면 Add - New Item 메뉴가 있습니다.
좌측 메뉴의 Visual C# Items 템플릿 중에서 Extensibility 카테고리에서 제공하는 아이템들을 사용할 수 있습니다.
예제
공식 문서에 여러가지 확장 기능 구현 방법 튜토리얼이 있습니다. 한국어 번역이 매끄럽지 않아 대략적인 작업 방식과 목표만 확인하고, 영어 원문으로 읽으며 따라하는 것을 권장합니다.
여기서는 공식문서에서 따로 분리되어있지 않는 방법을 이용해 간단한 예제를 구현해봅니다.
Command 템플릿을 OpenExplorerCommand.cs 이름으로 생성했습니다.
클래스의 하단에 메뉴 아이템을 실행했을 때의 구현부가 있습니다. (line:89)
위 코드는 메뉴아이템을 선택하면, 메시지 박스를 띄우는 동작을 합니다.
(아직까지는 꼭 프로젝트를 열어보지 않아도 괜찮습니다.)
개발중이던 확장을 테스트하기 위해서는 F5를 눌러 디버그모드로 진입합니다. 개발중이던 VS가 직접 새로운 비주얼 스튜디오의 인스턴스를 실행한 뒤 컴파일된 확장 프로그램을 링크해줍니다. 잠시 기다리면, 초기화면이 나타납니다.
오른쪽 하단의 Continue without code 메뉴를 누르면 아무런 프로젝트로 로드하지 않은 채 빈 비주얼 스튜디오를 열게 되지만 원하는 기능의 테스트는 진행이 가능합니다. 상단 메뉴 아이템들 중 Tools를 확인하면 Invoke OpenExplorerCommand라는 보통의 VS에서는 볼 수 없는 메뉴가 존재합니다.
선택해보시면 알림창이 열립니다. 나타난 텍스트로 보아 조금 전에 생성했던 Command 클래스에서 호출된 코드가 메시지 대화상자를 생성한 것으로 짐작해 볼 수 있습니다.
동작을 확인했으므로 새로 열려있는 인스턴스를 종료하겠습니다. X 버튼을 눌러 직접 종료하거나, 확장 개발을 진행하던 에디터에서 Shift + F5를 눌러 디버깅을 종료시키면 자동으로 인스턴스가 꺼집니다.
이제 원하는 동작을 구현해보겠습니다.
구현 목표
현재 열려있는 문서를 확인하고, 실제 존재하는 위치를 윈도우 탐색기로 여는 동작
메뉴 아이템의 이름 지정
메뉴 아이템에 노출될 버튼의 이름을 변경해보겠습니다. 솔루션 탐색기에서 현재 프로젝트에 속하는 파일들 중에 .vsct 확장자를 가진 파일이 있습니다. 이 파일을 수정합니다.
<ButtonText> 태그로 묶인 코드를 찾을 수 있습니다.
59번째줄에 ButtonText 태그로 감싸진 부분의 텍스트가 메뉴 아이템 버튼의 이름으로 나타납니다.
원하는 이름으로 수정하고 저장해줍니다.
의심이 많은 저는 F5를 눌러 인스턴스를 띄워 제대로 수정되었는지 확인작업을 거쳤습니다.
제대로 수정되었을거라는 확신이 있다면 꼭 확인해야하는 과정은 아닙니다.
수정되었음을 확인했습니다.
현재 열린 문서 가져오기
VS에서 제공하는 모듈인 DTE를 이용해서 가져올 수 있습니다.
DTE dte = Package.GetGlobalService(typeof(SDTE)) as DTE;
var document = dte.ActiveDocument;
if (document != null) {
string documentPath = document.FullName;
}
이 코드를 Execute 함수에서 사용하겠습니다.
현재 활성화된 Document를 찾고, 탐색기로 여는 로직을 작성합니다.
아무런 문서도 열려있지 않은 경우에는 메시지 대화상자로 알려줍니다.
이제 F5를 눌러 실행해보면 동작을 확인할 수 있습니다.
작성한 코드는 여기에서 확인하실 수 있습니다.
진행 중인 작업
유니티에서 작업할 때 셰이더 코드를 편집하는 과정에서 #include로 임포트한 외부 파일을 쉽게 열어주는 기능이 없는 불편함이 있습니다. 수정 가능한 렌더링 파이프라인이 외부로 노출되는 과정에서 HLSL로 작성된 코어 셰이더 코드들이 유니티 패키지에 포함되며 코드에 적히는 경로와 실제 파일이 위치한 경로가 달라 발생하는 이슈입니다. 기존 셰이더랩을 위해 구현된 플러그인들은 이를 제대로 체크해주지 못하고 있습니다.
저는 셰이더 작업을 VSCode에서 주로 해왔고 코어 파일들 역시 모두 Packages 폴더로 옮겨놓은 상태로 작업해 큰 불편함을 느끼지 못했습니다. 최근 TAN의 토요정기수다에서 관련 토픽이 언급되어 SRP 개발시 해당 문제가 있음을 인지하게 되었습니다.
그래서 조금 편리하게나마 파일을 열어보고 확인하기 위해 확장 플러그인 개발에 도전했습니다. 이미 VS에 구현되어있는 기능인 Go To Definition(정의로 이동) 메뉴와 단축키를 이용하고 싶었으나, 아직 SDK에 익숙하지 않아 눈에 쉽게 보이는 다른 방법으로 구현했습니다. '노란 전구'로 알려져 있는 Suggested Action을 이용해 기능을 구현했고, .shader, .hlsl, .glsl, .cginc 확장자를 지원하도록 지정했습니다.
Resharper가 HLSL 확장을 부분적으로 지원하고 있어 HLSL 파일을 여는 제안이 노출되지 않는 문제가 있습니다. 이 확장을 사용하기 위해서는 Resharper에서 HLSL 관련 기능을 꺼야 정상적으로 동작합니다.
소스코드, 다운로드 : https://github.com/seonghwan-dev/OpenInclude
참고사이트
'ETC' 카테고리의 다른 글
ASP.NET Core: 1. CORS 문제 해결 (0) | 2021.06.27 |
---|