This is my initial checkin for solvespace, a second attempt at
constraint solver drawing. I've started work on the user inteface, which will be based around two windows: one with the graphical sketch, and one command line. I've started to implement the command line, no other work. [git-p4: depot-paths = "//depot/solvespace/": change = 1652]solver
commit
67139236fc
|
@ -0,0 +1,36 @@
|
|||
DEFINES = /D_WIN32_WINNT=0x400 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x500 /DWIN32_LEAN_AND_MEAN /DWIN32
|
||||
CFLAGS = /W3 /nologo -I..\common\win32 /O2 /D_DEBUG /D_CRT_SECURE_NO_WARNINGS /Zi /I.
|
||||
|
||||
HEADERS = ..\common\win32\freeze.h ui.h solvespace.h dsc.h
|
||||
|
||||
OBJDIR = obj
|
||||
|
||||
FREEZE = $(OBJDIR)\freeze.obj
|
||||
|
||||
W32OBJS = $(OBJDIR)\w32main.obj \
|
||||
|
||||
SSOBJS = $(OBJDIR)\solvespace.obj \
|
||||
$(OBJDIR)\cmdline.obj \
|
||||
|
||||
|
||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib
|
||||
|
||||
all: $(OBJDIR)/solvespace.exe
|
||||
@cp $(OBJDIR)/solvespace.exe .
|
||||
solvespace
|
||||
|
||||
clean:
|
||||
rm -f obj/*
|
||||
|
||||
$(OBJDIR)/solvespace.exe: $(SSOBJS) $(W32OBJS) $(FREEZE)
|
||||
@$(CC) $(DEFINES) $(CFLAGS) -Fe$(OBJDIR)/solvespace.exe $(SSOBJS) $(W32OBJS) $(FREEZE) $(LIBS)
|
||||
@echo solvespace.exe
|
||||
|
||||
$(SSOBJS): $(@B).cpp $(HEADERS)
|
||||
@$(CC) $(CFLAGS) $(DEFINES) -c -Fo$(OBJDIR)/$(@B).obj $(@B).cpp
|
||||
|
||||
$(W32OBJS): win32/$(@B).cpp $(HEADERS)
|
||||
@$(CC) $(CFLAGS) $(DEFINES) -c -Fo$(OBJDIR)/$(@B).obj win32/$(@B).cpp
|
||||
|
||||
$(FREEZE): ..\common\win32\$(@B).cpp $(HEADERS)
|
||||
@$(CC) $(CFLAGS) $(DEFINES) -c -Fo$(OBJDIR)/$(@B).obj ..\common\win32\$(@B).cpp
|
|
@ -0,0 +1,85 @@
|
|||
#include "solvespace.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
void TextWindow::Init(void) {
|
||||
int i, j;
|
||||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
for(j = 0; j < MAX_COLS; j++) {
|
||||
text[i][j] = ' ';
|
||||
meta[i][j].color = COLOR_NORMAL;
|
||||
meta[i][j].link = NOT_A_LINK;
|
||||
}
|
||||
}
|
||||
ClearCommand();
|
||||
}
|
||||
|
||||
void TextWindow::Printf(char *fmt, ...) {
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
int r, c;
|
||||
if(rows < MAX_ROWS) {
|
||||
r = rows;
|
||||
rows++;
|
||||
} else {
|
||||
r = row0;
|
||||
row0++;
|
||||
}
|
||||
for(c = 0; c < MAX_COLS; c++) {
|
||||
text[r][c] = ' ';
|
||||
meta[r][c].link = NOT_A_LINK;
|
||||
}
|
||||
|
||||
int color = COLOR_NORMAL;
|
||||
|
||||
c = 0;
|
||||
while(*fmt) {
|
||||
if(*fmt == '%') {
|
||||
} else {
|
||||
if(c >= MAX_COLS) goto done;
|
||||
text[r][c++] = *fmt;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
|
||||
done:
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void TextWindow::ClearCommand(void) {
|
||||
int j;
|
||||
for(j = 0; j < MAX_COLS; j++) {
|
||||
cmd[j] = ' ';
|
||||
}
|
||||
memcpy(cmd, "+> ", 3);
|
||||
cmdLen = 0;
|
||||
cmdInsert = 3;
|
||||
row0 = 0;
|
||||
rows = 0;
|
||||
}
|
||||
|
||||
void TextWindow::KeyPressed(int c) {
|
||||
if(cmdLen >= MAX_COLS - 10) {
|
||||
ClearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
if(c == '\n' || c == '\r') {
|
||||
// process the command, and then
|
||||
ClearCommand();
|
||||
return;
|
||||
} else if(c == 27) {
|
||||
ClearCommand();
|
||||
} else if(c == '\b') {
|
||||
// backspace, delete from insertion point
|
||||
if(cmdInsert <= 3) return;
|
||||
memmove(cmd+cmdInsert-1, cmd+cmdInsert, MAX_COLS-cmdInsert);
|
||||
cmdLen--;
|
||||
cmdInsert--;
|
||||
} else {
|
||||
cmd[cmdInsert] = c;
|
||||
cmdInsert++;
|
||||
cmdLen++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#ifndef __DSC_H
|
||||
#define __DSC_H
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
typedef struct {
|
||||
double x, y, z;
|
||||
} Vector;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
SolveSpace SS;
|
||||
|
||||
void SolveSpace::Init(void) {
|
||||
TW.Init();
|
||||
|
||||
TW.Printf("She walks in beauty");
|
||||
TW.Printf("like the night");
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#ifndef __SOLVESPACE_H
|
||||
#define __SOLVESPACE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dsc.h"
|
||||
#include "ui.h"
|
||||
|
||||
// Debugging functions
|
||||
#define oops() exit(-1)
|
||||
void dbp(char *str, ...);
|
||||
|
||||
typedef struct {
|
||||
TextWindow TW;
|
||||
GraphicsWindow GW;
|
||||
|
||||
void Init(void);
|
||||
} SolveSpace;
|
||||
|
||||
extern SolveSpace SS;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
#ifndef __UI_H
|
||||
#define __UI_H
|
||||
|
||||
typedef struct {
|
||||
static const int MAX_COLS = 200;
|
||||
static const int MAX_ROWS = 500;
|
||||
|
||||
// The line with the user-typed command, that is currently being edited.
|
||||
char cmd[MAX_COLS];
|
||||
int cmdInsert;
|
||||
int cmdLen;
|
||||
|
||||
// The rest of the window, text displayed in response to typed commands;
|
||||
// some of this might do something if you click on it.
|
||||
|
||||
static const int NOT_A_LINK = 0;
|
||||
|
||||
static const int COLOR_NORMAL = 0;
|
||||
|
||||
BYTE text[MAX_ROWS][MAX_COLS];
|
||||
struct {
|
||||
int color;
|
||||
int link;
|
||||
DWORD data;
|
||||
} meta[MAX_ROWS][MAX_COLS];
|
||||
|
||||
int row0, rows;
|
||||
|
||||
void Init(void);
|
||||
void Printf(char *fmt, ...);
|
||||
void ClearScreen(void);
|
||||
|
||||
void ClearCommand(void);
|
||||
|
||||
// These are called by the platform-specific code.
|
||||
void KeyPressed(int c);
|
||||
bool IsHyperlink(int width, int height);
|
||||
} TextWindow;
|
||||
|
||||
typedef struct {
|
||||
// These parameters define the map from 2d screen coordinates to the
|
||||
// coordinates of the 3d sketch points. We will use an axonometric
|
||||
// projection.
|
||||
Vector offset;
|
||||
double scale;
|
||||
Vector projRight;
|
||||
Vector projDown;
|
||||
|
||||
// These are called by the platform-specific code.
|
||||
void Paint(void);
|
||||
void MouseMoved(double x, double y, bool leftDown, bool middleDown,
|
||||
bool rightDown);
|
||||
void MouseLeftClick(double x, double y);
|
||||
void MouseLeftDoubleClick(double x, double y);
|
||||
void MouseScroll(int delta);
|
||||
} GraphicsWindow;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,237 @@
|
|||
#include "solvespace.h"
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TEXT_HEIGHT 18
|
||||
#define TEXT_WIDTH 10
|
||||
|
||||
HINSTANCE Instance;
|
||||
|
||||
HWND TextWnd, GraphicsWnd;
|
||||
HWND TextWndScrollBar;
|
||||
int TextWndScrollPos;
|
||||
|
||||
int ClientIsSmallerBy;
|
||||
|
||||
HFONT FixedFont;
|
||||
|
||||
void dbp(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
char buf[1024];
|
||||
va_start(f, str);
|
||||
vsprintf(buf, str, f);
|
||||
OutputDebugString(buf);
|
||||
OutputDebugString("\n");
|
||||
}
|
||||
|
||||
static void PaintTextWnd(HDC hdc)
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(TextWnd, &rect);
|
||||
FillRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
||||
|
||||
SelectObject(hdc, FixedFont);
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetBkColor(hdc, RGB(0, 0, 0));
|
||||
|
||||
int h = rect.bottom - rect.top;
|
||||
int rows = h / TEXT_HEIGHT;
|
||||
rows--;
|
||||
|
||||
// Let's set up the scroll bar first
|
||||
SCROLLINFO si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cbSize = sizeof(si);
|
||||
si.fMask = SIF_DISABLENOSCROLL | SIF_ALL;
|
||||
si.nMin = 0;
|
||||
si.nMax = SS.TW.rows - 1;
|
||||
si.nPos = TextWndScrollPos;
|
||||
si.nPage = rows;
|
||||
SetScrollInfo(TextWndScrollBar, SB_CTL, &si, TRUE);
|
||||
|
||||
int r, c;
|
||||
for(r = TextWndScrollPos; r < (TextWndScrollPos+rows); r++) {
|
||||
if(r < 0) continue;
|
||||
if(r >= SS.TW.MAX_ROWS) continue;
|
||||
int rr = (r + SS.TW.row0);
|
||||
while(rr >= SS.TW.MAX_ROWS) rr -= SS.TW.MAX_ROWS;
|
||||
|
||||
for(c = 0; c < SS.TW.MAX_COLS; c++) {
|
||||
char v = '0' + (c % 10);
|
||||
TextOut(hdc, 4 + c*TEXT_WIDTH, r*TEXT_HEIGHT,
|
||||
(char *)&(SS.TW.text[rr][c]), 1);
|
||||
}
|
||||
}
|
||||
|
||||
TextOut(hdc, 4, rows*TEXT_HEIGHT, SS.TW.cmd, SS.TW.MAX_COLS);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
PaintTextWnd(hdc);
|
||||
EndPaint(hwnd, &ps);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SIZING: {
|
||||
RECT *r = (RECT *)lParam;
|
||||
int hc = (r->bottom - r->top) - ClientIsSmallerBy;
|
||||
int extra = hc % TEXT_HEIGHT;
|
||||
switch(wParam) {
|
||||
case WMSZ_BOTTOM:
|
||||
case WMSZ_BOTTOMLEFT:
|
||||
case WMSZ_BOTTOMRIGHT:
|
||||
r->bottom -= extra;
|
||||
break;
|
||||
|
||||
case WMSZ_TOP:
|
||||
case WMSZ_TOPLEFT:
|
||||
case WMSZ_TOPRIGHT:
|
||||
r->top += extra;
|
||||
break;
|
||||
}
|
||||
hc = (r->bottom - r->top) - ClientIsSmallerBy;
|
||||
extra = hc % TEXT_HEIGHT;
|
||||
dbp("extra=%d", extra);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CHAR:
|
||||
SS.TW.KeyPressed(wParam);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_SIZE: {
|
||||
RECT r;
|
||||
GetWindowRect(TextWndScrollBar, &r);
|
||||
int sw = r.right - r.left;
|
||||
GetClientRect(hwnd, &r);
|
||||
MoveWindow(TextWndScrollBar, r.right - sw, r.top, sw,
|
||||
(r.bottom - r.top) - TEXT_HEIGHT, TRUE);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void CreateMainWindows(void)
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
|
||||
// The text window, with a comand line and some textual information
|
||||
// about the sketch.
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC |
|
||||
CS_DBLCLKS;
|
||||
wc.lpfnWndProc = (WNDPROC)TextWndProc;
|
||||
wc.hInstance = Instance;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszClassName = "TextWnd";
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hIcon = NULL;
|
||||
wc.hIconSm = NULL;
|
||||
if(!RegisterClassEx(&wc)) oops();
|
||||
|
||||
TextWnd = CreateWindowEx(0, "TextWnd", "SolveSpace (Command Line)",
|
||||
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX,
|
||||
10, 10, 600, 300, NULL, (HMENU)NULL, Instance, NULL);
|
||||
if(!TextWnd) oops();
|
||||
|
||||
TextWndScrollBar = CreateWindowEx(0, WC_SCROLLBAR, "", WS_CHILD |
|
||||
SBS_VERT | SBS_LEFTALIGN | WS_VISIBLE | WS_CLIPSIBLINGS,
|
||||
200, 100, 100, 100, TextWnd, NULL, Instance, NULL);
|
||||
// Force the scrollbar to get resized to the window,
|
||||
TextWndProc(TextWnd, WM_SIZE, 0, 0);
|
||||
|
||||
ShowWindow(TextWnd, SW_SHOW);
|
||||
|
||||
// The graphics window, where the sketch is drawn and shown.
|
||||
wc.lpfnWndProc = (WNDPROC)GraphicsWndProc;
|
||||
wc.hInstance = Instance;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszClassName = "GraphicsWnd";
|
||||
if(!RegisterClassEx(&wc)) oops();
|
||||
|
||||
GraphicsWnd = CreateWindowEx(0, "GraphicsWnd", "SolveSpace (View Sketch)",
|
||||
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX,
|
||||
600, 300, 400, 400, NULL, (HMENU)NULL, Instance, NULL);
|
||||
if(!GraphicsWnd) oops();
|
||||
|
||||
ShowWindow(GraphicsWnd, SW_SHOW);
|
||||
|
||||
RECT r, rc;
|
||||
GetWindowRect(TextWnd, &r);
|
||||
GetClientRect(TextWnd, &rc);
|
||||
ClientIsSmallerBy = (r.bottom - r.top) - (rc.bottom - rc.top);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Entry point into the program.
|
||||
//-----------------------------------------------------------------------------
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine, INT nCmdShow)
|
||||
{
|
||||
Instance = hInstance;
|
||||
|
||||
// Create the root windows: one for control, with text, and one for
|
||||
// the graphics
|
||||
CreateMainWindows();
|
||||
|
||||
// A monospaced font
|
||||
FixedFont = CreateFont(TEXT_HEIGHT-1, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE,
|
||||
FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console");
|
||||
if(!FixedFont)
|
||||
FixedFont = (HFONT)GetStockObject(SYSTEM_FONT);
|
||||
|
||||
// Call in to the platform-independent code, and let them do their init
|
||||
SS.Init();
|
||||
|
||||
// And now it's the message loop. All calls in to the rest of the code
|
||||
// will be from the wndprocs.
|
||||
MSG msg;
|
||||
DWORD ret;
|
||||
while(ret = GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue